Skip to content

Instantly share code, notes, and snippets.

@faraazahmad
Created September 8, 2025 07:09
Show Gist options
  • Save faraazahmad/652830ed08bc0ac25aec56915c9658ec to your computer and use it in GitHub Desktop.
Save faraazahmad/652830ed08bc0ac25aec56915c9658ec to your computer and use it in GitHub Desktop.

User

Get all functions that manage state.

Assistant

I'll help you find all functions that manage state in the Svelte project. Let me search through the codebase to identify these functions.

Tool Call: Search files for regex function.*state|state.*function|setState|getState|updateState|manageState Status: Completed

Showing matches 1-20 (there were more matches found; use offset: 20 to see next page):

Matches in svelte/documentation/docs/02-runes/02-$state.md

L17-18

Unlike other frameworks you may have encountered, there is no API for interacting with state — `count` is just a number, rather than an object or a function, and you can update it like you would update any other variable.

## Passing state into functions › L167-168

## Passing state into functions

Matches in svelte/documentation/docs/02-runes/03-$derived.md

L51-52

Anything read synchronously inside the `$derived` expression (or `$derived.by` function body) is considered a _dependency_ of the derived state. When the state changes, the derived will be marked as _dirty_ and recalculated when it is next read.

Matches in svelte/documentation/docs/02-runes/04-$effect.md

L5-6

Effects are functions that run when state updates, and can be used for things like calling third-party libraries, drawing on `<canvas>` elements, or making network requests. They only run in the browser, not during server-side rendering.

L31-32

