From 45d3eeb4e6c905f44f1328200f7dc8e0c0e874b4 Mon Sep 17 00:00:00 2001 From: ComputerGuy <63362464+Ocean-OS@users.noreply.github.com> Date: Fri, 18 Jul 2025 03:00:43 -0700 Subject: [PATCH] add types, DRY out some logic --- packages/svelte/src/ambient.d.ts | 28 ++++++++++++ .../svelte/src/internal/client/constants.js | 5 +++ .../src/internal/client/reactivity/effects.js | 43 +++++++++++++------ packages/svelte/types/index.d.ts | 28 ++++++++++++ 4 files changed, 91 insertions(+), 13 deletions(-) diff --git a/packages/svelte/src/ambient.d.ts b/packages/svelte/src/ambient.d.ts index 7c3b941ed1..aaaddbe544 100644 --- a/packages/svelte/src/ambient.d.ts +++ b/packages/svelte/src/ambient.d.ts @@ -237,6 +237,34 @@ declare namespace $derived { declare function $effect(fn: () => void | (() => void)): void; declare namespace $effect { + /** + * The `$effect.active` rune is an advanced feature that indicates whether an effect or async `$derived` can be created in the current context. + * Effects and async deriveds can only be created in root effects, which are created during component setup, or can be programmatically created via `$effect.root`. + * + * Example: + * ```svelte + * + * + * + * ``` + * + * https://svelte.dev/docs/svelte/$effect#$effect.active + */ + export function active(): boolean; /** * Runs code right before a component is mounted to the DOM, and then whenever its dependencies change, i.e. `$state` or `$derived` values. * The timing of the execution is right before the DOM is updated. diff --git a/packages/svelte/src/internal/client/constants.js b/packages/svelte/src/internal/client/constants.js index 50a7a21ae8..de0ca92f12 100644 --- a/packages/svelte/src/internal/client/constants.js +++ b/packages/svelte/src/internal/client/constants.js @@ -41,3 +41,8 @@ export const ELEMENT_NODE = 1; export const TEXT_NODE = 3; export const COMMENT_NODE = 8; export const DOCUMENT_FRAGMENT_NODE = 11; + +export const VALID_EFFECT_PARENT = 0; +export const EFFECT_ORPHAN = 1; +export const UNOWNED_DERIVED_PARENT = 2; +export const EFFECT_TEARDOWN = 3; \ No newline at end of file diff --git a/packages/svelte/src/internal/client/reactivity/effects.js b/packages/svelte/src/internal/client/reactivity/effects.js index ccc2d9c9ec..7921b1e5e9 100644 --- a/packages/svelte/src/internal/client/reactivity/effects.js +++ b/packages/svelte/src/internal/client/reactivity/effects.js @@ -33,7 +33,11 @@ import { EFFECT_PRESERVED, STALE_REACTION, USER_EFFECT, - ASYNC + ASYNC, + EFFECT_ORPHAN, + EFFECT_TEARDOWN, + UNOWNED_DERIVED_PARENT, + VALID_EFFECT_PARENT } from '#client/constants'; import * as e from '../errors.js'; import { DEV } from 'esm-env'; @@ -44,19 +48,38 @@ import { Batch, schedule_effect } from './batch.js'; import { flatten } from './async.js'; /** - * @param {'$effect' | '$effect.pre' | '$inspect'} rune + * @returns {number} */ -export function validate_effect(rune) { +function active_root_effect() { if (active_effect === null && active_reaction === null) { - e.effect_orphan(rune); + return EFFECT_ORPHAN; } if (active_reaction !== null && (active_reaction.f & UNOWNED) !== 0 && active_effect === null) { - e.effect_in_unowned_derived(); + return UNOWNED_DERIVED_PARENT; } if (is_destroying_effect) { - e.effect_in_teardown(rune); + return EFFECT_TEARDOWN; + } + + return VALID_EFFECT_PARENT; +} + +/** + * @param {'$effect' | '$effect.pre' | '$inspect'} rune + */ +export function validate_effect(rune) { + const valid_effect_parent = active_root_effect(); + switch(valid_effect_parent) { + case VALID_EFFECT_PARENT: + return; + case EFFECT_ORPHAN: + e.effect_orphan(rune); + case UNOWNED_DERIVED_PARENT: + e.effect_in_unowned_derived(); + case EFFECT_TEARDOWN: + e.effect_in_teardown(rune); } } @@ -170,13 +193,7 @@ export function effect_tracking() { * @returns {boolean} */ export function effect_active() { - if (active_reaction === null && active_effect === null) { - return false; - } - if (is_destroying_effect) { - return false; - } - return true; + return active_root_effect() === VALID_EFFECT_PARENT; } /** diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts index a8b769d6d4..abe0213ed3 100644 --- a/packages/svelte/types/index.d.ts +++ b/packages/svelte/types/index.d.ts @@ -3311,6 +3311,34 @@ declare namespace $derived { declare function $effect(fn: () => void | (() => void)): void; declare namespace $effect { + /** + * The `$effect.active` rune is an advanced feature that indicates whether an effect or async `$derived` can be created in the current context. + * Effects and async deriveds can only be created in root effects, which are created during component setup, or can be programmatically created via `$effect.root`. + * + * Example: + * ```svelte + * + * + * + * ``` + * + * https://svelte.dev/docs/svelte/$effect#$effect.active + */ + export function active(): boolean; /** * Runs code right before a component is mounted to the DOM, and then whenever its dependencies change, i.e. `$state` or `$derived` values. * The timing of the execution is right before the DOM is updated.