diff --git a/src/compiler/compile/nodes/AwaitBlock.ts b/src/compiler/compile/nodes/AwaitBlock.ts index 55d9d5a7d2..67d073e536 100644 --- a/src/compiler/compile/nodes/AwaitBlock.ts +++ b/src/compiler/compile/nodes/AwaitBlock.ts @@ -56,7 +56,11 @@ function get_context_from_expression(node: Pattern, result: string[]): string[] return result; case 'ObjectPattern': for (const property of node.properties) { - get_context_from_expression(property.value, result); + if (property.type === 'Property') { + get_context_from_expression(property.value, result); + } else { + get_context_from_expression(property, result); + } } return result; case 'MemberExpression': diff --git a/src/compiler/compile/render_dom/wrappers/AwaitBlock.ts b/src/compiler/compile/render_dom/wrappers/AwaitBlock.ts index 3f293b0646..310bddb9e0 100644 --- a/src/compiler/compile/render_dom/wrappers/AwaitBlock.ts +++ b/src/compiler/compile/render_dom/wrappers/AwaitBlock.ts @@ -275,11 +275,16 @@ export default class AwaitBlockWrapper extends Wrapper { function replace_context(block: Block, pattern: Pattern) { if (pattern.type === 'ObjectPattern') { for (const property of pattern.properties) { - if (property.value.type === 'Identifier') { - // @ts-ignore - property.value = x`#ctx[${block.renderer.context_lookup.get(property.value.name).index}]`; + if (property.type === 'Property') { + if (property.value.type === 'Identifier') { + // @ts-ignore + property.value = x`#ctx[${block.renderer.context_lookup.get(property.value.name).index}]`; + } else { + replace_context(block, property.value); + } } else { - replace_context(block, property.value); + // @ts-ignore + replace_context(block, property); } } } else if (pattern.type === 'ArrayPattern') { diff --git a/src/compiler/parse/state/mustache.ts b/src/compiler/parse/state/mustache.ts index d46dec3797..28ef853f8e 100644 --- a/src/compiler/parse/state/mustache.ts +++ b/src/compiler/parse/state/mustache.ts @@ -305,7 +305,7 @@ export default function mustache(parser: Parser) { const await_block_shorthand = type === 'AwaitBlock' && parser.eat('then'); if (await_block_shorthand) { parser.require_whitespace(); - block.value = parser.read_identifier(); + block.value = parser.read_destructure_pattern(); parser.allow_whitespace(); } diff --git a/test/runtime/samples/await-then-destruct-array/_config.js b/test/runtime/samples/await-then-destruct-array/_config.js index 56ec7ebd24..a636eb12b8 100644 --- a/test/runtime/samples/await-then-destruct-array/_config.js +++ b/test/runtime/samples/await-then-destruct-array/_config.js @@ -1,6 +1,6 @@ export default { props: { - thePromise: new Promise(resolve => {}), + thePromise: new Promise(resolve => {}) }, html: ` @@ -8,22 +8,54 @@ export default { `, async test({ assert, component, target }) { - let promise = Promise.resolve([1, 2]); - component.thePromise = promise; - - await promise; - assert.htmlEqual(target.innerHTML, ` -
a: 1
-b: 2
- `); - - promise = Promise.resolve([4, 5]); - component.thePromise = promise; - - await promise; - assert.htmlEqual(target.innerHTML, ` -a: 4
-b: 5
- `); + await (component.thePromise = Promise.resolve([1, 2])); + + assert.htmlEqual( + target.innerHTML, + ` +a: 1
+b: 2
+ ` + ); + + await (component.thePromise = Promise.resolve([4, 5])); + + assert.htmlEqual( + target.innerHTML, + ` +a: 4
+b: 5
+ ` + ); + + try { + await (component.thePromise = Promise.reject(['a', [6, 7]])); + } catch { + // do nothing + } + + assert.htmlEqual( + target.innerHTML, + ` +c: a
+d: 6
+e: 7
+ ` + ); + + try { + await (component.thePromise = Promise.reject(['b', [8, 9]])); + } catch { + // do nothing + } + + assert.htmlEqual( + target.innerHTML, + ` +c: b
+d: 8
+e: 9
+ ` + ); } -}; \ No newline at end of file +}; diff --git a/test/runtime/samples/await-then-destruct-array/main.svelte b/test/runtime/samples/await-then-destruct-array/main.svelte index 71249207c1..cc0d217f79 100644 --- a/test/runtime/samples/await-then-destruct-array/main.svelte +++ b/test/runtime/samples/await-then-destruct-array/main.svelte @@ -7,4 +7,8 @@ {:then [ a, b ]}a: {a}
b: {b}
+{:catch [c, [d, e]]} +c: {c}
+d: {d}
+e: {e}
{/await} \ No newline at end of file diff --git a/test/runtime/samples/await-then-destruct-default/_config.js b/test/runtime/samples/await-then-destruct-default/_config.js new file mode 100644 index 0000000000..d0e5a49f28 --- /dev/null +++ b/test/runtime/samples/await-then-destruct-default/_config.js @@ -0,0 +1,23 @@ +export default { + async test({ assert, component, target }) { + await Promise.resolve(); + + assert.htmlEqual( + target.innerHTML, + ` +a: 3
+b: 2
+c: 3
+a: 1
+b: 2
+c: 3
+a: 3
+b: 2
+c: 3
+a: 1
+b: 2
+c: 3
+ ` + ); + } +}; diff --git a/test/runtime/samples/await-then-destruct-default/main.svelte b/test/runtime/samples/await-then-destruct-default/main.svelte new file mode 100644 index 0000000000..d559aadab1 --- /dev/null +++ b/test/runtime/samples/await-then-destruct-default/main.svelte @@ -0,0 +1,34 @@ + + +{#await object then { a = 3, b = 4, c }} +a: {a}
+b: {b}
+c: {c}
+{/await} + +{#await array then [a, b, c = 3]} +a: {a}
+b: {b}
+c: {c}
+{/await} + +{#await objectReject then value} + resolved +{:catch { a = 3, b = 4, c }} +a: {a}
+b: {b}
+c: {c}
+{/await} + +{#await arrayReject then value} + resolved +{:catch [a, b, c = 3]} +a: {a}
+b: {b}
+c: {c}
+{/await} \ No newline at end of file diff --git a/test/runtime/samples/await-then-destruct-object/_config.js b/test/runtime/samples/await-then-destruct-object/_config.js index 839a5a6854..af39b43640 100644 --- a/test/runtime/samples/await-then-destruct-object/_config.js +++ b/test/runtime/samples/await-then-destruct-object/_config.js @@ -1,6 +1,6 @@ export default { props: { - thePromise: new Promise(resolve => {}), + thePromise: new Promise(resolve => {}) }, html: ` @@ -8,20 +8,56 @@ export default { `, async test({ assert, component, target }) { - let promise = Promise.resolve({ error: 'error message' }); - component.thePromise = promise; + await (component.thePromise = Promise.resolve({ error: "error message" })); - await promise; - assert.htmlEqual(target.innerHTML, ` -error: error message
- `); + assert.htmlEqual( + target.innerHTML, + ` +error: error message
+result: undefined
+ ` + ); - promise = Promise.resolve({ result: '42' }); - component.thePromise = promise; + await (component.thePromise = Promise.resolve({ result: "42" })); - await promise; - assert.htmlEqual(target.innerHTML, ` -result: 42
- `); + assert.htmlEqual( + target.innerHTML, + ` +error: undefined
+result: 42
+ ` + ); + + try { + await (component.thePromise = Promise.reject({ + error: { message: "oops", code: "123" } + })); + } catch { + // do nothing + } + + assert.htmlEqual( + target.innerHTML, + ` +message: oops
+code: 123
+ ` + ); + + try { + await (component.thePromise = Promise.reject({ + error: { message: "timeout", code: "456" } + })); + } catch { + // do nothing + } + + assert.htmlEqual( + target.innerHTML, + ` +message: timeout
+code: 456
+ ` + ); } -}; \ No newline at end of file +}; diff --git a/test/runtime/samples/await-then-destruct-object/main.svelte b/test/runtime/samples/await-then-destruct-object/main.svelte index 9cac1e1614..ff574b7be8 100644 --- a/test/runtime/samples/await-then-destruct-object/main.svelte +++ b/test/runtime/samples/await-then-destruct-object/main.svelte @@ -5,9 +5,9 @@ {#await thePromise} loading... {:then { result, error }} - {#if error} -error: { error }
- {:else} -result: {result}
- {/if} +error: {error}
+result: {result}
+{:catch { error: { message, code } }} +message: {message}
+code: {code}
{/await} \ No newline at end of file diff --git a/test/runtime/samples/await-then-destruct-rest/_config.js b/test/runtime/samples/await-then-destruct-rest/_config.js new file mode 100644 index 0000000000..528568e569 --- /dev/null +++ b/test/runtime/samples/await-then-destruct-rest/_config.js @@ -0,0 +1,21 @@ +export default { + async test({ assert, component, target }) { + await Promise.resolve(); + + assert.htmlEqual( + target.innerHTML, + ` +a: 1
+rest: {"b":2,"c":3}
+a: 1
+b: 2
+rest: [3,4,5,6]
+a: 1
+rest: {"b":2,"c":3}
+a: 1
+b: 2
+rest: [3,4,5,6]
+ ` + ); + } +}; diff --git a/test/runtime/samples/await-then-destruct-rest/main.svelte b/test/runtime/samples/await-then-destruct-rest/main.svelte new file mode 100644 index 0000000000..a2d57dabf3 --- /dev/null +++ b/test/runtime/samples/await-then-destruct-rest/main.svelte @@ -0,0 +1,32 @@ + + +{#await object then { a, ...rest }} +a: {a}
+rest: {JSON.stringify(rest)}
+{/await} + +{#await array then [a, b, ...rest]} +a: {a}
+b: {b}
+rest: {JSON.stringify(rest)}
+{/await} + +{#await objectReject then value} + resolved +{:catch { a, ...rest }} +a: {a}
+rest: {JSON.stringify(rest)}
+{/await} + +{#await arrayReject then value} + resolved +{:catch [a, b, ...rest]} +a: {a}
+b: {b}
+rest: {JSON.stringify(rest)}
+{/await} \ No newline at end of file