From 42346c2015b1af312a01c17e8b8b6859cca8c73f Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sat, 5 May 2018 15:14:01 -0400 Subject: [PATCH] support transitions in await blocks - fixes #956 --- src/compile/nodes/AwaitBlock.ts | 18 ++++++++++-- src/shared/await-block.js | 29 +++++++++++++------ .../transition-js-await-block/_config.js | 21 +++++++++----- 3 files changed, 49 insertions(+), 19 deletions(-) diff --git a/src/compile/nodes/AwaitBlock.ts b/src/compile/nodes/AwaitBlock.ts index 19d863ccda..43fedabdf3 100644 --- a/src/compile/nodes/AwaitBlock.ts +++ b/src/compile/nodes/AwaitBlock.ts @@ -42,6 +42,8 @@ export default class AwaitBlock extends Node { block.addDependencies(this.expression.dependencies); let isDynamic = false; + let hasIntros = false; + let hasOutros = false; ['pending', 'then', 'catch'].forEach(status => { const child = this[status]; @@ -58,11 +60,22 @@ export default class AwaitBlock extends Node { isDynamic = true; block.addDependencies(child.block.dependencies); } + + if (child.block.hasIntroMethod) hasIntros = true; + if (child.block.hasOutroMethod) hasOutros = true; }); this.pending.block.hasUpdateMethod = isDynamic; this.then.block.hasUpdateMethod = isDynamic; this.catch.block.hasUpdateMethod = isDynamic; + + this.pending.block.hasIntroMethod = hasIntros; + this.then.block.hasIntroMethod = hasIntros; + this.catch.block.hasIntroMethod = hasIntros; + + this.pending.block.hasOutroMethod = hasOutros; + this.then.block.hasOutroMethod = hasOutros; + this.catch.block.hasOutroMethod = hasOutros; } build( @@ -92,7 +105,8 @@ export default class AwaitBlock extends Node { this.then.block.name && `then: ${this.then.block.name}`, this.catch.block.name && `catch: ${this.catch.block.name}`, this.then.block.name && `value: '${this.value}'`, - this.catch.block.name && `error: '${this.error}'` + this.catch.block.name && `error: '${this.error}'`, + this.pending.block.hasOutroMethod && `blocks: Array(3)` ].filter(Boolean); block.builders.init.addBlock(deindent` @@ -123,7 +137,7 @@ export default class AwaitBlock extends Node { const anchorNode = parentNode ? 'null' : 'anchor'; block.builders.mount.addBlock(deindent` - ${info}.block.m(${initialMountNode}, ${info}.anchor = ${anchorNode}); + ${info}.block.${this.pending.block.hasIntroMethod ? 'i' : 'm'}(${initialMountNode}, ${info}.anchor = ${anchorNode}); ${info}.mount = () => ${updateMountNode}; `); diff --git a/src/shared/await-block.js b/src/shared/await-block.js index c216f1e92a..0fa5c4d403 100644 --- a/src/shared/await-block.js +++ b/src/shared/await-block.js @@ -3,7 +3,7 @@ import { assign, isPromise } from './utils.js'; export function handlePromise(promise, info) { var token = info.token = {}; - function update(type, key, value) { + function update(type, index, key, value) { if (info.token !== token) return; info.resolved = key && { [key]: value }; @@ -12,32 +12,43 @@ export function handlePromise(promise, info) { const block = type && (info.current = type)(info.component, child_ctx); if (info.block) { - info.block.u(); - info.block.d(); + if (info.blocks) { + info.blocks.forEach((block, i) => { + if (i !== index) block.o(() => { + block.u(); + block.d(); + }); + }); + } else { + info.block.u(); + info.block.d(); + } + block.c(); - block.m(info.mount(), info.anchor); + block[block.i ? 'i' : 'm'](info.mount(), info.anchor); - info.component.root.set({}); + info.component.root.set({}); // flush any handlers that were created } info.block = block; + if (info.blocks) info.blocks[index] = block; } if (isPromise(promise)) { promise.then(value => { - update(info.then, info.value, value); + update(info.then, 1, info.value, value); }, error => { - update(info.catch, info.error, error); + update(info.catch, 2, info.error, error); }); // if we previously had a then/catch block, destroy it if (info.current !== info.pending) { - update(info.pending); + update(info.pending, 0); return true; } } else { if (info.current !== info.then) { - update(info.then, info.value, promise); + update(info.then, 1, info.value, promise); return true; } diff --git a/test/runtime/samples/transition-js-await-block/_config.js b/test/runtime/samples/transition-js-await-block/_config.js index fd879a12b3..d9a8970917 100644 --- a/test/runtime/samples/transition-js-await-block/_config.js +++ b/test/runtime/samples/transition-js-await-block/_config.js @@ -7,6 +7,8 @@ let promise = new Promise((f, r) => { }); export default { + solo: 1, + data: { promise }, @@ -19,14 +21,17 @@ export default { assert.equal(p.foo, 0); raf.tick(50); - assert.equal(p.foo, 0); + assert.equal(p.foo, 0.5); fulfil(42); - raf.tick(80); - let ps = document.querySelectorAll('p'); - assert.equal(p[0].className, 'pending'); - assert.equal(p[1].className, 'then'); - assert.equal(p[0].foo, 20); - assert.equal(p[1].foo, 30); - }, + + return promise.then(() => { + raf.tick(80); + let ps = document.querySelectorAll('p'); + assert.equal(ps[0].className, 'pending'); + assert.equal(ps[1].className, 'then'); + assert.equal(ps[0].foo, 0.2); + assert.equal(ps[1].foo, 0.3); + }); + } };