diff --git a/index.js b/index.js index 767bcc5f..fd2a7155 100644 --- a/index.js +++ b/index.js @@ -143,20 +143,19 @@ Choo.prototype.start = function () { this.emitter.prependListener(self._events.RENDER, nanoraf(function () { var renderTiming = nanotiming('choo.render') - self.state.href = self._createLocation() - var newTree = self.router(self.state.href) - assert.ok(newTree, 'choo.render: no valid DOM node returned for location ' + self.state.href) - - assert.equal(self._tree.nodeName, newTree.nodeName, 'choo.render: The target node <' + - self._tree.nodeName.toLowerCase() + '> is not the same type as the new node <' + - newTree.nodeName.toLowerCase() + '>.') - - var morphTiming = nanotiming('choo.morph') - nanomorph(self._tree, newTree) - morphTiming() - renderTiming() + var res = self.router(self.state.href) + if (self._hasWindow && res instanceof window.HTMLElement) { + self.morph(res) + renderTiming() + } else if (res && typeof res.then === 'function') { + res.then(function (tree) { + assert.ok(self._hasWindow && res instanceof window.HTMLElement) + self.morph(tree) + renderTiming() + }) + } })) documentReady(function () { @@ -167,6 +166,18 @@ Choo.prototype.start = function () { return this._tree } +Choo.prototype.morph = function (newTree) { + assert.ok(newTree, 'choo.render: no valid DOM node returned for location ' + this.state.href) + + assert.equal(this._tree.nodeName, newTree.nodeName, 'choo.render: The target node <' + + this._tree.nodeName.toLowerCase() + '> is not the same type as the new node <' + + newTree.nodeName.toLowerCase() + '>.') + + var morphTiming = nanotiming('choo.morph') + nanomorph(this._tree, newTree) + morphTiming() +} + Choo.prototype.mount = function mount (selector) { assert.equal(typeof window, 'object', 'choo.mount: window was not found. .mount() must be called in a browser, use .toString() if running in Node') assert.ok(typeof selector === 'string' || typeof selector === 'object', 'choo.mount: selector should be type String or HTMLElement') @@ -204,7 +215,8 @@ Choo.prototype.toString = function (location, state) { this.state.href = location.replace(/\?.+$/, '') this.state.query = nanoquery(location) - var html = this.router(location) - assert.ok(html, 'choo.toString: no valid value returned for the route ' + location) - return html.toString() + var res = this.router(location) + assert.ok(res, 'choo.toString: no valid value returned for the route ' + location) + assert.ok(typeof res.then !== 'function', 'choo.toString: not possible to stringify async route' + location) + return res.toString() } diff --git a/test.js b/test.js index e3b85f33..27c9b930 100644 --- a/test.js +++ b/test.js @@ -17,3 +17,20 @@ tape('should render on the server', function (t) { t.equal(res.toString().trim(), exp, 'result was OK') t.end() }) + +tape('async route should throw on server', function (t) { + var app = choo() + app.route('/', async function (state, emit) { + var strong = 'Hello filthy planet' + return html` +

${raw(strong)}

+ ` + }) + try { + var res = app.toString('/') + t.notOk(res, 'this should not be executed') + } catch (e) { + t.ok(e, 'throws expected error') + } + t.end() +})