diff --git a/packages/svelte/src/index-client.js b/packages/svelte/src/index-client.js
index 587d766233..bd2b353395 100644
--- a/packages/svelte/src/index-client.js
+++ b/packages/svelte/src/index-client.js
@@ -1,12 +1,13 @@
/** @import { ComponentContext, ComponentContextLegacy } from '#client' */
/** @import { EventDispatcher } from './index.js' */
/** @import { NotFunction } from './internal/types.js' */
-import { component_context, flush_sync, untrack } from './internal/client/runtime.js';
+import { flush_sync, untrack } from './internal/client/runtime.js';
import { is_array } from './internal/shared/utils.js';
import { user_effect } from './internal/client/index.js';
import * as e from './internal/client/errors.js';
import { lifecycle_outside_component } from './internal/shared/errors.js';
import { legacy_mode_flag } from './internal/flags/index.js';
+import { component_context } from './internal/client/context.js';
/**
* The `onMount` function schedules a callback to run as soon as the component has been mounted to the DOM.
@@ -179,15 +180,7 @@ export function flushSync(fn) {
flush_sync(fn);
}
+export { getContext, getAllContexts, hasContext, setContext } from './internal/client/context.js';
export { hydrate, mount, unmount } from './internal/client/render.js';
-
-export {
- getContext,
- getAllContexts,
- hasContext,
- setContext,
- tick,
- untrack
-} from './internal/client/runtime.js';
-
+export { tick, untrack } from './internal/client/runtime.js';
export { createRawSnippet } from './internal/client/dom/blocks/snippet.js';
diff --git a/packages/svelte/src/internal/client/context.js b/packages/svelte/src/internal/client/context.js
new file mode 100644
index 0000000000..1d7f0747cd
--- /dev/null
+++ b/packages/svelte/src/internal/client/context.js
@@ -0,0 +1,214 @@
+/** @import { ComponentContext } from '#client' */
+
+import { DEV } from 'esm-env';
+import { add_owner } from './dev/ownership.js';
+import { lifecycle_outside_component } from '../shared/errors.js';
+import { source } from './reactivity/sources.js';
+import {
+ active_effect,
+ active_reaction,
+ set_active_effect,
+ set_active_reaction
+} from './runtime.js';
+import { effect } from './reactivity/effects.js';
+import { legacy_mode_flag } from '../flags/index.js';
+
+/** @type {ComponentContext | null} */
+export let component_context = null;
+
+/** @param {ComponentContext | null} context */
+export function set_component_context(context) {
+ component_context = context;
+}
+
+/**
+ * The current component function. Different from current component context:
+ * ```html
+ *
+ *
+ *
+ *
+ * ```
+ * @type {ComponentContext['function']}
+ */
+export let dev_current_component_function = null;
+
+/** @param {ComponentContext['function']} fn */
+export function set_dev_current_component_function(fn) {
+ dev_current_component_function = fn;
+}
+
+/**
+ * Retrieves the context that belongs to the closest parent component with the specified `key`.
+ * Must be called during component initialisation.
+ *
+ * @template T
+ * @param {any} key
+ * @returns {T}
+ */
+export function getContext(key) {
+ const context_map = get_or_init_context_map('getContext');
+ const result = /** @type {T} */ (context_map.get(key));
+
+ if (DEV) {
+ const fn = /** @type {ComponentContext} */ (component_context).function;
+ if (fn) {
+ add_owner(result, fn, true);
+ }
+ }
+
+ return result;
+}
+
+/**
+ * Associates an arbitrary `context` object with the current component and the specified `key`
+ * and returns that object. The context is then available to children of the component
+ * (including slotted content) with `getContext`.
+ *
+ * Like lifecycle functions, this must be called during component initialisation.
+ *
+ * @template T
+ * @param {any} key
+ * @param {T} context
+ * @returns {T}
+ */
+export function setContext(key, context) {
+ const context_map = get_or_init_context_map('setContext');
+ context_map.set(key, context);
+ return context;
+}
+
+/**
+ * Checks whether a given `key` has been set in the context of a parent component.
+ * Must be called during component initialisation.
+ *
+ * @param {any} key
+ * @returns {boolean}
+ */
+export function hasContext(key) {
+ const context_map = get_or_init_context_map('hasContext');
+ return context_map.has(key);
+}
+
+/**
+ * Retrieves the whole context map that belongs to the closest parent component.
+ * Must be called during component initialisation. Useful, for example, if you
+ * programmatically create a component and want to pass the existing context to it.
+ *
+ * @template {Map} [T=Map]
+ * @returns {T}
+ */
+export function getAllContexts() {
+ const context_map = get_or_init_context_map('getAllContexts');
+
+ if (DEV) {
+ const fn = component_context?.function;
+ if (fn) {
+ for (const value of context_map.values()) {
+ add_owner(value, fn, true);
+ }
+ }
+ }
+
+ return /** @type {T} */ (context_map);
+}
+
+/**
+ * @param {Record} props
+ * @param {any} runes
+ * @param {Function} [fn]
+ * @returns {void}
+ */
+export function push(props, runes = false, fn) {
+ component_context = {
+ p: component_context,
+ c: null,
+ e: null,
+ m: false,
+ s: props,
+ x: null,
+ l: null
+ };
+
+ if (legacy_mode_flag && !runes) {
+ component_context.l = {
+ s: null,
+ u: null,
+ r1: [],
+ r2: source(false)
+ };
+ }
+
+ if (DEV) {
+ // component function
+ component_context.function = fn;
+ dev_current_component_function = fn;
+ }
+}
+
+/**
+ * @template {Record} T
+ * @param {T} [component]
+ * @returns {T}
+ */
+export function pop(component) {
+ const context_stack_item = component_context;
+ if (context_stack_item !== null) {
+ if (component !== undefined) {
+ context_stack_item.x = component;
+ }
+ const component_effects = context_stack_item.e;
+ if (component_effects !== null) {
+ var previous_effect = active_effect;
+ var previous_reaction = active_reaction;
+ context_stack_item.e = null;
+ try {
+ for (var i = 0; i < component_effects.length; i++) {
+ var component_effect = component_effects[i];
+ set_active_effect(component_effect.effect);
+ set_active_reaction(component_effect.reaction);
+ effect(component_effect.fn);
+ }
+ } finally {
+ set_active_effect(previous_effect);
+ set_active_reaction(previous_reaction);
+ }
+ }
+ component_context = context_stack_item.p;
+ if (DEV) {
+ dev_current_component_function = context_stack_item.p?.function ?? null;
+ }
+ context_stack_item.m = true;
+ }
+ // Micro-optimization: Don't set .a above to the empty object
+ // so it can be garbage-collected when the return here is unused
+ return component || /** @type {T} */ ({});
+}
+
+/**
+ * @param {string} name
+ * @returns {Map}
+ */
+function get_or_init_context_map(name) {
+ if (component_context === null) {
+ lifecycle_outside_component(name);
+ }
+
+ return (component_context.c ??= new Map(get_parent_context(component_context) || undefined));
+}
+
+/**
+ * @param {ComponentContext} component_context
+ * @returns {Map | null}
+ */
+function get_parent_context(component_context) {
+ let parent = component_context.p;
+ while (parent !== null) {
+ const context_map = parent.c;
+ if (context_map !== null) {
+ return context_map;
+ }
+ parent = parent.p;
+ }
+ return null;
+}
diff --git a/packages/svelte/src/internal/client/dev/legacy.js b/packages/svelte/src/internal/client/dev/legacy.js
index a1d2fc8823..138213c551 100644
--- a/packages/svelte/src/internal/client/dev/legacy.js
+++ b/packages/svelte/src/internal/client/dev/legacy.js
@@ -1,5 +1,5 @@
import * as e from '../errors.js';
-import { component_context } from '../runtime.js';
+import { component_context } from '../context.js';
import { FILENAME } from '../../../constants.js';
import { get_component } from './ownership.js';
diff --git a/packages/svelte/src/internal/client/dev/ownership.js b/packages/svelte/src/internal/client/dev/ownership.js
index d113d9ae90..70cfbb47f3 100644
--- a/packages/svelte/src/internal/client/dev/ownership.js
+++ b/packages/svelte/src/internal/client/dev/ownership.js
@@ -3,7 +3,7 @@
import { STATE_SYMBOL_METADATA } from '../constants.js';
import { render_effect, user_pre_effect } from '../reactivity/effects.js';
-import { dev_current_component_function } from '../runtime.js';
+import { dev_current_component_function } from '../context.js';
import { get_prototype_of } from '../../shared/utils.js';
import * as w from '../warnings.js';
import { FILENAME } from '../../../constants.js';
diff --git a/packages/svelte/src/internal/client/dom/blocks/await.js b/packages/svelte/src/internal/client/dom/blocks/await.js
index 62b2e4dd0c..633a6e5bab 100644
--- a/packages/svelte/src/internal/client/dom/blocks/await.js
+++ b/packages/svelte/src/internal/client/dom/blocks/await.js
@@ -3,18 +3,15 @@ import { DEV } from 'esm-env';
import { is_promise } from '../../../shared/utils.js';
import { block, branch, pause_effect, resume_effect } from '../../reactivity/effects.js';
import { internal_set, mutable_source, source } from '../../reactivity/sources.js';
+import { flush_sync, is_runes, set_active_effect, set_active_reaction } from '../../runtime.js';
+import { hydrate_next, hydrate_node, hydrating } from '../hydration.js';
+import { queue_micro_task } from '../task.js';
+import { UNINITIALIZED } from '../../../../constants.js';
import {
component_context,
- flush_sync,
- is_runes,
- set_active_effect,
- set_active_reaction,
set_component_context,
set_dev_current_component_function
-} from '../../runtime.js';
-import { hydrate_next, hydrate_node, hydrating } from '../hydration.js';
-import { queue_micro_task } from '../task.js';
-import { UNINITIALIZED } from '../../../../constants.js';
+} from '../../context.js';
const PENDING = 0;
const THEN = 1;
diff --git a/packages/svelte/src/internal/client/dom/blocks/boundary.js b/packages/svelte/src/internal/client/dom/blocks/boundary.js
index 7f4f000dce..c1ca7a9600 100644
--- a/packages/svelte/src/internal/client/dom/blocks/boundary.js
+++ b/packages/svelte/src/internal/client/dom/blocks/boundary.js
@@ -1,15 +1,14 @@
/** @import { Effect, TemplateNode, } from '#client' */
import { BOUNDARY_EFFECT, EFFECT_TRANSPARENT } from '../../constants.js';
+import { component_context, set_component_context } from '../../context.js';
import { block, branch, destroy_effect, pause_effect } from '../../reactivity/effects.js';
import {
active_effect,
active_reaction,
- component_context,
handle_error,
set_active_effect,
set_active_reaction,
- set_component_context,
reset_is_throwing_error
} from '../../runtime.js';
import {
diff --git a/packages/svelte/src/internal/client/dom/blocks/html.js b/packages/svelte/src/internal/client/dom/blocks/html.js
index 04ab0aee87..b3fc5a9c72 100644
--- a/packages/svelte/src/internal/client/dom/blocks/html.js
+++ b/packages/svelte/src/internal/client/dom/blocks/html.js
@@ -7,7 +7,7 @@ import { assign_nodes } from '../template.js';
import * as w from '../../warnings.js';
import { hash, sanitize_location } from '../../../../utils.js';
import { DEV } from 'esm-env';
-import { dev_current_component_function } from '../../runtime.js';
+import { dev_current_component_function } from '../../context.js';
import { get_first_child, get_next_sibling } from '../operations.js';
/**
diff --git a/packages/svelte/src/internal/client/dom/blocks/snippet.js b/packages/svelte/src/internal/client/dom/blocks/snippet.js
index cec57f83b7..b916a02ce5 100644
--- a/packages/svelte/src/internal/client/dom/blocks/snippet.js
+++ b/packages/svelte/src/internal/client/dom/blocks/snippet.js
@@ -6,7 +6,7 @@ import { branch, block, destroy_effect, teardown } from '../../reactivity/effect
import {
dev_current_component_function,
set_dev_current_component_function
-} from '../../runtime.js';
+} from '../../context.js';
import { hydrate_next, hydrate_node, hydrating } from '../hydration.js';
import { create_fragment_from_html } from '../reconciler.js';
import { assign_nodes } from '../template.js';
diff --git a/packages/svelte/src/internal/client/dom/blocks/svelte-element.js b/packages/svelte/src/internal/client/dom/blocks/svelte-element.js
index 35d2f223ae..18641300e5 100644
--- a/packages/svelte/src/internal/client/dom/blocks/svelte-element.js
+++ b/packages/svelte/src/internal/client/dom/blocks/svelte-element.js
@@ -17,7 +17,8 @@ import {
} from '../../reactivity/effects.js';
import { set_should_intro } from '../../render.js';
import { current_each_item, set_current_each_item } from './each.js';
-import { component_context, active_effect } from '../../runtime.js';
+import { active_effect } from '../../runtime.js';
+import { component_context } from '../../context.js';
import { DEV } from 'esm-env';
import { EFFECT_TRANSPARENT } from '../../constants.js';
import { assign_nodes } from '../template.js';
diff --git a/packages/svelte/src/internal/client/dom/legacy/lifecycle.js b/packages/svelte/src/internal/client/dom/legacy/lifecycle.js
index 5ffbacc670..a564712f04 100644
--- a/packages/svelte/src/internal/client/dom/legacy/lifecycle.js
+++ b/packages/svelte/src/internal/client/dom/legacy/lifecycle.js
@@ -1,8 +1,9 @@
/** @import { ComponentContextLegacy } from '#client' */
import { run, run_all } from '../../../shared/utils.js';
+import { component_context } from '../../context.js';
import { derived } from '../../reactivity/deriveds.js';
import { user_pre_effect, user_effect } from '../../reactivity/effects.js';
-import { component_context, deep_read_state, get, untrack } from '../../runtime.js';
+import { deep_read_state, get, untrack } from '../../runtime.js';
/**
* Legacy-mode only: Call `onMount` callbacks and set up `beforeUpdate`/`afterUpdate` effects
diff --git a/packages/svelte/src/internal/client/index.js b/packages/svelte/src/internal/client/index.js
index 2bf58c51f7..877f3c59ee 100644
--- a/packages/svelte/src/internal/client/index.js
+++ b/packages/svelte/src/internal/client/index.js
@@ -1,4 +1,5 @@
export { FILENAME, HMR, NAMESPACE_SVG } from '../../constants.js';
+export { push, pop } from './context.js';
export { assign, assign_and, assign_or, assign_nullish } from './dev/assign.js';
export { cleanup_styles } from './dev/css.js';
export { add_locations } from './dev/elements.js';
@@ -141,14 +142,8 @@ export {
update,
update_pre,
exclude_from_object,
- pop,
- push,
deep_read,
- deep_read_state,
- getAllContexts,
- getContext,
- setContext,
- hasContext
+ deep_read_state
} from './runtime.js';
export { validate_binding, validate_each_keys } from './validate.js';
export { raf } from './timing.js';
diff --git a/packages/svelte/src/internal/client/proxy.js b/packages/svelte/src/internal/client/proxy.js
index 6cbd6394df..4c262880f1 100644
--- a/packages/svelte/src/internal/client/proxy.js
+++ b/packages/svelte/src/internal/client/proxy.js
@@ -1,6 +1,7 @@
-/** @import { ProxyMetadata, ProxyStateObject, Source } from '#client' */
+/** @import { ProxyMetadata, Source } from '#client' */
import { DEV } from 'esm-env';
-import { get, component_context, active_effect } from './runtime.js';
+import { get, active_effect } from './runtime.js';
+import { component_context } from './context.js';
import {
array_prototype,
get_descriptor,
diff --git a/packages/svelte/src/internal/client/reactivity/deriveds.js b/packages/svelte/src/internal/client/reactivity/deriveds.js
index da5a75eb6e..e86963408c 100644
--- a/packages/svelte/src/internal/client/reactivity/deriveds.js
+++ b/packages/svelte/src/internal/client/reactivity/deriveds.js
@@ -17,8 +17,7 @@ import {
skip_reaction,
update_reaction,
increment_write_version,
- set_active_effect,
- component_context
+ set_active_effect
} from '../runtime.js';
import { equals, safe_equals } from './equality.js';
import * as e from '../errors.js';
@@ -26,6 +25,7 @@ import { destroy_effect } from './effects.js';
import { inspect_effects, set_inspect_effects } from './sources.js';
import { get_stack } from '../dev/tracing.js';
import { tracing_mode_flag } from '../../flags/index.js';
+import { component_context } from '../context.js';
/**
* @template V
diff --git a/packages/svelte/src/internal/client/reactivity/effects.js b/packages/svelte/src/internal/client/reactivity/effects.js
index 1faf9a47a0..8a7cffecd6 100644
--- a/packages/svelte/src/internal/client/reactivity/effects.js
+++ b/packages/svelte/src/internal/client/reactivity/effects.js
@@ -1,10 +1,8 @@
/** @import { ComponentContext, ComponentContextLegacy, Derived, Effect, TemplateNode, TransitionManager } from '#client' */
import {
check_dirtiness,
- component_context,
active_effect,
active_reaction,
- dev_current_component_function,
update_effect,
get,
is_destroying_effect,
@@ -45,6 +43,7 @@ import { DEV } from 'esm-env';
import { define_property } from '../../shared/utils.js';
import { get_next_sibling } from '../dom/operations.js';
import { derived, destroy_derived } from './deriveds.js';
+import { component_context, dev_current_component_function } from '../context.js';
/**
* @param {'$effect' | '$effect.pre' | '$inspect'} rune
diff --git a/packages/svelte/src/internal/client/reactivity/sources.js b/packages/svelte/src/internal/client/reactivity/sources.js
index c2448c9ee5..b3e66a3336 100644
--- a/packages/svelte/src/internal/client/reactivity/sources.js
+++ b/packages/svelte/src/internal/client/reactivity/sources.js
@@ -1,7 +1,6 @@
/** @import { Derived, Effect, Reaction, Source, Value } from '#client' */
import { DEV } from 'esm-env';
import {
- component_context,
active_reaction,
active_effect,
untracked_writes,
@@ -35,6 +34,7 @@ import {
import * as e from '../errors.js';
import { legacy_mode_flag, tracing_mode_flag } from '../../flags/index.js';
import { get_stack } from '../dev/tracing.js';
+import { component_context } from '../context.js';
export let inspect_effects = new Set();
diff --git a/packages/svelte/src/internal/client/render.js b/packages/svelte/src/internal/client/render.js
index 767b230131..bc74047f64 100644
--- a/packages/svelte/src/internal/client/render.js
+++ b/packages/svelte/src/internal/client/render.js
@@ -9,7 +9,8 @@ import {
init_operations
} from './dom/operations.js';
import { HYDRATION_END, HYDRATION_ERROR, HYDRATION_START } from '../../constants.js';
-import { push, pop, component_context, active_effect } from './runtime.js';
+import { active_effect } from './runtime.js';
+import { push, pop, component_context } from './context.js';
import { component_root, branch } from './reactivity/effects.js';
import {
hydrate_next,
diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js
index a002665b51..859925186f 100644
--- a/packages/svelte/src/internal/client/runtime.js
+++ b/packages/svelte/src/internal/client/runtime.js
@@ -5,7 +5,6 @@ import {
destroy_block_effect_children,
destroy_effect_children,
destroy_effect_deriveds,
- effect,
execute_effect_teardown,
unlink_effect
} from './reactivity/effects.js';
@@ -28,14 +27,18 @@ import {
BOUNDARY_EFFECT
} from './constants.js';
import { flush_tasks } from './dom/task.js';
-import { add_owner } from './dev/ownership.js';
-import { internal_set, set, source } from './reactivity/sources.js';
+import { internal_set, set } from './reactivity/sources.js';
import { destroy_derived, execute_derived, update_derived } from './reactivity/deriveds.js';
import * as e from './errors.js';
-import { lifecycle_outside_component } from '../shared/errors.js';
import { FILENAME } from '../../constants.js';
import { legacy_mode_flag, tracing_mode_flag } from '../flags/index.js';
import { tracing_expressions, get_stack } from './dev/tracing.js';
+import {
+ component_context,
+ dev_current_component_function,
+ set_component_context,
+ set_dev_current_component_function
+} from './context.js';
const FLUSH_MICROTASK = 0;
const FLUSH_SYNC = 1;
@@ -150,32 +153,6 @@ export function set_captured_signals(value) {
captured_signals = value;
}
-// Handling runtime component context
-/** @type {ComponentContext | null} */
-export let component_context = null;
-
-/** @param {ComponentContext | null} context */
-export function set_component_context(context) {
- component_context = context;
-}
-
-/**
- * The current component function. Different from current component context:
- * ```html
- *
- *
- *
- *
- * ```
- * @type {ComponentContext['function']}
- */
-export let dev_current_component_function = null;
-
-/** @param {ComponentContext['function']} fn */
-export function set_dev_current_component_function(fn) {
- dev_current_component_function = fn;
-}
-
export function increment_write_version() {
return ++write_version;
}
@@ -434,7 +411,7 @@ export function update_reaction(reaction) {
active_reaction = (flags & (BRANCH_EFFECT | ROOT_EFFECT)) === 0 ? reaction : null;
skip_reaction = !is_flushing_effect && (flags & UNOWNED) !== 0;
derived_sources = null;
- component_context = reaction.ctx;
+ set_component_context(reaction.ctx);
untracking = false;
read_version++;
@@ -498,7 +475,7 @@ export function update_reaction(reaction) {
active_reaction = previous_reaction;
skip_reaction = previous_skip_reaction;
derived_sources = prev_derived_sources;
- component_context = previous_component_context;
+ set_component_context(previous_component_context);
untracking = previous_untracking;
}
}
@@ -578,7 +555,7 @@ export function update_effect(effect) {
if (DEV) {
var previous_component_fn = dev_current_component_function;
- dev_current_component_function = effect.component_function;
+ set_dev_current_component_function(effect.component_function);
}
try {
@@ -620,7 +597,7 @@ export function update_effect(effect) {
active_effect = previous_effect;
if (DEV) {
- dev_current_component_function = previous_component_fn;
+ set_dev_current_component_function(previous_component_fn);
}
}
}
@@ -1114,109 +1091,6 @@ export function set_signal_status(signal, status) {
signal.f = (signal.f & STATUS_MASK) | status;
}
-/**
- * Retrieves the context that belongs to the closest parent component with the specified `key`.
- * Must be called during component initialisation.
- *
- * @template T
- * @param {any} key
- * @returns {T}
- */
-export function getContext(key) {
- const context_map = get_or_init_context_map('getContext');
- const result = /** @type {T} */ (context_map.get(key));
-
- if (DEV) {
- const fn = /** @type {ComponentContext} */ (component_context).function;
- if (fn) {
- add_owner(result, fn, true);
- }
- }
-
- return result;
-}
-
-/**
- * Associates an arbitrary `context` object with the current component and the specified `key`
- * and returns that object. The context is then available to children of the component
- * (including slotted content) with `getContext`.
- *
- * Like lifecycle functions, this must be called during component initialisation.
- *
- * @template T
- * @param {any} key
- * @param {T} context
- * @returns {T}
- */
-export function setContext(key, context) {
- const context_map = get_or_init_context_map('setContext');
- context_map.set(key, context);
- return context;
-}
-
-/**
- * Checks whether a given `key` has been set in the context of a parent component.
- * Must be called during component initialisation.
- *
- * @param {any} key
- * @returns {boolean}
- */
-export function hasContext(key) {
- const context_map = get_or_init_context_map('hasContext');
- return context_map.has(key);
-}
-
-/**
- * Retrieves the whole context map that belongs to the closest parent component.
- * Must be called during component initialisation. Useful, for example, if you
- * programmatically create a component and want to pass the existing context to it.
- *
- * @template {Map} [T=Map]
- * @returns {T}
- */
-export function getAllContexts() {
- const context_map = get_or_init_context_map('getAllContexts');
-
- if (DEV) {
- const fn = component_context?.function;
- if (fn) {
- for (const value of context_map.values()) {
- add_owner(value, fn, true);
- }
- }
- }
-
- return /** @type {T} */ (context_map);
-}
-
-/**
- * @param {string} name
- * @returns {Map}
- */
-function get_or_init_context_map(name) {
- if (component_context === null) {
- lifecycle_outside_component(name);
- }
-
- return (component_context.c ??= new Map(get_parent_context(component_context) || undefined));
-}
-
-/**
- * @param {ComponentContext} component_context
- * @returns {Map | null}
- */
-function get_parent_context(component_context) {
- let parent = component_context.p;
- while (parent !== null) {
- const context_map = parent.c;
- if (context_map !== null) {
- return context_map;
- }
- parent = parent.p;
- }
- return null;
-}
-
/**
* @template {number | bigint} T
* @param {Value} signal
@@ -1264,78 +1138,6 @@ export function exclude_from_object(obj, keys) {
return result;
}
-/**
- * @param {Record} props
- * @param {any} runes
- * @param {Function} [fn]
- * @returns {void}
- */
-export function push(props, runes = false, fn) {
- component_context = {
- p: component_context,
- c: null,
- e: null,
- m: false,
- s: props,
- x: null,
- l: null
- };
-
- if (legacy_mode_flag && !runes) {
- component_context.l = {
- s: null,
- u: null,
- r1: [],
- r2: source(false)
- };
- }
-
- if (DEV) {
- // component function
- component_context.function = fn;
- dev_current_component_function = fn;
- }
-}
-
-/**
- * @template {Record} T
- * @param {T} [component]
- * @returns {T}
- */
-export function pop(component) {
- const context_stack_item = component_context;
- if (context_stack_item !== null) {
- if (component !== undefined) {
- context_stack_item.x = component;
- }
- const component_effects = context_stack_item.e;
- if (component_effects !== null) {
- var previous_effect = active_effect;
- var previous_reaction = active_reaction;
- context_stack_item.e = null;
- try {
- for (var i = 0; i < component_effects.length; i++) {
- var component_effect = component_effects[i];
- set_active_effect(component_effect.effect);
- set_active_reaction(component_effect.reaction);
- effect(component_effect.fn);
- }
- } finally {
- set_active_effect(previous_effect);
- set_active_reaction(previous_reaction);
- }
- }
- component_context = context_stack_item.p;
- if (DEV) {
- dev_current_component_function = context_stack_item.p?.function ?? null;
- }
- context_stack_item.m = true;
- }
- // Micro-optimization: Don't set .a above to the empty object
- // so it can be garbage-collected when the return here is unused
- return component || /** @type {T} */ ({});
-}
-
/**
* Possibly traverse an object and read all its properties so that they're all reactive in case this is `$state`.
* Does only check first level of an object for performance reasons (heuristic should be good for 99% of all cases).
diff --git a/packages/svelte/src/internal/client/validate.js b/packages/svelte/src/internal/client/validate.js
index 24e280edf8..ec3d805447 100644
--- a/packages/svelte/src/internal/client/validate.js
+++ b/packages/svelte/src/internal/client/validate.js
@@ -1,4 +1,4 @@
-import { dev_current_component_function } from './runtime.js';
+import { dev_current_component_function } from './context.js';
import { is_array } from '../shared/utils.js';
import * as e from './errors.js';
import { FILENAME } from '../../constants.js';
diff --git a/packages/svelte/src/legacy/legacy-client.js b/packages/svelte/src/legacy/legacy-client.js
index 3715617f4c..3a05bc0496 100644
--- a/packages/svelte/src/legacy/legacy-client.js
+++ b/packages/svelte/src/legacy/legacy-client.js
@@ -3,19 +3,13 @@ import { DIRTY, LEGACY_PROPS, MAYBE_DIRTY } from '../internal/client/constants.j
import { user_pre_effect } from '../internal/client/reactivity/effects.js';
import { mutable_source, set } from '../internal/client/reactivity/sources.js';
import { hydrate, mount, unmount } from '../internal/client/render.js';
-import {
- active_effect,
- component_context,
- dev_current_component_function,
- flush_sync,
- get,
- set_signal_status
-} from '../internal/client/runtime.js';
+import { active_effect, flush_sync, get, set_signal_status } from '../internal/client/runtime.js';
import { lifecycle_outside_component } from '../internal/shared/errors.js';
import { define_property, is_array } from '../internal/shared/utils.js';
import * as w from '../internal/client/warnings.js';
import { DEV } from 'esm-env';
import { FILENAME } from '../constants.js';
+import { component_context, dev_current_component_function } from '../internal/client/context.js';
/**
* Takes the same options as a Svelte 4 component and the component function and returns a Svelte 4 compatible component.
diff --git a/packages/svelte/tests/signals/test.ts b/packages/svelte/tests/signals/test.ts
index 5f0b93e136..aa1dbf3132 100644
--- a/packages/svelte/tests/signals/test.ts
+++ b/packages/svelte/tests/signals/test.ts
@@ -1,6 +1,7 @@
import { describe, assert, it } from 'vitest';
import { flushSync } from '../../src/index-client';
import * as $ from '../../src/internal/client/runtime';
+import { push, pop } from '../../src/internal/client/context';
import {
effect,
effect_root,
@@ -22,13 +23,13 @@ import { SvelteSet } from '../../src/reactivity/set';
function run_test(runes: boolean, fn: (runes: boolean) => () => void) {
return () => {
// Create a component context to test runes vs legacy mode
- $.push({}, runes);
+ push({}, runes);
// Create a render context so that effect validations etc don't fail
let execute: any;
const destroy = effect_root(() => {
execute = fn(runes);
});
- $.pop();
+ pop();
execute();
destroy();
};
diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts
index d00b2b01ed..eb3e93e4b5 100644
--- a/packages/svelte/types/index.d.ts
+++ b/packages/svelte/types/index.d.ts
@@ -421,6 +421,34 @@ declare module 'svelte' {
}): Snippet;
/** Anything except a function */
type NotFunction = T extends Function ? never : T;
+ /**
+ * Retrieves the context that belongs to the closest parent component with the specified `key`.
+ * Must be called during component initialisation.
+ *
+ * */
+ export function getContext(key: any): T;
+ /**
+ * Associates an arbitrary `context` object with the current component and the specified `key`
+ * and returns that object. The context is then available to children of the component
+ * (including slotted content) with `getContext`.
+ *
+ * Like lifecycle functions, this must be called during component initialisation.
+ *
+ * */
+ export function setContext(key: any, context: T): T;
+ /**
+ * Checks whether a given `key` has been set in the context of a parent component.
+ * Must be called during component initialisation.
+ *
+ * */
+ export function hasContext(key: any): boolean;
+ /**
+ * Retrieves the whole context map that belongs to the closest parent component.
+ * Must be called during component initialisation. Useful, for example, if you
+ * programmatically create a component and want to pass the existing context to it.
+ *
+ * */
+ export function getAllContexts = Map>(): T;
/**
* Mounts a component to the given target and returns the exports and potentially the props (if compiled with `accessors: true`) of the component.
* Transitions will play during the initial render unless the `intro` option is set to `false`.
@@ -484,34 +512,6 @@ declare module 'svelte' {
* ```
* */
export function untrack(fn: () => T): T;
- /**
- * Retrieves the context that belongs to the closest parent component with the specified `key`.
- * Must be called during component initialisation.
- *
- * */
- export function getContext(key: any): T;
- /**
- * Associates an arbitrary `context` object with the current component and the specified `key`
- * and returns that object. The context is then available to children of the component
- * (including slotted content) with `getContext`.
- *
- * Like lifecycle functions, this must be called during component initialisation.
- *
- * */
- export function setContext(key: any, context: T): T;
- /**
- * Checks whether a given `key` has been set in the context of a parent component.
- * Must be called during component initialisation.
- *
- * */
- export function hasContext(key: any): boolean;
- /**
- * Retrieves the whole context map that belongs to the closest parent component.
- * Must be called during component initialisation. Useful, for example, if you
- * programmatically create a component and want to pass the existing context to it.
- *
- * */
- export function getAllContexts = Map>(): T;
type Getters = {
[K in keyof T]: () => T[K];
};