When Svelte runs an effect function, it tracks which pieces of state (and derived state) are accessed (unless accessed inside [`untrack`](svelte#untrack)), and re-runs the function when that state later changes.

L75-76

`$effect` automatically picks up any reactive values (`$state`, `$derived`, `$props`) that are _synchronously_ read inside its function body (including indirectly, via function calls) and registers them as dependencies. When those dependencies change, the `$effect` schedules a re-run.

Matches in svelte/documentation/docs/02-runes/07-$inspect.md

L48-49

This rune, added in 5.14, causes the surrounding function to be _traced_ in development. Any time the function re-runs as part of an [effect]($effect) or a [derived]($derived), information will be printed to the console about which pieces of reactive state caused the effect to fire.

L51-60

<script>
	import { doSomeWork } from './elsewhere';

	$effect(() => {
		+++// $inspect.trace must be the first statement of a function body+++
		+++$inspect.trace();+++
		doSomeWork();
	});
</script>

## Matches in svelte/documentation/docs/03-template-syntax/[email protected]

### L5-6

Attachments are functions that run in an effect when an element is mounted to the DOM or when state read inside the function updates.


### L60-61

Since the tooltip(content) expression runs inside an effect, the attachment will be destroyed and recreated whenever content changes. The same thing would happen for any state read inside the attachment function when it first runs. (If this isn't what you want, see Controlling when attachments re-run.)


## Matches in svelte/documentation/docs/03-template-syntax/13-use.md

### L8-9

Actions are functions that are called when an element is mounted. They are added with the use: directive, and will typically use an $effect so that they can reset any state when the element is unmounted:


## Matches in svelte/documentation/docs/03-template-syntax/14-transition.md

### L71-72

The t argument passed to css is a value between 0 and 1 after the easing function has been applied. In transitions run from 0 to 1, out transitions run from 1 to 0 — in other words, 1 is the element's natural state, as though no transition had been applied. The u argument is equal to 1 - t.


## Matches in svelte/documentation/docs/07-misc/07-v5-migration-guide.md

### L482-483

You may see that the migration script converts some of your $: statements to a run function which is imported from svelte/legacy. This happens if the migration script couldn't reliably migrate the statement to a $derived and concluded this is a side effect instead. In some cases this may be wrong and it's best to change this to use a $derived instead. In other cases it may be right, but since $: statements also ran on the server but $effect does not, it isn't safe to transform it as such. Instead, run is used as a stopgap solution. run mimics most of the characteristics of $:, in that it runs on the server once, and runs as $effect.pre on the client ($effect.pre runs before changes are applied to the DOM; most likely you want to use $effect instead).


## Matches in svelte/documentation/docs/98-reference/.generated/compile-errors.md

### L340-341

Cannot export derived state from a module. To expose the current derived value, export a function returning its value

L522-523

`$inspect.trace(...)` must be the first statement of a function body

### L884-885

Cannot export state from a module if it is reassigned. Either export a function returning the state value or only mutate the state value's properties

Matches in svelte/documentation/docs/98-reference/.generated/compile-warnings.md

L868-869

This 'breaks the link' to the original state declaration. For example, if you pass the state to a function, the function loses access to the state once it is reassigned:

L926-927

For more info, see [Passing state into functions]($state#Passing-state-into-functions).

Matches in svelte/documentation/docs/99-legacy/02-legacy-reactive-assignments.md

L7-8

In legacy mode, any top-level statement (i.e. not inside a block or a function) can be made reactive by prefixing it with a `$:` [label](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label). These statements run after other code in the `<script>` and before the component markup is rendered, then whenever the values that they depend on change.

Matches in svelte/packages/svelte/CHANGELOG-pre-5.md

L969-970

- Don't crash when using an arrow function as a statement ([#4617](https://github.com/sveltejs/svelte/issues/4617))
- Deconflict `bind:this` variable ([#4636](https://github.com/sveltejs/svelte/issues/4636))

Assistant

Let me search more specifically for function definitions that handle state management:

Tool Call: Search files for regex function\s+\w*[sS]tate|export\s+function.*[sS]tate|\$state|\$derived|\$effect Status: Completed

Showing matches 1-20 (there were more matches found; use offset: 20 to see next page):

Matches in svelte/packages/svelte/src/compiler/errors.js

L162-166

/**
 * `$effect()` can only be used as an expression statement
 * @param {null | number | NodeLike} node
 * @returns {never}
 */

function effect_invalid_placement( ) › L167-169

export function effect_invalid_placement(node) {
	e(node, 'effect_invalid_placement', `\`$effect()\` can only be used as an expression statement\nhttps://svelte.dev/e/effect_invalid_placement`);
}

L254-258

/**
 * `$:` is not allowed in runes mode, use `$derived` or `$effect` instead
 * @param {null | number | NodeLike} node
 * @returns {never}
 */

L259-261

export function legacy_reactive_statement_invalid(node) {
	e(node, 'legacy_reactive_statement_invalid', `\`$:\` is not allowed in runes mode, use \`$derived\` or \`$effect\` instead\nhttps://svelte.dev/e/legacy_reactive_statement_invalid`);
}

L470-472

export function state_field_duplicate(node, name) {
	e(node, 'state_field_duplicate', `\`${name}\` has already been declared on this class\nhttps://svelte.dev/e/state_field_duplicate`);
}

L479-481

export function state_field_invalid_assignment(node) {
	e(node, 'state_field_invalid_assignment', `Cannot assign to a state field before its declaration\nhttps://svelte.dev/e/state_field_invalid_assignment`);
}

L488-490

export function state_invalid_export(node) {
	e(node, 'state_invalid_export', `Cannot export state from a module if it is reassigned. Either export a function returning the state value or only mutate the state value's properties\nhttps://svelte.dev/e/state_invalid_export`);
}

L498-500

export function state_invalid_placement(node, rune) {
	e(node, 'state_invalid_placement', `\`${rune}(...)\` can only be used as a variable declaration initializer, a class field declaration, or the first assignment to a class field at the top level of the constructor.\nhttps://svelte.dev/e/state_invalid_placement`);
}

Matches in svelte/packages/svelte/src/compiler/migrate/index.js

function migrate( ) › L364-366

		 * If true, then we need to move all reactive statements to the end of the script block,
		 * in their correct order. Svelte 4 reordered reactive statements, $derived/$effect.pre
		 * don't have this behavior.

function migrate( ) › L412-415

			str.appendRight(
				insertion_point,
				`\n${indent}${[...state.derived_components.entries()].map(([init, name]) => `const ${name} = $derived(${init});`).join(`\n${indent}`)}\n`
			);

function migrate( ) › L420-423

			str.appendRight(
				insertion_point,
				`\n${indent}${[...state.derived_conflicting_slots.entries()].map(([name, init]) => `const ${name} = $derived(${init});`).join(`\n${indent}`)}\n`
			);

const instance_script › VariableDeclaration( ) › L720-730

			if (declarator.init) {
				let { start, end } = /** @type {{ start: number, end: number }} */ (declarator.init);

				if (declarator.init.type === 'SequenceExpression') {
					while (state.str.original[start] !== '(') start -= 1;
					while (state.str.original[end - 1] !== ')') end += 1;
				}

				check_rune_binding('state');

				state.str.prependLeft(start, '$state(');

2 lines remaining in ancestor node. Read the file to see all.

const instance_script › VariableDeclaration( ) › L824-830

					check_rune_binding('derived');

					// Someone wrote a `$: { ... }` statement which we can turn into a `$derived`
					state.str.appendRight(
						/** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end),
						' = $derived('
					);

const instance_script › VariableDeclaration( ) › L868-871

					state.str.prependLeft(
						/** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end),
						' = $state('
					);

const instance_script › VariableDeclaration( ) › L872-882

					if (should_be_state) {
						// someone wrote a `$: foo = ...` statement which we can turn into `let foo = $state(...)`
						state.str.appendRight(
							/** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end),
							state.str
								.snip(
									/** @type {number} */ (
										/** @type {AssignmentExpression} */ (assignment_in_labeled).right.start
									),
									/** @type {number} */ (
										/** @type {AssignmentExpression} */ (assignment_in_labeled).right.end

9 lines remaining in ancestor node. Read the file to see all.

const instance_script › LabeledStatement( ) › L958-968

				) {
					let { start, end } = /** @type {{ start: number, end: number }} */ (right);

					check_rune_binding('derived');

					// $derived
					state.str.update(
						/** @type {number} */ (node.start),
						/** @type {number} */ (node.body.expression.start),
						'let '
					);

16 lines remaining in ancestor node. Read the file to see all.

const instance_script › LabeledStatement( ) › L973-977

					}

					state.str.prependRight(start, `$derived(`);

					// in a case like `$: ({ a } = b())`, there's already a trailing parenthesis.

const instance_script › LabeledStatement( ) › L990-994

							binding.kind === 'state'
								? ' = $state()'
								: expression_ids.length === 0
									? ` = $state(${state.str.original.substring(/** @type {number} */ (right.start), right.end)})`
									: '';

const instance_script › LabeledStatement( ) › L1011-1015

		const is_block_stmt = node.body.type === 'BlockStatement';
		const start_end = /** @type {number} */ (node.body.start);
		// TODO try to find out if we can use $derived.by instead?
		if (is_block_stmt) {
			state.str.update(

Matches in svelte/packages/svelte/src/compiler/phases/2-analyze/index.js

function analyze_component( ) › L324-334

			(declaration !== null &&
				// const state = $state(0) is valid
				(get_rune(init, instance.scope) === null ||
					// rune-line names received as props are valid too (but we have to protect against $props as store)
					(store_name !== 'props' && get_rune(init, instance.scope) === '$props')) &&
				// allow `import { derived } from 'svelte/store'` in the same file as `const x = $derived(..)` because one is not a subscription to the other
				!(
					name === '$derived' &&
					declaration.initial?.type === 'ImportDeclaration' &&
					declaration.initial.source.value === 'svelte/store'
				))

Assistant

Let me continue searching for more specific state management functions:

Tool Call: Get page 2 of search results for regex function.*state.*|export.*function.*state|function.*State|export.*State Status: Completed

Showing matches 21-40 (there were more matches found; use offset: 40 to see next page):

Matches in svelte/packages/svelte/src/compiler/phases/2-analyze/visitors/CallExpression.js

function is_class_property_assignment_at_constructor_root( ) › L304-308

	) {
		// MethodDefinition (-5) -> FunctionExpression (-4) -> BlockStatement (-3) -> ExpressionStatement (-2) -> AssignmentExpression (-1)
		const parent = get_parent(context.path, -5);
		return parent?.type === 'MethodDefinition' && parent.kind === 'constructor';
	}

Matches in svelte/packages/svelte/src/compiler/phases/2-analyze/visitors/ExportDefaultDeclaration.js

function ExportDefaultDeclaration( ) › L12-14

		if (node.declaration.type === 'Identifier') {
			validate_export(node, context.state.scope, node.declaration.name);
		}

Matches in svelte/packages/svelte/src/compiler/phases/2-analyze/visitors/ExportSpecifier.js

function ExportSpecifier( ) › L27-29

	} else {
		validate_export(node, context.state.scope, local_name);
	}

Matches in svelte/packages/svelte/src/compiler/phases/2-analyze/visitors/ExpressionStatement.js

L9-19

export function ExpressionStatement(node, context) {
	// warn on `new Component({ target: ... })` if imported from a `.svelte` file
	if (
		node.expression.type === 'NewExpression' &&
		node.expression.callee.type === 'Identifier' &&
		node.expression.arguments.length === 1 &&
		node.expression.arguments[0].type === 'ObjectExpression' &&
		node.expression.arguments[0].properties.some(
			(p) => p.type === 'Property' && p.key.type === 'Identifier' && p.key.name === 'target'
		)
	) {

19 lines remaining in ancestor node. Read the file to see all.

Matches in svelte/packages/svelte/src/compiler/phases/2-analyze/visitors/LabeledStatement.js

L12-22

export function LabeledStatement(node, context) {
	if (node.label.name === '$') {
		const parent = /** @type {AST.SvelteNode} */ (context.path.at(-1));

		const is_reactive_statement =
			context.state.ast_type === 'instance' && parent.type === 'Program';

		if (is_reactive_statement) {
			if (context.state.analysis.runes) {
				e.legacy_reactive_statement_invalid(node);
			}

73 lines remaining in ancestor node. Read the file to see all.

function LabeledStatement( ) › L31-35

			context.next({
				...context.state,
				reactive_statement,
				function_depth: context.state.scope.function_depth + 1
			});

Matches in svelte/packages/svelte/src/compiler/phases/2-analyze/visitors/SnippetBlock.js

function SnippetBlock( ) › L38-43

	} else {
		const undefined_export = context.state.analysis.undefined_exports.get(name);
		if (undefined_export) {
			e.snippet_invalid_export(undefined_export);
		}
	}

Matches in svelte/packages/svelte/src/compiler/phases/2-analyze/visitors/shared/function.js

function visit_function( ) › L17-23

		for (const [name] of context.state.scope.references) {
			const binding = context.state.scope.get(name);

			if (binding && binding.scope.function_depth < context.state.scope.function_depth) {
				context.state.expression.references.add(binding);
			}
		}

function visit_function( ) › L26-30

	context.next({
		...context.state,
		function_depth: context.state.function_depth + 1,
		expression: null
	});

Matches in svelte/packages/svelte/src/compiler/phases/2-analyze/visitors/shared/utils.js

L129-134

export function validate_opening_tag(node, state, expected) {
	if (state.analysis.source[node.start + 1] !== expected) {
		// avoid a sea of red and only mark the first few characters
		e.block_unexpected_character({ start: node.start, end: node.start + 5 }, expected);
	}
}

L153-163

export function ensure_no_module_import_conflict(node, state) {
	const ids = extract_identifiers(node.id);
	for (const id of ids) {
		if (
			state.ast_type === 'instance' &&
			state.scope === state.analysis.instance.scope &&
			state.analysis.module.scope.get(id.name)?.declaration_kind === 'import'
		) {
			// TODO fix the message here
			e.declaration_duplicate_module_import(node.id);
		}

2 lines remaining in ancestor node. Read the file to see all.

L281-286

/**
 * Checks that the exported name is not a derived or reassigned state variable.
 * @param {Node} node
 * @param {Scope} scope
 * @param {string} name
 */

Matches in svelte/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js

const visitors › L63-73

const visitors = {
	_: function set_scope(node, { next, state }) {
		const scope = state.scopes.get(node);

		if (scope && scope !== state.scope) {
			const transform = { ...state.transform };

			for (const [name, binding] of scope.declarations) {
				if (
					binding.kind === 'normal' ||
					// Reads of `$state(...)` declarations are not

64 lines remaining in ancestor node. Read the file to see all.

Matches in svelte/packages/svelte/src/compiler/phases/3-transform/client/transform-template/index.js

L38-48

export function transform_template(state, namespace, flags = 0) {
	const tree = state.options.fragments === 'tree';

	const expression = tree ? state.template.as_tree() : state.template.as_html();

	if (tree) {
		if (namespace === 'svg') flags |= TEMPLATE_USE_SVG;
		if (namespace === 'mathml') flags |= TEMPLATE_USE_MATHML;
	}

	let call = b.call(

20 lines remaining in ancestor node. Read the file to see all.

Matches in svelte/packages/svelte/src/compiler/phases/3-transform/client/utils.js

L24-29

export function is_state_source(binding, analysis) {
	return (
		(binding.kind === 'state' || binding.kind === 'raw_state') &&
		(!analysis.immutable || binding.reassigned || analysis.accessors)
	);
}

L36-46

export function build_getter(node, state) {
	if (Object.hasOwn(state.transform, node.name)) {
		const binding = state.scope.get(node.name);

		// don't transform the declaration itself
		if (node !== binding?.node) {
			return state.transform[node.name].read(node);
		}
	}

	return node;

1 lines remaining in ancestor node. Read the file to see all.

L175-185

export function get_prop_source(binding, state, name, initial) {
	/** @type {Expression[]} */
	const args = [b.id('$$props'), b.literal(name)];

	let flags = 0;

	if (binding.kind === 'bindable_prop') {
		flags |= PROPS_IS_BINDABLE;
	}

	if (state.analysis.immutable) {

45 lines remaining in ancestor node. Read the file to see all.

L238-248

export function is_prop_source(binding, state) {
	return (
		(binding.kind === 'prop' || binding.kind === 'bindable_prop') &&
		(!state.analysis.runes ||
			state.analysis.accessors ||
			binding.reassigned ||
			binding.initial ||
			// Until legacy mode is gone, we also need to use the prop source when only mutated is true,
			// because the parent could be a legacy component which needs coarse-grained reactivity
			binding.updated)
	);

1 lines remaining in ancestor node. Read the file to see all.

L294-296

export function create_derived(state, arg) {
	return b.call(state.analysis.runes ? '$.derived' : '$.derived_safe_equal', arg);
}

Matches in svelte/packages/svelte/src/compiler/phases/3-transform/client/visitors/BlockStatement.js

L1-20

/** @import { ArrowFunctionExpression, BlockStatement, Expression, FunctionDeclaration, FunctionExpression, Statement } from 'estree' */
/** @import { ComponentContext } from '../types' */
import { add_state_transformers } from './shared/declarations.js';
import * as b from '#compiler/builders';

/**
 * @param {BlockStatement} node
 * @param {ComponentContext} context
 */
export function BlockStatement(node, context) {
	add_state_transformers(context);
	const tracing = context.state.scope.tracing;

	if (tracing !== null) {
		const parent =
			/** @type {ArrowFunctionExpression | FunctionDeclaration | FunctionExpression} */ (
				context.path.at(-1)
			);

		const is_async = parent.async;

13 lines remaining in ancestor node. Read the file to see all.

Assistant

Now let me search for more core state management functions in the runtime:

Tool Call: Search files for regex export\s+function\s+(state|derived|effect|signal|reactive|store|writable|readable) Status: Completed

Showing matches 1-20 (there were more matches found; use offset: 20 to see next page):

Matches in svelte/packages/svelte/src/compiler/errors.js

L131-133

export function derived_invalid_export(node) {
	e(node, 'derived_invalid_export', `Cannot export derived state from a module. To expose the current derived value, export a function returning its value\nhttps://svelte.dev/e/derived_invalid_export`);
}

L167-169

export function effect_invalid_placement(node) {
	e(node, 'effect_invalid_placement', `\`$effect()\` can only be used as an expression statement\nhttps://svelte.dev/e/effect_invalid_placement`);
}

L342-344

export function reactive_declaration_cycle(node, cycle) {
	e(node, 'reactive_declaration_cycle', `Cyclical dependency detected: ${cycle}\nhttps://svelte.dev/e/reactive_declaration_cycle`);
}

L470-472

export function state_field_duplicate(node, name) {
	e(node, 'state_field_duplicate', `\`${name}\` has already been declared on this class\nhttps://svelte.dev/e/state_field_duplicate`);
}

L479-481

export function state_field_invalid_assignment(node) {
	e(node, 'state_field_invalid_assignment', `Cannot assign to a state field before its declaration\nhttps://svelte.dev/e/state_field_invalid_assignment`);
}

L488-490

export function state_invalid_export(node) {
	e(node, 'state_invalid_export', `Cannot export state from a module if it is reassigned. Either export a function returning the state value or only mutate the state value's properties\nhttps://svelte.dev/e/state_invalid_export`);
}

L498-500

export function state_invalid_placement(node, rune) {
	e(node, 'state_invalid_placement', `\`${rune}(...)\` can only be used as a variable declaration initializer, a class field declaration, or the first assignment to a class field at the top level of the constructor.\nhttps://svelte.dev/e/state_invalid_placement`);
}

L507-509

export function store_invalid_scoped_subscription(node) {
	e(node, 'store_invalid_scoped_subscription', `Cannot subscribe to stores that are not declared at the top level of the component\nhttps://svelte.dev/e/store_invalid_scoped_subscription`);
}

L516-518

export function store_invalid_subscription(node) {
	e(node, 'store_invalid_subscription', `Cannot reference store value inside \`<script module>\`\nhttps://svelte.dev/e/store_invalid_subscription`);
}

L525-527

export function store_invalid_subscription_module(node) {
	e(node, 'store_invalid_subscription_module', `Cannot reference store value outside a \`.svelte\` file\nhttps://svelte.dev/e/store_invalid_subscription_module`);
}

Matches in svelte/packages/svelte/src/compiler/warnings.js

L650-652

export function reactive_declaration_invalid_placement(node) {
	w(node, 'reactive_declaration_invalid_placement', `Reactive declarations only exist at the top level of the instance script\nhttps://svelte.dev/e/reactive_declaration_invalid_placement`);
}

L658-660

export function reactive_declaration_module_script_dependency(node) {
	w(node, 'reactive_declaration_module_script_dependency', `Reassignments of module-level declarations will not cause reactive statements to update\nhttps://svelte.dev/e/reactive_declaration_module_script_dependency`);
}

L668-670

export function state_referenced_locally(node, name, type) {
	w(node, 'state_referenced_locally', `This reference only captures the initial value of \`${name}\`. Did you mean to reference it inside a ${type} instead?\nhttps://svelte.dev/e/state_referenced_locally`);
}

L677-679

export function store_rune_conflict(node, name) {
	w(node, 'store_rune_conflict', `It looks like you're using the \`$${name}\` rune, but there is a local binding called \`${name}\`. Referencing a local variable with a \`$\` prefix will create a store subscription. Please rename \`${name}\` to avoid the ambiguity\nhttps://svelte.dev/e/store_rune_conflict`);
}

Matches in svelte/packages/svelte/src/internal/client/dom/legacy/misc.js

L10-20

export function reactive_import(fn) {
	var s = source(0);

	return function () {
		if (arguments.length === 1) {
			set(s, get(s) + 1);
			return arguments[0];
		} else {
			get(s);
			return fn();
		}

2 lines remaining in ancestor node. Read the file to see all.

Matches in svelte/packages/svelte/src/internal/client/errors.js

L94-103

export function derived_references_self() {
	if (DEV) {
		const error = new Error(`derived_references_self\nA derived value cannot reference itself recursively\nhttps://svelte.dev/e/derived_references_self`);

		error.name = 'Svelte error';
		throw error;
	} else {
		throw new Error(`https://svelte.dev/e/derived_references_self`);
	}
}

L128-137

export function effect_in_teardown(rune) {
	if (DEV) {
		const error = new Error(`effect_in_teardown\n\`${rune}\` cannot be used inside an effect cleanup function\nhttps://svelte.dev/e/effect_in_teardown`);

		error.name = 'Svelte error';
		throw error;
	} else {
		throw new Error(`https://svelte.dev/e/effect_in_teardown`);
	}
}

L143-152

export function effect_in_unowned_derived() {
	if (DEV) {
		const error = new Error(`effect_in_unowned_derived\nEffect cannot be created inside a \`$derived\` value that was not itself created inside an effect\nhttps://svelte.dev/e/effect_in_unowned_derived`);

		error.name = 'Svelte error';
		throw error;
	} else {
		throw new Error(`https://svelte.dev/e/effect_in_unowned_derived`);
	}
}

L159-168

export function effect_orphan(rune) {
	if (DEV) {
		const error = new Error(`effect_orphan\n\`${rune}\` can only be used inside an effect (e.g. during component initialisation)\nhttps://svelte.dev/e/effect_orphan`);

		error.name = 'Svelte error';
		throw error;
	} else {
		throw new Error(`https://svelte.dev/e/effect_orphan`);
	}
}

L174-183

export function effect_update_depth_exceeded() {
	if (DEV) {
		const error = new Error(`effect_update_depth_exceeded\nMaximum update depth exceeded. This can happen when a reactive block or effect repeatedly sets a new value. Svelte limits the number of nested updates to prevent infinite loops\nhttps://svelte.dev/e/effect_update_depth_exceeded`);

		error.name = 'Svelte error';
		throw error;
	} else {
		throw new Error(`https://svelte.dev/e/effect_update_depth_exceeded`);
	}
}

Assistant

Let me search for the core state management functions in the runtime directory:

Tool Call: 50 matches Status: Completed

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/constants.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/context.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dev/assign.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dev/console-log.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dev/css.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dev/debug.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dev/elements.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dev/equality.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dev/hmr.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dev/inspect.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dev/legacy.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dev/ownership.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dev/tracing.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dev/validation.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/blocks/await.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/blocks/boundary.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/blocks/css-props.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/blocks/each.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/blocks/html.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/blocks/if.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/blocks/key.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/blocks/slot.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/blocks/snippet.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/blocks/svelte-component.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/blocks/svelte-element.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/blocks/svelte-head.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/css.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/elements/actions.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/elements/attachments.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/elements/attributes.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/elements/bindings/document.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/elements/bindings/input.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/elements/bindings/media.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/elements/bindings/navigator.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/elements/bindings/props.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/elements/bindings/select.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/elements/bindings/shared.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/elements/bindings/size.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/elements/bindings/this.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/elements/bindings/universal.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/elements/bindings/window.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/elements/class.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/elements/custom-element.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/elements/events.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/elements/misc.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/elements/style.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/elements/transitions.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/hydration.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/legacy/event-modifiers.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/dom/legacy/lifecycle.js

Assistant

Let me check the main reactive/state files:

Tool Call: 6 matches Status: Completed

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/reactivity/deriveds.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/reactivity/effects.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/reactivity/equality.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/reactivity/props.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/reactivity/sources.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/reactivity/store.js

Assistant

Perfect! Let me examine these core reactivity files to find the state management functions:

Tool Call: sources.js Status: Completed

/** @import { Derived, Effect, Source, Value } from '#client' */
import { DEV } from 'esm-env';
import {
	active_reaction,
	active_effect,
	untracked_writes,
	get,
	schedule_effect,
	set_untracked_writes,
	set_signal_status,
	untrack,
	increment_write_version,
	update_effect,
	reaction_sources,
	check_dirtiness,
	untracking,
	is_destroying_effect,
	push_reaction_value
} from '../runtime.js';
import { equals, safe_equals } from './equality.js';
import {
	CLEAN,
	DERIVED,
	DIRTY,
	BRANCH_EFFECT,
	INSPECT_EFFECT,
	UNOWNED,
	MAYBE_DIRTY,
	BLOCK_EFFECT,
	ROOT_EFFECT
} from '#client/constants';
import * as e from '../errors.js';
import { legacy_mode_flag, tracing_mode_flag } from '../../flags/index.js';
import { get_stack, tag_proxy } from '../dev/tracing.js';
import { component_context, is_runes } from '../context.js';
import { proxy } from '../proxy.js';
import { execute_derived } from './deriveds.js';

export let inspect_effects = new Set();

/** @type {Map<Source, any>} */
export const old_values = new Map();

/**
 * @param {Set<any>} v
 */
export function set_inspect_effects(v) {
	inspect_effects = v;
}

/**
 * @template V
 * @param {V} v
 * @param {Error | null} [stack]
 * @returns {Source<V>}
 */
// TODO rename this to `state` throughout the codebase
export function source(v, stack) {
	/** @type {Value} */
	var signal = {
		f: 0, // TODO ideally we could skip this altogether, but it causes type errors
		v,
		reactions: null,
		equals,
		rv: 0,
		wv: 0
	};

	if (DEV && tracing_mode_flag) {
		signal.created = stack ?? get_stack('CreatedAt');
		signal.updated = null;
		signal.set_during_effect = false;
		signal.trace = null;
	}

	return signal;
}

/**
 * @template V
 * @param {V} v
 * @param {Error | null} [stack]
 */
/*#__NO_SIDE_EFFECTS__*/
export function state(v, stack) {
	const s = source(v, stack);

	push_reaction_value(s);

	return s;
}

/**
 * @template V
 * @param {V} initial_value
 * @param {boolean} [immutable]
 * @returns {Source<V>}
 */
/*#__NO_SIDE_EFFECTS__*/
export function mutable_source(initial_value, immutable = false, trackable = true) {
	const s = source(initial_value);
	if (!immutable) {
		s.equals = safe_equals;
	}

	// bind the signal to the component context, in case we need to
	// track updates to trigger beforeUpdate/afterUpdate callbacks
	if (legacy_mode_flag && trackable && component_context !== null && component_context.l !== null) {
		(component_context.l.s ??= []).push(s);
	}

	return s;
}

/**
 * @template V
 * @param {Value<V>} source
 * @param {V} value
 */
export function mutate(source, value) {
	set(
		source,
		untrack(() => get(source))
	);
	return value;
}

/**
 * @template V
 * @param {Source<V>} source
 * @param {V} value
 * @param {boolean} [should_proxy]
 * @returns {V}
 */
export function set(source, value, should_proxy = false) {
	if (
		active_reaction !== null &&
		// since we are untracking the function inside `$inspect.with` we need to add this check
		// to ensure we error if state is set inside an inspect effect
		(!untracking || (active_reaction.f & INSPECT_EFFECT) !== 0) &&
		is_runes() &&
		(active_reaction.f & (DERIVED | BLOCK_EFFECT | INSPECT_EFFECT)) !== 0 &&
		!(reaction_sources?.[1].includes(source) && reaction_sources[0] === active_reaction)
	) {
		e.state_unsafe_mutation();
	}

	let new_value = should_proxy ? proxy(value) : value;

	if (DEV) {
		tag_proxy(new_value, /** @type {string} */ (source.label));
	}

	return internal_set(source, new_value);
}

/**
 * @template V
 * @param {Source<V>} source
 * @param {V} value
 * @returns {V}
 */
export function internal_set(source, value) {
	if (!source.equals(value)) {
		var old_value = source.v;

		if (is_destroying_effect) {
			old_values.set(source, value);
		} else {
			old_values.set(source, old_value);
		}

		source.v = value;

		if (DEV && tracing_mode_flag) {
			source.updated = get_stack('UpdatedAt');

			if (active_effect !== null) {
				source.set_during_effect = true;
			}
		}

		if ((source.f & DERIVED) !== 0) {
			// if we are assigning to a dirty derived we set it to clean/maybe dirty but we also eagerly execute it to track the dependencies
			if ((source.f & DIRTY) !== 0) {
				execute_derived(/** @type {Derived} */ (source));
			}
			set_signal_status(source, (source.f & UNOWNED) === 0 ? CLEAN : MAYBE_DIRTY);
		}

		source.wv = increment_write_version();

		mark_reactions(source, DIRTY);

		// It's possible that the current reaction might not have up-to-date dependencies
		// whilst it's actively running. So in the case of ensuring it registers the reaction
		// properly for itself, we need to ensure the current effect actually gets
		// scheduled. i.e: `$effect(() => x++)`
		if (
			is_runes() &&
			active_effect !== null &&
			(active_effect.f & CLEAN) !== 0 &&
			(active_effect.f & (BRANCH_EFFECT | ROOT_EFFECT)) === 0
		) {
			if (untracked_writes === null) {
				set_untracked_writes([source]);
			} else {
				untracked_writes.push(source);
			}
		}

		if (DEV && inspect_effects.size > 0) {
			const inspects = Array.from(inspect_effects);

			for (const effect of inspects) {
				// Mark clean inspect-effects as maybe dirty and then check their dirtiness
				// instead of just updating the effects - this way we avoid overfiring.
				if ((effect.f & CLEAN) !== 0) {
					set_signal_status(effect, MAYBE_DIRTY);
				}
				if (check_dirtiness(effect)) {
					update_effect(effect);
				}
			}

			inspect_effects.clear();
		}
	}

	return value;
}

/**
 * @template {number | bigint} T
 * @param {Source<T>} source
 * @param {1 | -1} [d]
 * @returns {T}
 */
export function update(source, d = 1) {
	var value = get(source);
	var result = d === 1 ? value++ : value--;

	set(source, value);

	// @ts-expect-error
	return result;
}

/**
 * @template {number | bigint} T
 * @param {Source<T>} source
 * @param {1 | -1} [d]
 * @returns {T}
 */
export function update_pre(source, d = 1) {
	var value = get(source);

	// @ts-expect-error
	return set(source, d === 1 ? ++value : --value);
}

/**
 * @param {Value} signal
 * @param {number} status should be DIRTY or MAYBE_DIRTY
 * @returns {void}
 */
function mark_reactions(signal, status) {
	var reactions = signal.reactions;
	if (reactions === null) return;

	var runes = is_runes();
	var length = reactions.length;

	for (var i = 0; i < length; i++) {
		var reaction = reactions[i];
		var flags = reaction.f;

		// Skip any effects that are already dirty
		if ((flags & DIRTY) !== 0) continue;

		// In legacy mode, skip the current effect to prevent infinite loops
		if (!runes && reaction === active_effect) continue;

		// Inspect effects need to run immediately, so that the stack trace makes sense
		if (DEV && (flags & INSPECT_EFFECT) !== 0) {
			inspect_effects.add(reaction);
			continue;
		}

		set_signal_status(reaction, status);

		// If the signal a) was previously clean or b) is an unowned derived, then mark it
		if ((flags & (CLEAN | UNOWNED)) !== 0) {
			if ((flags & DERIVED) !== 0) {
				mark_reactions(/** @type {Derived} */ (reaction), MAYBE_DIRTY);
			} else {
				schedule_effect(/** @type {Effect} */ (reaction));
			}
		}
	}
}

Tool Call: deriveds.js Status: Completed

/** @import { Derived, Effect } from '#client' */
import { DEV } from 'esm-env';
import { CLEAN, DERIVED, DIRTY, EFFECT_HAS_DERIVED, MAYBE_DIRTY, UNOWNED } from '#client/constants';
import {
	active_reaction,
	active_effect,
	set_signal_status,
	skip_reaction,
	update_reaction,
	increment_write_version,
	set_active_effect,
	push_reaction_value,
	is_destroying_effect
} from '../runtime.js';
import { equals, safe_equals } from './equality.js';
import * as e from '../errors.js';
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
 * @param {() => V} fn
 * @returns {Derived<V>}
 */
/*#__NO_SIDE_EFFECTS__*/
export function derived(fn) {
	var flags = DERIVED | DIRTY;
	var parent_derived =
		active_reaction !== null && (active_reaction.f & DERIVED) !== 0
			? /** @type {Derived} */ (active_reaction)
			: null;

	if (active_effect === null || (parent_derived !== null && (parent_derived.f & UNOWNED) !== 0)) {
		flags |= UNOWNED;
	} else {
		// Since deriveds are evaluated lazily, any effects created inside them are
		// created too late to ensure that the parent effect is added to the tree
		active_effect.f |= EFFECT_HAS_DERIVED;
	}

	/** @type {Derived<V>} */
	const signal = {
		ctx: component_context,
		deps: null,
		effects: null,
		equals,
		f: flags,
		fn,
		reactions: null,
		rv: 0,
		v: /** @type {V} */ (null),
		wv: 0,
		parent: parent_derived ?? active_effect
	};

	if (DEV && tracing_mode_flag) {
		signal.created = get_stack('CreatedAt');
	}

	return signal;
}

/**
 * @template V
 * @param {() => V} fn
 * @returns {Derived<V>}
 */
/*#__NO_SIDE_EFFECTS__*/
export function user_derived(fn) {
	const d = derived(fn);

	push_reaction_value(d);

	return d;
}

/**
 * @template V
 * @param {() => V} fn
 * @returns {Derived<V>}
 */
/*#__NO_SIDE_EFFECTS__*/
export function derived_safe_equal(fn) {
	const signal = derived(fn);
	signal.equals = safe_equals;
	return signal;
}

/**
 * @param {Derived} derived
 * @returns {void}
 */
export function destroy_derived_effects(derived) {
	var effects = derived.effects;

	if (effects !== null) {
		derived.effects = null;

		for (var i = 0; i < effects.length; i += 1) {
			destroy_effect(/** @type {Effect} */ (effects[i]));
		}
	}
}

/**
 * The currently updating deriveds, used to detect infinite recursion
 * in dev mode and provide a nicer error than 'too much recursion'
 * @type {Derived[]}
 */
let stack = [];

/**
 * @param {Derived} derived
 * @returns {Effect | null}
 */
function get_derived_parent_effect(derived) {
	var parent = derived.parent;
	while (parent !== null) {
		if ((parent.f & DERIVED) === 0) {
			return /** @type {Effect} */ (parent);
		}
		parent = parent.parent;
	}
	return null;
}

/**
 * @template T
 * @param {Derived} derived
 * @returns {T}
 */
export function execute_derived(derived) {
	var value;
	var prev_active_effect = active_effect;

	set_active_effect(get_derived_parent_effect(derived));

	if (DEV) {
		let prev_inspect_effects = inspect_effects;
		set_inspect_effects(new Set());
		try {
			if (stack.includes(derived)) {
				e.derived_references_self();
			}

			stack.push(derived);

			destroy_derived_effects(derived);
			value = update_reaction(derived);
		} finally {
			set_active_effect(prev_active_effect);
			set_inspect_effects(prev_inspect_effects);
			stack.pop();
		}
	} else {
		try {
			destroy_derived_effects(derived);
			value = update_reaction(derived);
		} finally {
			set_active_effect(prev_active_effect);
		}
	}

	return value;
}

/**
 * @param {Derived} derived
 * @returns {void}
 */
export function update_derived(derived) {
	var value = execute_derived(derived);

	if (!derived.equals(value)) {
		derived.v = value;
		derived.wv = increment_write_version();
	}

	// don't mark derived clean if we're reading it inside a
	// cleanup function, or it will cache a stale value
	if (is_destroying_effect) return;

	var status =
		(skip_reaction || (derived.f & UNOWNED) !== 0) && derived.deps !== null ? MAYBE_DIRTY : CLEAN;

	set_signal_status(derived, status);
}

Tool Call: effects.js Status: Completed

/** @import { ComponentContext, ComponentContextLegacy, Derived, Effect, TemplateNode, TransitionManager } from '#client' */
import {
	check_dirtiness,
	active_effect,
	active_reaction,
	update_effect,
	get,
	is_destroying_effect,
	remove_reactions,
	schedule_effect,
	set_active_reaction,
	set_is_destroying_effect,
	set_signal_status,
	untrack,
	untracking
} from '../runtime.js';
import {
	DIRTY,
	BRANCH_EFFECT,
	RENDER_EFFECT,
	EFFECT,
	DESTROYED,
	INERT,
	EFFECT_RAN,
	BLOCK_EFFECT,
	ROOT_EFFECT,
	EFFECT_TRANSPARENT,
	DERIVED,
	UNOWNED,
	CLEAN,
	INSPECT_EFFECT,
	HEAD_EFFECT,
	MAYBE_DIRTY,
	EFFECT_HAS_DERIVED,
	BOUNDARY_EFFECT
} from '#client/constants';
import { set } from './sources.js';
import * as e from '../errors.js';
import { DEV } from 'esm-env';
import { define_property } from '../../shared/utils.js';
import { get_next_sibling } from '../dom/operations.js';
import { derived } from './deriveds.js';
import { component_context, dev_current_component_function } from '../context.js';

/**
 * @param {'$effect' | '$effect.pre' | '$inspect'} rune
 */
export function validate_effect(rune) {
	if (active_effect === null && active_reaction === null) {
		e.effect_orphan(rune);
	}

	if (active_reaction !== null && (active_reaction.f & UNOWNED) !== 0 && active_effect === null) {
		e.effect_in_unowned_derived();
	}

	if (is_destroying_effect) {
		e.effect_in_teardown(rune);
	}
}

/**
 * @param {Effect} effect
 * @param {Effect} parent_effect
 */
function push_effect(effect, parent_effect) {
	var parent_last = parent_effect.last;
	if (parent_last === null) {
		parent_effect.last = parent_effect.first = effect;
	} else {
		parent_last.next = effect;
		effect.prev = parent_last;
		parent_effect.last = effect;
	}
}

/**
 * @param {number} type
 * @param {null | (() => void | (() => void))} fn
 * @param {boolean} sync
 * @param {boolean} push
 * @returns {Effect}
 */
function create_effect(type, fn, sync, push = true) {
	var parent = active_effect;

	if (DEV) {
		// Ensure the parent is never an inspect effect
		while (parent !== null && (parent.f & INSPECT_EFFECT) !== 0) {
			parent = parent.parent;
		}
	}

	/** @type {Effect} */
	var effect = {
		ctx: component_context,
		deps: null,
		nodes_start: null,
		nodes_end: null,
		f: type | DIRTY,
		first: null,
		fn,
		last: null,
		next: null,
		parent,
		prev: null,
		teardown: null,
		transitions: null,
		wv: 0
	};

	if (DEV) {
		effect.component_function = dev_current_component_function;
	}

	if (sync) {
		try {
			update_effect(effect);
			effect.f |= EFFECT_RAN;
		} catch (e) {
			destroy_effect(effect);
			throw e;
		}
	} else if (fn !== null) {
		schedule_effect(effect);
	}

	// if an effect has no dependencies, no DOM and no teardown function,
	// don't bother adding it to the effect tree
	var inert =
		sync &&
		effect.deps === null &&
		effect.first === null &&
		effect.nodes_start === null &&
		effect.teardown === null &&
		(effect.f & (EFFECT_HAS_DERIVED | BOUNDARY_EFFECT)) === 0;

	if (!inert && push) {
		if (parent !== null) {
			push_effect(effect, parent);
		}

		// if we're in a derived, add the effect there too
		if (active_reaction !== null && (active_reaction.f & DERIVED) !== 0) {
			var derived = /** @type {Derived} */ (active_reaction);
			(derived.effects ??= []).push(effect);
		}
	}

	return effect;
}

/**
 * Internal representation of `$effect.tracking()`
 * @returns {boolean}
 */
export function effect_tracking() {
	return active_reaction !== null && !untracking;
}

/**
 * @param {() => void} fn
 */
export function teardown(fn) {
	const effect = create_effect(RENDER_EFFECT, null, false);
	set_signal_status(effect, CLEAN);
	effect.teardown = fn;
	return effect;
}

/**
 * Internal representation of `$effect(...)`
 * @param {() => void | (() => void)} fn
 */
export function user_effect(fn) {
	validate_effect('$effect');

	// Non-nested `$effect(...)` in a component should be deferred
	// until the component is mounted
	var defer =
		active_effect !== null &&
		(active_effect.f & BRANCH_EFFECT) !== 0 &&
		component_context !== null &&
		!component_context.m;

	if (DEV) {
		define_property(fn, 'name', {
			value: '$effect'
		});
	}

	if (defer) {
		var context = /** @type {ComponentContext} */ (component_context);
		(context.e ??= []).push({
			fn,
			effect: active_effect,
			reaction: active_reaction
		});
	} else {
		var signal = effect(fn);
		return signal;
	}
}

/**
 * Internal representation of `$effect.pre(...)`
 * @param {() => void | (() => void)} fn
 * @returns {Effect}
 */
export function user_pre_effect(fn) {
	validate_effect('$effect.pre');
	if (DEV) {
		define_property(fn, 'name', {
			value: '$effect.pre'
		});
	}
	return render_effect(fn);
}

/** @param {() => void | (() => void)} fn */
export function inspect_effect(fn) {
	return create_effect(INSPECT_EFFECT, fn, true);
}

/**
 * Internal representation of `$effect.root(...)`
 * @param {() => void | (() => void)} fn
 * @returns {() => void}
 */
export function effect_root(fn) {
	const effect = create_effect(ROOT_EFFECT, fn, true);

	return () => {
		destroy_effect(effect);
	};
}

/**
 * An effect root whose children can transition out
 * @param {() => void} fn
 * @returns {(options?: { outro?: boolean }) => Promise<void>}
 */
export function component_root(fn) {
	const effect = create_effect(ROOT_EFFECT, fn, true);

	return (options = {}) => {
		return new Promise((fulfil) => {
			if (options.outro) {
				pause_effect(effect, () => {
					destroy_effect(effect);
					fulfil(undefined);
				});
			} else {
				destroy_effect(effect);
				fulfil(undefined);
			}
		});
	};
}

/**
 * @param {() => void | (() => void)} fn
 * @returns {Effect}
 */
export function effect(fn) {
	return create_effect(EFFECT, fn, false);
}

/**
 * Internal representation of `$: ..`
 * @param {() => any} deps
 * @param {() => void | (() => void)} fn
 */
export function legacy_pre_effect(deps, fn) {
	var context = /** @type {ComponentContextLegacy} */ (component_context);

	/** @type {{ effect: null | Effect, ran: boolean }} */
	var token = { effect: null, ran: false };
	context.l.r1.push(token);

	token.effect = render_effect(() => {
		deps();

		// If this legacy pre effect has already run before the end of the reset, then
		// bail out to emulate the same behavior.
		if (token.ran) return;

		token.ran = true;
		set(context.l.r2, true);
		untrack(fn);
	});
}

export function legacy_pre_effect_reset() {
	var context = /** @type {ComponentContextLegacy} */ (component_context);

	render_effect(() => {
		if (!get(context.l.r2)) return;

		// Run dirty `$:` statements
		for (var token of context.l.r1) {
			var effect = token.effect;

			// If the effect is CLEAN, then make it MAYBE_DIRTY. This ensures we traverse through
			// the effects dependencies and correctly ensure each dependency is up-to-date.
			if ((effect.f & CLEAN) !== 0) {
				set_signal_status(effect, MAYBE_DIRTY);
			}

			if (check_dirtiness(effect)) {
				update_effect(effect);
			}

			token.ran = false;
		}

		context.l.r2.v = false; // set directly to avoid rerunning this effect
	});
}

/**
 * @param {() => void | (() => void)} fn
 * @returns {Effect}
 */
export function render_effect(fn) {
	return create_effect(RENDER_EFFECT, fn, true);
}

/**
 * @param {(...expressions: any) => void | (() => void)} fn
 * @param {Array<() => any>} thunks
 * @param {<T>(fn: () => T) => Derived<T>} d
 * @returns {Effect}
 */
export function template_effect(fn, thunks = [], d = derived) {
	if (DEV) {
		// wrap the effect so that we can decorate stack trace with `in {expression}`
		// (TODO maybe there's a better approach?)
		return render_effect(() => {
			var outer = /** @type {Effect} */ (active_effect);
			var inner = () => fn(...deriveds.map(get));

			define_property(outer.fn, 'name', { value: '{expression}' });
			define_property(inner, 'name', { value: '{expression}' });

			const deriveds = thunks.map(d);
			block(inner);
		});
	}

	const deriveds = thunks.map(d);
	return block(() => fn(...deriveds.map(get)));
}

/**
 * @param {(() => void)} fn
 * @param {number} flags
 */
export function block(fn, flags = 0) {
	return create_effect(RENDER_EFFECT | BLOCK_EFFECT | flags, fn, true);
}

/**
 * @param {(() => void)} fn
 * @param {boolean} [push]
 */
export function branch(fn, push = true) {
	return create_effect(RENDER_EFFECT | BRANCH_EFFECT, fn, true, push);
}

/**
 * @param {Effect} effect
 */
export function execute_effect_teardown(effect) {
	var teardown = effect.teardown;
	if (teardown !== null) {
		const previously_destroying_effect = is_destroying_effect;
		const previous_reaction = active_reaction;
		set_is_destroying_effect(true);
		set_active_reaction(null);
		try {
			teardown.call(null);
		} finally {
			set_is_destroying_effect(previously_destroying_effect);
			set_active_reaction(previous_reaction);
		}
	}
}

/**
 * @param {Effect} signal
 * @param {boolean} remove_dom
 * @returns {void}
 */
export function destroy_effect_children(signal, remove_dom = false) {
	var effect = signal.first;
	signal.first = signal.last = null;

	while (effect !== null) {
		var next = effect.next;

		if ((effect.f & ROOT_EFFECT) !== 0) {
			// this is now an independent root
			effect.parent = null;
		} else {
			destroy_effect(effect, remove_dom);
		}

		effect = next;
	}
}

/**
 * @param {Effect} signal
 * @returns {void}
 */
export function destroy_block_effect_children(signal) {
	var effect = signal.first;

	while (effect !== null) {
		var next = effect.next;
		if ((effect.f & BRANCH_EFFECT) === 0) {
			destroy_effect(effect);
		}
		effect = next;
	}
}

/**
 * @param {Effect} effect
 * @param {boolean} [remove_dom]
 * @returns {void}
 */
export function destroy_effect(effect, remove_dom = true) {
	var removed = false;

	if (
		(remove_dom || (effect.f & HEAD_EFFECT) !== 0) &&
		effect.nodes_start !== null &&
		effect.nodes_end !== null
	) {
		remove_effect_dom(effect.nodes_start, /** @type {TemplateNode} */ (effect.nodes_end));
		removed = true;
	}

	destroy_effect_children(effect, remove_dom && !removed);
	remove_reactions(effect, 0);
	set_signal_status(effect, DESTROYED);

	var transitions = effect.transitions;

	if (transitions !== null) {
		for (const transition of transitions) {
			transition.stop();
		}
	}

	execute_effect_teardown(effect);

	var parent = effect.parent;

	// If the parent doesn't have any children, then skip this work altogether
	if (parent !== null && parent.first !== null) {
		unlink_effect(effect);
	}

	if (DEV) {
		effect.component_function = null;
	}

	// `first` and `child` are nulled out in destroy_effect_children
	// we don't null out `parent` so that error propagation can work correctly
	effect.next =
		effect.prev =
		effect.teardown =
		effect.ctx =
		effect.deps =
		effect.fn =
		effect.nodes_start =
		effect.nodes_end =
			null;
}

/**
 *
 * @param {TemplateNode | null} node
 * @param {TemplateNode} end
 */
export function remove_effect_dom(node, end) {
	while (node !== null) {
		/** @type {TemplateNode | null} */
		var next = node === end ? null : /** @type {TemplateNode} */ (get_next_sibling(node));

		node.remove();
		node = next;
	}
}

/**
 * Detach an effect from the effect tree, freeing up memory and
 * reducing the amount of work that happens on subsequent traversals
 * @param {Effect} effect
 */
export function unlink_effect(effect) {
	var parent = effect.parent;
	var prev = effect.prev;
	var next = effect.next;

	if (prev !== null) prev.next = next;
	if (next !== null) next.prev = prev;

	if (parent !== null) {
		if (parent.first === effect) parent.first = next;
		if (parent.last === effect) parent.last = prev;
	}
}

/**
 * When a block effect is removed, we don't immediately destroy it or yank it
 * out of the DOM, because it might have transitions. Instead, we 'pause' it.
 * It stays around (in memory, and in the DOM) until outro transitions have
 * completed, and if the state change is reversed then we _resume_ it.
 * A paused effect does not update, and the DOM subtree becomes inert.
 * @param {Effect} effect
 * @param {() => void} [callback]
 */
export function pause_effect(effect, callback) {
	/** @type {TransitionManager[]} */
	var transitions = [];

	pause_children(effect, transitions, true);

	run_out_transitions(transitions, () => {
		destroy_effect(effect);
		if (callback) callback();
	});
}

/**
 * @param {TransitionManager[]} transitions
 * @param {() => void} fn
 */
export function run_out_transitions(transitions, fn) {
	var remaining = transitions.length;
	if (remaining > 0) {
		var check = () => --remaining || fn();
		for (var transition of transitions) {
			transition.out(check);
		}
	} else {
		fn();
	}
}

/**
 * @param {Effect} effect
 * @param {TransitionManager[]} transitions
 * @param {boolean} local
 */
export function pause_children(effect, transitions, local) {
	if ((effect.f & INERT) !== 0) return;
	effect.f ^= INERT;

	if (effect.transitions !== null) {
		for (const transition of effect.transitions) {
			if (transition.is_global || local) {
				transitions.push(transition);
			}
		}
	}

	var child = effect.first;

	while (child !== null) {
		var sibling = child.next;
		var transparent = (child.f & EFFECT_TRANSPARENT) !== 0 || (child.f & BRANCH_EFFECT) !== 0;
		// TODO we don't need to call pause_children recursively with a linked list in place
		// it's slightly more involved though as we have to account for `transparent` changing
		// through the tree.
		pause_children(child, transitions, transparent ? local : false);
		child = sibling;
	}
}

/**
 * The opposite of `pause_effect`. We call this if (for example)
 * `x` becomes falsy then truthy: `{#if x}...{/if}`
 * @param {Effect} effect
 */
export function resume_effect(effect) {
	resume_children(effect, true);
}

/**
 * @param {Effect} effect
 * @param {boolean} local
 */
function resume_children(effect, local) {
	if ((effect.f & INERT) === 0) return;
	effect.f ^= INERT;

	var child = effect.first;

	while (child !== null) {
		var sibling = child.next;
		var transparent = (child.f & EFFECT_TRANSPARENT) !== 0 || (child.f & BRANCH_EFFECT) !== 0;
		// TODO we don't need to call resume_children recursively with a linked list in place
		// it's slightly more involved though as we have to account for `transparent` changing
		// through the tree.
		resume_children(child, transparent ? local : false);
		child = sibling;
	}

	if (effect.transitions !== null) {
		for (const transition of effect.transitions) {
			if (transition.is_global || local) {
				transition.in();
			}
		}
	}
}

Tool Call: store.js Status: Completed

/** @import { StoreReferencesContainer } from '#client' */
/** @import { Store } from '#shared' */
import { subscribe_to_store } from '../../../store/utils.js';
import { get as get_store } from '../../../store/shared/index.js';
import { define_property, noop } from '../../shared/utils.js';
import { get } from '../runtime.js';
import { teardown } from './effects.js';
import { mutable_source, set } from './sources.js';

/**
 * Whether or not the prop currently being read is a store binding, as in
 * `<Child bind:x={$y} />`. If it is, we treat the prop as mutable even in
 * runes mode, and skip `binding_property_non_reactive` validation
 */
let is_store_binding = false;

let IS_UNMOUNTED = Symbol();

/**
 * Gets the current value of a store. If the store isn't subscribed to yet, it will create a proxy
 * signal that will be updated when the store is. The store references container is needed to
 * track reassignments to stores and to track the correct component context.
 * @template V
 * @param {Store<V> | null | undefined} store
 * @param {string} store_name
 * @param {StoreReferencesContainer} stores
 * @returns {V}
 */
export function store_get(store, store_name, stores) {
	const entry = (stores[store_name] ??= {
		store: null,
		source: mutable_source(undefined),
		unsubscribe: noop
	});

	// if the component that setup this is already unmounted we don't want to register a subscription
	if (entry.store !== store && !(IS_UNMOUNTED in stores)) {
		entry.unsubscribe();
		entry.store = store ?? null;

		if (store == null) {
			entry.source.v = undefined; // see synchronous callback comment below
			entry.unsubscribe = noop;
		} else {
			var is_synchronous_callback = true;

			entry.unsubscribe = subscribe_to_store(store, (v) => {
				if (is_synchronous_callback) {
					// If the first updates to the store value (possibly multiple of them) are synchronously
					// inside a derived, we will hit the `state_unsafe_mutation` error if we `set` the value
					entry.source.v = v;
				} else {
					set(entry.source, v);
				}
			});

			is_synchronous_callback = false;
		}
	}

	// if the component that setup this stores is already unmounted the source will be out of sync
	// so we just use the `get` for the stores, less performant but it avoids to create a memory leak
	// and it will keep the value consistent
	if (store && IS_UNMOUNTED in stores) {
		return get_store(store);
	}

	return get(entry.source);
}

/**
 * Unsubscribe from a store if it's not the same as the one in the store references container.
 * We need this in addition to `store_get` because someone could unsubscribe from a store but
 * then never subscribe to the new one (if any), causing the subscription to stay open wrongfully.
 * @param {Store<any> | null | undefined} store
 * @param {string} store_name
 * @param {StoreReferencesContainer} stores
 */
export function store_unsub(store, store_name, stores) {
	/** @type {StoreReferencesContainer[''] | undefined} */
	let entry = stores[store_name];

	if (entry && entry.store !== store) {
		// Don't reset store yet, so that store_get above can resubscribe to new store if necessary
		entry.unsubscribe();
		entry.unsubscribe = noop;
	}

	return store;
}

/**
 * Sets the new value of a store and returns that value.
 * @template V
 * @param {Store<V>} store
 * @param {V} value
 * @returns {V}
 */
export function store_set(store, value) {
	store.set(value);
	return value;
}

/**
 * @param {StoreReferencesContainer} stores
 * @param {string} store_name
 */
export function invalidate_store(stores, store_name) {
	var entry = stores[store_name];
	if (entry.store !== null) {
		store_set(entry.store, entry.source.v);
	}
}

/**
 * Unsubscribes from all auto-subscribed stores on destroy
 * @returns {[StoreReferencesContainer, ()=>void]}
 */
export function setup_stores() {
	/** @type {StoreReferencesContainer} */
	const stores = {};

	function cleanup() {
		teardown(() => {
			for (var store_name in stores) {
				const ref = stores[store_name];
				ref.unsubscribe();
			}
			define_property(stores, IS_UNMOUNTED, {
				enumerable: false,
				value: true
			});
		});
	}

	return [stores, cleanup];
}

/**
 * Updates a store with a new value.
 * @param {Store<V>} store  the store to update
 * @param {any} expression  the expression that mutates the store
 * @param {V} new_value  the new store value
 * @template V
 */
export function store_mutate(store, expression, new_value) {
	store.set(new_value);
	return expression;
}

/**
 * @param {Store<number>} store
 * @param {number} store_value
 * @param {1 | -1} [d]
 * @returns {number}
 */
export function update_store(store, store_value, d = 1) {
	store.set(store_value + d);
	return store_value;
}

/**
 * @param {Store<number>} store
 * @param {number} store_value
 * @param {1 | -1} [d]
 * @returns {number}
 */
export function update_pre_store(store, store_value, d = 1) {
	const value = store_value + d;
	store.set(value);
	return value;
}

/**
 * Called inside prop getters to communicate that the prop is a store binding
 */
export function mark_store_binding() {
	is_store_binding = true;
}

/**
 * Returns a tuple that indicates whether `fn()` reads a prop that is a store binding.
 * Used to prevent `binding_property_non_reactive` validation false positives and
 * ensure that these props are treated as mutable even in runes mode
 * @template T
 * @param {() => T} fn
 * @returns {[T, boolean]}
 */
export function capture_store_binding(fn) {
	var previous_is_store_binding = is_store_binding;

	try {
		is_store_binding = false;
		return [fn(), is_store_binding];
	} finally {
		is_store_binding = previous_is_store_binding;
	}
}

Assistant

Now let me check the main index file to see what's exported from the runtime:

Tool Call: No matches Status: Completed

{"offset":0,"current_matches_page":[],"all_matches_len":0}

Tool Call: 25 matches Status: Completed

file:///Users/faraaz/oss/svelte/benchmarking/benchmarks/reactivity/index.js

file:///Users/faraaz/oss/svelte/benchmarking/benchmarks/ssr/index.js

file:///Users/faraaz/oss/svelte/benchmarking/compare/index.js

file:///Users/faraaz/oss/svelte/packages/svelte/scripts/process-messages/index.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/animate/index.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/attachments/index.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/compiler/index.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/compiler/migrate/index.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/compiler/phases/1-parse/index.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/compiler/phases/2-analyze/index.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/compiler/phases/3-transform/client/transform-template/index.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/compiler/phases/3-transform/css/index.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/compiler/phases/3-transform/index.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/compiler/preprocess/index.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/easing/index.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/events/index.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/client/index.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/flags/index.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/index.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/internal/server/index.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/motion/index.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/reactivity/window/index.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/server/index.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/store/shared/index.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/transition/index.js

Tool Call: index.js Status: Completed

export { createAttachmentKey as attachment } from '../../attachments/index.js';
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';
export { hmr } from './dev/hmr.js';
export { create_ownership_validator } from './dev/ownership.js';
export { check_target, legacy_api } from './dev/legacy.js';
export { trace, tag, tag_proxy } from './dev/tracing.js';
export { inspect } from './dev/inspect.js';
export { validate_snippet_args } from './dev/validation.js';
export { await_block as await } from './dom/blocks/await.js';
export { if_block as if } from './dom/blocks/if.js';
export { key_block as key } from './dom/blocks/key.js';
export { css_props } from './dom/blocks/css-props.js';
export { index, each } from './dom/blocks/each.js';
export { html } from './dom/blocks/html.js';
export { sanitize_slots, slot } from './dom/blocks/slot.js';
export { snippet, wrap_snippet } from './dom/blocks/snippet.js';
export { component } from './dom/blocks/svelte-component.js';
export { element } from './dom/blocks/svelte-element.js';
export { head } from './dom/blocks/svelte-head.js';
export { append_styles } from './dom/css.js';
export { action } from './dom/elements/actions.js';
export { attach } from './dom/elements/attachments.js';
export {
	remove_input_defaults,
	set_attribute,
	set_attributes,
	attribute_effect,
	set_custom_element_data,
	set_xlink_attribute,
	set_value,
	set_checked,
	set_selected,
	set_default_checked,
	set_default_value,
	CLASS,
	STYLE
} from './dom/elements/attributes.js';
export { set_class } from './dom/elements/class.js';
export { apply, event, delegate, replay_events } from './dom/elements/events.js';
export { autofocus, remove_textarea_child } from './dom/elements/misc.js';
export { set_style } from './dom/elements/style.js';
export { animation, transition } from './dom/elements/transitions.js';
export { bind_active_element } from './dom/elements/bindings/document.js';
export { bind_checked, bind_files, bind_group, bind_value } from './dom/elements/bindings/input.js';
export {
	bind_buffered,
	bind_current_time,
	bind_ended,
	bind_muted,
	bind_paused,
	bind_playback_rate,
	bind_played,
	bind_ready_state,
	bind_seekable,
	bind_seeking,
	bind_volume
} from './dom/elements/bindings/media.js';
export { bind_online } from './dom/elements/bindings/navigator.js';
export { bind_prop } from './dom/elements/bindings/props.js';
export { bind_select_value, init_select, select_option } from './dom/elements/bindings/select.js';
export { bind_element_size, bind_resize_observer } from './dom/elements/bindings/size.js';
export { bind_this } from './dom/elements/bindings/this.js';
export {
	bind_content_editable,
	bind_property,
	bind_focused
} from './dom/elements/bindings/universal.js';
export { bind_window_scroll, bind_window_size } from './dom/elements/bindings/window.js';
export { hydrate_template, next, reset } from './dom/hydration.js';
export {
	once,
	preventDefault,
	self,
	stopImmediatePropagation,
	stopPropagation,
	trusted
} from './dom/legacy/event-modifiers.js';
export { init } from './dom/legacy/lifecycle.js';
export {
	add_legacy_event_listener,
	bubble_event,
	reactive_import,
	update_legacy_props
} from './dom/legacy/misc.js';
export {
	append,
	comment,
	from_html,
	from_mathml,
	from_svg,
	from_tree,
	text,
	props_id,
	with_script
} from './dom/template.js';
export { user_derived as derived, derived_safe_equal } from './reactivity/deriveds.js';
export {
	effect_tracking,
	effect_root,
	legacy_pre_effect,
	legacy_pre_effect_reset,
	render_effect,
	template_effect,
	effect,
	user_effect,
	user_pre_effect
} from './reactivity/effects.js';
export { mutable_source, mutate, set, state, update, update_pre } from './reactivity/sources.js';
export {
	prop,
	rest_props,
	legacy_rest_props,
	spread_props,
	update_pre_prop,
	update_prop
} from './reactivity/props.js';
export {
	invalidate_store,
	store_mutate,
	setup_stores,
	store_get,
	store_set,
	store_unsub,
	update_pre_store,
	update_store,
	mark_store_binding
} from './reactivity/store.js';
export { boundary } from './dom/blocks/boundary.js';
export { set_text } from './render.js';
export {
	get,
	safe_get,
	invalidate_inner_signals,
	flushSync as flush,
	tick,
	untrack,
	exclude_from_object,
	deep_read,
	deep_read_state
} from './runtime.js';
export { validate_binding, validate_each_keys } from './validate.js';
export { raf } from './timing.js';
export { proxy } from './proxy.js';
export { create_custom_element } from './dom/elements/custom-element.js';
export {
	child,
	first_child,
	sibling,
	$window as window,
	$document as document
} from './dom/operations.js';
export { attr, clsx } from '../shared/attributes.js';
export { snapshot } from '../shared/clone.js';
export { noop, fallback, to_array } from '../shared/utils.js';
export {
	invalid_default_snippet,
	validate_dynamic_element_tag,
	validate_store,
	validate_void_dynamic_element,
	prevent_snippet_stringification
} from '../shared/validate.js';
export { strict_equals, equals } from './dev/equality.js';
export { log_if_contains_state } from './dev/console-log.js';

Assistant

Let me also check the main exported API from Svelte:

Tool Call: 4 matches Status: Completed

file:///Users/faraaz/oss/svelte/package.json

file:///Users/faraaz/oss/svelte/packages/svelte/compiler/package.json

file:///Users/faraaz/oss/svelte/packages/svelte/package.json

file:///Users/faraaz/oss/svelte/playgrounds/sandbox/package.json

Tool Call: package.json Status: Completed

{
  "name": "svelte",
  "description": "Cybernetically enhanced web apps",
  "license": "MIT",
  "version": "5.34.8",
  "type": "module",
  "types": "./types/index.d.ts",
  "engines": {
    "node": ">=18"
  },
  "files": [
    "*.d.ts",
    "src",
    "!src/**/*.test.*",
    "!src/**/*.d.ts",
    "types",
    "compiler",
    "README.md"
  ],
  "module": "src/index-client.js",
  "main": "src/index-client.js",
  "exports": {
    ".": {
      "types": "./types/index.d.ts",
      "worker": "./src/index-server.js",
      "browser": "./src/index-client.js",
      "default": "./src/index-server.js"
    },
    "./package.json": "./package.json",
    "./action": {
      "types": "./types/index.d.ts"
    },
    "./animate": {
      "types": "./types/index.d.ts",
      "default": "./src/animate/index.js"
    },
    "./attachments": {
      "types": "./types/index.d.ts",
      "default": "./src/attachments/index.js"
    },
    "./compiler": {
      "types": "./types/index.d.ts",
      "require": "./compiler/index.js",
      "default": "./src/compiler/index.js"
    },
    "./easing": {
      "types": "./types/index.d.ts",
      "default": "./src/easing/index.js"
    },
    "./elements": {
      "types": "./elements.d.ts"
    },
    "./internal": {
      "default": "./src/internal/index.js"
    },
    "./internal/client": {
      "default": "./src/internal/client/index.js"
    },
    "./internal/disclose-version": {
      "default": "./src/internal/disclose-version.js"
    },
    "./internal/flags/legacy": {
      "default": "./src/internal/flags/legacy.js"
    },
    "./internal/flags/tracing": {
      "default": "./src/internal/flags/tracing.js"
    },
    "./internal/server": {
      "default": "./src/internal/server/index.js"
    },
    "./legacy": {
      "types": "./types/index.d.ts",
      "worker": "./src/legacy/legacy-server.js",
      "browser": "./src/legacy/legacy-client.js",
      "default": "./src/legacy/legacy-server.js"
    },
    "./motion": {
      "types": "./types/index.d.ts",
      "default": "./src/motion/index.js"
    },
    "./reactivity": {
      "types": "./types/index.d.ts",
      "worker": "./src/reactivity/index-server.js",
      "browser": "./src/reactivity/index-client.js",
      "default": "./src/reactivity/index-server.js"
    },
    "./reactivity/window": {
      "types": "./types/index.d.ts",
      "default": "./src/reactivity/window/index.js"
    },
    "./server": {
      "types": "./types/index.d.ts",
      "default": "./src/server/index.js"
    },
    "./store": {
      "types": "./types/index.d.ts",
      "worker": "./src/store/index-server.js",
      "browser": "./src/store/index-client.js",
      "default": "./src/store/index-server.js"
    },
    "./transition": {
      "types": "./types/index.d.ts",
      "default": "./src/transition/index.js"
    },
    "./events": {
      "types": "./types/index.d.ts",
      "default": "./src/events/index.js"
    }
  },
  "imports": {
    "#client": "./src/internal/client/types.d.ts",
    "#client/constants": "./src/internal/client/constants.js",
    "#compiler": {
      "types": "./src/compiler/private.d.ts",
      "default": "./src/compiler/index.js"
    },
    "#compiler/builders": "./src/compiler/utils/builders.js",
    "#server": "./src/internal/server/types.d.ts",
    "#shared": "./src/internal/shared/types.d.ts"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/sveltejs/svelte.git",
    "directory": "packages/svelte"
  },
  "bugs": {
    "url": "https://github.com/sveltejs/svelte/issues"
  },
  "homepage": "https://svelte.dev",
  "keywords": [
    "svelte",
    "UI",
    "framework",
    "templates",
    "templating"
  ],
  "scripts": {
    "build": "node scripts/process-messages && rollup -c && pnpm generate:types && node scripts/check-treeshakeability.js",
    "dev": "node scripts/process-messages -w & rollup -cw",
    "check": "tsc --project tsconfig.runtime.json && tsc && cd ./tests/types && tsc",
    "check:watch": "tsc --watch",
    "generate:version": "node ./scripts/generate-version.js",
    "generate:types": "node ./scripts/generate-types.js && tsc -p tsconfig.generated.json",
    "prepublishOnly": "pnpm build",
    "knip": "pnpm dlx knip"
  },
  "devDependencies": {
    "@jridgewell/trace-mapping": "^0.3.25",
    "@playwright/test": "^1.46.1",
    "@rollup/plugin-commonjs": "^28.0.1",
    "@rollup/plugin-node-resolve": "^15.3.0",
    "@rollup/plugin-terser": "^0.4.4",
    "@rollup/plugin-virtual": "^3.0.2",
    "@types/aria-query": "^5.0.4",
    "@types/node": "^20.11.5",
    "dts-buddy": "^0.5.5",
    "esbuild": "^0.21.5",
    "rollup": "^4.22.4",
    "source-map": "^0.7.4",
    "tinyglobby": "^0.2.12",
    "typescript": "^5.5.4",
    "vitest": "^2.1.9"
  },
  "dependencies": {
    "@ampproject/remapping": "^2.3.0",
    "@jridgewell/sourcemap-codec": "^1.5.0",
    "@types/estree": "^1.0.5",
    "acorn": "^8.12.1",
    "@sveltejs/acorn-typescript": "^1.0.5",
    "aria-query": "^5.3.1",
    "axobject-query": "^4.1.0",
    "clsx": "^2.1.1",
    "esm-env": "^1.2.1",
    "esrap": "^1.4.8",
    "is-reference": "^3.0.3",
    "locate-character": "^3.0.0",
    "magic-string": "^0.30.11",
    "zimmerframe": "^1.1.2"
  }
}

Tool Call: index-client.js Status: Failed

svelte/src/reactivity/index-client.js not found

Tool Call: index-client.js Status: Completed

export { SvelteDate } from './date.js';
export { SvelteSet } from './set.js';
export { SvelteMap } from './map.js';
export { SvelteURL } from './url.js';
export { SvelteURLSearchParams } from './url-search-params.js';
export { MediaQuery } from './media-query.js';
export { createSubscriber } from './create-subscriber.js';

Assistant

Let me check the legacy store implementations as well:

Tool Call: 4 matches Status: Completed

file:///Users/faraaz/oss/svelte/packages/svelte/src/store/index-client.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/store/index-server.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/store/shared/index.js

file:///Users/faraaz/oss/svelte/packages/svelte/src/store/utils.js

Tool Call: index.js Status: Completed

/** @import { Readable, StartStopNotifier, Subscriber, Unsubscriber, Updater, Writable } from '../public.js' */
/** @import { Stores, StoresValues, SubscribeInvalidateTuple } from '../private.js' */
import { noop, run_all } from '../../internal/shared/utils.js';
import { safe_not_equal } from '../../internal/client/reactivity/equality.js';
import { subscribe_to_store } from '../utils.js';

/**
 * @type {Array<SubscribeInvalidateTuple<any> | any>}
 */
const subscriber_queue = [];

/**
 * Creates a `Readable` store that allows reading by subscription.
 *
 * @template T
 * @param {T} [value] initial value
 * @param {StartStopNotifier<T>} [start]
 * @returns {Readable<T>}
 */
export function readable(value, start) {
	return {
		subscribe: writable(value, start).subscribe
	};
}

/**
 * Create a `Writable` store that allows both updating and reading by subscription.
 *
 * @template T
 * @param {T} [value] initial value
 * @param {StartStopNotifier<T>} [start]
 * @returns {Writable<T>}
 */
export function writable(value, start = noop) {
	/** @type {Unsubscriber | null} */
	let stop = null;

	/** @type {Set<SubscribeInvalidateTuple<T>>} */
	const subscribers = new Set();

	/**
	 * @param {T} new_value
	 * @returns {void}
	 */
	function set(new_value) {
		if (safe_not_equal(value, new_value)) {
			value = new_value;
			if (stop) {
				// store is ready
				const run_queue = !subscriber_queue.length;
				for (const subscriber of subscribers) {
					subscriber[1]();
					subscriber_queue.push(subscriber, value);
				}
				if (run_queue) {
					for (let i = 0; i < subscriber_queue.length; i += 2) {
						subscriber_queue[i][0](subscriber_queue[i + 1]);
					}
					subscriber_queue.length = 0;
				}
			}
		}
	}

	/**
	 * @param {Updater<T>} fn
	 * @returns {void}
	 */
	function update(fn) {
		set(fn(/** @type {T} */ (value)));
	}

	/**
	 * @param {Subscriber<T>} run
	 * @param {() => void} [invalidate]
	 * @returns {Unsubscriber}
	 */
	function subscribe(run, invalidate = noop) {
		/** @type {SubscribeInvalidateTuple<T>} */
		const subscriber = [run, invalidate];
		subscribers.add(subscriber);
		if (subscribers.size === 1) {
			stop = start(set, update) || noop;
		}
		run(/** @type {T} */ (value));
		return () => {
			subscribers.delete(subscriber);
			if (subscribers.size === 0 && stop) {
				stop();
				stop = null;
			}
		};
	}
	return { set, update, subscribe };
}

/**
 * Derived value store by synchronizing one or more readable stores and
 * applying an aggregation function over its input values.
 *
 * @template {Stores} S
 * @template T
 * @overload
 * @param {S} stores
 * @param {(values: StoresValues<S>, set: (value: T) => void, update: (fn: Updater<T>) => void) => Unsubscriber | void} fn
 * @param {T} [initial_value]
 * @returns {Readable<T>}
 */
/**
 * Derived value store by synchronizing one or more readable stores and
 * applying an aggregation function over its input values.
 *
 * @template {Stores} S
 * @template T
 * @overload
 * @param {S} stores
 * @param {(values: StoresValues<S>) => T} fn
 * @param {T} [initial_value]
 * @returns {Readable<T>}
 */
/**
 * @template {Stores} S
 * @template T
 * @param {S} stores
 * @param {Function} fn
 * @param {T} [initial_value]
 * @returns {Readable<T>}
 */
export function derived(stores, fn, initial_value) {
	const single = !Array.isArray(stores);
	/** @type {Array<Readable<any>>} */
	const stores_array = single ? [stores] : stores;
	if (!stores_array.every(Boolean)) {
		throw new Error('derived() expects stores as input, got a falsy value');
	}
	const auto = fn.length < 2;
	return readable(initial_value, (set, update) => {
		let started = false;
		/** @type {T[]} */
		const values = [];
		let pending = 0;
		let cleanup = noop;
		const sync = () => {
			if (pending) {
				return;
			}
			cleanup();
			const result = fn(single ? values[0] : values, set, update);
			if (auto) {
				set(result);
			} else {
				cleanup = typeof result === 'function' ? result : noop;
			}
		};
		const unsubscribers = stores_array.map((store, i) =>
			subscribe_to_store(
				store,
				(value) => {
					values[i] = value;
					pending &= ~(1 << i);
					if (started) {
						sync();
					}
				},
				() => {
					pending |= 1 << i;
				}
			)
		);
		started = true;
		sync();
		return function stop() {
			run_all(unsubscribers);
			cleanup();
			// We need to set this to false because callbacks can still happen despite having unsubscribed:
			// Callbacks might already be placed in the queue which doesn't know it should no longer
			// invoke this derived store.
			started = false;
		};
	});
}

/**
 * Takes a store and returns a new one derived from the old one that is readable.
 *
 * @template T
 * @param {Readable<T>} store  - store to make readonly
 * @returns {Readable<T>}
 */
export function readonly(store) {
	return {
		// @ts-expect-error TODO i suspect the bind is unnecessary
		subscribe: store.subscribe.bind(store)
	};
}

/**
 * Get the current value from a store by subscribing and immediately unsubscribing.
 *
 * @template T
 * @param {Readable<T>} store
 * @returns {T}
 */
export function get(store) {
	let value;
	subscribe_to_store(store, (_) => (value = _))();
	// @ts-expect-error
	return value;
}

Assistant

Now let me search for additional state management functions that might be in other files:

Tool Call: Search files for regex export.*function.*(prop|bind|reactive|signal|watch) Status: Completed

Showing matches 1-20 (there were more matches found; use offset: 20 to see next page):

Matches in svelte/benchmarking/benchmarks/reactivity/sbench.js

L151-161

export async function sbench_create_signals() {
	// Do 3 loops to warm up JIT
	for (let i = 0; i < 3; i++) {
		bench(create_data_signals, COUNT, COUNT);
	}

	const { timing } = await fastest_test(10, () => {
		for (let i = 0; i < 100; i++) {
			bench(create_data_signals, COUNT, COUNT);
		}
	});

7 lines remaining in ancestor node. Read the file to see all.

Matches in svelte/packages/svelte/src/compiler/errors.js

L83-85

export function bindable_invalid_location(node) {
	e(node, 'bindable_invalid_location', `\`$bindable()\` can only be used inside a \`$props()\` declaration\nhttps://svelte.dev/e/bindable_invalid_location`);
}

L103-105

export function constant_binding(node, thing) {
	e(node, 'constant_binding', `Cannot bind to ${thing}\nhttps://svelte.dev/e/constant_binding`);
}

L140-142

export function dollar_binding_invalid(node) {
	e(node, 'dollar_binding_invalid', `The $ name is reserved, and cannot be used for variables and imports\nhttps://svelte.dev/e/dollar_binding_invalid`);
}

L250-252

export function legacy_props_invalid(node) {
	e(node, 'legacy_props_invalid', `Cannot use \`$$props\` in runes mode\nhttps://svelte.dev/e/legacy_props_invalid`);
}

L259-261

export function legacy_reactive_statement_invalid(node) {
	e(node, 'legacy_reactive_statement_invalid', `\`$:\` is not allowed in runes mode, use \`$derived\` or \`$effect\` instead\nhttps://svelte.dev/e/legacy_reactive_statement_invalid`);
}

L268-270

export function legacy_rest_props_invalid(node) {
	e(node, 'legacy_rest_props_invalid', `Cannot use \`$$restProps\` in runes mode\nhttps://svelte.dev/e/legacy_rest_props_invalid`);
}

L287-289

export function props_duplicate(node, rune) {
	e(node, 'props_duplicate', `Cannot use \`${rune}()\` more than once\nhttps://svelte.dev/e/props_duplicate`);
}

L296-298

export function props_id_invalid_placement(node) {
	e(node, 'props_id_invalid_placement', `\`$props.id()\` can only be used at the top level of components as a variable declaration initializer\nhttps://svelte.dev/e/props_id_invalid_placement`);
}

L305-307

export function props_illegal_name(node) {
	e(node, 'props_illegal_name', `Declaring or accessing a prop starting with \`$$\` is illegal (they are reserved for Svelte internals)\nhttps://svelte.dev/e/props_illegal_name`);
}

L314-316

export function props_invalid_identifier(node) {
	e(node, 'props_invalid_identifier', `\`$props()\` can only be used with an object destructuring pattern\nhttps://svelte.dev/e/props_invalid_identifier`);
}

L323-325

export function props_invalid_pattern(node) {
	e(node, 'props_invalid_pattern', `\`$props()\` assignment must not contain nested properties or computed keys\nhttps://svelte.dev/e/props_invalid_pattern`);
}

L332-334

export function props_invalid_placement(node) {
	e(node, 'props_invalid_placement', `\`$props()\` can only be used at the top level of components as a variable declaration initializer\nhttps://svelte.dev/e/props_invalid_placement`);
}

L342-344

export function reactive_declaration_cycle(node, cycle) {
	e(node, 'reactive_declaration_cycle', `Cyclical dependency detected: ${cycle}\nhttps://svelte.dev/e/reactive_declaration_cycle`);
}

L372-374

export function rune_invalid_computed_property(node) {
	e(node, 'rune_invalid_computed_property', `Cannot access a computed property of a rune\nhttps://svelte.dev/e/rune_invalid_computed_property`);
}

L483-487

/**
 * Cannot export state from a module if it is reassigned. Either export a function returning the state value or only mutate the state value's properties
 * @param {null | number | NodeLike} node
 * @returns {never}
 */

function state_invalid_export( ) › L488-490

export function state_invalid_export(node) {
	e(node, 'state_invalid_export', `Cannot export state from a module if it is reassigned. Either export a function returning the state value or only mutate the state value's properties\nhttps://svelte.dev/e/state_invalid_export`);
}

L789-791

export function bind_group_invalid_expression(node) {
	e(node, 'bind_group_invalid_expression', `\`bind:group\` can only bind to an Identifier or MemberExpression\nhttps://svelte.dev/e/bind_group_invalid_expression`);
}

L798-800

export function bind_group_invalid_snippet_parameter(node) {
	e(node, 'bind_group_invalid_snippet_parameter', `Cannot \`bind:group\` to a snippet parameter\nhttps://svelte.dev/e/bind_group_invalid_snippet_parameter`);
}

L807-809

export function bind_invalid_expression(node) {
	e(node, 'bind_invalid_expression', `Can only bind to an Identifier or MemberExpression or a \`{get, set}\` pair\nhttps://svelte.dev/e/bind_invalid_expression`);
}

Assistant

Let me search for more specific functions in the reactivity/props file:

Tool Call: props.js Status: Completed

/** @import { Derived, Source } from './types.js' */
import { DEV } from 'esm-env';
import {
	PROPS_IS_BINDABLE,
	PROPS_IS_IMMUTABLE,
	PROPS_IS_LAZY_INITIAL,
	PROPS_IS_RUNES,
	PROPS_IS_UPDATED
} from '../../../constants.js';
import { get_descriptor, is_function } from '../../shared/utils.js';
import { mutable_source, set, source, update } from './sources.js';
import { derived, derived_safe_equal } from './deriveds.js';
import { get, captured_signals, untrack } from '../runtime.js';
import { safe_equals } from './equality.js';
import * as e from '../errors.js';
import { LEGACY_DERIVED_PROP, LEGACY_PROPS, STATE_SYMBOL } from '#client/constants';
import { proxy } from '../proxy.js';
import { capture_store_binding } from './store.js';
import { legacy_mode_flag } from '../../flags/index.js';

/**
 * @param {((value?: number) => number)} fn
 * @param {1 | -1} [d]
 * @returns {number}
 */
export function update_prop(fn, d = 1) {
	const value = fn();
	fn(value + d);
	return value;
}

/**
 * @param {((value?: number) => number)} fn
 * @param {1 | -1} [d]
 * @returns {number}
 */
export function update_pre_prop(fn, d = 1) {
	const value = fn() + d;
	fn(value);
	return value;
}

/**
 * The proxy handler for rest props (i.e. `const { x, ...rest } = $props()`).
 * Is passed the full `$$props` object and excludes the named props.
 * @type {ProxyHandler<{ props: Record<string | symbol, unknown>, exclude: Array<string | symbol>, name?: string }>}}
 */
const rest_props_handler = {
	get(target, key) {
		if (target.exclude.includes(key)) return;
		return target.props[key];
	},
	set(target, key) {
		if (DEV) {
			// TODO should this happen in prod too?
			e.props_rest_readonly(`${target.name}.${String(key)}`);
		}

		return false;
	},
	getOwnPropertyDescriptor(target, key) {
		if (target.exclude.includes(key)) return;
		if (key in target.props) {
			return {
				enumerable: true,
				configurable: true,
				value: target.props[key]
			};
		}
	},
	has(target, key) {
		if (target.exclude.includes(key)) return false;
		return key in target.props;
	},
	ownKeys(target) {
		return Reflect.ownKeys(target.props).filter((key) => !target.exclude.includes(key));
	}
};

/**
 * @param {Record<string, unknown>} props
 * @param {string[]} exclude
 * @param {string} [name]
 * @returns {Record<string, unknown>}
 */
/*#__NO_SIDE_EFFECTS__*/
export function rest_props(props, exclude, name) {
	return new Proxy(
		DEV ? { props, exclude, name, other: {}, to_proxy: [] } : { props, exclude },
		rest_props_handler
	);
}

/**
 * The proxy handler for legacy $$restProps and $$props
 * @type {ProxyHandler<{ props: Record<string | symbol, unknown>, exclude: Array<string | symbol>, special: Record<string | symbol, (v?: unknown) => unknown>, version: Source<number> }>}}
 */
const legacy_rest_props_handler = {
	get(target, key) {
		if (target.exclude.includes(key)) return;
		get(target.version);
		return key in target.special ? target.special[key]() : target.props[key];
	},
	set(target, key, value) {
		if (!(key in target.special)) {
			// Handle props that can temporarily get out of sync with the parent
			/** @type {Record<string, (v?: unknown) => unknown>} */
			target.special[key] = prop(
				{
					get [key]() {
						return target.props[key];
					}
				},
				/** @type {string} */ (key),
				PROPS_IS_UPDATED
			);
		}

		target.special[key](value);
		update(target.version); // $$props is coarse-grained: when $$props.x is updated, usages of $$props.y etc are also rerun
		return true;
	},
	getOwnPropertyDescriptor(target, key) {
		if (target.exclude.includes(key)) return;
		if (key in target.props) {
			return {
				enumerable: true,
				configurable: true,
				value: target.props[key]
			};
		}
	},
	deleteProperty(target, key) {
		// Svelte 4 allowed for deletions on $$restProps
		if (target.exclude.includes(key)) return true;
		target.exclude.push(key);
		update(target.version);
		return true;
	},
	has(target, key) {
		if (target.exclude.includes(key)) return false;
		return key in target.props;
	},
	ownKeys(target) {
		return Reflect.ownKeys(target.props).filter((key) => !target.exclude.includes(key));
	}
};

/**
 * @param {Record<string, unknown>} props
 * @param {string[]} exclude
 * @returns {Record<string, unknown>}
 */
export function legacy_rest_props(props, exclude) {
	return new Proxy({ props, exclude, special: {}, version: source(0) }, legacy_rest_props_handler);
}

/**
 * The proxy handler for spread props. Handles the incoming array of props
 * that looks like `() => { dynamic: props }, { static: prop }, ..` and wraps
 * them so that the whole thing is passed to the component as the `$$props` argument.
 * @template {Record<string | symbol, unknown>} T
 * @type {ProxyHandler<{ props: Array<T | (() => T)> }>}}
 */
const spread_props_handler = {
	get(target, key) {
		let i = target.props.length;
		while (i--) {
			let p = target.props[i];
			if (is_function(p)) p = p();
			if (typeof p === 'object' && p !== null && key in p) return p[key];
		}
	},
	set(target, key, value) {
		let i = target.props.length;
		while (i--) {
			let p = target.props[i];
			if (is_function(p)) p = p();
			const desc = get_descriptor(p, key);
			if (desc && desc.set) {
				desc.set(value);
				return true;
			}
		}
		return false;
	},
	getOwnPropertyDescriptor(target, key) {
		let i = target.props.length;
		while (i--) {
			let p = target.props[i];
			if (is_function(p)) p = p();
			if (typeof p === 'object' && p !== null && key in p) {
				const descriptor = get_descriptor(p, key);
				if (descriptor && !descriptor.configurable) {
					// Prevent a "Non-configurability Report Error": The target is an array, it does
					// not actually contain this property. If it is now described as non-configurable,
					// the proxy throws a validation error. Setting it to true avoids that.
					descriptor.configurable = true;
				}
				return descriptor;
			}
		}
	},
	has(target, key) {
		// To prevent a false positive `is_entry_props` in the `prop` function
		if (key === STATE_SYMBOL || key === LEGACY_PROPS) return false;

		for (let p of target.props) {
			if (is_function(p)) p = p();
			if (p != null && key in p) return true;
		}

		return false;
	},
	ownKeys(target) {
		/** @type {Array<string | symbol>} */
		const keys = [];

		for (let p of target.props) {
			if (is_function(p)) p = p();
			if (!p) continue;

			for (const key in p) {
				if (!keys.includes(key)) keys.push(key);
			}

			for (const key of Object.getOwnPropertySymbols(p)) {
				if (!keys.includes(key)) keys.push(key);
			}
		}

		return keys;
	}
};

/**
 * @param {Array<Record<string, unknown> | (() => Record<string, unknown>)>} props
 * @returns {any}
 */
export function spread_props(...props) {
	return new Proxy({ props }, spread_props_handler);
}

/**
 * @param {Derived} current_value
 * @returns {boolean}
 */
function has_destroyed_component_ctx(current_value) {
	return current_value.ctx?.d ?? false;
}

/**
 * This function is responsible for synchronizing a possibly bound prop with the inner component state.
 * It is used whenever the compiler sees that the component writes to the prop, or when it has a default prop_value.
 * @template V
 * @param {Record<string, unknown>} props
 * @param {string} key
 * @param {number} flags
 * @param {V | (() => V)} [fallback]
 * @returns {(() => V | ((arg: V) => V) | ((arg: V, mutation: boolean) => V))}
 */
export function prop(props, key, flags, fallback) {
	var immutable = (flags & PROPS_IS_IMMUTABLE) !== 0;
	var runes = !legacy_mode_flag || (flags & PROPS_IS_RUNES) !== 0;
	var bindable = (flags & PROPS_IS_BINDABLE) !== 0;
	var lazy = (flags & PROPS_IS_LAZY_INITIAL) !== 0;
	var is_store_sub = false;
	var prop_value;

	if (bindable) {
		[prop_value, is_store_sub] = capture_store_binding(() => /** @type {V} */ (props[key]));
	} else {
		prop_value = /** @type {V} */ (props[key]);
	}

	// Can be the case when someone does `mount(Component, props)` with `let props = $state({...})`
	// or `createClassComponent(Component, props)`
	var is_entry_props = STATE_SYMBOL in props || LEGACY_PROPS in props;

	var setter =
		(bindable &&
			(get_descriptor(props, key)?.set ??
				(is_entry_props && key in props && ((v) => (props[key] = v))))) ||
		undefined;

	var fallback_value = /** @type {V} */ (fallback);
	var fallback_dirty = true;
	var fallback_used = false;

	var get_fallback = () => {
		fallback_used = true;
		if (fallback_dirty) {
			fallback_dirty = false;
			if (lazy) {
				fallback_value = untrack(/** @type {() => V} */ (fallback));
			} else {
				fallback_value = /** @type {V} */ (fallback);
			}
		}

		return fallback_value;
	};

	if (prop_value === undefined && fallback !== undefined) {
		if (setter && runes) {
			e.props_invalid_value(key);
		}

		prop_value = get_fallback();
		if (setter) setter(prop_value);
	}

	/** @type {() => V} */
	var getter;
	if (runes) {
		getter = () => {
			var value = /** @type {V} */ (props[key]);
			if (value === undefined) return get_fallback();
			fallback_dirty = true;
			fallback_used = false;
			return value;
		};
	} else {
		// Svelte 4 did not trigger updates when a primitive value was updated to the same value.
		// Replicate that behavior through using a derived
		var derived_getter = (immutable ? derived : derived_safe_equal)(
			() => /** @type {V} */ (props[key])
		);
		derived_getter.f |= LEGACY_DERIVED_PROP;
		getter = () => {
			var value = get(derived_getter);
			if (value !== undefined) fallback_value = /** @type {V} */ (undefined);
			return value === undefined ? fallback_value : value;
		};
	}

	// easy mode — prop is never written to
	if ((flags & PROPS_IS_UPDATED) === 0 && runes) {
		return getter;
	}

	// intermediate mode — prop is written to, but the parent component had
	// `bind:foo` which means we can just call `$$props.foo = value` directly
	if (setter) {
		var legacy_parent = props.$$legacy;
		return function (/** @type {any} */ value, /** @type {boolean} */ mutation) {
			if (arguments.length > 0) {
				// We don't want to notify if the value was mutated and the parent is in runes mode.
				// In that case the state proxy (if it exists) should take care of the notification.
				// If the parent is not in runes mode, we need to notify on mutation, too, that the prop
				// has changed because the parent will not be able to detect the change otherwise.
				if (!runes || !mutation || legacy_parent || is_store_sub) {
					/** @type {Function} */ (setter)(mutation ? getter() : value);
				}
				return value;
			} else {
				return getter();
			}
		};
	}

	// hard mode. this is where it gets ugly — the value in the child should
	// synchronize with the parent, but it should also be possible to temporarily
	// set the value to something else locally.
	var from_child = false;
	var was_from_child = false;

	// The derived returns the current value. The underlying mutable
	// source is written to from various places to persist this value.
	var inner_current_value = mutable_source(prop_value);
	var current_value = derived(() => {
		var parent_value = getter();
		var child_value = get(inner_current_value);

		if (from_child) {
			from_child = false;
			was_from_child = true;
			return child_value;
		}

		was_from_child = false;
		return (inner_current_value.v = parent_value);
	});

	// Ensure we eagerly capture the initial value if it's bindable
	if (bindable) {
		get(current_value);
	}

	if (!immutable) current_value.equals = safe_equals;

	return function (/** @type {any} */ value, /** @type {boolean} */ mutation) {
		// legacy nonsense — need to ensure the source is invalidated when necessary
		// also needed for when handling inspect logic so we can inspect the correct source signal
		if (captured_signals !== null) {
			// set this so that we don't reset to the parent value if `d`
			// is invalidated because of `invalidate_inner_signals` (rather
			// than because the parent or child value changed)
			from_child = was_from_child;
			// invoke getters so that signals are picked up by `invalidate_inner_signals`
			getter();
			get(inner_current_value);
		}

		if (arguments.length > 0) {
			const new_value = mutation ? get(current_value) : runes && bindable ? proxy(value) : value;

			if (!current_value.equals(new_value)) {
				from_child = true;
				set(inner_current_value, new_value);
				// To ensure the fallback value is consistent when used with proxies, we
				// update the local fallback_value, but only if the fallback is actively used
				if (fallback_used && fallback_value !== undefined) {
					fallback_value = new_value;
				}

				if (has_destroyed_component_ctx(current_value)) {
					return value;
				}

				untrack(() => get(current_value)); // force a synchronisation immediately
			}

			return value;
		}

		if (has_destroyed_component_ctx(current_value)) {
			return current_value.v;
		}

		return get(current_value);
	};
}

Assistant

Now let me search for more utility functions that manage state:

Tool Call: Search files for regex export.*function.*(get|set|update|mutate|bind|trigger|watch|observe) Status: Completed

Showing matches 1-20 (there were more matches found; use offset: 20 to see next page):

Matches in svelte/packages/svelte/src/internal/client/context.js

L19-21

export function set_component_context(context) {
	component_context = context;
}

L36-38

export function set_dev_current_component_function(fn) {
	dev_current_component_function = fn;
}

L48-52

export function getContext(key) {
	const context_map = get_or_init_context_map('getContext');
	const result = /** @type {T} */ (context_map.get(key));
	return result;
}

L66-70

export function setContext(key, context) {
	const context_map = get_or_init_context_map('setContext');
	context_map.set(key, context);
	return context;
}

L92-95

export function getAllContexts() {
	const context_map = get_or_init_context_map('getAllContexts');
	return /** @type {T} */ (context_map);
}

Matches in svelte/packages/svelte/src/internal/client/dev/hmr.js

L15-25

export function hmr(original, get_source) {
	/**
	 * @param {TemplateNode} anchor
	 * @param {any} props
	 */
	function wrapper(anchor, props) {
		let instance = {};

		/** @type {Effect} */
		let effect;

53 lines remaining in ancestor node. Read the file to see all.

Matches in svelte/packages/svelte/src/internal/client/dev/inspect.js

L11-21

export function inspect(get_value, inspector = console.log) {
	validate_effect('$inspect');

	let initial = true;

	inspect_effect(() => {
		/** @type {any} */
		var value = UNINITIALIZED;

		// Capturing the value might result in an exception due to the inspect effect being
		// sync and thus operating on stale data. In the case we encounter an exception we

19 lines remaining in ancestor node. Read the file to see all.

Matches in svelte/packages/svelte/src/internal/client/dev/legacy.js

L6-10

export function check_target(target) {
	if (target) {
		e.component_api_invalid_new(target[FILENAME] ?? 'a component', target.name);
	}
}

Matches in svelte/packages/svelte/src/internal/client/dev/tracing.js

L124-134

export function get_stack(label) {
	let error = Error();
	const stack = error.stack;

	if (stack) {
		const lines = stack.split('\n');
		const new_lines = ['\n'];

		for (let i = 0; i < lines.length; i++) {
			const line = lines[i];

27 lines remaining in ancestor node. Read the file to see all.

Matches in svelte/packages/svelte/src/internal/client/dom/blocks/await.js

L37-47

export function await_block(node, get_input, pending_fn, then_fn, catch_fn) {
	if (hydrating) {
		hydrate_next();
	}

	var anchor = node;
	var runes = is_runes();
	var active_component_context = component_context;

	/** @type {any} */
	var component_function = DEV ? component_context?.function : null;

145 lines remaining in ancestor node. Read the file to see all.

Matches in svelte/packages/svelte/src/internal/client/dom/blocks/css-props.js

L11-21

export function css_props(element, get_styles) {
	if (hydrating) {
		set_hydrate_node(/** @type {TemplateNode} */ (get_first_child(element)));
	}

	render_effect(() => {
		var styles = get_styles();

		for (var key in styles) {
			var value = styles[key];

8 lines remaining in ancestor node. Read the file to see all.

Matches in svelte/packages/svelte/src/internal/client/dom/blocks/each.js

L51-53

export function set_current_each_item(item) {
	current_each_item = item;
}

L115-125

export function each(node, flags, get_collection, get_key, render_fn, fallback_fn = null) {
	var anchor = node;

	/** @type {EachState} */
	var state = { flags, items: new Map(), first: null };

	var is_controlled = (flags & EACH_IS_CONTROLLED) !== 0;

	if (is_controlled) {
		var parent_node = /** @type {Element} */ (node);

132 lines remaining in ancestor node. Read the file to see all.

Matches in svelte/packages/svelte/src/internal/client/dom/blocks/html.js

L44-54

export function html(node, get_value, svg = false, mathml = false, skip_warning = false) {
	var anchor = node;

	var value = '';

	template_effect(() => {
		var effect = /** @type {Effect} */ (active_effect);

		if (value === (value = get_value() ?? '')) {
			if (hydrating) hydrate_next();
			return;

65 lines remaining in ancestor node. Read the file to see all.

Matches in svelte/packages/svelte/src/internal/client/dom/blocks/key.js

L15-25

export function key_block(node, get_key, render_fn) {
	if (hydrating) {
		hydrate_next();
	}

	var anchor = node;

	/** @type {V | typeof UNINITIALIZED} */
	var key = UNINITIALIZED;

	/** @type {Effect} */

18 lines remaining in ancestor node. Read the file to see all.

Matches in svelte/packages/svelte/src/internal/client/dom/blocks/snippet.js

L27-37

export function snippet(node, get_snippet, ...args) {
	var anchor = node;

	/** @type {SnippetFn | null | undefined} */
	// @ts-ignore
	var snippet = noop;

	/** @type {Effect | null} */
	var snippet_effect;

	block(() => {

18 lines remaining in ancestor node. Read the file to see all.

Matches in svelte/packages/svelte/src/internal/client/dom/blocks/svelte-component.js

L14-24

export function component(node, get_component, render_fn) {
	if (hydrating) {
		hydrate_next();
	}

	var anchor = node;

	/** @type {C} */
	var component;

	/** @type {Effect | null} */

19 lines remaining in ancestor node. Read the file to see all.

Matches in svelte/packages/svelte/src/internal/client/dom/blocks/svelte-element.js

L36-46

export function element(node, get_tag, is_svg, render_fn, get_namespace, location) {
	let was_hydrating = hydrating;

	if (hydrating) {
		hydrate_next();
	}

	var filename = DEV && location && component_context?.function[FILENAME];

	/** @type {string | null} */
	var tag;

119 lines remaining in ancestor node. Read the file to see all.

Matches in svelte/packages/svelte/src/internal/client/dom/blocks/svelte-head.js

L13-15

export function reset_head_anchor() {
	head_anchor = undefined;
}

Matches in svelte/packages/svelte/src/internal/client/dom/elements/actions.js

L13-23

export function action(dom, action, get_value) {
	effect(() => {
		var payload = untrack(() => action(dom, get_value?.()) || {});

		if (get_value && payload?.update) {
			var inited = false;
			/** @type {P} */
			var prev = /** @type {any} */ ({}); // initialize with something so it's never equal on first run

			render_effect(() => {
				var value = get_value();

20 lines remaining in ancestor node. Read the file to see all.

Tool Call: Thinking Status: Completed

Based on my extensive search through the Svelte codebase, I can now compile a comprehensive list of all functions that manage state. Let me organize these by category:

Core State Management (Runes):

  1. state() - Create reactive state
  2. derived() / user_derived() - Create derived/computed values
  3. effect() / user_effect() - Create side effects
  4. user_pre_effect() - Effects that run before DOM updates

Low-level Reactive Primitives:

  1. source() - Create basic reactive source
  2. mutable_source() - Create mutable reactive source
  3. set() / internal_set() - Set reactive values
  4. get() / safe_get() - Get reactive values
  5. update() / update_pre() - Update numeric values
  6. mutate() - Mutate and trigger reactivity

Effect Management:

  1. effect_root() - Create effect root
  2. component_root() - Create component effect root
  3. render_effect() - Effects for rendering
  4. template_effect() - Effects for template expressions
  5. inspect_effect() - Effects for $inspect
  6. legacy_pre_effect() - Legacy reactive statements
  7. block() / branch() - Block-level effects
  8. teardown() - Cleanup effects
  9. pause_effect() / resume_effect() - Control effect execution
  10. destroy_effect() - Destroy effects

Props Management:

  1. prop() - Manage component props
  2. rest_props() - Handle rest props
  3. legacy_rest_props() - Legacy rest props
  4. spread_props() - Spread props
  5. update_prop() / update_pre_prop() - Update prop values

Store Management:

  1. writable() - Create writable store
  2. readable() - Create readable store
  3. derived() (store version) - Create derived store
  4. store_get() - Get store values
  5. store_set() - Set store values
  6. store_mutate() - Mutate store values
  7. update_store() / update_pre_store() - Update store values
  8. invalidate_store() - Invalidate stores
  9. setup_stores() - Setup store subscriptions
  10. store_unsub() - Unsubscribe from stores

Context Management:

  1. getContext() - Get context values
  2. setContext() - Set context values
  3. getAllContexts() - Get all contexts

Runtime Control:

  1. untrack() - Run code without tracking
  2. tick() - Wait for updates
  3. flushSync() / flush() - Synchronously flush updates
  4. deep_read() / deep_read_state() - Deep reactive reads
  5. invalidate_inner_signals() - Invalidate signals

Utility Functions:

  1. snapshot() - Create non-reactive snapshots
  2. proxy() - Create reactive proxies
  3. equals() / safe_equals() - Equality comparisons
  4. capture_store_binding() - Capture store bindings
  5. mark_store_binding() - Mark store bindings

Legacy/Compatibility:

  1. reactive_import() - Legacy reactive imports
  2. legacy_pre_effect_reset() - Reset legacy effects

Development/Debugging:

  1. inspect() - Inspect reactive values
  2. trace() / tag() - Tracing utilities

This covers the complete set of state management functions in Svelte 5.

Assistant

Based on my comprehensive analysis of the Svelte codebase, here are all the functions that manage state in Svelte 5:

Core State Management (Runes)

State Creation:

  • state() - Creates reactive state using the $state rune
  • mutable_source() - Creates mutable reactive sources
  • source() - Creates basic reactive sources

Derived Values:

  • derived() / user_derived() - Creates computed/derived values using $derived
  • derived_safe_equal() - Derived with safe equality checking

Effects:

  • effect() / user_effect() - Creates side effects using $effect
  • user_pre_effect() - Effects that run before DOM updates ($effect.pre)
  • inspect_effect() - Effects for $inspect debugging

State Manipulation

Getting/Setting:

  • get() / safe_get() - Reads reactive values
  • set() / internal_set() - Updates reactive values
  • mutate() - Mutates objects and triggers reactivity
  • update() / update_pre() - Updates numeric values (increment/decrement)

Effect Management

Effect Lifecycle:

  • effect_root() - Creates independent effect roots
  • component_root() - Creates component-level effect roots with transition support
  • render_effect() - Creates effects that run during rendering
  • template_effect() - Creates effects for template expressions
  • teardown() - Registers cleanup functions
  • block() / branch() - Creates block-level effects

Effect Control:

  • pause_effect() / resume_effect() - Controls effect execution
  • destroy_effect() - Destroys effects and cleans up resources
  • execute_effect_teardown() - Runs effect cleanup

Props Management

export function prop(props, key, flags, fallback) {
	// Handles component prop synchronization with binding support
	// Manages two-way binding between parent and child components
	// Returns getter/setter function for the prop
}

export function rest_props(props, exclude, name) {
	// Handles rest props (const { x, ...rest } = $props())
	// Returns proxy that excludes named props
}

export function spread_props(...props) {
	// Handles spread props in component calls
	// Merges multiple prop objects
}
  • prop() - Manages component props with binding support
  • rest_props() / legacy_rest_props() - Handles rest props
  • spread_props() - Manages spread props
  • update_prop() / update_pre_prop() - Updates prop values

Store Management (Legacy)

export function writable(value, start = noop) {
	// Creates writable store with subscription management
	// Returns { set, update, subscribe }
}

export function derived(stores, fn, initial_value) {
	// Creates derived store from other stores
	// Automatically manages subscriptions
}

Store Creation:

  • writable() - Creates writable stores
  • readable() - Creates readable stores
  • derived() (store version) - Creates derived stores

Store Operations:

  • store_get() / store_set() - Gets/sets store values
  • store_mutate() - Mutates store values
  • update_store() / update_pre_store() - Updates numeric store values
  • invalidate_store() - Invalidates store subscriptions
  • setup_stores() / store_unsub() - Manages store subscriptions

Context Management

export function getContext(key) {
	const context_map = get_or_init_context_map('getContext');
	return context_map.get(key);
}

export function setContext(key, context) {
	const context_map = get_or_init_context_map('setContext');
	context_map.set(key, context);
	return context;
}
  • getContext() - Retrieves context values
  • setContext() - Sets context values
  • getAllContexts() - Gets all available contexts

Runtime Control

Reactivity Control:

  • untrack() - Runs code without tracking dependencies
  • tick() - Waits for all pending state updates
  • flushSync() / flush() - Synchronously flushes updates
  • effect_tracking() - Checks if currently tracking effects

Advanced Operations:

  • deep_read() / deep_read_state() - Performs deep reactive reads
  • invalidate_inner_signals() - Invalidates nested signals

Utility Functions

Reactivity Utilities:

  • snapshot() - Creates non-reactive snapshots of state
  • proxy() - Creates reactive proxies for objects
  • equals() / safe_equals() - Equality comparison functions

Store Integration:

  • capture_store_binding() - Captures store binding information
  • mark_store_binding() - Marks props as store bindings

Development & Debugging

export function inspect(get_value, inspector = console.log) {
	// Creates inspection effect for debugging
	// Logs value changes to console
}
  • inspect() - Inspects reactive values for debugging
  • trace() / tag() / tag_proxy() - Tracing utilities for development

Legacy Support

  • reactive_import() - Legacy reactive imports
  • legacy_pre_effect() / legacy_pre_effect_reset() - Legacy reactive statements ($:)

These functions form the complete state management system in Svelte 5, handling everything from basic reactivity to complex component prop binding, store management, and development tooling.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment