diff --git a/packages/svelte/src/compiler/phases/1-parse/state/tag.js b/packages/svelte/src/compiler/phases/1-parse/state/tag.js index 0fc6135bf2..7996d64ded 100644 --- a/packages/svelte/src/compiler/phases/1-parse/state/tag.js +++ b/packages/svelte/src/compiler/phases/1-parse/state/tag.js @@ -182,17 +182,21 @@ function open(parser) { const matches = parser.eat('}', true, false); - // Parser may have read the `as` as part of the expression (e.g. in `{#each foo. as x}`) - if (!matches && parser.template.slice(parser.index - 4, parser.index) === ' as ') { - const prev_index = parser.index; - context = read_pattern(parser); - parser.eat('}', true); - expression = { - type: 'Identifier', - name: '', - start: expression.start, - end: prev_index - 4 - }; + if (!matches) { + // Parser may have read the `as` as part of the expression (e.g. in `{#each foo. as x}`) + if (parser.template.slice(parser.index - 4, parser.index) === ' as ') { + const prev_index = parser.index; + context = read_pattern(parser); + parser.eat('}', true); + expression = { + type: 'Identifier', + name: '', + start: expression.start, + end: prev_index - 4 + }; + } else { + parser.eat('}', true); // rerun to produce the parser error + } } /** @type {AST.EachBlock} */ @@ -259,7 +263,39 @@ function open(parser) { parser.fragments.push(block.pending); } - parser.eat('}', true); + const matches = parser.eat('}', true, false); + + // Parser may have read the `then/catch` as part of the expression (e.g. in `{#await foo. then x}`) + if (!matches) { + if (parser.template.slice(parser.index - 6, parser.index) === ' then ') { + const prev_index = parser.index; + block.value = read_pattern(parser); + parser.eat('}', true); + block.expression = { + type: 'Identifier', + name: '', + start: expression.start, + end: prev_index - 6 + }; + block.then = block.pending; + block.pending = null; + } else if (parser.template.slice(parser.index - 7, parser.index) === ' catch ') { + const prev_index = parser.index; + block.error = read_pattern(parser); + parser.eat('}', true); + block.expression = { + type: 'Identifier', + name: '', + start: expression.start, + end: prev_index - 7 + }; + block.catch = block.pending; + block.pending = null; + } else { + parser.eat('}', true); // rerun to produce the parser error + } + } + parser.stack.push(block); return; diff --git a/packages/svelte/tests/parser-legacy/samples/loose-invalid-expression/input.svelte b/packages/svelte/tests/parser-legacy/samples/loose-invalid-expression/input.svelte index 3f44de96a7..b64f15c5c1 100644 --- a/packages/svelte/tests/parser-legacy/samples/loose-invalid-expression/input.svelte +++ b/packages/svelte/tests/parser-legacy/samples/loose-invalid-expression/input.svelte @@ -15,3 +15,9 @@ asd{a.}asd {#each array as item (item.)}{/each} {#each obj. as item}{/each} + +{#await x.}{/await} + +{#await x. then y}{/await} + +{#await x. catch y}{/await} diff --git a/packages/svelte/tests/parser-legacy/samples/loose-invalid-expression/output.json b/packages/svelte/tests/parser-legacy/samples/loose-invalid-expression/output.json index 57fb01c77d..0564d6d295 100644 --- a/packages/svelte/tests/parser-legacy/samples/loose-invalid-expression/output.json +++ b/packages/svelte/tests/parser-legacy/samples/loose-invalid-expression/output.json @@ -2,7 +2,7 @@ "html": { "type": "Fragment", "start": 0, - "end": 246, + "end": 324, "children": [ { "type": "Element", @@ -345,6 +345,163 @@ "start": 226, "end": 230 } + }, + { + "type": "Text", + "start": 246, + "end": 248, + "raw": "\n\n", + "data": "\n\n" + }, + { + "type": "AwaitBlock", + "start": 248, + "end": 267, + "expression": { + "type": "Identifier", + "start": 256, + "end": 258, + "name": "" + }, + "value": null, + "error": null, + "pending": { + "type": "PendingBlock", + "start": 259, + "end": 259, + "children": [], + "skip": false + }, + "then": { + "type": "ThenBlock", + "start": null, + "end": null, + "children": [], + "skip": true + }, + "catch": { + "type": "CatchBlock", + "start": null, + "end": null, + "children": [], + "skip": true + } + }, + { + "type": "Text", + "start": 267, + "end": 269, + "raw": "\n\n", + "data": "\n\n" + }, + { + "type": "AwaitBlock", + "start": 269, + "end": 295, + "expression": { + "type": "Identifier", + "name": "", + "start": 277, + "end": 279 + }, + "value": { + "type": "Identifier", + "name": "y", + "start": 285, + "loc": { + "start": { + "line": 21, + "column": 16, + "character": 285 + }, + "end": { + "line": 21, + "column": 17, + "character": 286 + } + }, + "end": 286 + }, + "error": null, + "pending": { + "type": "PendingBlock", + "start": null, + "end": null, + "children": [], + "skip": true + }, + "then": { + "type": "ThenBlock", + "start": 287, + "end": 267, + "children": [], + "skip": false + }, + "catch": { + "type": "CatchBlock", + "start": null, + "end": null, + "children": [], + "skip": true + } + }, + { + "type": "Text", + "start": 295, + "end": 297, + "raw": "\n\n", + "data": "\n\n" + }, + { + "type": "AwaitBlock", + "start": 297, + "end": 324, + "expression": { + "type": "Identifier", + "name": "", + "start": 305, + "end": 307 + }, + "value": null, + "error": { + "type": "Identifier", + "name": "y", + "start": 314, + "loc": { + "start": { + "line": 23, + "column": 17, + "character": 314 + }, + "end": { + "line": 23, + "column": 18, + "character": 315 + } + }, + "end": 315 + }, + "pending": { + "type": "PendingBlock", + "start": null, + "end": null, + "children": [], + "skip": true + }, + "then": { + "type": "ThenBlock", + "start": null, + "end": null, + "children": [], + "skip": true + }, + "catch": { + "type": "CatchBlock", + "start": 316, + "end": 295, + "children": [], + "skip": false + } } ] } diff --git a/packages/svelte/tests/parser-modern/samples/loose-invalid-expression/input.svelte b/packages/svelte/tests/parser-modern/samples/loose-invalid-expression/input.svelte index 3f44de96a7..b64f15c5c1 100644 --- a/packages/svelte/tests/parser-modern/samples/loose-invalid-expression/input.svelte +++ b/packages/svelte/tests/parser-modern/samples/loose-invalid-expression/input.svelte @@ -15,3 +15,9 @@ asd{a.}asd {#each array as item (item.)}{/each} {#each obj. as item}{/each} + +{#await x.}{/await} + +{#await x. then y}{/await} + +{#await x. catch y}{/await} diff --git a/packages/svelte/tests/parser-modern/samples/loose-invalid-expression/output.json b/packages/svelte/tests/parser-modern/samples/loose-invalid-expression/output.json index a1a7148e02..56fa4286dd 100644 --- a/packages/svelte/tests/parser-modern/samples/loose-invalid-expression/output.json +++ b/packages/svelte/tests/parser-modern/samples/loose-invalid-expression/output.json @@ -2,7 +2,7 @@ "css": null, "js": [], "start": 0, - "end": 246, + "end": 324, "type": "Root", "fragment": { "type": "Fragment", @@ -367,6 +367,118 @@ }, "end": 238 } + }, + { + "type": "Text", + "start": 246, + "end": 248, + "raw": "\n\n", + "data": "\n\n" + }, + { + "type": "AwaitBlock", + "start": 248, + "end": 267, + "expression": { + "type": "Identifier", + "start": 256, + "end": 258, + "name": "" + }, + "value": null, + "error": null, + "pending": { + "type": "Fragment", + "nodes": [] + }, + "then": null, + "catch": null + }, + { + "type": "Text", + "start": 267, + "end": 269, + "raw": "\n\n", + "data": "\n\n" + }, + { + "type": "AwaitBlock", + "start": 269, + "end": 295, + "expression": { + "type": "Identifier", + "name": "", + "start": 277, + "end": 279 + }, + "value": { + "type": "Identifier", + "name": "y", + "start": 285, + "loc": { + "start": { + "line": 21, + "column": 16, + "character": 285 + }, + "end": { + "line": 21, + "column": 17, + "character": 286 + } + }, + "end": 286 + }, + "error": null, + "pending": null, + "then": { + "type": "Fragment", + "nodes": [] + }, + "catch": null + }, + { + "type": "Text", + "start": 295, + "end": 297, + "raw": "\n\n", + "data": "\n\n" + }, + { + "type": "AwaitBlock", + "start": 297, + "end": 324, + "expression": { + "type": "Identifier", + "name": "", + "start": 305, + "end": 307 + }, + "value": null, + "error": { + "type": "Identifier", + "name": "y", + "start": 314, + "loc": { + "start": { + "line": 23, + "column": 17, + "character": 314 + }, + "end": { + "line": 23, + "column": 18, + "character": 315 + } + }, + "end": 315 + }, + "pending": null, + "then": null, + "catch": { + "type": "Fragment", + "nodes": [] + } } ] },