Skip to content

fix: more accurate error message when creating orphan effects #11227

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/loud-socks-look.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: more accurate error message when creating orphan effects
8 changes: 2 additions & 6 deletions packages/svelte/src/internal/client/dev/inspect.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { snapshot } from '../proxy.js';
import { render_effect } from '../reactivity/effects.js';
import { render_effect, validate_effect } from '../reactivity/effects.js';
import { current_effect, deep_read } from '../runtime.js';
import { array_prototype, get_prototype_of, object_prototype } from '../utils.js';

Expand All @@ -20,11 +20,7 @@ export let inspect_captured_signals = [];
*/
// eslint-disable-next-line no-console
export function inspect(get_value, inspector = console.log) {
if (!current_effect) {
throw new Error(
'$inspect can only be used inside an effect (e.g. during component initialisation)'
);
}
validate_effect(current_effect, '$inspect');

let initial = true;

Expand Down
54 changes: 25 additions & 29 deletions packages/svelte/src/internal/client/reactivity/effects.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,29 @@ import {
import { set } from './sources.js';
import { remove } from '../dom/reconciler.js';

/**
* @param {import('#client').Effect | null} effect
* @param {'$effect' | '$effect.pre' | '$inspect'} rune
* @returns {asserts effect}
*/
export function validate_effect(effect, rune) {
if (effect === null) {
throw new Error(
'ERR_SVELTE_ORPHAN_EFFECT' +
(DEV
? `: ${rune} can only be used inside an effect (e.g. during component initialisation)`
: '')
);
}

if (is_destroying_effect) {
throw new Error(
'ERR_SVELTE_EFFECT_IN_TEARDOWN' +
(DEV ? `: ${rune} cannot be used inside an effect cleanup function.` : '')
);
}
}

/**
* @param {import("#client").Effect} effect
* @param {import("#client").Reaction} parent_effect
Expand Down Expand Up @@ -105,18 +128,7 @@ export function effect_active() {
* @param {() => void | (() => void)} fn
*/
export function user_effect(fn) {
if (current_effect === null) {
throw new Error(
'ERR_SVELTE_ORPHAN_EFFECT' +
(DEV ? ': The Svelte $effect rune can only be used during component initialisation.' : '')
);
}
if (is_destroying_effect) {
throw new Error(
'ERR_SVELTE_EFFECT_IN_TEARDOWN' +
(DEV ? ': The Svelte $effect rune can not be used in the teardown phase of an effect.' : '')
);
}
validate_effect(current_effect, '$effect');

// Non-nested `$effect(...)` in a component should be deferred
// until the component is mounted
Expand All @@ -140,23 +152,7 @@ export function user_effect(fn) {
* @returns {import('#client').Effect}
*/
export function user_pre_effect(fn) {
if (current_effect === null) {
throw new Error(
'ERR_SVELTE_ORPHAN_EFFECT' +
(DEV
? ': The Svelte $effect.pre rune can only be used during component initialisation.'
: '')
);
}
if (is_destroying_effect) {
throw new Error(
'ERR_SVELTE_EFFECT_IN_TEARDOWN' +
(DEV
? ': The Svelte $effect.pre rune can not be used in the teardown phase of an effect.'
: '')
);
}

validate_effect(current_effect, '$effect.pre');
return render_effect(fn);
}

Expand Down