text: var __ref = require("./../internal/ref");
  
  var $ref = require("./../types/ref");
  
  var getBoundValue = require("./../get/getBoundValue");
  
  var promote = require("./../lru/promote");
  var getSize = require("./../support/getSize");
  var isExpired = require("./../support/isExpired");
  var isFunction = require("./../support/isFunction");
  var isPrimitive = require("./../support/isPrimitive");
  var expireNode = require("./../support/expireNode");
  var iterateKeySet = require("falcor-path-utils").iterateKeySet;
  var incrementVersion = require("./../support/incrementVersion");
  var updateNodeAncestors = require("./../support/updateNodeAncestors");
  var removeNodeAndDescendants = require("./../support/removeNodeAndDescendants");
  
  /**
   * Invalidates a list of Paths in a JSON Graph.
   * @function
   * @param {Object} model - the Model for which to insert the PathValues.
   * @param {Array.<PathValue>} paths - the PathValues to set.
   */
  
  module.exports = function invalidatePathSets(model, paths) {
  
      var modelRoot = model._root;
      var lru = modelRoot;
      var expired = modelRoot.expired;
      var version = incrementVersion();
      var bound = model._path;
      var cache = modelRoot.cache;
      var node = bound.length ? getBoundValue(model, bound).value : cache;
      // eslint-disable-next-line camelcase
      var parent = node.$_parent || cache;
      // eslint-disable-next-line camelcase
      var initialVersion = cache.$_version;
  
      var pathIndex = -1;
      var pathCount = paths.length;
  
      while (++pathIndex < pathCount) {
  
          var path = paths[pathIndex];
  
          invalidatePathSet(
              path, 0, cache, parent, node,
              version, expired, lru
          );
      }
  
      // eslint-disable-next-line camelcase
      var newVersion = cache.$_version;
      var rootChangeHandler = modelRoot.onChange;
  
      if (isFunction(rootChangeHandler) && initialVersion !== newVersion) {
          rootChangeHandler();
      }
  };
  
  function invalidatePathSet(
      path, depth, root, parent, node,
      version, expired, lru) {
  
      var note = {};
      var branch = depth < path.length - 1;
      var keySet = path[depth];
      var key = iterateKeySet(keySet, note);
  
      do {
          var results = invalidateNode(
              root, parent, node,
              key, branch, false,
              version, expired, lru
          );
          var nextNode = results[0];
          var nextParent = results[1];
          if (nextNode) {
              if (branch) {
                  invalidatePathSet(
                      path, depth + 1,
                      root, nextParent, nextNode,
                      version, expired, lru
                  );
              } else if (removeNodeAndDescendants(nextNode, nextParent, key, lru)) {
                  updateNodeAncestors(nextParent, getSize(nextNode), lru, version);
              }
          }
          key = iterateKeySet(keySet, note);
      } while (!note.done);
  }
  
  function invalidateReference(root, node, version, expired, lru) {
  
      if (isExpired(node)) {
          expireNode(node, expired, lru);
          return [undefined, root];
      }
  
      promote(lru, node);
  
      var container = node;
      var reference = node.value;
      var parent = root;
  
      // eslint-disable-next-line camelcase
      node = node.$_context;
  
      if (node != null) {
          // eslint-disable-next-line camelcase
          parent = node.$_parent || root;
      } else {
  
          var index = 0;
          var count = reference.length - 1;
  
          parent = node = root;
  
          do {
              var key = reference[index];
              var branch = index < count;
              var results = invalidateNode(
                  root, parent, node,
                  key, branch, true,
                  version, expired, lru
              );
              node = results[0];
              if (isPrimitive(node)) {
                  return results;
              }
              parent = results[1];
          } while (index++ < count);
  
          // eslint-disable-next-line camelcase
          if (container.$_context !== node) {
              // eslint-disable-next-line camelcase
              var backRefs = node.$_refsLength || 0;
              // eslint-disable-next-line camelcase
              node.$_refsLength = backRefs + 1;
              node[__ref + backRefs] = container;
              // eslint-disable-next-line camelcase
              container.$_context = node;
              // eslint-disable-next-line camelcase
              container.$_refIndex = backRefs;
          }
      }
  
      return [node, parent];
  }
  
  function invalidateNode(
      root, parent, node,
      key, branch, reference,
      version, expired, lru) {
  
      var type = node.$type;
  
      while (type === $ref) {
  
          var results = invalidateReference(root, node, version, expired, lru);
  
          node = results[0];
  
          if (isPrimitive(node)) {
              return results;
          }
  
          parent = results[1];
          type = node.$type;
      }
  
      if (type !== void 0) {
          return [node, parent];
      }
  
      if (key == null) {
          if (branch) {
              throw new Error("`null` is not allowed in branch key positions.");
          } else if (node) {
              key = node.$_key;
          }
      } else {
          parent = node;
          node = parent[key];
      }
  
      return [node, parent];
  }
  