UNPKG

falcor

Version:

A JavaScript library for efficient data fetching.

174 lines (138 loc) 5 kB
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, 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, undefined)) { updateNodeAncestors(nextParent, getSize(nextNode), lru, version); } } key = iterateKeySet(keySet, note); } while (!note.done); } function invalidateReference(root, node, 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, 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, expired, lru) { var type = node.$type; while (type === $ref) { var results = invalidateReference(root, node, 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]; }