Skip to content

Commit 1ac3135

Browse files
authored
fix: handle TypeScript's optional parameter syntax in snippets (#10671)
fixes #10530
1 parent b1b51a4 commit 1ac3135

File tree

6 files changed

+48
-7
lines changed

6 files changed

+48
-7
lines changed

.changeset/popular-ligers-perform.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"svelte": patch
3+
---
4+
5+
fix: handle TypeScript's optional parameter syntax in snippets

packages/svelte/src/compiler/phases/1-parse/read/context.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,17 @@ import { error } from '../../../errors.js';
1313

1414
/**
1515
* @param {import('../index.js').Parser} parser
16+
* @param {boolean} [optional_allowed]
1617
* @returns {import('estree').Pattern}
1718
*/
18-
export default function read_pattern(parser) {
19+
export default function read_pattern(parser, optional_allowed = false) {
1920
const start = parser.index;
2021
let i = parser.index;
2122

2223
const code = full_char_code_at(parser.template, i);
2324
if (isIdentifierStart(code, true)) {
2425
const name = /** @type {string} */ (parser.read_identifier());
25-
const annotation = read_type_annotation(parser);
26+
const annotation = read_type_annotation(parser, optional_allowed);
2627

2728
return {
2829
type: 'Identifier',
@@ -83,7 +84,7 @@ export default function read_pattern(parser) {
8384
parse_expression_at(`${space_with_newline}(${pattern_string} = 1)`, parser.ts, start - 1)
8485
).left;
8586

86-
expression.typeAnnotation = read_type_annotation(parser);
87+
expression.typeAnnotation = read_type_annotation(parser, optional_allowed);
8788
if (expression.typeAnnotation) {
8889
expression.end = expression.typeAnnotation.end;
8990
}
@@ -96,12 +97,19 @@ export default function read_pattern(parser) {
9697

9798
/**
9899
* @param {import('../index.js').Parser} parser
100+
* @param {boolean} [optional_allowed]
99101
* @returns {any}
100102
*/
101-
function read_type_annotation(parser) {
103+
function read_type_annotation(parser, optional_allowed = false) {
102104
const start = parser.index;
103105
parser.allow_whitespace();
104106

107+
if (optional_allowed && parser.eat('?')) {
108+
// Acorn-TS puts the optional info as a property on the surrounding node.
109+
// We spare the work here because it doesn't matter for us anywhere else.
110+
parser.allow_whitespace();
111+
}
112+
105113
if (!parser.eat(':')) {
106114
parser.index = start;
107115
return undefined;

packages/svelte/src/compiler/phases/1-parse/state/tag.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ function open(parser) {
276276
const parameters = [];
277277

278278
while (!parser.match(')')) {
279-
let pattern = read_pattern(parser);
279+
let pattern = read_pattern(parser, true);
280280

281281
parser.allow_whitespace();
282282
if (parser.eat('=')) {

packages/svelte/tests/runtime-runes/samples/snippet-optional-arguments/main.svelte

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,11 @@
1717

1818
{#snippet counter(c)}
1919
{#if c}
20-
<button on:click={() => (c.value += 1)}>{c.value}</button>
20+
<button on:click={() => (c.value += 1)}>{c.value}</button>
2121
{:else}
2222
<p>fallback</p>
2323
{/if}
2424
{/snippet}
2525

2626
{@render counter()}
2727
{@render counter(count)}
28-
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { test } from '../../test';
2+
3+
export default test({
4+
html: '1 2 3 4 5'
5+
});
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<script lang="ts">
2+
</script>
3+
4+
{#snippet counter1(c: number)}
5+
{c}
6+
{/snippet}
7+
{#snippet counter2({ c }: {c: number})}
8+
{c}
9+
{/snippet}
10+
{#snippet counter3(c?: number)}
11+
{c}
12+
{/snippet}
13+
{#snippet counter4(c: number = 4)}
14+
{c}
15+
{/snippet}
16+
{#snippet counter5(c?: number = 5)}
17+
{c}
18+
{/snippet}
19+
20+
{@render counter1(1)}
21+
{@render counter2({ c: 2 })}
22+
{@render counter3(3)}
23+
{@render counter4()}
24+
{@render counter5()}

0 commit comments

Comments
 (0)