async function getReferences (currentNode, isOutOfRoot, pathSolver, parentFilename, version, rootMainKeys,
  commonPathFromData, allData, globalReferences, remoteRefResolver) {
  let referencesInNode = [],
    nodeReferenceDirectory = {},
    mainKeys = {},
    remoteRefContentMap = new Map(),
    remoteRefSet = new Set(),
    remoteRefResolutionPromises = [];

  remoteRefResolver && traverseUtility(currentNode).forEach(function (property) {
    if (property) {
      let hasReferenceTypeKey;

      hasReferenceTypeKey = Object.keys(property)
        .find(
          (key) => {
            const isExternal = isExtURLRef(property, key),
              isReferenciable = isExternal;

            return isReferenciable;
          }
        );

      if (hasReferenceTypeKey) {
        const tempRef = calculatePath(parentFilename, property.$ref),
          isRefEncountered = remoteRefSet.has(tempRef);

        if (isRefEncountered) {
          return;
        }

        remoteRefResolutionPromises.push(
          new Promise(async (resolveInner) => {

            /**
             * Converts contents received from remoteRefResolver into stringified JSON
             * @param {string | object} content - contents from remoteRefResolver
             * @returns {string} Stringified JSON contents
             */
            function convertToJSONString (content) {
              if (typeof content === 'object') {
                return JSON.stringify(content);
              }

              const parsedFile = parseFile(content);

              return JSON.stringify(parsedFile.oasObject);
            }

            try {
              let contentFromRemote = await remoteRefResolver(property.$ref),
                nodeTemp = {
                  fileName: tempRef,
                  path: tempRef,
                  content: convertToJSONString(contentFromRemote),
                  href: property.$ref
                };

              remoteRefContentMap.set(tempRef, contentFromRemote);

              allData.push(nodeTemp);
            }
            catch (err) {
              // swallow the err
            }
            finally {
              resolveInner();
            }
          })
        );

        remoteRefSet.add(tempRef);
      }
    }
  });

  await Promise.all(remoteRefResolutionPromises);

  traverseUtility(currentNode).forEach(function (property) {
    if (property) {
      let hasReferenceTypeKey;
      hasReferenceTypeKey = Object.keys(property)
        .find(
          (key) => {
            const isLocalOutOfRoot = isOutOfRoot && isLocalRef(property, key),
              isExternal = isExtRef(property, key),
              isReferenciable = isLocalOutOfRoot || isExternal;
            return isReferenciable;
          }
        );
      if (hasReferenceTypeKey) {
        const tempRef = calculatePath(parentFilename, property.$ref),
          nodeTrace = handleLocalCollisions(
            getTraceFromParentKeyInComponents(this, tempRef, mainKeys, version, commonPathFromData),
            rootMainKeys
          ),
          componentKey = nodeTrace[nodeTrace.length - 1],
          referenceInDocument = getJsonPointerRelationToRoot(
            tempRef,
            nodeTrace,
            version
          ),
          traceToParent = [...this.parents.map((item) => {
            return item.key;
          }).filter((item) => {
            return item !== undefined;
          }), this.key];
        let newValue,
          [, local] = tempRef.split(localPointer),
          nodeFromData,
          refHasContent = false,
          parseResult,
          newRefInDoc,
          inline;

        newValue = Object.assign({}, this.node);
        nodeFromData = findNodeFromPath(tempRef, allData);
        if (nodeFromData && nodeFromData.content) {
          parseResult = parseFile(nodeFromData.content);
          if (parseResult.result) {
            newValue.$ref = referenceInDocument;
            refHasContent = true;
            nodeFromData.parsed = parseResult;
          }
        }
        this.update({ $ref: tempRef });

        if (nodeTrace.length === 0) {
          inline = true;
        }

        if (_.isNil(globalReferences[tempRef])) {
          nodeReferenceDirectory[tempRef] = {
            local,
            keyInComponents: nodeTrace,
            node: newValue,
            reference: inline ? newRefInDoc : referenceInDocument,
            traceToParent,
            parentNodeKey: parentFilename,
            mainKeyInTrace: nodeTrace[nodeTrace.length - 1],
            refHasContent,
            inline
          };
        }

        mainKeys[componentKey] = tempRef;

        if (!added(property.$ref, referencesInNode)) {
          referencesInNode.push({ path: pathSolver(property), keyInComponents: nodeTrace, newValue: this.node });
        }
      }

      const hasRemoteReferenceTypeKey = Object.keys(property)
          .find(
            (key) => {
              const isExternal = isExtURLRef(property, key),

                // Only process URL refs if remoteRefResolver is provided and a valid function
                isReferenciable = isExternal && _.isFunction(remoteRefResolver);

              return isReferenciable;
            }
          ),
        handleRemoteURLReference = () => {
          const tempRef = calculatePath(parentFilename, property.$ref);

          if (remoteRefContentMap.get(tempRef) === undefined) {
            return;
          }

          let nodeTrace = handleLocalCollisions(
              getTraceFromParentKeyInComponents(this, tempRef, mainKeys, version, commonPathFromData),
              rootMainKeys
            ),
            componentKey = nodeTrace[nodeTrace.length - 1],
            referenceInDocument = getJsonPointerRelationToRoot(
              tempRef,
              nodeTrace,
              version
            ),
            traceToParent = [...this.parents.map((item) => {
              return item.key;
            }).filter((item) => {
              return item !== undefined;
            }), this.key],
            newValue = Object.assign({}, this.node),
            [, local] = tempRef.split(localPointer),
            nodeFromData,
            refHasContent = false,
            parseResult,
            newRefInDoc,
            inline,
            contentFromRemote = remoteRefContentMap.get(tempRef),
            nodeTemp = {
              fileName: tempRef,
              path: tempRef,
              content: contentFromRemote
            };

          nodeFromData = nodeTemp;

          if (nodeFromData && nodeFromData.content) {
            parseResult = parseFile(JSON.stringify(nodeFromData.content));
            if (parseResult.result) {
              newValue.$ref = referenceInDocument;
              refHasContent = true;
              nodeFromData.parsed = parseResult;
            }
          }
          this.update({ $ref: tempRef });

          if (nodeTrace.length === 0) {
            inline = true;
          }

          if (_.isNil(globalReferences[tempRef])) {
            nodeReferenceDirectory[tempRef] = {
              local,
              keyInComponents: nodeTrace,
              node: newValue,
              reference: inline ? newRefInDoc : referenceInDocument,
              traceToParent,
              parentNodeKey: parentFilename,
              mainKeyInTrace: nodeTrace[nodeTrace.length - 1],
              refHasContent,
              inline
            };
          }

          mainKeys[componentKey] = tempRef;

          if (!added(property.$ref, referencesInNode)) {
            referencesInNode.push({ path: pathSolver(property), keyInComponents: nodeTrace, newValue: this.node });
          }
        };

      if (hasRemoteReferenceTypeKey) {
        handleRemoteURLReference();
      }
    }
  });

  return { referencesInNode, nodeReferenceDirectory };
}
Gets all the $refs from an object
@param {object} currentNode - current node in process
@param {Function} isOutOfRoot - A filter to know if the current components was called from root or not
@param {Function} pathSolver - function to resolve the Path
@param {string} parentFilename - The parent's filename
@param {object} version - The version of the spec we are bundling
@param {object} rootMainKeys - A dictionary with the component keys in local components object and its mainKeys
@param {string} commonPathFromData - The common path in the file's paths
@param {Array} allData -  array of { path, content} objects
@param {object} globalReferences - The accumulated global references from all nodes
@param {function} remoteRefResolver - The function that would be called to fetch remote ref contents
@returns {object} - The references in current node and the new content from the node