lib/dereference.js
function crawl (obj, path, pathFromRoot, parents, $refs, options) {
  var dereferenced;
  var result = {
    value: obj,
    circular: false
  };

  if (obj && typeof obj === "object") {
    parents.push(obj);

    if ($Ref.isAllowed$Ref(obj, options)) {
      dereferenced = dereference$Ref(obj, path, pathFromRoot, parents, $refs, options);
      result.circular = dereferenced.circular;
      result.value = dereferenced.value;
    }
    else {
      Object.keys(obj).forEach(function (key) {
        var keyPath = Pointer.join(path, key);
        var keyPathFromRoot = Pointer.join(pathFromRoot, key);
        var value = obj[key];
        var circular = false;

        if ($Ref.isAllowed$Ref(value, options)) {
          dereferenced = dereference$Ref(value, keyPath, keyPathFromRoot, parents, $refs, options);
          circular = dereferenced.circular;
          obj[key] = dereferenced.value;
        }
        else {
          if (parents.indexOf(value) === -1) {
            dereferenced = crawl(value, keyPath, keyPathFromRoot, parents, $refs, options);
            circular = dereferenced.circular;
            obj[key] = dereferenced.value;
          }
          else {
            circular = foundCircularReference(keyPath, $refs, options);
          }
        }

        // Set the "isCircular" flag if this or any other property is circular
        result.circular = result.circular || circular;
      });
    }

    parents.pop();
  }

  return result;
}
function crawl (obj, path, pathFromRoot, parents, $refs, options) {
  var dereferenced;
  var result = {
    value: obj,
    circular: false
  };

  if (obj && typeof obj === "object") {
    parents.push(obj);

    if ($Ref.isAllowed$Ref(obj, options)) {
      dereferenced = dereference$Ref(obj, path, pathFromRoot, parents, $refs, options);
      result.circular = dereferenced.circular;
      result.value = dereferenced.value;
    }
    else {
      Object.keys(obj).forEach(function (key) {
        var keyPath = Pointer.join(path, key);
        var keyPathFromRoot = Pointer.join(pathFromRoot, key);
        var value = obj[key];
        var circular = false;

        if ($Ref.isAllowed$Ref(value, options)) {
          dereferenced = dereference$Ref(value, keyPath, keyPathFromRoot, parents, $refs, options);
          circular = dereferenced.circular;
          obj[key] = dereferenced.value;
        }
        else {
          if (parents.indexOf(value) === -1) {
            dereferenced = crawl(value, keyPath, keyPathFromRoot, parents, $refs, options);
            circular = dereferenced.circular;
            obj[key] = dereferenced.value;
          }
          else {
            circular = foundCircularReference(keyPath, $refs, options);
          }
        }

        // Set the "isCircular" flag if this or any other property is circular
        result.circular = result.circular || circular;
      });
    }

    parents.pop();
  }

  return result;
}
function crawl ( obj , path , pathFromRoot , parents , $refs , options ) { var dereferenced ; var result = { value : obj , circular : false } ; if ( obj && typeof obj === "object" ) { parents . push ( obj ) ; if ( $Ref . isAllowed$Ref ( obj , options ) ) { dereferenced = dereference$Ref ( obj , path , pathFromRoot , parents , $refs , options ) ; result . circular = dereferenced . circular ; result . value = dereferenced . value ; } else { Object . keys ( obj ) . forEach ( function ( key ) { var keyPath = Pointer . join ( path , key ) ; var keyPathFromRoot = Pointer . join ( pathFromRoot , key ) ; var value = obj [ key ] ; var circular = false ; if ( $Ref . isAllowed$Ref ( value , options ) ) { dereferenced = dereference$Ref ( value , keyPath , keyPathFromRoot , parents , $refs , options ) ; circular = dereferenced . circular ; obj [ key ] = dereferenced . value ; } else { if ( parents . indexOf ( value ) === - 1 ) { dereferenced = crawl ( value , keyPath , keyPathFromRoot , parents , $refs , options ) ; circular = dereferenced . circular ; obj [ key ] = dereferenced . value ; } else { circular = foundCircularReference ( keyPath , $refs , options ) ; } } // Set the "isCircular" flag if this or any other property is circular
 result . circular = result . circular || circular ; } ) ; } parents . pop ( ) ; } return result ; }
Recursively crawls the given value, and dereferences any JSON references.

@param {*} obj - The value to crawl. If it's not an object or array, it will be ignored.
@param {string} path - The full path of `obj`, possibly with a JSON Pointer in the hash
@param {string} pathFromRoot - The path of `obj` from the schema root
@param {object[]} parents - An array of the parent objects that have already been dereferenced
@param {$Refs} $refs
@param {$RefParserOptions} options
@returns {{value: object, circular: boolean}}
Recursively crawls the given value and dereferences any JSON references .