From 1222a9a3ab1374d327d9a3d067af5d519547dd82 Mon Sep 17 00:00:00 2001 From: Leo Horie Date: Mon, 26 Dec 2016 12:19:20 -0500 Subject: [PATCH] change onbeforeremove and make state inherit from prototype --- render/render.js | 22 ++++---- render/tests/index.html | 1 + render/tests/test-component.js | 12 ++--- render/tests/test-onbeforeremove.js | 82 ++++++++--------------------- 4 files changed, 41 insertions(+), 76 deletions(-) diff --git a/render/render.js b/render/render.js index 731ebdf3..c71177e9 100644 --- a/render/render.js +++ b/render/render.js @@ -97,7 +97,9 @@ module.exports = function($window) { function createComponent(vnode, hooks, ns) { // For object literals since `Vnode()` always sets the `state` field. if (!vnode.state) vnode.state = {} - assign(vnode.state, vnode.tag) + var constructor = function() {} + constructor.prototype = vnode.tag + vnode.state = new constructor var view = vnode.tag.view if (view.reentrantLock != null) return $emptyFragment @@ -380,12 +382,18 @@ module.exports = function($window) { function removeNode(vnode, context) { var expected = 1, called = 0 if (vnode.attrs && vnode.attrs.onbeforeremove) { - expected++ - vnode.attrs.onbeforeremove.call(vnode.state, vnode, once(continuation)) + var result = vnode.attrs.onbeforeremove.call(vnode.state, vnode) + if (result != null && typeof result.then === "function") { + expected++ + result.then(continuation, continuation) + } } if (typeof vnode.tag !== "string" && vnode.tag.onbeforeremove) { - expected++ - vnode.tag.onbeforeremove.call(vnode.state, vnode, once(continuation)) + var result = vnode.tag.onbeforeremove.call(vnode.state, vnode) + if (result != null && typeof result.then === "function") { + expected++ + result.then(continuation, continuation) + } } continuation() function continuation() { @@ -559,10 +567,6 @@ module.exports = function($window) { return false } - function assign(target, source) { - Object.keys(source).forEach(function(k){target[k] = source[k]}) - } - function render(dom, vnodes) { if (!dom) throw new Error("Ensure the DOM element being passed to m.route/m.mount/m.render is not undefined.") var hooks = [] diff --git a/render/tests/index.html b/render/tests/index.html index 3cc2da65..480b8b7c 100644 --- a/render/tests/index.html +++ b/render/tests/index.html @@ -14,6 +14,7 @@ + diff --git a/render/tests/test-component.js b/render/tests/test-component.js index d6d26e43..f4aad629 100644 --- a/render/tests/test-component.js +++ b/render/tests/test-component.js @@ -588,14 +588,12 @@ o.spec("component", function() { o("calls onbeforeremove", function() { var called = 0 var component = { - onbeforeremove: function(vnode, done) { + onbeforeremove: function(vnode) { called++ o(vnode.dom).notEquals(undefined) o(vnode.dom).equals(root.firstChild) o(root.childNodes.length).equals(1) - - done() }, view: function() { return {tag: "div", attrs: {id: "a"}, text: "b"} @@ -614,14 +612,12 @@ o.spec("component", function() { o("calls onbeforeremove when returning fragment", function() { var called = 0 var component = { - onbeforeremove: function(vnode, done) { + onbeforeremove: function(vnode) { called++ o(vnode.dom).notEquals(undefined) o(vnode.dom).equals(root.firstChild) o(root.childNodes.length).equals(1) - - done() }, view: function() { return [{tag: "div", attrs: {id: "a"}, text: "b"}] @@ -672,6 +668,10 @@ o.spec("component", function() { function init(vnode) { o(vnode.state.data).deepEquals(data) o(vnode.state.data).equals(data) + + //inherits state via prototype + component.x = 1 + o(vnode.state.x).equals(1) } }) o("state copy is shallow", function() { diff --git a/render/tests/test-onbeforeremove.js b/render/tests/test-onbeforeremove.js index 84e9077c..82a859d0 100644 --- a/render/tests/test-onbeforeremove.js +++ b/render/tests/test-onbeforeremove.js @@ -4,6 +4,7 @@ var o = require("../../ospec/ospec") var callAsync = require("../../test-utils/callAsync") var domMock = require("../../test-utils/domMock") var vdom = require("../../render/render") +var Promise = require("../../promise/promise") o.spec("onbeforeremove", function() { var $window, root, render @@ -43,17 +44,13 @@ o.spec("onbeforeremove", function() { render(root, [vnode]) render(root, []) - function remove(node, complete) { + function remove(node) { o(node).equals(vnode) o(this).equals(vnode.state) o(root.childNodes.length).equals(1) o(root.firstChild).equals(vnode.dom) callAsync(function() { - o(root.childNodes.length).equals(1) - - complete() - o(root.childNodes.length).equals(0) done() @@ -66,16 +63,12 @@ o.spec("onbeforeremove", function() { render(root, [vnode]) render(root, []) - function remove(node, complete) { + function remove(node) { o(node).equals(vnode) o(root.childNodes.length).equals(1) o(root.firstChild).equals(vnode.dom) callAsync(function() { - o(root.childNodes.length).equals(1) - - complete() - o(root.childNodes.length).equals(0) done() @@ -88,16 +81,12 @@ o.spec("onbeforeremove", function() { render(root, [vnode]) render(root, []) - function remove(node, complete) { + function remove(node) { o(node).equals(vnode) o(root.childNodes.length).equals(1) o(root.firstChild).equals(vnode.dom) callAsync(function() { - o(root.childNodes.length).equals(1) - - complete() - o(root.childNodes.length).equals(0) done() @@ -110,16 +99,12 @@ o.spec("onbeforeremove", function() { render(root, [vnode]) render(root, []) - function remove(node, complete) { + function remove(node) { o(node).equals(vnode) o(root.childNodes.length).equals(1) o(root.firstChild).equals(vnode.dom) callAsync(function() { - o(root.childNodes.length).equals(1) - - complete() - o(root.childNodes.length).equals(0) done() @@ -133,17 +118,12 @@ o.spec("onbeforeremove", function() { render(root, [vnode]) render(root, []) - function remove(node, complete) { + function remove(node) { o(node).equals(vnode) o(root.childNodes.length).equals(1) o(root.firstChild).equals(vnode.dom) callAsync(function() { - o(root.childNodes.length).equals(1) - o(spy.callCount).equals(0) - - complete() - o(root.childNodes.length).equals(0) o(spy.callCount).equals(1) @@ -161,7 +141,7 @@ o.spec("onbeforeremove", function() { o(vnode.dom.attributes["onbeforeremove"]).equals(undefined) }) o("does not recycle when there's an onbeforeremove", function() { - var remove = function(vnode, done) {done()} + var remove = function(vnode) {} var vnode = {tag: "div", key: 1, attrs: {onbeforeremove: remove}} var updated = {tag: "div", key: 1, attrs: {onbeforeremove: remove}} @@ -171,9 +151,8 @@ o.spec("onbeforeremove", function() { o(vnode.dom).notEquals(updated.dom) }) - o("does not leave elements out of order during removal", function() { - var finish - var remove = function(vnode, done) {finish = done} + o("does not leave elements out of order during removal", function(done) { + var remove = function(vnode) {return Promise.resolve()} var vnodes = [{tag: "div", key: 1, attrs: {onbeforeremove: remove}, text: "1"}, {tag: "div", key: 2, attrs: {onbeforeremove: remove}, text: "2"}] var updated = {tag: "div", key: 2, attrs: {onbeforeremove: remove}, text: "2"} @@ -183,14 +162,16 @@ o.spec("onbeforeremove", function() { o(root.childNodes.length).equals(2) o(root.firstChild.firstChild.nodeValue).equals("1") - finish() - - o(root.childNodes.length).equals(1) - o(root.firstChild.firstChild.nodeValue).equals("2") + callAsync(function() { + o(root.childNodes.length).equals(1) + o(root.firstChild.firstChild.nodeValue).equals("2") + + done() + }) }) - o("finalizes the remove phase only once when `done()` is called synchronously from both attrs- and tag.onbeforeremove", function() { + o("finalizes the remove phase asynchronously when promise is returned synchronously from both attrs- and tag.onbeforeremove", function(done) { var onremove = o.spy() - var onbeforeremove = function(vnode, done){done()} + var onbeforeremove = function(){return Promise.resolve()} var component = { onbeforeremove: onbeforeremove, onremove: onremove, @@ -198,30 +179,9 @@ o.spec("onbeforeremove", function() { } render(root, [{tag: component, attrs: {onbeforeremove: onbeforeremove, onremove: onremove}}]) render(root, []) - o(onremove.callCount).equals(2) // once for `tag`, once for `attrs` - }) - o("doesn't finalize prematurely if `done` is called twice in the `tag` hook", function(done) { - var async = false - var component = { - view: function() {}, - onbeforeremove: function(vnode, doneRemoving){ - doneRemoving() - doneRemoving() - }, - onremove: function() { - o(async).equals(true) - done() - }, - } - render(root, [{ - tag:component, - attrs: { - onbeforeremove: function(vnode, doneRemoving){ - callAsync(doneRemoving) - } - } - }]) - render(root, []) - async = true + callAsync(function() { + o(onremove.callCount).equals(2) // once for `tag`, once for `attrs` + done() + }) }) })