diff --git a/.changeset/ninety-olives-report.md b/.changeset/ninety-olives-report.md new file mode 100644 index 0000000000..3e66a41d02 --- /dev/null +++ b/.changeset/ninety-olives-report.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: replace `undefined` with `void(0)` in CallExpressions diff --git a/.changeset/wise-schools-report.md b/.changeset/wise-schools-report.md new file mode 100644 index 0000000000..47ec887256 --- /dev/null +++ b/.changeset/wise-schools-report.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: place store setup inside async body diff --git a/documentation/docs/07-misc/04-custom-elements.md b/documentation/docs/07-misc/04-custom-elements.md index 7e6a17b947..4e5afff7d2 100644 --- a/documentation/docs/07-misc/04-custom-elements.md +++ b/documentation/docs/07-misc/04-custom-elements.md @@ -4,7 +4,7 @@ title: Custom elements -Svelte components can also be compiled to custom elements (aka web components) using the `customElement: true` compiler option. You should specify a tag name for the component using the `` [element](svelte-options). +Svelte components can also be compiled to custom elements (aka web components) using the `customElement: true` compiler option. You should specify a tag name for the component using the `` [element](svelte-options). Within the custom element you can access the host element via the [`$host`](https://svelte.dev/docs/svelte/$host) rune. ```svelte 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 54e33110e2..ae8007085b 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 @@ -360,15 +360,27 @@ export function client_component(analysis, options) { let component_block = b.block([ store_init, - ...store_setup, ...legacy_reactive_declarations, ...group_binding_declarations ]); + const should_inject_context = + dev || + analysis.needs_context || + analysis.reactive_statements.size > 0 || + component_returned_object.length > 0; + if (analysis.instance.has_await) { + if (should_inject_context && component_returned_object.length > 0) { + component_block.body.push(b.var('$$exports')); + } const body = b.block([ + ...store_setup, ...state.instance_level_snippets, .../** @type {ESTree.Statement[]} */ (instance.body), + ...(should_inject_context && component_returned_object.length > 0 + ? [b.stmt(b.assignment('=', b.id('$$exports'), b.object(component_returned_object)))] + : []), b.if(b.call('$.aborted'), b.return()), .../** @type {ESTree.Statement[]} */ (template.body) ]); @@ -379,6 +391,10 @@ export function client_component(analysis, options) { ...state.instance_level_snippets, .../** @type {ESTree.Statement[]} */ (instance.body) ); + if (should_inject_context && component_returned_object.length > 0) { + component_block.body.push(b.var('$$exports', b.object(component_returned_object))); + } + component_block.body.unshift(...store_setup); if (!analysis.runes && analysis.needs_context) { component_block.body.push(b.stmt(b.call('$.init', analysis.immutable ? b.true : undefined))); @@ -393,12 +409,6 @@ export function client_component(analysis, options) { ); } - const should_inject_context = - dev || - analysis.needs_context || - analysis.reactive_statements.size > 0 || - component_returned_object.length > 0; - let should_inject_props = should_inject_context || analysis.needs_props || @@ -445,7 +455,7 @@ export function client_component(analysis, options) { let to_push; if (component_returned_object.length > 0) { - let pop_call = b.call('$.pop', b.object(component_returned_object)); + let pop_call = b.call('$.pop', b.id('$$exports')); to_push = needs_store_cleanup ? b.var('$$pop', pop_call) : b.return(pop_call); } else { to_push = b.stmt(b.call('$.pop')); @@ -456,6 +466,7 @@ export function client_component(analysis, options) { if (needs_store_cleanup) { component_block.body.push(b.stmt(b.call('$$cleanup'))); + if (component_returned_object.length > 0) { component_block.body.push(b.return(b.id('$$pop'))); } diff --git a/packages/svelte/src/compiler/utils/builders.js b/packages/svelte/src/compiler/utils/builders.js index 56a5f31ffe..03a946ff9c 100644 --- a/packages/svelte/src/compiler/utils/builders.js +++ b/packages/svelte/src/compiler/utils/builders.js @@ -100,7 +100,7 @@ export function call(callee, ...args) { if (typeof callee === 'string') callee = id(callee); args = args.slice(); - // replacing missing arguments with `undefined`, unless they're at the end in which case remove them + // replacing missing arguments with `void(0)`, unless they're at the end in which case remove them let i = args.length; let popping = true; while (i--) { @@ -108,7 +108,7 @@ export function call(callee, ...args) { if (popping) { args.pop(); } else { - args[i] = id('undefined'); + args[i] = void0; } } else { popping = false; diff --git a/packages/svelte/src/internal/client/dom/blocks/boundary.js b/packages/svelte/src/internal/client/dom/blocks/boundary.js index 1866931ef2..60fe2b7d3c 100644 --- a/packages/svelte/src/internal/client/dom/blocks/boundary.js +++ b/packages/svelte/src/internal/client/dom/blocks/boundary.js @@ -1,10 +1,5 @@ /** @import { Effect, Source, TemplateNode, } from '#client' */ -import { - BOUNDARY_EFFECT, - EFFECT_PRESERVED, - EFFECT_RAN, - EFFECT_TRANSPARENT -} from '#client/constants'; +import { BOUNDARY_EFFECT, EFFECT_PRESERVED, EFFECT_TRANSPARENT } from '#client/constants'; import { component_context, set_component_context } from '../../context.js'; import { handle_error, invoke_error_boundary } from '../../error-handling.js'; import { block, branch, destroy_effect, pause_effect } from '../../reactivity/effects.js';