Comparing version 2.3.0 to 2.3.1
# Changelog | ||
## v2.3.1 | ||
* Adding internal `tree.getMonkey`. | ||
* Fixing issue concerning monkey's recursivity. | ||
* Fixing a bug concerning setters & dynamic paths. | ||
## v2.3.0 | ||
@@ -4,0 +10,0 @@ |
@@ -225,4 +225,2 @@ /** | ||
var register = []; | ||
var walk = function walk(data) { | ||
@@ -235,4 +233,2 @@ var p = arguments.length <= 1 || arguments[1] === undefined ? [] : arguments[1]; | ||
register.push(monkeyInstance); | ||
(0, _update3['default'])(_this2._monkeys, p, { type: 'set', value: monkeyInstance }, { | ||
@@ -258,5 +254,2 @@ immutable: false, | ||
walk(this._data); | ||
register.forEach(function (m) { | ||
return m.checkRecursivity(); | ||
}); | ||
} else { | ||
@@ -271,5 +264,2 @@ var monkeysNode = getIn(this._monkeys, path).data; | ||
walk(node, path); | ||
register.forEach(function (m) { | ||
return m.checkRecursivity(); | ||
}); | ||
} | ||
@@ -503,2 +493,20 @@ } | ||
/** | ||
* Method returning a monkey at the given path or else `null`. | ||
* | ||
* @param {path} path - Path of the monkey to retrieve. | ||
* @return {Monkey|null} - The Monkey instance of `null`. | ||
*/ | ||
}, { | ||
key: 'getMonkey', | ||
value: function getMonkey(path) { | ||
path = coercePath(path); | ||
var monkey = getIn(this._monkeys, [].concat(path)).data; | ||
if (monkey instanceof _monkey.Monkey) return monkey; | ||
return null; | ||
} | ||
/** | ||
* Method used to watch a collection of paths within the tree. Very useful | ||
@@ -594,3 +602,3 @@ * to bind UI components and such to the tree. | ||
*/ | ||
Baobab.VERSION = '2.3.0'; | ||
Baobab.VERSION = '2.3.1'; | ||
module.exports = exports['default']; |
@@ -372,6 +372,6 @@ /* eslint eqeqeq: 0 */ | ||
*/ | ||
var notFoundObject = { data: undefined, solvedPath: null, exists: false }; | ||
var NOT_FOUND_OBJECT = { data: undefined, solvedPath: null, exists: false }; | ||
function getIn(object, path) { | ||
if (!path) return notFoundObject; | ||
if (!path) return NOT_FOUND_OBJECT; | ||
@@ -387,9 +387,13 @@ var solvedPath = []; | ||
for (i = 0, l = path.length; i < l; i++) { | ||
if (!c) return { data: undefined, solvedPath: path, exists: false }; | ||
if (!c) return { | ||
data: undefined, | ||
solvedPath: solvedPath.concat(path.slice(i)), | ||
exists: false | ||
}; | ||
if (typeof path[i] === 'function') { | ||
if (!_type2['default'].array(c)) return notFoundObject; | ||
if (!_type2['default'].array(c)) return NOT_FOUND_OBJECT; | ||
idx = index(c, path[i]); | ||
if (! ~idx) return notFoundObject; | ||
if (! ~idx) return NOT_FOUND_OBJECT; | ||
@@ -399,3 +403,3 @@ solvedPath.push(idx); | ||
} else if (typeof path[i] === 'object') { | ||
if (!_type2['default'].array(c)) return notFoundObject; | ||
if (!_type2['default'].array(c)) return NOT_FOUND_OBJECT; | ||
@@ -405,3 +409,3 @@ idx = index(c, function (e) { | ||
}); | ||
if (! ~idx) return notFoundObject; | ||
if (! ~idx) return NOT_FOUND_OBJECT; | ||
@@ -408,0 +412,0 @@ solvedPath.push(idx); |
@@ -95,3 +95,2 @@ /** | ||
this.definition = definition; | ||
this.isRecursive = false; | ||
@@ -125,5 +124,5 @@ // Adapting the definition's paths & projection to this monkey's case | ||
* are of any use to the monkey and, if so, will update the tree's node | ||
* where the monkey sits with a lazy getter. | ||
* where the monkey sits. | ||
*/ | ||
this.listener = function (_ref) { | ||
this.writeListener = function (_ref) { | ||
var path = _ref.data.path; | ||
@@ -139,5 +138,29 @@ | ||
// Binding listener | ||
this.tree.on('write', this.listener); | ||
/** | ||
* Listener on the tree's `monkey` event. | ||
* | ||
* When another monkey updates, this listener will check whether the | ||
* updated paths are of any use to the monkey and, if so, will update the | ||
* tree's node where the monkey sits. | ||
*/ | ||
this.recursiveListener = function (_ref2) { | ||
var _ref2$data = _ref2.data; | ||
var monkey = _ref2$data.monkey; | ||
var path = _ref2$data.path; | ||
if (_this2.state.killed) return; | ||
// Breaking if this is the same monkey | ||
if (_this2 === monkey) return; | ||
// Is the monkey affected by the current monkey event? | ||
var concerned = (0, _helpers.solveUpdate)([path], _this2.relatedPaths(false)); | ||
if (concerned) _this2.update(); | ||
}; | ||
// Binding listeners | ||
this.tree.on('write', this.writeListener); | ||
this.tree.on('_monkey', this.recursiveListener); | ||
// Updating relevant node | ||
@@ -148,46 +171,29 @@ this.update(); | ||
/** | ||
* Method triggering a recursivity check. | ||
* Method returning solved paths related to the monkey. | ||
* | ||
* @return {Monkey} - Returns itself for chaining purposes. | ||
* @param {boolean} recursive - Should we compute recursive paths? | ||
* @return {array} - An array of related paths. | ||
*/ | ||
_createClass(Monkey, [{ | ||
key: 'checkRecursivity', | ||
value: function checkRecursivity() { | ||
key: 'relatedPaths', | ||
value: function relatedPaths() { | ||
var _this3 = this; | ||
this.isRecursive = this.depPaths.some(function (p) { | ||
return !!_type2['default'].monkeyPath(_this3.tree._monkeys, p); | ||
}); | ||
var recursive = arguments.length <= 0 || arguments[0] === undefined ? true : arguments[0]; | ||
// Putting the recursive monkeys' listeners at the end of the stack | ||
// NOTE: this is a dirty hack and a more thorough solution should be found | ||
if (this.isRecursive) { | ||
this.tree.off('write', this.listener); | ||
this.tree.on('write', this.listener); | ||
} | ||
return this; | ||
} | ||
/** | ||
* Method returning solved paths related to the monkey. | ||
* | ||
* @return {array} - An array of related paths. | ||
*/ | ||
}, { | ||
key: 'relatedPaths', | ||
value: function relatedPaths() { | ||
var _this4 = this; | ||
var paths = undefined; | ||
if (this.definition.hasDynamicPaths) paths = this.depPaths.map(function (p) { | ||
return (0, _helpers.getIn)(_this4.tree._data, p).solvedPath; | ||
return (0, _helpers.getIn)(_this3.tree._data, p).solvedPath; | ||
});else paths = this.depPaths; | ||
if (!this.isRecursive) return paths; | ||
var isRecursive = recursive && this.depPaths.some(function (p) { | ||
return !!_type2['default'].monkeyPath(_this3.tree._monkeys, p); | ||
}); | ||
if (!isRecursive) return paths; | ||
return paths.reduce(function (accumulatedPaths, path) { | ||
var monkeyPath = _type2['default'].monkeyPath(_this4.tree._monkeys, path); | ||
var monkeyPath = _type2['default'].monkeyPath(_this3.tree._monkeys, path); | ||
@@ -197,3 +203,3 @@ if (!monkeyPath) return accumulatedPaths.concat([path]); | ||
// Solving recursive path | ||
var relatedMonkey = (0, _helpers.getIn)(_this4.tree._monkeys, monkeyPath).data; | ||
var relatedMonkey = (0, _helpers.getIn)(_this3.tree._monkeys, monkeyPath).data; | ||
@@ -253,2 +259,5 @@ return accumulatedPaths.concat(relatedMonkey.relatedPaths()); | ||
// Notifying the monkey's update so we can handle recursivity | ||
this.tree.emit('_monkey', { monkey: this, path: this.path }); | ||
return this; | ||
@@ -265,3 +274,4 @@ } | ||
// Unbinding events | ||
this.tree.off('write', this.listener); | ||
this.tree.off('write', this.writeListener); | ||
this.tree.off('_monkey', this.monkeyListener); | ||
this.state.killed = true; | ||
@@ -268,0 +278,0 @@ |
{ | ||
"name": "baobab", | ||
"version": "2.3.0", | ||
"version": "2.3.1", | ||
"description": "JavaScript persistent data tree with cursors.", | ||
@@ -10,6 +10,6 @@ "main": "./dist/baobab.js", | ||
"devDependencies": { | ||
"@yomguithereal/eslint-config": "^1.1.0", | ||
"add-banner": "^0.1.0", | ||
"async": "^1.2.1", | ||
"babel": "^5.6.14", | ||
"babel-eslint": "^4.0.5", | ||
"babelify": "^6.1.2", | ||
@@ -19,3 +19,2 @@ "benchmark": "^1.0.0", | ||
"eslint": "^1.1.0", | ||
"eslint-config-airbnb": "^1.0.0", | ||
"lodash": "^3.6.0", | ||
@@ -31,3 +30,3 @@ "mkdirp": "^0.5.1", | ||
"dist": "babel ./src --out-dir dist", | ||
"lint": "eslint ./src ./test", | ||
"lint": "eslint -c eslint.config.js ./src ./test", | ||
"prepublish": "npm run dist", | ||
@@ -34,0 +33,0 @@ "test": "mocha -R spec --compilers js:babel/register ./test/endpoint.js" |
@@ -196,4 +196,2 @@ /** | ||
const register = []; | ||
const walk = (data, p = []) => { | ||
@@ -210,4 +208,2 @@ | ||
register.push(monkeyInstance); | ||
update(this._monkeys, p, {type: 'set', value: monkeyInstance}, { | ||
@@ -232,3 +228,2 @@ immutable: false, | ||
walk(this._data); | ||
register.forEach(m => m.checkRecursivity()); | ||
} | ||
@@ -245,3 +240,2 @@ else { | ||
walk(node, path); | ||
register.forEach(m => m.checkRecursivity()); | ||
} | ||
@@ -352,3 +346,3 @@ } | ||
`Baobab.update: unknown operation type "${operation.type}".`, | ||
{operation: operation} | ||
{operation} | ||
); | ||
@@ -495,2 +489,19 @@ | ||
/** | ||
* Method returning a monkey at the given path or else `null`. | ||
* | ||
* @param {path} path - Path of the monkey to retrieve. | ||
* @return {Monkey|null} - The Monkey instance of `null`. | ||
*/ | ||
getMonkey(path) { | ||
path = coercePath(path); | ||
const monkey = getIn(this._monkeys, [].concat(path)).data; | ||
if (monkey instanceof Monkey) | ||
return monkey; | ||
return null; | ||
} | ||
/** | ||
* Method used to watch a collection of paths within the tree. Very useful | ||
@@ -577,2 +588,2 @@ * to bind UI components and such to the tree. | ||
*/ | ||
Baobab.VERSION = '2.3.0'; | ||
Baobab.VERSION = '2.3.1'; |
@@ -741,3 +741,3 @@ /** | ||
return { | ||
next: function() { | ||
next() { | ||
if (i < length) { | ||
@@ -744,0 +744,0 @@ return { |
@@ -354,7 +354,7 @@ /* eslint eqeqeq: 0 */ | ||
*/ | ||
const notFoundObject = {data: undefined, solvedPath: null, exists: false}; | ||
const NOT_FOUND_OBJECT = {data: undefined, solvedPath: null, exists: false}; | ||
export function getIn(object, path) { | ||
if (!path) | ||
return notFoundObject; | ||
return NOT_FOUND_OBJECT; | ||
@@ -371,11 +371,15 @@ const solvedPath = []; | ||
if (!c) | ||
return {data: undefined, solvedPath: path, exists: false}; | ||
return { | ||
data: undefined, | ||
solvedPath: solvedPath.concat(path.slice(i)), | ||
exists: false | ||
}; | ||
if (typeof path[i] === 'function') { | ||
if (!type.array(c)) | ||
return notFoundObject; | ||
return NOT_FOUND_OBJECT; | ||
idx = index(c, path[i]); | ||
if (!~idx) | ||
return notFoundObject; | ||
return NOT_FOUND_OBJECT; | ||
@@ -387,7 +391,7 @@ solvedPath.push(idx); | ||
if (!type.array(c)) | ||
return notFoundObject; | ||
return NOT_FOUND_OBJECT; | ||
idx = index(c, e => compare(e, path[i])); | ||
if (!~idx) | ||
return notFoundObject; | ||
return NOT_FOUND_OBJECT; | ||
@@ -394,0 +398,0 @@ solvedPath.push(idx); |
@@ -77,3 +77,2 @@ /** | ||
this.definition = definition; | ||
this.isRecursive = false; | ||
@@ -107,5 +106,5 @@ // Adapting the definition's paths & projection to this monkey's case | ||
* are of any use to the monkey and, if so, will update the tree's node | ||
* where the monkey sits with a lazy getter. | ||
* where the monkey sits. | ||
*/ | ||
this.listener = ({data: {path}}) => { | ||
this.writeListener = ({data: {path}}) => { | ||
if (this.state.killed) | ||
@@ -121,27 +120,30 @@ return; | ||
// Binding listener | ||
this.tree.on('write', this.listener); | ||
/** | ||
* Listener on the tree's `monkey` event. | ||
* | ||
* When another monkey updates, this listener will check whether the | ||
* updated paths are of any use to the monkey and, if so, will update the | ||
* tree's node where the monkey sits. | ||
*/ | ||
this.recursiveListener = ({data: {monkey, path}}) => { | ||
if (this.state.killed) | ||
return; | ||
// Updating relevant node | ||
this.update(); | ||
} | ||
// Breaking if this is the same monkey | ||
if (this === monkey) | ||
return; | ||
/** | ||
* Method triggering a recursivity check. | ||
* | ||
* @return {Monkey} - Returns itself for chaining purposes. | ||
*/ | ||
checkRecursivity() { | ||
this.isRecursive = this.depPaths.some( | ||
p => !!type.monkeyPath(this.tree._monkeys, p) | ||
); | ||
// Is the monkey affected by the current monkey event? | ||
const concerned = solveUpdate([path], this.relatedPaths(false)); | ||
// Putting the recursive monkeys' listeners at the end of the stack | ||
// NOTE: this is a dirty hack and a more thorough solution should be found | ||
if (this.isRecursive) { | ||
this.tree.off('write', this.listener); | ||
this.tree.on('write', this.listener); | ||
} | ||
if (concerned) | ||
this.update(); | ||
}; | ||
return this; | ||
// Binding listeners | ||
this.tree.on('write', this.writeListener); | ||
this.tree.on('_monkey', this.recursiveListener); | ||
// Updating relevant node | ||
this.update(); | ||
} | ||
@@ -152,5 +154,6 @@ | ||
* | ||
* @return {array} - An array of related paths. | ||
* @param {boolean} recursive - Should we compute recursive paths? | ||
* @return {array} - An array of related paths. | ||
*/ | ||
relatedPaths() { | ||
relatedPaths(recursive = true) { | ||
let paths; | ||
@@ -165,3 +168,7 @@ | ||
if (!this.isRecursive) | ||
const isRecursive = recursive && this.depPaths.some( | ||
p => !! type.monkeyPath(this.tree._monkeys, p) | ||
); | ||
if (!isRecursive) | ||
return paths; | ||
@@ -247,2 +254,5 @@ | ||
// Notifying the monkey's update so we can handle recursivity | ||
this.tree.emit('_monkey', {monkey: this, path: this.path}); | ||
return this; | ||
@@ -257,3 +267,4 @@ } | ||
// Unbinding events | ||
this.tree.off('write', this.listener); | ||
this.tree.off('write', this.writeListener); | ||
this.tree.off('_monkey', this.monkeyListener); | ||
this.state.killed = true; | ||
@@ -260,0 +271,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
201917
12
22
4956