Skip to content

Commit

Permalink
Merge pull request #5 from Matt-Esch/correct-vdom-thunk
Browse files Browse the repository at this point in the history
correct thunk handling logic
  • Loading branch information
Matt-Esch committed Jul 19, 2014
2 parents 6343908 + 7cf61bc commit 4cd3d56
Show file tree
Hide file tree
Showing 5 changed files with 212 additions and 11 deletions.
12 changes: 4 additions & 8 deletions diff.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ var isVNode = require("./is-vnode")
var isVText = require("./is-vtext")
var isWidget = require("./is-widget")
var isThunk = require("./is-thunk")
var handleThunk = require("./handle-thunk")

module.exports = diff

Expand All @@ -16,14 +17,9 @@ function diff(a, b) {
}

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)
}
}
var nodes = handleThunk(a, b);
a = nodes.a
b = nodes.b

if (a === b) {
hooks(b, patch, index)
Expand Down
40 changes: 40 additions & 0 deletions handle-thunk.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
var isVNode = require('./is-vnode')
var isVText = require('./is-vtext')
var isWidget = require('./is-widget')
var isThunk = require('./is-thunk')

module.exports = handleThunk

function handleThunk(a, b) {
var renderedA = a
var renderedB = b

if (isThunk(b)) {
renderedB = renderThunk(b, a)
}

if (isThunk(a)) {
renderedA = renderThunk(a, null)
}

return {
a: renderedA,
b: renderedB
}
}

function renderThunk(thunk, previous) {
var renderedThunk = thunk.vnode

if (!renderedThunk) {
renderedThunk = thunk.vnode = thunk.render(previous)
}

if (!(isVNode(renderedThunk) ||
isVText(renderedThunk) ||
isWidget(renderedThunk))) {
throw new Error("thunk did not return a valid node");
}

return renderedThunk
}
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vtree",
"version": "0.0.5",
"version": "0.0.13",
"description": "a realtime tree diffing algorithm",
"keywords": [],
"author": "Matt Esch <[email protected]>",
Expand All @@ -21,7 +21,7 @@
"is-object": "^0.1.2"
},
"devDependencies": {
"tape": "^2.13.1",
"tape": "^2.13.3",
"virtual-dom": "0.0.10"
},
"licenses": [
Expand All @@ -31,7 +31,9 @@
}
],
"scripts": {
"test": "node ./test/index.js"
"test": "node ./test/index.js",
"cover": "istanbul cover --report none --print detail ./test/index.js",
"view-cover": "istanbul report html && open ./coverage/index.html"
},
"testling": {
"files": "test/index.js",
Expand Down
162 changes: 162 additions & 0 deletions test/handle-thunk.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
var test = require("tape")

var handleThunk = require("../handle-thunk")
var VNode = require("../vnode")
var VText = require("../vtext")

test("render a new thunk to vnode", function (assert) {
var aNode = {
render: function (previous) {
assert.error("Render should not be called for cached thunk")
},
type: "Thunk"
}

aNode.vnode = new VNode("div")

var renderedBNode = new VNode("div")

var bNode = {
render: function (previous) {
assert.equal(previous, aNode)
return renderedBNode
},
type: "Thunk"
}

var result = handleThunk(aNode, bNode)

assert.equal(result.a, aNode.vnode)
assert.equal(result.b, renderedBNode)
assert.equal(bNode.vnode, renderedBNode)
assert.end()
})

test("render a new thunk to vtext", function (assert) {
var aNode = {
render: function (previous) {
assert.error("Render should not be called for cached thunk")
},
type: "Thunk"
}

aNode.vnode = new VNode("div")

var renderedBNode = new VText("text")

var bNode = {
render: function (previous) {
assert.equal(previous, aNode)
return renderedBNode
},
type: "Thunk"
}

var result = handleThunk(aNode, bNode)

assert.equal(result.a, aNode.vnode)
assert.equal(result.b, renderedBNode)
assert.equal(bNode.vnode, renderedBNode)
assert.end()
})

test("render a new thunk to a widget", function (assert) {
var aNode = {
render: function (previous) {
assert.error("Render should not be called for cached thunk")
},
type: "Thunk"
}

aNode.vnode = new VNode("div")

var renderedBNode = { type: "Widget" }

var bNode = {
render: function (previous) {
assert.equal(previous, aNode)
return renderedBNode
},
type: "Thunk"
}

var result = handleThunk(aNode, bNode)

assert.equal(result.a, aNode.vnode)
assert.equal(result.b, renderedBNode)
assert.equal(bNode.vnode, renderedBNode)
assert.end()
})

test("render current thunk to a thunk throws exception", function (assert) {
var aNode = {
render: function (previous) {
assert.error("Render should not be called for cached thunk")
},
type: "Thunk"
}

aNode.vnode = new VNode("div")

var bNode = {
render: function (previous) {
assert.equal(previous, aNode)
return { type: "Thunk" }
},
type: "Thunk"
}

var result

try {
handleThunk(aNode, bNode)
} catch (e) {
result = e
}

assert.equal(result.message, "thunk did not return a valid node")
assert.end()
})

test("render previous thunk to a thunk throws exception", function (assert) {
var aNode = {
render: function (previous) {
assert.equal(previous, null)
return { type: "Thunk" }
},
type: "Thunk"
}

var renderedBNode = new VNode("div")

var bNode = {
render: function (previous) {
assert.equal(previous, aNode)
return renderedBNode
},
type: "Thunk"
}

var result

try {
handleThunk(aNode, bNode)
} catch (e) {
result = e
}

assert.equal(result.message, "thunk did not return a valid node")
assert.end()
})

test("normal nodes are returned", function (assert) {
var aNode = new VNode('div')
var bNode = new VNode('div')

var result = handleThunk(aNode, bNode)

assert.equal(result.a, aNode)
assert.equal(result.b, bNode)
assert.end()
})

1 change: 1 addition & 0 deletions test/index.js
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
require("virtual-dom/test")
require('./handle-thunk.js')

0 comments on commit 4cd3d56

Please sign in to comment.