Comparing version 0.3.10 to 0.3.11
120
lib/arch.js
@@ -22,2 +22,3 @@ var UTIL = require('util'), | ||
this.children = {}; | ||
this.lazyLinks = {} | ||
this.plans = {}; | ||
@@ -139,2 +140,4 @@ this.locked = 0; | ||
this.applyLazyLinks(node); | ||
return this; | ||
@@ -144,2 +147,23 @@ }, | ||
/** | ||
* Attempts to establish lazy links of the specified node as real | ||
* @param {Object|String} node Node to apply links for | ||
*/ | ||
applyLazyLinks: function(node) { | ||
var id = U.getNodeId(node); | ||
if (this.lazyLinks[id]) { | ||
var links = this.lazyLinks[id]; | ||
links.forEach(function(l) { | ||
if (this.hasNode(U.getNodeId(l.parent)) && this.hasNode(U.getNodeId(l.child)) && | ||
!this.hasParents(l.child, l.parent)) | ||
{ | ||
this.link(l.child, l.parent); | ||
l.ref++; | ||
} | ||
}, this); | ||
} | ||
}, | ||
/** | ||
* Add new node or replace existing node having same id with specified. | ||
@@ -195,2 +219,4 @@ * | ||
this.unlinkLazy(id); | ||
delete this.nodes[id]; | ||
@@ -279,9 +305,33 @@ | ||
* @param {String[]|String} children Children nodes IDs. | ||
* @param {Boolean} [lazy] pass true to add lazy links | ||
* @return {Arch} | ||
*/ | ||
addChildren: function(id, children) { | ||
return this.link(children, U.getNodeId(id)); | ||
addChildren: function(id, children, lazy) { | ||
var parent = U.getNodeId(id); | ||
children = U.toArray(children); | ||
return this.link(children, parent, lazy); | ||
}, | ||
/** | ||
* Returns true if lazy link between parent and child exists false otherwise | ||
* @param {String|Object} parent | ||
* @param {String|Object} child | ||
* @return {Boolean} | ||
* @private | ||
*/ | ||
_lazyLinkExist: function(parent, child) { | ||
var links = this.lazyLinks[U.getNodeId(parent)]; | ||
if (!links) return false; | ||
for(var i = 0; i < links.length; i++) { | ||
var link = links[i]; | ||
if (link.parent === parent && link.child === child) return true; | ||
} | ||
return false; | ||
}, | ||
/** | ||
* Link specified parents to node. | ||
@@ -291,6 +341,10 @@ * | ||
* @param {String[]|String} parents Parents nodes IDs. | ||
* @param {Boolean} [lazy] pass true to add links as lazy | ||
* @return {Arch} | ||
*/ | ||
addParents: function(id, parents) { | ||
return this.link(U.getNodeId(id), parents); | ||
addParents: function(id, parents, lazy) { | ||
var child = U.getNodeId(id); | ||
parents = U.toArray(parents); | ||
return this.link(child, parents, lazy); | ||
}, | ||
@@ -303,13 +357,14 @@ | ||
* @param {String[]|String} parents IDs of parent nodes. | ||
* @param {Boolean} [lazy] pass true to add links as lazy | ||
* @returns {Arch} Chainable API. | ||
*/ | ||
link: function(children, parents) { | ||
link: function(children, parents, lazy) { | ||
children = U.toArray(children); | ||
parents = U.toArray(parents); | ||
ASSERTS.hasIds(children, this); | ||
ASSERTS.hasIds(parents, this); | ||
!lazy && ASSERTS.hasIds(children, this); | ||
!lazy && ASSERTS.hasIds(parents, this); | ||
children.forEach(function(child) { | ||
this._link(child, parents); | ||
this._link(child, parents, lazy); | ||
}, this); | ||
@@ -325,4 +380,5 @@ | ||
* @param {Array} parents Parent nodes IDs. | ||
* @param {Boolean} [lazy] pass true to add links as lazy | ||
*/ | ||
_link: function(child, parents) { | ||
_link: function(child, parents, lazy) { | ||
child = U.getNodeId(child); | ||
@@ -336,2 +392,17 @@ | ||
if (lazy) { | ||
var link = { | ||
parent: parent, | ||
child: child, | ||
ref: 0 | ||
}; | ||
if (!this._lazyLinkExist(parent, child)) { | ||
(this.lazyLinks[child] = this.lazyLinks[child] || []).push(link); | ||
(this.lazyLinks[parent] = this.lazyLinks[parent] || []).push(link); | ||
} | ||
if (!this.hasNode(parent) || !this.hasNode(child)) return; | ||
} | ||
if (this.hasParents(child, parent)) return; | ||
@@ -361,2 +432,6 @@ | ||
ASSERTS.idTypeIsString(id2); | ||
this.unlinkLazy(id1, id2); | ||
this.unlinkLazy(id2, id1); | ||
ASSERTS.hasId(id1, this); | ||
@@ -377,2 +452,29 @@ ASSERTS.hasId(id2, this); | ||
/** | ||
* Removes lazy links. | ||
* @param {String} id1 First Node ID to unlink. | ||
* @param {String} [id2] Second Node ID to unlink. If not specified all links where id1 is involved will be removed. | ||
*/ | ||
unlinkLazy: function(id1, id2) { | ||
var links = this.lazyLinks[id1]; | ||
if (links) { | ||
for(var i = links.length - 1; i >= 0; i--) { | ||
var link = links[i]; | ||
if (id2) { | ||
if ((link.parent === id1 && link.child === id2) || | ||
(link.parent === id2 && link.child === id1)) { | ||
links.splice(i, 1); | ||
break; | ||
} | ||
} else { | ||
this.unlinkLazy(link.parent, link.child); | ||
this.unlinkLazy(link.child, link.parent); | ||
} | ||
} | ||
if (links.length === 0) delete this.lazyLinks[id1]; | ||
} | ||
}, | ||
/** | ||
* Remove tree from arch. | ||
@@ -379,0 +481,0 @@ * Use forced removal to remove nodes with links to other parents (not belonging to removed tree). |
@@ -246,3 +246,3 @@ var INHERIT = require('inherit'), | ||
_collectLeaves: function(id, leaves, wasHere) { | ||
if (!wasHere[id] && !this.isJobAlreadyDone(id)) { | ||
if (!wasHere[id] && !this.isJobAlreadyDone(id) && !this.hasLazyLinks(id)) { | ||
@@ -264,2 +264,20 @@ wasHere[id] = 1; | ||
/** | ||
* Returns true if specified node has lazy links with children which were not established as real yet false otherwise | ||
* @param id | ||
* @return {Boolean} | ||
*/ | ||
hasLazyLinks: function(id) { | ||
var links = this.arch.lazyLinks[id]; | ||
if (!links) return false; | ||
for(var i = 0; i < links.length; i++) { | ||
var link = links[i]; | ||
if (link.parent === id && !U.hasLink(id, this.arch, 'children', link.child)) return true; | ||
} | ||
return false; | ||
}, | ||
/** | ||
* Refactor jobs after adding new jobs: | ||
@@ -525,3 +543,4 @@ * 1. Add leaves. | ||
!this.isActiveJob(id) && | ||
this.jobs.indexOf(id) === -1) this.jobs.push(id); | ||
this.jobs.indexOf(id) === -1 && | ||
!this.hasLazyLinks(id)) this.jobs.push(id); | ||
@@ -528,0 +547,0 @@ return this; |
{ | ||
"name": "apw", | ||
"version": "0.3.10", | ||
"version": "0.3.11", | ||
"homepage": "http://github.com/bem/apw", | ||
@@ -5,0 +5,0 @@ "author": "Sergey Kryzhanovsky <skryzhanovsky@ya.ru> (http://github.com/afelix)", |
@@ -5,2 +5,4 @@ var APW = require('..'), | ||
extend = require('node.extend'), | ||
getSimpleArch = COMMON.getSimpleArch, | ||
@@ -278,2 +280,66 @@ getEmptyArch = COMMON.getEmptyArch, | ||
describe('Node lazy links', function() { | ||
var arch; | ||
beforeEach(function() { | ||
arch = getArch2(); | ||
}); | ||
it('link() E -> nonexistent creates lazy link', function() { | ||
var c = extend({}, arch.children), | ||
p = extend({}, arch.parents), | ||
link = { | ||
parent: 'E', | ||
child: 'X', | ||
ref: 0 | ||
}; | ||
arch.addParents('X', 'E', true); | ||
ASSERT.deepEqual(arch.children, c); | ||
ASSERT.deepEqual(arch.parents, p); | ||
ASSERT.deepEqual(arch.lazyLinks, | ||
{ | ||
E: [link], | ||
X: [link] | ||
} | ||
); | ||
}); | ||
it('lazy link becomes real when both linking nodes become available in arch', function() { | ||
arch.addParents('E', 'X', true); | ||
arch.addNode(createNode('X')); | ||
ASSERT(arch.hasChildren('X', 'E')); | ||
}); | ||
it('unlink() removes lazy link', function() { | ||
arch.addParents('E', 'X', true); | ||
arch.addNode(createNode('X')); | ||
arch.unlink('E', 'X'); | ||
ASSERT.deepEqual(arch.lazyLinks, {}); | ||
}); | ||
it('removeNode() removes lazy link when child is removed', function() { | ||
arch.addParents('E', 'X', true); | ||
arch.addNode(createNode('X')); | ||
arch.removeNode('E'); | ||
ASSERT.deepEqual(arch.lazyLinks, {}); | ||
}); | ||
it('removeNode() removes lazy link when parent is removed', function() { | ||
arch.addParents('E', 'X', true); | ||
arch.addNode(createNode('X')); | ||
arch.removeNode('X'); | ||
ASSERT.deepEqual(arch.lazyLinks, {}); | ||
}); | ||
}); | ||
describe('Node unlink', function() { | ||
@@ -280,0 +346,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
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
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
2534
97127
20
1