From fc3ee2fc16e5769999119dfc77c30ed36c51a3a7 Mon Sep 17 00:00:00 2001 From: baseballyama Date: Sun, 16 Jun 2024 16:10:30 +0900 Subject: [PATCH 1/6] fix: correct start of `{:else if}` and `{:else}` --- .changeset/cold-teachers-turn.md | 5 +++++ .../src/compiler/phases/1-parse/state/tag.js | 18 +++++++++--------- .../samples/if-block-elseif/output.json | 2 +- 3 files changed, 15 insertions(+), 10 deletions(-) create mode 100644 .changeset/cold-teachers-turn.md diff --git a/.changeset/cold-teachers-turn.md b/.changeset/cold-teachers-turn.md new file mode 100644 index 000000000000..e86ffbcdfea1 --- /dev/null +++ b/.changeset/cold-teachers-turn.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: correct start of `{:else if}` and `{:else}` 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 0dc7b9709eed..2e0ce9edb924 100644 --- a/packages/svelte/src/compiler/phases/1-parse/state/tag.js +++ b/packages/svelte/src/compiler/phases/1-parse/state/tag.js @@ -319,13 +319,13 @@ function open(parser) { /** @param {import('../index.js').Parser} parser */ function next(parser) { - const start = parser.index - 1; + const next_to_bracket = parser.index - 1; const block = parser.current(); // TODO type should not be TemplateNode, that's much too broad if (block.type === 'IfBlock') { - if (!parser.eat('else')) e.expected_token(start, '{:else} or {:else if}'); - if (parser.eat('if')) e.block_invalid_elseif(start); + if (!parser.eat('else')) e.expected_token(next_to_bracket, '{:else} or {:else if}'); + if (parser.eat('if')) e.block_invalid_elseif(next_to_bracket); parser.allow_whitespace(); @@ -345,7 +345,7 @@ function next(parser) { /** @type {ReturnType>} */ const child = parser.append({ - start: parser.index, + start: next_to_bracket - 1, end: -1, type: 'IfBlock', elseif: true, @@ -367,7 +367,7 @@ function next(parser) { } if (block.type === 'EachBlock') { - if (!parser.eat('else')) e.expected_token(start, '{:else}'); + if (!parser.eat('else')) e.expected_token(next_to_bracket, '{:else}'); parser.allow_whitespace(); parser.eat('}', true); @@ -383,7 +383,7 @@ function next(parser) { if (block.type === 'AwaitBlock') { if (parser.eat('then')) { if (block.then) { - e.block_duplicate_clause(start, '{:then}'); + e.block_duplicate_clause(next_to_bracket, '{:then}'); } if (!parser.eat('}')) { @@ -402,7 +402,7 @@ function next(parser) { if (parser.eat('catch')) { if (block.catch) { - e.block_duplicate_clause(start, '{:catch}'); + e.block_duplicate_clause(next_to_bracket, '{:catch}'); } if (!parser.eat('}')) { @@ -419,10 +419,10 @@ function next(parser) { return; } - e.expected_token(start, '{:then ...} or {:catch ...}'); + e.expected_token(next_to_bracket, '{:then ...} or {:catch ...}'); } - e.block_invalid_continuation_placement(start); + e.block_invalid_continuation_placement(next_to_bracket); } /** @param {import('../index.js').Parser} parser */ diff --git a/packages/svelte/tests/parser-legacy/samples/if-block-elseif/output.json b/packages/svelte/tests/parser-legacy/samples/if-block-elseif/output.json index 3e6953ab0b3d..40411d677940 100644 --- a/packages/svelte/tests/parser-legacy/samples/if-block-elseif/output.json +++ b/packages/svelte/tests/parser-legacy/samples/if-block-elseif/output.json @@ -82,7 +82,7 @@ "children": [ { "type": "IfBlock", - "start": 58, + "start": 42, "end": 89, "expression": { "type": "BinaryExpression", From 16d839ca54e906c99b0cd45db82f546985a19f0f Mon Sep 17 00:00:00 2001 From: baseballyama Date: Sat, 29 Jun 2024 14:02:31 +0900 Subject: [PATCH 2/6] fix legacy ast --- packages/svelte/src/compiler/legacy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/svelte/src/compiler/legacy.js b/packages/svelte/src/compiler/legacy.js index caa7f8238e6c..3a9b9a8e795a 100644 --- a/packages/svelte/src/compiler/legacy.js +++ b/packages/svelte/src/compiler/legacy.js @@ -357,7 +357,7 @@ export function convert(source, ast) { return { type: 'IfBlock', - start: node.start, + start: node.elseif ? node.consequent.nodes[0].start : node.start, end: node.end, expression: node.test, children: node.consequent.nodes.map( From 302d77528071f4e530f006accd64286f83d359b3 Mon Sep 17 00:00:00 2001 From: baseballyama Date: Sat, 29 Jun 2024 14:24:21 +0900 Subject: [PATCH 3/6] fix test --- .../tests/parser-legacy/samples/if-block-elseif/output.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/svelte/tests/parser-legacy/samples/if-block-elseif/output.json b/packages/svelte/tests/parser-legacy/samples/if-block-elseif/output.json index 40411d677940..912613b51617 100644 --- a/packages/svelte/tests/parser-legacy/samples/if-block-elseif/output.json +++ b/packages/svelte/tests/parser-legacy/samples/if-block-elseif/output.json @@ -82,7 +82,7 @@ "children": [ { "type": "IfBlock", - "start": 42, + "start": 60, "end": 89, "expression": { "type": "BinaryExpression", From 777ebb3f72ad1e7647c4b45cf8a421e307e51381 Mon Sep 17 00:00:00 2001 From: baseballyama Date: Sat, 29 Jun 2024 14:37:34 +0900 Subject: [PATCH 4/6] fix --- packages/svelte/src/compiler/legacy.js | 3 ++- .../tests/parser-legacy/samples/if-block-elseif/output.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/svelte/src/compiler/legacy.js b/packages/svelte/src/compiler/legacy.js index 3a9b9a8e795a..da0ba058d36a 100644 --- a/packages/svelte/src/compiler/legacy.js +++ b/packages/svelte/src/compiler/legacy.js @@ -353,11 +353,12 @@ export function convert(source, ast) { }; } + const start = node.elseif ? node.consequent.nodes[0].start : node.start; remove_surrounding_whitespace_nodes(node.consequent.nodes); return { type: 'IfBlock', - start: node.elseif ? node.consequent.nodes[0].start : node.start, + start, end: node.end, expression: node.test, children: node.consequent.nodes.map( diff --git a/packages/svelte/tests/parser-legacy/samples/if-block-elseif/output.json b/packages/svelte/tests/parser-legacy/samples/if-block-elseif/output.json index 912613b51617..3e6953ab0b3d 100644 --- a/packages/svelte/tests/parser-legacy/samples/if-block-elseif/output.json +++ b/packages/svelte/tests/parser-legacy/samples/if-block-elseif/output.json @@ -82,7 +82,7 @@ "children": [ { "type": "IfBlock", - "start": 60, + "start": 58, "end": 89, "expression": { "type": "BinaryExpression", From 806a86dc7661fccdd1e1aec7f90dec3cdb934611 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Mon, 8 Jul 2024 11:38:12 +0200 Subject: [PATCH 5/6] add tests --- .../samples/if-block-else/input.svelte | 5 + .../samples/if-block-else/output.json | 116 ++++++++++ .../samples/if-block-elseif/input.svelte | 5 + .../samples/if-block-elseif/output.json | 211 ++++++++++++++++++ .../samples/if-block/input.svelte | 1 + .../samples/if-block/output.json | 50 +++++ 6 files changed, 388 insertions(+) create mode 100644 packages/svelte/tests/parser-modern/samples/if-block-else/input.svelte create mode 100644 packages/svelte/tests/parser-modern/samples/if-block-else/output.json create mode 100644 packages/svelte/tests/parser-modern/samples/if-block-elseif/input.svelte create mode 100644 packages/svelte/tests/parser-modern/samples/if-block-elseif/output.json create mode 100644 packages/svelte/tests/parser-modern/samples/if-block/input.svelte create mode 100644 packages/svelte/tests/parser-modern/samples/if-block/output.json diff --git a/packages/svelte/tests/parser-modern/samples/if-block-else/input.svelte b/packages/svelte/tests/parser-modern/samples/if-block-else/input.svelte new file mode 100644 index 000000000000..28b41c046c07 --- /dev/null +++ b/packages/svelte/tests/parser-modern/samples/if-block-else/input.svelte @@ -0,0 +1,5 @@ +{#if foo} +

foo

+{:else} +

not foo

+{/if} diff --git a/packages/svelte/tests/parser-modern/samples/if-block-else/output.json b/packages/svelte/tests/parser-modern/samples/if-block-else/output.json new file mode 100644 index 000000000000..1193af156e0a --- /dev/null +++ b/packages/svelte/tests/parser-modern/samples/if-block-else/output.json @@ -0,0 +1,116 @@ +{ + "css": null, + "js": [], + "start": 0, + "end": 51, + "type": "Root", + "fragment": { + "type": "Fragment", + "nodes": [ + { + "type": "IfBlock", + "elseif": false, + "start": 0, + "end": 51, + "test": { + "type": "Identifier", + "start": 5, + "end": 8, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 8 + } + }, + "name": "foo" + }, + "consequent": { + "type": "Fragment", + "nodes": [ + { + "type": "Text", + "start": 9, + "end": 11, + "raw": "\n\t", + "data": "\n\t" + }, + { + "type": "RegularElement", + "start": 11, + "end": 21, + "name": "p", + "attributes": [], + "fragment": { + "type": "Fragment", + "nodes": [ + { + "type": "Text", + "start": 14, + "end": 17, + "raw": "foo", + "data": "foo" + } + ], + "transparent": true + } + }, + { + "type": "Text", + "start": 21, + "end": 22, + "raw": "\n", + "data": "\n" + } + ], + "transparent": false + }, + "alternate": { + "type": "Fragment", + "nodes": [ + { + "type": "Text", + "start": 29, + "end": 31, + "raw": "\n\t", + "data": "\n\t" + }, + { + "type": "RegularElement", + "start": 31, + "end": 45, + "name": "p", + "attributes": [], + "fragment": { + "type": "Fragment", + "nodes": [ + { + "type": "Text", + "start": 34, + "end": 41, + "raw": "not foo", + "data": "not foo" + } + ], + "transparent": true + } + }, + { + "type": "Text", + "start": 45, + "end": 46, + "raw": "\n", + "data": "\n" + } + ], + "transparent": false + } + } + ], + "transparent": false + }, + "options": null +} diff --git a/packages/svelte/tests/parser-modern/samples/if-block-elseif/input.svelte b/packages/svelte/tests/parser-modern/samples/if-block-elseif/input.svelte new file mode 100644 index 000000000000..2566aef258c6 --- /dev/null +++ b/packages/svelte/tests/parser-modern/samples/if-block-elseif/input.svelte @@ -0,0 +1,5 @@ +{#if x > 10} +

x is greater than 10

+{:else if x < 5} +

x is less than 5

+{/if} diff --git a/packages/svelte/tests/parser-modern/samples/if-block-elseif/output.json b/packages/svelte/tests/parser-modern/samples/if-block-elseif/output.json new file mode 100644 index 000000000000..e68b154a55a5 --- /dev/null +++ b/packages/svelte/tests/parser-modern/samples/if-block-elseif/output.json @@ -0,0 +1,211 @@ +{ + "css": null, + "js": [], + "start": 0, + "end": 89, + "type": "Root", + "fragment": { + "type": "Fragment", + "nodes": [ + { + "type": "IfBlock", + "elseif": false, + "start": 0, + "end": 89, + "test": { + "type": "BinaryExpression", + "start": 5, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 11 + } + }, + "left": { + "type": "Identifier", + "start": 5, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 6 + } + }, + "name": "x" + }, + "operator": ">", + "right": { + "type": "Literal", + "start": 9, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 9 + }, + "end": { + "line": 1, + "column": 11 + } + }, + "value": 10, + "raw": "10" + } + }, + "consequent": { + "type": "Fragment", + "nodes": [ + { + "type": "Text", + "start": 12, + "end": 14, + "raw": "\n\t", + "data": "\n\t" + }, + { + "type": "RegularElement", + "start": 14, + "end": 41, + "name": "p", + "attributes": [], + "fragment": { + "type": "Fragment", + "nodes": [ + { + "type": "Text", + "start": 17, + "end": 37, + "raw": "x is greater than 10", + "data": "x is greater than 10" + } + ], + "transparent": true + } + }, + { + "type": "Text", + "start": 41, + "end": 42, + "raw": "\n", + "data": "\n" + } + ], + "transparent": false + }, + "alternate": { + "type": "Fragment", + "nodes": [ + { + "start": 42, + "end": 89, + "type": "IfBlock", + "elseif": true, + "test": { + "type": "BinaryExpression", + "start": 52, + "end": 57, + "loc": { + "start": { + "line": 3, + "column": 10 + }, + "end": { + "line": 3, + "column": 15 + } + }, + "left": { + "type": "Identifier", + "start": 52, + "end": 53, + "loc": { + "start": { + "line": 3, + "column": 10 + }, + "end": { + "line": 3, + "column": 11 + } + }, + "name": "x" + }, + "operator": "<", + "right": { + "type": "Literal", + "start": 56, + "end": 57, + "loc": { + "start": { + "line": 3, + "column": 14 + }, + "end": { + "line": 3, + "column": 15 + } + }, + "value": 5, + "raw": "5" + } + }, + "consequent": { + "type": "Fragment", + "nodes": [ + { + "type": "Text", + "start": 58, + "end": 60, + "raw": "\n\t", + "data": "\n\t" + }, + { + "type": "RegularElement", + "start": 60, + "end": 83, + "name": "p", + "attributes": [], + "fragment": { + "type": "Fragment", + "nodes": [ + { + "type": "Text", + "start": 63, + "end": 79, + "raw": "x is less than 5", + "data": "x is less than 5" + } + ], + "transparent": true + } + }, + { + "type": "Text", + "start": 83, + "end": 84, + "raw": "\n", + "data": "\n" + } + ], + "transparent": false + }, + "alternate": null + } + ], + "transparent": false + } + } + ], + "transparent": false + }, + "options": null +} diff --git a/packages/svelte/tests/parser-modern/samples/if-block/input.svelte b/packages/svelte/tests/parser-modern/samples/if-block/input.svelte new file mode 100644 index 000000000000..5851347a88d7 --- /dev/null +++ b/packages/svelte/tests/parser-modern/samples/if-block/input.svelte @@ -0,0 +1 @@ +{#if foo}bar{/if} diff --git a/packages/svelte/tests/parser-modern/samples/if-block/output.json b/packages/svelte/tests/parser-modern/samples/if-block/output.json new file mode 100644 index 000000000000..965f2b5614ce --- /dev/null +++ b/packages/svelte/tests/parser-modern/samples/if-block/output.json @@ -0,0 +1,50 @@ +{ + "css": null, + "js": [], + "start": 0, + "end": 17, + "type": "Root", + "fragment": { + "type": "Fragment", + "nodes": [ + { + "type": "IfBlock", + "elseif": false, + "start": 0, + "end": 17, + "test": { + "type": "Identifier", + "start": 5, + "end": 8, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 8 + } + }, + "name": "foo" + }, + "consequent": { + "type": "Fragment", + "nodes": [ + { + "type": "Text", + "start": 9, + "end": 12, + "raw": "bar", + "data": "bar" + } + ], + "transparent": false + }, + "alternate": null + } + ], + "transparent": false + }, + "options": null +} From a46c2de44cb50a76629818f3fb90bb3057f0c3e7 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Mon, 8 Jul 2024 11:39:29 +0200 Subject: [PATCH 6/6] rename --- .../src/compiler/phases/1-parse/state/tag.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) 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 2e0ce9edb924..e91cd019eb8d 100644 --- a/packages/svelte/src/compiler/phases/1-parse/state/tag.js +++ b/packages/svelte/src/compiler/phases/1-parse/state/tag.js @@ -319,13 +319,13 @@ function open(parser) { /** @param {import('../index.js').Parser} parser */ function next(parser) { - const next_to_bracket = parser.index - 1; + const start = parser.index - 1; const block = parser.current(); // TODO type should not be TemplateNode, that's much too broad if (block.type === 'IfBlock') { - if (!parser.eat('else')) e.expected_token(next_to_bracket, '{:else} or {:else if}'); - if (parser.eat('if')) e.block_invalid_elseif(next_to_bracket); + if (!parser.eat('else')) e.expected_token(start, '{:else} or {:else if}'); + if (parser.eat('if')) e.block_invalid_elseif(start); parser.allow_whitespace(); @@ -345,7 +345,7 @@ function next(parser) { /** @type {ReturnType>} */ const child = parser.append({ - start: next_to_bracket - 1, + start: start - 1, end: -1, type: 'IfBlock', elseif: true, @@ -367,7 +367,7 @@ function next(parser) { } if (block.type === 'EachBlock') { - if (!parser.eat('else')) e.expected_token(next_to_bracket, '{:else}'); + if (!parser.eat('else')) e.expected_token(start, '{:else}'); parser.allow_whitespace(); parser.eat('}', true); @@ -383,7 +383,7 @@ function next(parser) { if (block.type === 'AwaitBlock') { if (parser.eat('then')) { if (block.then) { - e.block_duplicate_clause(next_to_bracket, '{:then}'); + e.block_duplicate_clause(start, '{:then}'); } if (!parser.eat('}')) { @@ -402,7 +402,7 @@ function next(parser) { if (parser.eat('catch')) { if (block.catch) { - e.block_duplicate_clause(next_to_bracket, '{:catch}'); + e.block_duplicate_clause(start, '{:catch}'); } if (!parser.eat('}')) { @@ -419,10 +419,10 @@ function next(parser) { return; } - e.expected_token(next_to_bracket, '{:then ...} or {:catch ...}'); + e.expected_token(start, '{:then ...} or {:catch ...}'); } - e.block_invalid_continuation_placement(next_to_bracket); + e.block_invalid_continuation_placement(start); } /** @param {import('../index.js').Parser} parser */