Esempio n. 1
0
  function writeGraph(root, headerful) {
    if (headerful) {
      writeMagic();
    }

    var refInfo = findBackRefsAndHoles(root, holeFilter);
    backRefSet = refInfo.backRefs;
    holeMap = refInfo.holes;

    if (backRefSet.size() !== 0) {
      backRefMap = oid.createMap();
    }

    iterate.iterate(root, visitor);

    if (headerful) {
      writeFooter();
    }
  }
Esempio n. 2
0
/**
 * Determine the sets of all back-referenced objects and all non-data
 * "holes" under the given root. The holes are filtered using the
 * given filter, resulting in a map with bindings from the original
 * to the filtered objects.
 */
function findBackRefsAndHoles(root, holeFilter) {
  var allowHoles = typ.isDefined(holeFilter);
  var allRefs = oid.createMap();
  var holes = allowHoles ? oid.createMap() : undefined;

  function nop() {
    // This space intentionally left blank.
  }

  function keepGoing(obj, name, value, innerVisitor) {
    if (innerVisitor) {
      innerVisitor();
    }
  }

  function addRef(obj, innerVisitor, mustBeHole) {
    if (mustBeHole && !allowHoles) {
      throw new Error("Hole-ful graph, but no hole filter.");
    }

    var count = allRefs.get(obj, 0) + 1;

    allRefs.set(obj, count);

    if (count === 1) {
      if (mustBeHole) {
        var already = holes.get(obj);
        if (!already) {
          var replacement = fixReplacement(obj, holeFilter(obj));
          holes.set(obj, replacement);
          iterate.iterate(replacement.obj, visitor);
        }
      } else if (innerVisitor) {
        innerVisitor();
      }
    }
  }

  function visitFunction(func, innerVisitor) {
    addRef(func, innerVisitor, true);
  }

  function visitObject(obj, innerVisitor) {
    if (Buffer.isBuffer(obj)) {
      // Suppress the inner visit for buffers, because it is too
      // odious to imagine having to cons up all the keys for
      // the buffer indices. (Too bad there's no
      // `Object.getOwnNamedProperties()` or somesuch.)
      addRef(obj, undefined);
    } else {
      addRef(obj, innerVisitor, !typ.isMap(obj));
    }
  }

  var visitor = {
    visitObject: visitObject,
    visitArray: addRef,
    visitFunction: visitFunction,
    visitString: addRef,

    visitObjectPrototype: keepGoing,
    visitObjectBinding: keepGoing,
    visitObjectGetter: keepGoing,
    visitObjectSetter: keepGoing,
    visitArrayElement: keepGoing,

    visitNumber: nop,
    visitBoolean: nop,
    visitUndefined: nop,
    visitNull: nop
  };

  iterate.iterate(root, visitor);

  var backRefs = oid.createSet();
  allRefs.forEach(function (ref, count) {
    if (count > 1) {
      backRefs.add(ref);
    }
  });

  return { backRefs: backRefs, holes: holes };
}