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.