Skip to content

Commit

Permalink
fix: take other snippets into account when checking for hoistability (#…
Browse files Browse the repository at this point in the history
…2668)

Closes #2664
  • Loading branch information
paoloricciuti authored Jan 17, 2025
1 parent 2f46701 commit 9b44c6d
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 3 deletions.
11 changes: 8 additions & 3 deletions packages/svelte2tsx/src/htmlxtojsx_v2/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export interface TemplateProcessResult {
scriptTag: BaseNode;
moduleScriptTag: BaseNode;
/** Start/end positions of snippets that should be moved to the instance script or possibly even module script */
rootSnippets: Array<[start: number, end: number, globals: Map<string, any>]>;
rootSnippets: Array<[start: number, end: number, globals: Map<string, any>, string]>;
/** To be added later as a comment on the default class export */
componentDocumentation: ComponentDocumentation;
events: ComponentEvents;
Expand Down Expand Up @@ -93,7 +93,7 @@ export function convertHtmlxToJsx(

stripDoctype(str);

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

const pendingSnippetHoistCheck = new Set<BaseNode>();
Expand Down Expand Up @@ -264,7 +264,12 @@ export function convertHtmlxToJsx(
}
});

rootSnippets.push([node.start, node.end, result.globals]);
rootSnippets.push([
node.start,
node.end,
result.globals,
node.expression.name
]);
} else {
pendingSnippetHoistCheck.add(parent);
}
Expand Down
4 changes: 4 additions & 0 deletions packages/svelte2tsx/src/svelte2tsx/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,10 @@ export function svelte2tsx(
}
}

if (moduleScriptTag && rootSnippets.length > 0) {
exportedNames.hoistableInterfaces.analyzeSnippets(rootSnippets);
}

if (moduleScriptTag || scriptTag) {
for (const [start, end, globals] of rootSnippets) {
const hoist_to_module =
Expand Down
22 changes: 22 additions & 0 deletions packages/svelte2tsx/src/svelte2tsx/nodes/HoistableInterfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,28 @@ export class HoistableInterfaces {
value_deps: new Set<string>()
};

analyzeSnippets(
rootSnippets: [start: number, end: number, globals: Map<string, any>, string][]
) {
let prev_disallowed_values_size;
// we need to recalculate the disallowed values until they are stable because
// one snippet might depend on another snippet which was previously hoistable
while (
prev_disallowed_values_size == null ||
this.disallowed_values.size !== prev_disallowed_values_size
) {
prev_disallowed_values_size = this.disallowed_values.size;
for (const [, , globals, name] of rootSnippets) {
const hoist_to_module =
globals.size === 0 ||
[...globals.keys()].every((id) => this.isAllowedReference(id));
if (!hoist_to_module) {
this.disallowed_values.add(name);
}
}
}
}

/** should be called before analyzeInstanceScriptNode */
analyzeModuleScriptNode(node: ts.Node) {
// Handle Import Declarations
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
///<reference types="svelte" />
;

;; const hoistable/*Ωignore_positionΩ*/ = ()/*Ωignore_startΩ*/: ReturnType<import('svelte').Snippet>/*Ωignore_endΩ*/ => { async ()/*Ωignore_positionΩ*/ => {
{ svelteHTML.createElement("h1", {}); }
};return __sveltets_2_any(0)};function render() {
const chain/*Ωignore_positionΩ*/ = ()/*Ωignore_startΩ*/: ReturnType<import('svelte').Snippet>/*Ωignore_endΩ*/ => { async ()/*Ωignore_positionΩ*/ => {
{ svelteHTML.createElement("div", {});foo; }
};return __sveltets_2_any(0)}; const chain2/*Ωignore_positionΩ*/ = ()/*Ωignore_startΩ*/: ReturnType<import('svelte').Snippet>/*Ωignore_endΩ*/ => { async ()/*Ωignore_positionΩ*/ => {
;__sveltets_2_ensureSnippet(chain());
};return __sveltets_2_any(0)}; const chain3/*Ωignore_positionΩ*/ = ()/*Ωignore_startΩ*/: ReturnType<import('svelte').Snippet>/*Ωignore_endΩ*/ => { async ()/*Ωignore_positionΩ*/ => {
;__sveltets_2_ensureSnippet(chain2());
};return __sveltets_2_any(0)};
let foo = true;
;
async () => {









};
return { props: /** @type {Record<string, never>} */ ({}), exports: {}, bindings: "", slots: {}, events: {} }}
const Input__SvelteComponent_ = __sveltets_2_isomorphic_component(__sveltets_2_partial(__sveltets_2_with_any_event(render())));
/*Ωignore_startΩ*/type Input__SvelteComponent_ = InstanceType<typeof Input__SvelteComponent_>;
/*Ωignore_endΩ*/export default Input__SvelteComponent_;
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<script module lang="ts">
</script>

<script>
let foo = true;
</script>

{#snippet chain()}
<div>{foo}</div>
{/snippet}

{#snippet chain2()}
{@render chain()}
{/snippet}

{#snippet chain3()}
{@render chain2()}
{/snippet}

{#snippet hoistable()}
<h1>hoist me</h1>
{/snippet}

0 comments on commit 9b44c6d

Please sign in to comment.