Comparing version 2.0.0-dev5 to 2.0.0-dev6
@@ -154,7 +154,6 @@ /** | ||
* | ||
* @param {array} [path] - Path to the modified node. | ||
* @param {mixed} [node] - The new node. | ||
* @return {Baobab} - The tree itself for chaining purposes. | ||
* @param {array} [path] - Path to the modified node. | ||
* @return {Baobab} - The tree itself for chaining purposes. | ||
*/ | ||
value: function _refreshComputedDataIndex(path, node) { | ||
value: function _refreshComputedDataIndex(path) { | ||
var _this2 = this; | ||
@@ -188,12 +187,14 @@ | ||
if (!path) { | ||
if (!path || !path.length) { | ||
// Walk the whole tree | ||
return walk(this.data); | ||
} else { | ||
// Retrieving parent of affected node | ||
var parentNode = (0, _helpers.getIn)(this.data, path.slice(0, -1)).data; | ||
// Walk the affected leaf | ||
return walk(parentNode, path.slice(0, -1)); | ||
} | ||
// else { | ||
// // Walk the affected leaf | ||
// return walk(node, path); | ||
// } | ||
} | ||
@@ -267,10 +268,8 @@ }, { | ||
// Stashing previous data if this is the frame's first update | ||
if (!this._transaction.length) this.previousData = this.data; | ||
// Solving the given path | ||
// Applying the operation | ||
var _getIn = (0, _helpers.getIn)(this.data, path, this._computedDataIndex); | ||
var solvedPath = _getIn.solvedPath; | ||
var exists = _getIn.exists; | ||
@@ -282,4 +281,12 @@ // If we couldn't solve the path, we throw | ||
// We don't unset irrelevant paths | ||
if (operation.type === 'unset' && !exists) return; | ||
// Stashing previous data if this is the frame's first update | ||
if (!this._transaction.length) this.previousData = this.data; | ||
var hash = hashPath(solvedPath); | ||
// Applying the operation | ||
var _update2 = (0, _update4['default'])(this.data, solvedPath, operation, this.options); | ||
@@ -290,6 +297,2 @@ | ||
// Refreshing facet index | ||
// TODO: provide a setting to disable this or at least selectively for perf | ||
this._refreshComputedDataIndex(solvedPath, node); | ||
// Updating data and transaction | ||
@@ -300,2 +303,6 @@ this.data = data; | ||
// Refreshing facet index | ||
// TODO: provide a setting to disable this or at least selectively for perf | ||
this._refreshComputedDataIndex(solvedPath); | ||
// Emitting a `write` event | ||
@@ -445,3 +452,3 @@ this.emit('write', { path: solvedPath }); | ||
Object.defineProperty(Baobab, 'version', { | ||
value: '2.0.0-dev5' | ||
value: '2.0.0-dev6' | ||
}); | ||
@@ -448,0 +455,0 @@ |
@@ -110,2 +110,16 @@ /** | ||
/** | ||
* Listener bound to the tree's writes so that cursors with dynamic paths | ||
* may update their solved path correctly. | ||
* | ||
* @param {object} event - The event fired by the tree. | ||
*/ | ||
this._writeHandler = function (_ref) { | ||
var data = _ref.data; | ||
if (!(0, _helpers.solveUpdate)([data.path], _this._getComparedPaths())) return; | ||
_this.solvedPath = (0, _helpers.getIn)(_this.tree.data, _this.path, _this._computedDataIndex).solvedPath; | ||
}; | ||
/** | ||
* Function in charge of actually trigger the cursor's updates and | ||
@@ -147,32 +161,4 @@ * deal with the archived records. | ||
var update = fireUpdate.bind(_this, previousData); | ||
var comparedPaths = _this._getComparedPaths(); | ||
var comparedPaths = undefined; | ||
// Standard cursor | ||
if (!_this._watch) { | ||
// Checking whether we should keep track of some dependencies | ||
var additionalPaths = _this._facetPath ? (0, _helpers.getIn)(_this.tree._computedDataIndex, _this._facetPath).data.relatedPaths() : []; | ||
// If the cursor's path is dynamic, we need to recompute it | ||
if (_this._dynamicPath) _this.solvedPath = (0, _helpers.getIn)(_this.tree.data, _this.path, _this._computedDataIndex).solvedPath; | ||
comparedPaths = [_this.solvedPath].concat(additionalPaths); | ||
} | ||
// Watcher cursor | ||
else { | ||
comparedPaths = _this._watchedPaths.reduce(function (cp, p) { | ||
if (_type2['default'].dynamicPath(p)) p = (0, _helpers.getIn)(_this.tree.data, p, _this._computedDataIndex).solvedPath; | ||
if (!p) return cp; | ||
var facetPath = _type2['default'].facetPath(p); | ||
if (facetPath) return cp.concat((0, _helpers.getIn)(_this.tree._computedDataIndex, p).data.relatedPaths()); | ||
return cp.concat([p]); | ||
}, []); | ||
} | ||
if ((0, _helpers.solveUpdate)(paths, comparedPaths)) return update(); | ||
@@ -187,2 +173,5 @@ }; | ||
bound = true; | ||
if (_this._dynamicPath) _this.tree.on('write', _this._writeHandler); | ||
return _this.tree.on('update', _this._updateHandler); | ||
@@ -192,3 +181,2 @@ }; | ||
// If the path is dynamic, we actually need to listen to the tree | ||
// TODO: there should be another way | ||
if (this._dynamicPath) { | ||
@@ -205,2 +193,47 @@ this._lazyBind(); | ||
_createClass(Cursor, [{ | ||
key: '_getComparedPaths', | ||
/** | ||
* Internal helpers | ||
* ----------------- | ||
*/ | ||
/** | ||
* Method returning the paths of the tree watched over by the cursor and that | ||
* should be taken into account when solving a potential update. | ||
* | ||
* @return {array} - Array of paths to compare with a given update. | ||
*/ | ||
value: function _getComparedPaths() { | ||
var _this2 = this; | ||
var comparedPaths = undefined; | ||
// Standard cursor | ||
if (!this._watch) { | ||
// Checking whether we should keep track of some dependencies | ||
var additionalPaths = this._facetPath ? (0, _helpers.getIn)(this.tree._computedDataIndex, this._facetPath).data.relatedPaths() : []; | ||
comparedPaths = [this.solvedPath].concat(additionalPaths); | ||
} | ||
// Watcher cursor | ||
else { | ||
comparedPaths = this._watchedPaths.reduce(function (cp, p) { | ||
if (_type2['default'].dynamicPath(p)) p = (0, _helpers.getIn)(_this2.tree.data, p, _this2._computedDataIndex).solvedPath; | ||
if (!p) return cp; | ||
var facetPath = _type2['default'].facetPath(p); | ||
if (facetPath) return cp.concat((0, _helpers.getIn)(_this2.tree._computedDataIndex, p).data.relatedPaths()); | ||
return cp.concat([p]); | ||
}, []); | ||
} | ||
return comparedPaths; | ||
} | ||
}, { | ||
key: 'isRoot', | ||
@@ -470,3 +503,3 @@ | ||
* Arity (2): | ||
* @param {..step} path - Path to serialize in the tree. | ||
* @param {..step} path - Path to serialize in the tree. | ||
* | ||
@@ -620,3 +653,5 @@ * @return {mixed} - The retrieved raw data. | ||
// Removing listener on parent | ||
// Removing listeners on parent | ||
if (this._dynamicPath) this.tree.off('write', this._writeHandler); | ||
this.tree.off('update', this._updateHandler); | ||
@@ -690,2 +725,8 @@ | ||
* | ||
* Note: this is not really possible to make those setters variadic because | ||
* it would create an impossible polymorphism with path. | ||
* | ||
* @todo: perform value validation elsewhere so that tree.update can | ||
* beneficiate from it. | ||
* | ||
* Arity (1): | ||
@@ -692,0 +733,0 @@ * @param {mixed} value - New value to set at cursor's path. |
@@ -64,2 +64,6 @@ /** | ||
this._hasDynamicPaths = this.paths.some(function (p) { | ||
return _type2['default'].dynamicPath(p); | ||
}); | ||
// Is the facet recursive? | ||
@@ -109,3 +113,9 @@ this.isRecursive = this.paths.some(function (p) { | ||
if (!this.isRecursive) return this.paths;else return this.paths.reduce(function (paths, path) { | ||
var paths = undefined; | ||
if (this._hasDynamicPaths) paths = this.paths.map(function (p) { | ||
return (0, _helpers.getIn)(_this2.tree.data, p, _this2.tree._computedDataIndex).solvedPath; | ||
});else paths = this.paths; | ||
if (!this.isRecursive) return paths;else return paths.reduce(function (paths, path) { | ||
var facetPath = _type2['default'].facetPath(path); | ||
@@ -112,0 +122,0 @@ if (!facetPath) return paths.concat(path); |
@@ -342,3 +342,3 @@ /** | ||
*/ | ||
var notFoundObject = { data: undefined, solvedPath: null }; | ||
var notFoundObject = { data: undefined, solvedPath: null, exists: false }; | ||
@@ -359,3 +359,3 @@ function getIn(object, path) { | ||
for (i = 0, l = path.length; i < l; i++) { | ||
if (!c) return { data: undefined, solvedPath: path }; | ||
if (!c) return { data: undefined, solvedPath: path, exists: false }; | ||
@@ -402,3 +402,3 @@ if (typeof path[i] === 'function') { | ||
return { data: c, solvedPath: solvedPath }; | ||
return { data: c, solvedPath: solvedPath, exists: true }; | ||
} | ||
@@ -405,0 +405,0 @@ |
@@ -122,3 +122,3 @@ /** | ||
else if (operationType === 'unset') { | ||
if (_type2['default'].object(p)) delete p[s]; | ||
if (_type2['default'].object(p)) delete p[s];else if (_type2['default'].array(p)) p.splice(s, 1); | ||
} | ||
@@ -125,0 +125,0 @@ |
{ | ||
"name": "baobab", | ||
"version": "2.0.0-dev5", | ||
"version": "2.0.0-dev6", | ||
"description": "JavaScript persistent data tree with cursors.", | ||
@@ -5,0 +5,0 @@ "main": "./dist/baobab.js", |
@@ -136,7 +136,6 @@ /** | ||
* | ||
* @param {array} [path] - Path to the modified node. | ||
* @param {mixed} [node] - The new node. | ||
* @return {Baobab} - The tree itself for chaining purposes. | ||
* @param {array} [path] - Path to the modified node. | ||
* @return {Baobab} - The tree itself for chaining purposes. | ||
*/ | ||
_refreshComputedDataIndex(path, node) { | ||
_refreshComputedDataIndex(path) { | ||
@@ -173,3 +172,3 @@ // Refreshing the whole tree | ||
if (!path) { | ||
if (!path || !path.length) { | ||
@@ -179,7 +178,10 @@ // Walk the whole tree | ||
} | ||
// else { | ||
else { | ||
// // Walk the affected leaf | ||
// return walk(node, path); | ||
// } | ||
// Retrieving parent of affected node | ||
const parentNode = getIn(this.data, path.slice(0, -1)).data; | ||
// Walk the affected leaf | ||
return walk(parentNode, path.slice(0, -1)); | ||
} | ||
} | ||
@@ -254,8 +256,4 @@ | ||
// Stashing previous data if this is the frame's first update | ||
if (!this._transaction.length) | ||
this.previousData = this.data; | ||
// Applying the operation | ||
const {solvedPath} = getIn( | ||
// Solving the given path | ||
const {solvedPath, exists} = getIn( | ||
this.data, | ||
@@ -272,4 +270,13 @@ path, | ||
// We don't unset irrelevant paths | ||
if (operation.type === 'unset' && !exists) | ||
return; | ||
// Stashing previous data if this is the frame's first update | ||
if (!this._transaction.length) | ||
this.previousData = this.data; | ||
const hash = hashPath(solvedPath); | ||
// Applying the operation | ||
const {data, node} = update( | ||
@@ -282,6 +289,2 @@ this.data, | ||
// Refreshing facet index | ||
// TODO: provide a setting to disable this or at least selectively for perf | ||
this._refreshComputedDataIndex(solvedPath, node); | ||
// Updating data and transaction | ||
@@ -292,2 +295,6 @@ this.data = data; | ||
// Refreshing facet index | ||
// TODO: provide a setting to disable this or at least selectively for perf | ||
this._refreshComputedDataIndex(solvedPath); | ||
// Emitting a `write` event | ||
@@ -430,3 +437,3 @@ this.emit('write', {path: solvedPath}); | ||
Object.defineProperty(Baobab, 'version', { | ||
value: '2.0.0-dev5' | ||
value: '2.0.0-dev6' | ||
}); | ||
@@ -433,0 +440,0 @@ |
@@ -103,2 +103,19 @@ /** | ||
/** | ||
* Listener bound to the tree's writes so that cursors with dynamic paths | ||
* may update their solved path correctly. | ||
* | ||
* @param {object} event - The event fired by the tree. | ||
*/ | ||
this._writeHandler = ({data}) => { | ||
if (!solveUpdate([data.path], this._getComparedPaths())) | ||
return; | ||
this.solvedPath = getIn( | ||
this.tree.data, | ||
this.path, | ||
this._computedDataIndex | ||
).solvedPath; | ||
}; | ||
/** | ||
* Function in charge of actually trigger the cursor's updates and | ||
@@ -139,50 +156,5 @@ * deal with the archived records. | ||
const {paths, previousData} = event.data, | ||
update = fireUpdate.bind(this, previousData); | ||
update = fireUpdate.bind(this, previousData), | ||
comparedPaths = this._getComparedPaths(); | ||
let comparedPaths; | ||
// Standard cursor | ||
if (!this._watch) { | ||
// Checking whether we should keep track of some dependencies | ||
const additionalPaths = this._facetPath ? | ||
getIn(this.tree._computedDataIndex, this._facetPath) | ||
.data | ||
.relatedPaths() : | ||
[]; | ||
// If the cursor's path is dynamic, we need to recompute it | ||
if (this._dynamicPath) | ||
this.solvedPath = getIn( | ||
this.tree.data, | ||
this.path, | ||
this._computedDataIndex | ||
).solvedPath; | ||
comparedPaths = [this.solvedPath].concat(additionalPaths); | ||
} | ||
// Watcher cursor | ||
else { | ||
comparedPaths = this._watchedPaths.reduce((cp, p) => { | ||
if (type.dynamicPath(p)) | ||
p = getIn( | ||
this.tree.data, | ||
p, | ||
this._computedDataIndex | ||
).solvedPath; | ||
if (!p) | ||
return cp; | ||
const facetPath = type.facetPath(p); | ||
if (facetPath) | ||
return cp.concat( | ||
getIn(this.tree._computedDataIndex, p).data.relatedPaths()); | ||
return cp.concat([p]); | ||
}, []); | ||
} | ||
if (solveUpdate(paths, comparedPaths)) | ||
@@ -199,2 +171,6 @@ return update(); | ||
bound = true; | ||
if (this._dynamicPath) | ||
this.tree.on('write', this._writeHandler); | ||
return this.tree.on('update', this._updateHandler); | ||
@@ -204,3 +180,2 @@ }; | ||
// If the path is dynamic, we actually need to listen to the tree | ||
// TODO: there should be another way | ||
if (this._dynamicPath) { | ||
@@ -218,2 +193,55 @@ this._lazyBind(); | ||
/** | ||
* Internal helpers | ||
* ----------------- | ||
*/ | ||
/** | ||
* Method returning the paths of the tree watched over by the cursor and that | ||
* should be taken into account when solving a potential update. | ||
* | ||
* @return {array} - Array of paths to compare with a given update. | ||
*/ | ||
_getComparedPaths() { | ||
let comparedPaths; | ||
// Standard cursor | ||
if (!this._watch) { | ||
// Checking whether we should keep track of some dependencies | ||
const additionalPaths = this._facetPath ? | ||
getIn(this.tree._computedDataIndex, this._facetPath) | ||
.data | ||
.relatedPaths() : | ||
[]; | ||
comparedPaths = [this.solvedPath].concat(additionalPaths); | ||
} | ||
// Watcher cursor | ||
else { | ||
comparedPaths = this._watchedPaths.reduce((cp, p) => { | ||
if (type.dynamicPath(p)) | ||
p = getIn( | ||
this.tree.data, | ||
p, | ||
this._computedDataIndex | ||
).solvedPath; | ||
if (!p) | ||
return cp; | ||
const facetPath = type.facetPath(p); | ||
if (facetPath) | ||
return cp.concat( | ||
getIn(this.tree._computedDataIndex, p).data.relatedPaths()); | ||
return cp.concat([p]); | ||
}, []); | ||
} | ||
return comparedPaths; | ||
} | ||
/** | ||
* Predicates | ||
@@ -474,3 +502,3 @@ * ----------- | ||
* Arity (2): | ||
* @param {..step} path - Path to serialize in the tree. | ||
* @param {..step} path - Path to serialize in the tree. | ||
* | ||
@@ -615,3 +643,6 @@ * @return {mixed} - The retrieved raw data. | ||
// Removing listener on parent | ||
// Removing listeners on parent | ||
if (this._dynamicPath) | ||
this.tree.off('write', this._writeHandler); | ||
this.tree.off('update', this._updateHandler); | ||
@@ -677,2 +708,8 @@ | ||
* | ||
* Note: this is not really possible to make those setters variadic because | ||
* it would create an impossible polymorphism with path. | ||
* | ||
* @todo: perform value validation elsewhere so that tree.update can | ||
* beneficiate from it. | ||
* | ||
* Arity (1): | ||
@@ -679,0 +716,0 @@ * @param {mixed} value - New value to set at cursor's path. |
@@ -55,2 +55,4 @@ /** | ||
this._hasDynamicPaths = this.paths.some(p => type.dynamicPath(p)); | ||
// Is the facet recursive? | ||
@@ -92,6 +94,15 @@ this.isRecursive = this.paths.some(p => !!type.facetPath(p)); | ||
relatedPaths() { | ||
let paths; | ||
if (this._hasDynamicPaths) | ||
paths = this.paths.map( | ||
p => getIn(this.tree.data, p, this.tree._computedDataIndex).solvedPath | ||
); | ||
else | ||
paths = this.paths; | ||
if (!this.isRecursive) | ||
return this.paths; | ||
return paths; | ||
else | ||
return this.paths.reduce((paths, path) => { | ||
return paths.reduce((paths, path) => { | ||
const facetPath = type.facetPath(path); | ||
@@ -98,0 +109,0 @@ if (!facetPath) |
@@ -320,3 +320,3 @@ /** | ||
*/ | ||
const notFoundObject = {data: undefined, solvedPath: null}; | ||
const notFoundObject = {data: undefined, solvedPath: null, exists: false}; | ||
@@ -335,3 +335,3 @@ export function getIn(object, path, mask=null, opts={}) { | ||
if (!c) | ||
return {data: undefined, solvedPath: path}; | ||
return {data: undefined, solvedPath: path, exists: false}; | ||
@@ -384,3 +384,3 @@ if (typeof path[i] === 'function') { | ||
return {data: c, solvedPath}; | ||
return {data: c, solvedPath, exists: true}; | ||
} | ||
@@ -387,0 +387,0 @@ |
@@ -139,2 +139,5 @@ /** | ||
delete p[s]; | ||
else if (type.array(p)) | ||
p.splice(s, 1); | ||
} | ||
@@ -141,0 +144,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
155211
3905