add types, DRY out some logic

effect-active
ComputerGuy 2 months ago
parent 64fa513e8b
commit 45d3eeb4e6

@ -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
* <script>
* console.log('in component setup', $effect.active()); // true
*
* function onclick() {
* console.log('after component setup', $effect.active()); // false
* }
* function ondblclick() {
* $effect.root(() => {
* console.log('in root effect', $effect.active()); // true
* return () => {
* console.log('in effect teardown', $effect.active()); // false
* }
* })();
* }
* </script>
* <button {onclick}>Click me!</button>
* <button {ondblclick}>Click me twice!</button>
* ```
*
* 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.

@ -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;

@ -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;
}
/**

@ -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
* <script>
* console.log('in component setup', $effect.active()); // true
*
* function onclick() {
* console.log('after component setup', $effect.active()); // false
* }
* function ondblclick() {
* $effect.root(() => {
* console.log('in root effect', $effect.active()); // true
* return () => {
* console.log('in effect teardown', $effect.active()); // false
* }
* })();
* }
* </script>
* <button {onclick}>Click me!</button>
* <button {ondblclick}>Click me twice!</button>
* ```
*
* 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.

Loading…
Cancel
Save