Skip to content

Commit

Permalink
fix: snippets with TS incorrect transformation (#2412)
Browse files Browse the repository at this point in the history
After sveltejs/svelte#12070 the AST for the SnippetBlock has changed (to be more correct).

The problem is that svelte2tsx was using that wrong information for the transformation. This means that currently last version of svelte produces wrong ts code from svelte2tsx.
  • Loading branch information
paoloricciuti committed Jun 24, 2024
1 parent be5e535 commit bdfa37a
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 15 deletions.
31 changes: 20 additions & 11 deletions packages/svelte2tsx/src/htmlxtojsx_v2/nodes/SnippetBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,20 @@ export function handleSnippet(
}
);

const lastParameter = snippetBlock.parameters?.at(-1);

const startEnd =
str.original.indexOf(
'}',
// context was the first iteration in a .next release, remove at some point
snippetBlock.parameters?.at(-1)?.end || snippetBlock.expression.end
lastParameter?.typeAnnotation?.end ?? lastParameter?.end ?? snippetBlock.expression.end
) + 1;

if (isImplicitProp) {
str.overwrite(snippetBlock.start, snippetBlock.expression.start, '', { contentOnly: true });
const transforms: TransformationArray = ['('];
if (snippetBlock.parameters?.length) {
const start = snippetBlock.parameters?.[0].start;
const end = snippetBlock.parameters.at(-1).end;
const start = snippetBlock.parameters[0].start;
const end = lastParameter.typeAnnotation?.end ?? lastParameter.end;
transforms.push([start, end]);
str.overwrite(snippetBlock.expression.end, start, '', {
contentOnly: true
Expand All @@ -73,15 +74,23 @@ export function handleSnippet(
let generic = '';
if (snippetBlock.parameters?.length) {
generic = `<[${snippetBlock.parameters
.map((p) =>
p.typeAnnotation?.typeAnnotation
.map((p) => {
let typeAnnotation = p.typeAnnotation;
if (!typeAnnotation && p.type === 'AssignmentPattern') {
typeAnnotation = p.left?.typeAnnotation;
if (!typeAnnotation) {
typeAnnotation = p.right?.typeAnnotation;
}
}
if (!typeAnnotation) return 'any';
return typeAnnotation.typeAnnotation
? str.original.slice(
p.typeAnnotation.typeAnnotation.start,
p.typeAnnotation.typeAnnotation.end
typeAnnotation.typeAnnotation.start,
typeAnnotation.typeAnnotation.end
)
: // slap any on to it to silence "implicit any" errors; JSDoc people can't add types to snippets
'any'
)
'any';
})
.join(', ')}]>`;
}

Expand All @@ -94,7 +103,7 @@ export function handleSnippet(

if (snippetBlock.parameters?.length) {
const start = snippetBlock.parameters[0].start;
const end = snippetBlock.parameters.at(-1).end;
const end = lastParameter.typeAnnotation?.end ?? lastParameter.end;
transforms.push([start, end]);
}

Expand Down
12 changes: 8 additions & 4 deletions packages/svelte2tsx/test/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,12 +320,16 @@ export function test_samples(dir: string, transform: TransformSampleFn, js: 'js'
try {
assert.strictEqual(actual, expected, TestError.WrongExpected);
} catch (e) {
// html2jsx tests don't have the default export
const expectDefaultExportPosition = expected.lastIndexOf(
'\n\nexport default class'
);
if (expectDefaultExportPosition === -1) {
throw e;
}
// retry with the last part (the returned default export) stripped because it's always differing between old and new,
// and if that fails then we're going to rethrow the original error
const expectedModified = expected.substring(
0,
expected.lastIndexOf('\n\nexport default class')
);
const expectedModified = expected.substring(0, expectDefaultExportPosition);
const actualModified = actual.substring(0, actual.lastIndexOf('\nconst '));
try {
assert.strictEqual(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ item as string;

var foo3/*Ωignore_startΩ*/: import('svelte').Snippet<[string | number, (str: string)=>void]>/*Ωignore_endΩ*/ = (bar : string | number, baz : (str: string)=>void) => {async () => { };return __sveltets_2_any(0)};

var foo3/*Ωignore_startΩ*/: import('svelte').Snippet<[{baz: string}]>/*Ωignore_endΩ*/ = (bar: {baz: string}) => {async () => { };return __sveltets_2_any(0)};

;__sveltets_2_ensureSnippet(foo(bar as string));

{ svelteHTML.createElement("button", { "onclick":(e: Event) => {e as any},}); }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@
snippet
{/snippet}

{#snippet foo3(bar: {baz: string})}
snippet
{/snippet}

{@render foo(bar as string)}

<button onclick={(e: Event) => {e as any}}>click</button>
Expand Down

0 comments on commit bdfa37a

Please sign in to comment.