falcor
Version:
A JavaScript library for efficient data fetching.
174 lines (138 loc) • 5 kB
JavaScript
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];
}