diff --git a/src/compiler/compile/render_ssr/index.ts b/src/compiler/compile/render_ssr/index.ts index e256ba78fbf0..670aa9baeb3b 100644 --- a/src/compiler/compile/render_ssr/index.ts +++ b/src/compiler/compile/render_ssr/index.ts @@ -198,7 +198,7 @@ export default function ssr( instance_javascript, ...parent_bindings, css.code && b`$$result.css.add(#css);`, - main + b`return @no_current_component(() => { ${main} });` ].filter(Boolean); const css_sourcemap_enabled = check_enable_sourcemap(options.enableSourcemap, 'css'); diff --git a/src/runtime/internal/Component.ts b/src/runtime/internal/Component.ts index a8a500b25b02..c29bd68f0821 100644 --- a/src/runtime/internal/Component.ts +++ b/src/runtime/internal/Component.ts @@ -1,5 +1,5 @@ import { add_render_callback, flush, flush_render_callbacks, schedule_update, dirty_components } from './scheduler'; -import { current_component, set_current_component } from './lifecycle'; +import { current_component, no_current_component, set_current_component } from './lifecycle'; import { blank_object, is_empty, is_function, run, run_all, noop } from './utils'; import { children, detach, start_hydrating, end_hydrating } from './dom'; import { transition_in } from './transitions'; @@ -121,26 +121,29 @@ export function init(component, options, instance, create_fragment, not_equal, p ready = true; run_all($$.before_update); - // `false` as a special case of no DOM component - $$.fragment = create_fragment ? create_fragment($$.ctx) : false; - - if (options.target) { - if (options.hydrate) { - start_hydrating(); - const nodes = children(options.target); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - $$.fragment && $$.fragment!.l(nodes); - nodes.forEach(detach); - } else { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - $$.fragment && $$.fragment!.c(); - } + no_current_component(() => { + // `false` as a special case of no DOM component + $$.fragment = create_fragment ? create_fragment($$.ctx) : false; + + + if (options.target) { + if (options.hydrate) { + start_hydrating(); + const nodes = children(options.target); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + $$.fragment && $$.fragment!.l(nodes); + nodes.forEach(detach); + } else { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + $$.fragment && $$.fragment!.c(); + } - if (options.intro) transition_in(component.$$.fragment); - mount_component(component, options.target, options.anchor, options.customElement); - end_hydrating(); - flush(); - } + if (options.intro) transition_in(component.$$.fragment); + mount_component(component, options.target, options.anchor, options.customElement); + end_hydrating(); + flush(); + } + }); set_current_component(parent_component); } diff --git a/src/runtime/internal/lifecycle.ts b/src/runtime/internal/lifecycle.ts index e75bbdc501f4..a69483ac3f2c 100644 --- a/src/runtime/internal/lifecycle.ts +++ b/src/runtime/internal/lifecycle.ts @@ -11,6 +11,14 @@ export function get_current_component() { return current_component; } +export function no_current_component(callback: () => void) { + const old_current_component = current_component; + current_component = undefined; + const value = callback(); + current_component = old_current_component; + return value; +} + /** * Schedules a callback to run immediately before the component is updated after any state change. * diff --git a/test/runtime/samples/context-api-in-element-1/_config.js b/test/runtime/samples/context-api-in-element-1/_config.js new file mode 100644 index 000000000000..79b5908ab718 --- /dev/null +++ b/test/runtime/samples/context-api-in-element-1/_config.js @@ -0,0 +1,3 @@ +export default { + error: 'Function called outside component initialization' +}; diff --git a/test/runtime/samples/context-api-in-element-1/main.svelte b/test/runtime/samples/context-api-in-element-1/main.svelte new file mode 100644 index 000000000000..584d2bb05389 --- /dev/null +++ b/test/runtime/samples/context-api-in-element-1/main.svelte @@ -0,0 +1,5 @@ + + +{getContext('test')} diff --git a/test/runtime/samples/context-api-in-element-2/_config.js b/test/runtime/samples/context-api-in-element-2/_config.js new file mode 100644 index 000000000000..79b5908ab718 --- /dev/null +++ b/test/runtime/samples/context-api-in-element-2/_config.js @@ -0,0 +1,3 @@ +export default { + error: 'Function called outside component initialization' +}; diff --git a/test/runtime/samples/context-api-in-element-2/main.svelte b/test/runtime/samples/context-api-in-element-2/main.svelte new file mode 100644 index 000000000000..c852c7f5d7ad --- /dev/null +++ b/test/runtime/samples/context-api-in-element-2/main.svelte @@ -0,0 +1,5 @@ + + +xxx diff --git a/test/runtime/samples/context-api-in-element-3/_config.js b/test/runtime/samples/context-api-in-element-3/_config.js new file mode 100644 index 000000000000..79b5908ab718 --- /dev/null +++ b/test/runtime/samples/context-api-in-element-3/_config.js @@ -0,0 +1,3 @@ +export default { + error: 'Function called outside component initialization' +}; diff --git a/test/runtime/samples/context-api-in-element-3/main.svelte b/test/runtime/samples/context-api-in-element-3/main.svelte new file mode 100644 index 000000000000..04f969fff35f --- /dev/null +++ b/test/runtime/samples/context-api-in-element-3/main.svelte @@ -0,0 +1,5 @@ + + +{getContext('test')}