Skip to content

Commit 9b44c6d

Browse files
fix: take other snippets into account when checking for hoistability (#2668)
Closes #2664
1 parent 2f46701 commit 9b44c6d

File tree

5 files changed

+87
-3
lines changed

5 files changed

+87
-3
lines changed

packages/svelte2tsx/src/htmlxtojsx_v2/index.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export interface TemplateProcessResult {
5454
scriptTag: BaseNode;
5555
moduleScriptTag: BaseNode;
5656
/** Start/end positions of snippets that should be moved to the instance script or possibly even module script */
57-
rootSnippets: Array<[start: number, end: number, globals: Map<string, any>]>;
57+
rootSnippets: Array<[start: number, end: number, globals: Map<string, any>, string]>;
5858
/** To be added later as a comment on the default class export */
5959
componentDocumentation: ComponentDocumentation;
6060
events: ComponentEvents;
@@ -93,7 +93,7 @@ export function convertHtmlxToJsx(
9393

9494
stripDoctype(str);
9595

96-
const rootSnippets: Array<[number, number, Map<string, any>]> = [];
96+
const rootSnippets: Array<[number, number, Map<string, any>, string]> = [];
9797
let element: Element | InlineComponent | undefined;
9898

9999
const pendingSnippetHoistCheck = new Set<BaseNode>();
@@ -264,7 +264,12 @@ export function convertHtmlxToJsx(
264264
}
265265
});
266266

267-
rootSnippets.push([node.start, node.end, result.globals]);
267+
rootSnippets.push([
268+
node.start,
269+
node.end,
270+
result.globals,
271+
node.expression.name
272+
]);
268273
} else {
269274
pendingSnippetHoistCheck.add(parent);
270275
}

packages/svelte2tsx/src/svelte2tsx/index.ts

+4
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,10 @@ export function svelte2tsx(
165165
}
166166
}
167167

168+
if (moduleScriptTag && rootSnippets.length > 0) {
169+
exportedNames.hoistableInterfaces.analyzeSnippets(rootSnippets);
170+
}
171+
168172
if (moduleScriptTag || scriptTag) {
169173
for (const [start, end, globals] of rootSnippets) {
170174
const hoist_to_module =

packages/svelte2tsx/src/svelte2tsx/nodes/HoistableInterfaces.ts

+22
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,28 @@ export class HoistableInterfaces {
1919
value_deps: new Set<string>()
2020
};
2121

22+
analyzeSnippets(
23+
rootSnippets: [start: number, end: number, globals: Map<string, any>, string][]
24+
) {
25+
let prev_disallowed_values_size;
26+
// we need to recalculate the disallowed values until they are stable because
27+
// one snippet might depend on another snippet which was previously hoistable
28+
while (
29+
prev_disallowed_values_size == null ||
30+
this.disallowed_values.size !== prev_disallowed_values_size
31+
) {
32+
prev_disallowed_values_size = this.disallowed_values.size;
33+
for (const [, , globals, name] of rootSnippets) {
34+
const hoist_to_module =
35+
globals.size === 0 ||
36+
[...globals.keys()].every((id) => this.isAllowedReference(id));
37+
if (!hoist_to_module) {
38+
this.disallowed_values.add(name);
39+
}
40+
}
41+
}
42+
}
43+
2244
/** should be called before analyzeInstanceScriptNode */
2345
analyzeModuleScriptNode(node: ts.Node) {
2446
// Handle Import Declarations
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
///<reference types="svelte" />
2+
;
3+
4+
;; const hoistable/*Ωignore_positionΩ*/ = ()/*Ωignore_startΩ*/: ReturnType<import('svelte').Snippet>/*Ωignore_endΩ*/ => { async ()/*Ωignore_positionΩ*/ => {
5+
{ svelteHTML.createElement("h1", {}); }
6+
};return __sveltets_2_any(0)};function render() {
7+
const chain/*Ωignore_positionΩ*/ = ()/*Ωignore_startΩ*/: ReturnType<import('svelte').Snippet>/*Ωignore_endΩ*/ => { async ()/*Ωignore_positionΩ*/ => {
8+
{ svelteHTML.createElement("div", {});foo; }
9+
};return __sveltets_2_any(0)}; const chain2/*Ωignore_positionΩ*/ = ()/*Ωignore_startΩ*/: ReturnType<import('svelte').Snippet>/*Ωignore_endΩ*/ => { async ()/*Ωignore_positionΩ*/ => {
10+
;__sveltets_2_ensureSnippet(chain());
11+
};return __sveltets_2_any(0)}; const chain3/*Ωignore_positionΩ*/ = ()/*Ωignore_startΩ*/: ReturnType<import('svelte').Snippet>/*Ωignore_endΩ*/ => { async ()/*Ωignore_positionΩ*/ => {
12+
;__sveltets_2_ensureSnippet(chain2());
13+
};return __sveltets_2_any(0)};
14+
let foo = true;
15+
;
16+
async () => {
17+
18+
19+
20+
21+
22+
23+
24+
25+
26+
};
27+
return { props: /** @type {Record<string, never>} */ ({}), exports: {}, bindings: "", slots: {}, events: {} }}
28+
const Input__SvelteComponent_ = __sveltets_2_isomorphic_component(__sveltets_2_partial(__sveltets_2_with_any_event(render())));
29+
/*Ωignore_startΩ*/type Input__SvelteComponent_ = InstanceType<typeof Input__SvelteComponent_>;
30+
/*Ωignore_endΩ*/export default Input__SvelteComponent_;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<script module lang="ts">
2+
3+
</script>
4+
5+
<script>
6+
let foo = true;
7+
</script>
8+
9+
{#snippet chain()}
10+
<div>{foo}</div>
11+
{/snippet}
12+
13+
{#snippet chain2()}
14+
{@render chain()}
15+
{/snippet}
16+
17+
{#snippet chain3()}
18+
{@render chain2()}
19+
{/snippet}
20+
21+
{#snippet hoistable()}
22+
<h1>hoist me</h1>
23+
{/snippet}

0 commit comments

Comments
 (0)