Comparing version 0.0.1 to 0.0.2
308
diff.js
@@ -1,3 +0,309 @@ | ||
var diff = require("virtual-dom/vtree/diff") | ||
var isArray = require("x-is-array") | ||
var isObject = require("is-object") | ||
var VPatch = require("./vpatch") | ||
var isVNode = require("./is-vnode") | ||
var isVText = require("./is-vtext") | ||
var isWidget = require("./is-widget") | ||
var isThunk = require("./is-thunk") | ||
module.exports = diff | ||
function diff(a, b) { | ||
var patch = { a: a } | ||
walk(a, b, patch, 0) | ||
return patch | ||
} | ||
function walk(a, b, patch, index) { | ||
if (isThunk(b)) { | ||
if (isThunk(a)) { | ||
b = b.vnode = b.render(a) | ||
a = a.vnode | ||
} else { | ||
b = b.vnode = b.render(null) | ||
} | ||
} | ||
if (a === b) { | ||
hooks(b, patch, index) | ||
return | ||
} | ||
var apply = patch[index] | ||
if (b == null) { | ||
apply = appendPatch(apply, new VPatch(VPatch.REMOVE, a, b)) | ||
destroyWidgets(a, patch, index) | ||
} else if (isVNode(b)) { | ||
if (isVNode(a)) { | ||
if (a.tagName === b.tagName && | ||
a.namespace === b.namespace && | ||
a.key === b.key) { | ||
var propsPatch = diffProps(a.properties, b.properties, b.hooks) | ||
if (propsPatch) { | ||
apply = appendPatch(apply, | ||
new VPatch(VPatch.PROPS, a, propsPatch)) | ||
} | ||
} else { | ||
apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)) | ||
destroyWidgets(a, patch, index) | ||
} | ||
apply = diffChildren(a, b, patch, apply, index) | ||
} else { | ||
apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)) | ||
destroyWidgets(a, patch, index) | ||
} | ||
} else if (isVText(b)) { | ||
if (!isVText(a)) { | ||
apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)) | ||
destroyWidgets(a, patch, index) | ||
} else if (a.text !== b.text) { | ||
apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)) | ||
} | ||
} else if (isWidget(b)) { | ||
apply = appendPatch(apply, new VPatch(VPatch.WIDGET, a, b)) | ||
if (!isWidget(a)) { | ||
destroyWidgets(a, patch, index) | ||
} | ||
} | ||
if (apply) { | ||
patch[index] = apply | ||
} | ||
} | ||
function diffProps(a, b, hooks) { | ||
var diff | ||
for (var aKey in a) { | ||
if (!(aKey in b)) { | ||
diff = diff || {} | ||
diff[aKey] = undefined | ||
} | ||
var aValue = a[aKey] | ||
var bValue = b[aKey] | ||
if (hooks && aKey in hooks) { | ||
diff = diff || {} | ||
diff[aKey] = bValue | ||
} else { | ||
if (isObject(aValue) && isObject(bValue)) { | ||
if (getPrototype(bValue) !== getPrototype(aValue)) { | ||
diff = diff || {} | ||
diff[aKey] = bValue | ||
} else { | ||
var objectDiff = diffProps(aValue, bValue) | ||
if (objectDiff) { | ||
diff = diff || {} | ||
diff[aKey] = objectDiff | ||
} | ||
} | ||
} else if (aValue !== bValue && bValue !== undefined) { | ||
diff = diff || {} | ||
diff[aKey] = bValue | ||
} | ||
} | ||
} | ||
for (var bKey in b) { | ||
if (!(bKey in a)) { | ||
diff = diff || {} | ||
diff[bKey] = b[bKey] | ||
} | ||
} | ||
return diff | ||
} | ||
function getPrototype(value) { | ||
if (Object.getPrototypeOf) { | ||
return Object.getPrototypeOf(value) | ||
} else if (value.__proto__) { | ||
return value.__proto__ | ||
} else if (value.constructor) { | ||
return value.constructor.prototype | ||
} | ||
} | ||
function diffChildren(a, b, patch, apply, index) { | ||
var aChildren = a.children | ||
var bChildren = reorder(aChildren, b.children) | ||
var aLen = aChildren.length | ||
var bLen = bChildren.length | ||
var len = aLen > bLen ? aLen : bLen | ||
for (var i = 0; i < len; i++) { | ||
var leftNode = aChildren[i] | ||
var rightNode = bChildren[i] | ||
index += 1 | ||
if (!leftNode) { | ||
if (rightNode) { | ||
// Excess nodes in b need to be added | ||
apply = appendPatch(apply, new VPatch(VPatch.INSERT, null, rightNode)) | ||
} | ||
} else if (!rightNode) { | ||
if (leftNode) { | ||
// Excess nodes in a need to be removed | ||
patch[index] = new VPatch(VPatch.REMOVE, leftNode, null) | ||
destroyWidgets(leftNode, patch, index) | ||
} | ||
} else { | ||
walk(leftNode, rightNode, patch, index) | ||
} | ||
if (isVNode(leftNode) && leftNode.count) { | ||
index += leftNode.count | ||
} | ||
} | ||
if (bChildren.moves) { | ||
// Reorder nodes last | ||
apply = appendPatch(apply, new VPatch(VPatch.ORDER, a, bChildren.moves)) | ||
} | ||
return apply | ||
} | ||
// Patch records for all destroyed widgets must be added because we need | ||
// a DOM node reference for the destroy function | ||
function destroyWidgets(vNode, patch, index) { | ||
if (isWidget(vNode)) { | ||
if (typeof vNode.destroy === "function") { | ||
patch[index] = new VPatch(VPatch.REMOVE, vNode, null) | ||
} | ||
} else if (isVNode(vNode) && vNode.hasWidgets) { | ||
var children = vNode.children | ||
var len = children.length | ||
for (var i = 0; i < len; i++) { | ||
var child = children[i] | ||
index += 1 | ||
destroyWidgets(child, patch, index) | ||
if (isVNode(child) && child.count) { | ||
index += child.count | ||
} | ||
} | ||
} | ||
} | ||
// Execute hooks when two nodes are identical | ||
function hooks(vNode, patch, index) { | ||
if (isVNode(vNode)) { | ||
if (vNode.hooks) { | ||
patch[index] = new VPatch(VPatch.PROPS, vNode.hooks, vNode.hooks) | ||
} | ||
if (vNode.descendantHooks) { | ||
var children = vNode.children | ||
var len = children.length | ||
for (var i = 0; i < len; i++) { | ||
var child = children[i] | ||
index += 1 | ||
hooks(child, patch, index) | ||
if (isVNode(child) && child.count) { | ||
index += child.count | ||
} | ||
} | ||
} | ||
} | ||
} | ||
// List diff, naive left to right reordering | ||
function reorder(aChildren, bChildren) { | ||
var bKeys = keyIndex(bChildren) | ||
if (!bKeys) { | ||
return bChildren | ||
} | ||
var aKeys = keyIndex(aChildren) | ||
if (!aKeys) { | ||
return bChildren | ||
} | ||
var bMatch = {}, aMatch = {} | ||
for (var key in bKeys) { | ||
bMatch[bKeys[key]] = aKeys[key] | ||
} | ||
for (var key in aKeys) { | ||
aMatch[aKeys[key]] = bKeys[key] | ||
} | ||
var aLen = aChildren.length | ||
var bLen = bChildren.length | ||
var len = aLen > bLen ? aLen : bLen | ||
var shuffle = [] | ||
var freeIndex = 0 | ||
var i = 0 | ||
var moveIndex = 0 | ||
var moves = shuffle.moves = {} | ||
while (freeIndex < len) { | ||
var move = aMatch[i] | ||
if (move !== undefined) { | ||
shuffle[i] = bChildren[move] | ||
moves[move] = moveIndex++ | ||
} else if (i in aMatch) { | ||
shuffle[i] = undefined | ||
moves[move] = moveIndex++ | ||
} else { | ||
while (bMatch[freeIndex] !== undefined) { | ||
freeIndex++ | ||
} | ||
if (freeIndex < len) { | ||
var freeChild = bChildren[freeIndex] | ||
if (freeChild) { | ||
moves[freeIndex] = moveIndex++ | ||
shuffle[i] = freeChild | ||
} | ||
freeIndex++ | ||
} | ||
} | ||
i++ | ||
} | ||
return shuffle | ||
} | ||
function keyIndex(children) { | ||
var i, keys | ||
for (i = 0; i < children.length; i++) { | ||
var child = children[i] | ||
if (child.key !== undefined) { | ||
keys = keys || {} | ||
keys[child.key] = i | ||
} | ||
} | ||
return keys | ||
} | ||
function appendPatch(apply, patch) { | ||
if (apply) { | ||
if (isArray(apply)) { | ||
apply.push(patch) | ||
} else { | ||
apply = [apply, patch] | ||
} | ||
return apply | ||
} else { | ||
return patch | ||
} | ||
} |
@@ -1,3 +0,6 @@ | ||
var isVHook = require("virtual-dom/vtree/is-vhook") | ||
module.exports = isHook | ||
module.exports = isVHook | ||
function isHook(hook) { | ||
return hook && typeof hook.hook === "function" && | ||
!hook.hasOwnProperty("hook") | ||
} |
@@ -1,3 +0,7 @@ | ||
var isVNode = require("virtual-dom/vtree/is-vnode") | ||
var version = require("./version") | ||
module.exports = isVNode | ||
module.exports = isVirtualNode | ||
function isVirtualNode(x) { | ||
return x && x.type === "VirtualNode" && x.version === version | ||
} |
@@ -1,3 +0,7 @@ | ||
var isVText = require("virtual-dom/vtree/is-vtext") | ||
var version = require("./version") | ||
module.exports = isVText | ||
module.exports = isVirtualText | ||
function isVirtualText(x) { | ||
return x && x.type === "VirtualText" && x.version === version | ||
} |
@@ -1,3 +0,5 @@ | ||
var isWidget = require("virtual-dom/vtree/is-widget") | ||
module.exports = isWidget | ||
module.exports = isWidget | ||
function isWidget(w) { | ||
return w && w.type === "Widget" | ||
} |
{ | ||
"name": "vtree", | ||
"version": "0.0.1", | ||
"version": "0.0.2", | ||
"description": "a realtime tree diffing algorithm", | ||
@@ -19,7 +19,6 @@ "keywords": [], | ||
}, | ||
"dependencies": { | ||
"virtual-dom": "0.0.8" | ||
}, | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"tape": "^2.12.3" | ||
"tape": "^2.13.1", | ||
"virtual-dom": "0.0.10" | ||
}, | ||
@@ -26,0 +25,0 @@ "licenses": [ |
@@ -1,3 +0,1 @@ | ||
var version = require("virtual-dom/vtree/version") | ||
module.exports = version | ||
module.exports = "1" |
64
vnode.js
@@ -1,3 +0,63 @@ | ||
var vnode = require("virtual-dom/vtree/vnode.js") | ||
var version = require("./version") | ||
var isVNode = require("./is-vnode") | ||
var isWidget = require("./is-widget") | ||
var isVHook = require("./is-vhook") | ||
module.exports = vnode | ||
module.exports = VirtualNode | ||
var noProperties = {} | ||
var noChildren = [] | ||
function VirtualNode(tagName, properties, children, key, namespace) { | ||
this.tagName = tagName | ||
this.properties = properties || noProperties | ||
this.children = children || noChildren | ||
this.key = key != null ? String(key) : undefined | ||
this.namespace = (typeof namespace === "string") ? namespace : null | ||
var count = (children && children.length) || 0 | ||
var descendants = 0 | ||
var hasWidgets = false | ||
var descendantHooks = false | ||
var hooks | ||
for (var propName in properties) { | ||
if (properties.hasOwnProperty(propName)) { | ||
var property = properties[propName] | ||
if (isVHook(property)) { | ||
if (!hooks) { | ||
hooks = {} | ||
} | ||
hooks[propName] = property | ||
} | ||
} | ||
} | ||
for (var i = 0; i < count; i++) { | ||
var child = children[i] | ||
if (isVNode(child)) { | ||
descendants += child.count || 0 | ||
if (!hasWidgets && child.hasWidgets) { | ||
hasWidgets = true | ||
} | ||
if (!descendantHooks && (child.hooks || child.descendantHooks)) { | ||
descendantHooks = true | ||
} | ||
} else if (!hasWidgets && isWidget(child)) { | ||
if (typeof child.destroy === "function") { | ||
hasWidgets = true | ||
} | ||
} | ||
} | ||
this.count = count + descendants | ||
this.hasWidgets = hasWidgets | ||
this.hooks = hooks | ||
this.descendantHooks = descendantHooks | ||
} | ||
VirtualNode.prototype.version = version | ||
VirtualNode.prototype.type = "VirtualNode" |
@@ -1,3 +0,21 @@ | ||
var vpatch = require("virtual-dom/vtree/vpatch") | ||
var version = require("./version") | ||
module.exports = vpatch | ||
VirtualPatch.NONE = 0 | ||
VirtualPatch.VTEXT = 1 | ||
VirtualPatch.VNODE = 2 | ||
VirtualPatch.WIDGET = 3 | ||
VirtualPatch.PROPS = 4 | ||
VirtualPatch.ORDER = 5 | ||
VirtualPatch.INSERT = 6 | ||
VirtualPatch.REMOVE = 7 | ||
module.exports = VirtualPatch | ||
function VirtualPatch(type, vNode, patch) { | ||
this.type = Number(type) | ||
this.vNode = vNode | ||
this.patch = patch | ||
} | ||
VirtualPatch.prototype.version = version | ||
VirtualPatch.prototype.type = "VirtualPatch" |
11
vtext.js
@@ -1,3 +0,10 @@ | ||
var vtext = require("virtual-dom/vtree/vtext") | ||
var version = require("./version") | ||
module.exports = vtext | ||
module.exports = VirtualText | ||
function VirtualText(text) { | ||
this.text = String(text) | ||
} | ||
VirtualText.prototype.version = version | ||
VirtualText.prototype.type = "VirtualText" |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
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
14401
0
16
361
2
1
- Removedvirtual-dom@0.0.8
- Removedbrowser-split@0.0.1(transitive)
- Removeddom-walk@0.1.2(transitive)
- Removedglobal@3.0.2(transitive)
- Removedis-object@0.1.2(transitive)
- Removedmin-document@2.19.0(transitive)
- Removedprocess@0.5.2(transitive)
- Removedvirtual-dom@0.0.8(transitive)
- Removedx-is-array@0.1.0(transitive)
- Removedx-is-string@0.1.0(transitive)