diff --git a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js index 0e0dc55607..3805c15efd 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js @@ -350,7 +350,7 @@ export function client_component(analysis, options) { const push_args = [b.id('$$props'), b.literal(analysis.runes)]; if (dev) push_args.push(b.id(analysis.name)); - const component_block = b.block([ + let component_block = b.block([ ...store_setup, ...legacy_reactive_declarations, ...group_binding_declarations, @@ -362,10 +362,6 @@ export function client_component(analysis, options) { .../** @type {ESTree.Statement[]} */ (template.body) ]); - if (analysis.disposable.length > 0) { - component_block.body.push(b.stmt(b.call('$.dispose', ...analysis.disposable))); - } - if (!analysis.runes) { // Bind static exports to props so that people can access them with bind:x for (const { name, alias } of analysis.exports) { @@ -495,6 +491,16 @@ export function client_component(analysis, options) { body = [...imports, ...state.module_level_snippets, ...body]; + if (analysis.disposable.length > 0) { + component_block = b.block([ + b.declaration( + 'var', + analysis.disposable.map((id) => b.declarator(id)) + ), + b.try(component_block.body, null, [b.stmt(b.call('$.dispose', ...analysis.disposable))]) + ]); + } + const component = b.function_declaration( b.id(analysis.name), should_inject_props ? [b.id('$$anchor'), b.id('$$props')] : [b.id('$$anchor')], diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js index 5d066b0df8..a8aea14d56 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js @@ -351,14 +351,14 @@ export function VariableDeclaration(node, context) { ...node.declarations.map((declarator) => /** @type {Identifier} */ (declarator.id)) ); - if (dev) { - declarations = declarations.map((declarator) => ({ - ...declarator, - init: b.call('$.disposable', /** @type {Expression} */ (declarator.init)) - })); - } + const assignments = declarations.map((declarator) => { + let init = /** @type {Expression} */ (declarator.init); + if (dev) init = b.call('$.disposable', init); + + return b.assignment('=', declarator.id, init); + }); - kind = 'const'; + return assignments.length === 1 ? assignments[0] : b.sequence(assignments); } return { diff --git a/packages/svelte/src/compiler/utils/builders.js b/packages/svelte/src/compiler/utils/builders.js index 736738d19f..22d2c2c9af 100644 --- a/packages/svelte/src/compiler/utils/builders.js +++ b/packages/svelte/src/compiler/utils/builders.js @@ -635,6 +635,35 @@ export function throw_error(str) { }; } +/** + * @param {ESTree.Statement[]} body + * @param {ESTree.CatchClause | null} handler + * @param {ESTree.Statement[] | null} finalizer + * @returns {ESTree.TryStatement} + */ +function try_builder(body, handler, finalizer) { + return { + type: 'TryStatement', + block: block(body), + handler, + finalizer: finalizer && block(finalizer) + }; +} + +/** + * + * @param {ESTree.Pattern | null} param + * @param {ESTree.Statement[]} body + * @returns {ESTree.CatchClause} + */ +function catch_clause(param, body) { + return { + type: 'CatchClause', + param, + body: block(body) + }; +} + export { await_builder as await, let_builder as let, @@ -648,7 +677,9 @@ export { if_builder as if, this_instance as this, null_instance as null, - debugger_builder as debugger + debugger_builder as debugger, + try_builder as try, + catch_clause as catch }; /**