async PathItemElement(pathItemElement, key, parent, path, ancestors, link) {
    try {
      // ignore PathItemElement without $ref field
      if (!isStringElement(pathItemElement.$ref)) {
        return undefined;
      }

      // skip current referencing element as it's already been access
      if (this.indirections.includes(pathItemElement)) {
        return false;
      }

      // skip already identified cycled Path Item Objects
      if (includesClasses(['cycle'], pathItemElement.$ref)) {
        return false;
      }

      const [ancestorsLineage, directAncestors] = this.toAncestorLineage([...ancestors, parent]);

      const retrievalURI = this.toBaseURI(toValue(pathItemElement.$ref));
      const isInternalReference = url.stripHash(this.reference.uri) === retrievalURI;
      const isExternalReference = !isInternalReference;

      // ignore resolving internal Path Item Elements
      if (!this.options.resolve.internal && isInternalReference) {
        return undefined;
      }
      // ignore resolving external Path Item Elements
      if (!this.options.resolve.external && isExternalReference) {
        return undefined;
      }

      const reference = await this.toReference(toValue(pathItemElement.$ref));
      const $refBaseURI = url.resolve(retrievalURI, toValue(pathItemElement.$ref));

      this.indirections.push(pathItemElement);

      const jsonPointer = URIFragmentIdentifier.fromURIReference($refBaseURI);

      // possibly non-semantic referenced element
      let referencedElement = jsonPointerEvaluate(reference.value.result, jsonPointer);
      referencedElement.id = identityManager.identify(referencedElement);

      // applying semantics to a referenced element
      if (isPrimitiveElement(referencedElement)) {
        const cacheKey = `path-item-${toValue(identityManager.identify(referencedElement))}`;

        if (this.refractCache.has(cacheKey)) {
          referencedElement = this.refractCache.get(cacheKey);
        } else {
          referencedElement = PathItemElement.refract(referencedElement);
          this.refractCache.set(cacheKey, referencedElement);
        }
      }

      // detect direct or indirect reference
      if (pathItemElement === referencedElement) {
        throw new ApiDOMError('Recursive Path Item Object reference detected');
      }

      // detect maximum depth of dereferencing
      if (this.indirections.length > this.options.dereference.maxDepth) {
        throw new MaximumDereferenceDepthError(
          `Maximum dereference depth of "${this.options.dereference.maxDepth}" has been exceeded in file "${this.reference.uri}"`
        );
      }

      // detect second deep dive into the same fragment and avoid it
      if (ancestorsLineage.includes(referencedElement)) {
        reference.refSet.circular = true;

        if (this.options.dereference.circular === 'error') {
          throw new ApiDOMError('Circular reference detected');
        } else if (this.options.dereference.circular === 'replace') {
          const refElement = new RefElement(referencedElement.id, {
            type: 'path-item',
            uri: reference.uri,
            $ref: toValue(pathItemElement.$ref),
            baseURI: $refBaseURI,
            referencingElement: pathItemElement,
          });
          const replacer =
            this.options.dereference.strategyOpts['openapi-3-1']?.circularReplacer ??
            this.options.dereference.circularReplacer;
          const replacement = replacer(refElement);

          link.replaceWith(refElement, mutationReplacer);

          return !parent ? replacement : false;
        }
      }

      /**
       * Dive deep into the fragment.
       *
       * Cases to consider:
       *  1. We're crossing document boundary
       *  2. Fragment is from non-root document
       *  3. Fragment is a Path Item Object with $ref field. We need to follow it to get the eventual value
       *  4. We are dereferencing the fragment lazily/eagerly depending on circular mode
       */
      const isNonRootDocument = url.stripHash(reference.refSet.rootRef.uri) !== reference.uri;
      const shouldDetectCircular = ['error', 'replace'].includes(this.options.dereference.circular);
      if (
        (isExternalReference ||
          isNonRootDocument ||
          (isPathItemElement(referencedElement) && isStringElement(referencedElement.$ref)) ||
          shouldDetectCircular) &&
        !ancestorsLineage.includesCycle(referencedElement)
      ) {
        // append referencing schema to ancestors lineage
        directAncestors.add(pathItemElement);

        // dive deep into the referenced element
        const visitor = new OpenAPI3_1SwaggerClientDereferenceVisitor({
          reference,
          namespace: this.namespace,
          indirections: [...this.indirections],
          options: this.options,
          ancestors: ancestorsLineage,
          allowMetaPatches: this.allowMetaPatches,
          useCircularStructures: this.useCircularStructures,
          basePath: this.basePath ?? [...toPath([...ancestors, parent, pathItemElement]), '$ref'],
        });
        referencedElement = await visitAsync(referencedElement, visitor, {
          keyMap,
          nodeTypeGetter: getNodeType,
        });

        // remove referencing schema from ancestors lineage
        directAncestors.delete(pathItemElement);
      }

      this.indirections.pop();

      /**
       * Creating a new version of Path Item by merging fields from referenced Path Item with referencing one.
       */
      if (isPathItemElement(referencedElement)) {
        const mergedElement = new PathItemElement(
          [...referencedElement.content],
          cloneDeep(referencedElement.meta),
          cloneDeep(referencedElement.attributes)
        );
        // existing keywords from referencing PathItemElement overrides ones from referenced element
        pathItemElement.forEach((value, keyElement, item) => {
          mergedElement.remove(toValue(keyElement));
          mergedElement.content.push(item);
        });
        mergedElement.remove('$ref');

        // annotate referenced element with info about original referencing element
        mergedElement.setMetaProperty('ref-fields', {
          $ref: toValue(pathItemElement.$ref),
        });
        // annotate referenced element with info about origin
        mergedElement.setMetaProperty('ref-origin', reference.uri);
        // annotate fragment with info about referencing element
        mergedElement.setMetaProperty(
          'ref-referencing-element-id',
          cloneDeep(identityManager.identify(pathItemElement))
        );

        // apply meta patches
        if (this.allowMetaPatches) {
          // apply meta patch only when not already applied
          if (typeof mergedElement.get('$$ref') === 'undefined') {
            const baseURI = url.resolve(retrievalURI, $refBaseURI);
            mergedElement.set('$$ref', baseURI);
          }
        }

        referencedElement = mergedElement;
      }

      /**
       * Transclude referencing element with merged referenced element.
       */
      link.replaceWith(referencedElement, mutationReplacer);

      /**
       * We're at the root of the tree, so we're just replacing the entire tree.
       */
      return !parent ? referencedElement : undefined;
    } catch (error) {
      const rootCause = getRootCause(error);
      const wrappedError = wrapError(rootCause, {
        baseDoc: this.reference.uri,
        $ref: toValue(pathItemElement.$ref),
        pointer: URIFragmentIdentifier.fromURIReference(toValue(pathItemElement.$ref)),
        fullPath: this.basePath ?? [...toPath([...ancestors, parent, pathItemElement]), '$ref'],
      });
      this.options.dereference.dereferenceOpts?.errors?.push?.(wrappedError);

      return undefined;
    }
  }
We're at the root of the tree, so we're just replacing the entire tree.