Skip to content

Commit 516cd22

Browse files
authored
fix: more accurate error message when creating orphan effects (#11227)
1 parent eac4218 commit 516cd22

File tree

3 files changed

+32
-35
lines changed

3 files changed

+32
-35
lines changed

.changeset/loud-socks-look.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: more accurate error message when creating orphan effects

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { snapshot } from '../proxy.js';
2-
import { render_effect } from '../reactivity/effects.js';
2+
import { render_effect, validate_effect } from '../reactivity/effects.js';
33
import { current_effect, deep_read } from '../runtime.js';
44
import { array_prototype, get_prototype_of, object_prototype } from '../utils.js';
55

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

2925
let initial = true;
3026

packages/svelte/src/internal/client/reactivity/effects.js

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,29 @@ import {
3131
import { set } from './sources.js';
3232
import { remove } from '../dom/reconciler.js';
3333

34+
/**
35+
* @param {import('#client').Effect | null} effect
36+
* @param {'$effect' | '$effect.pre' | '$inspect'} rune
37+
* @returns {asserts effect}
38+
*/
39+
export function validate_effect(effect, rune) {
40+
if (effect === null) {
41+
throw new Error(
42+
'ERR_SVELTE_ORPHAN_EFFECT' +
43+
(DEV
44+
? `: ${rune} can only be used inside an effect (e.g. during component initialisation)`
45+
: '')
46+
);
47+
}
48+
49+
if (is_destroying_effect) {
50+
throw new Error(
51+
'ERR_SVELTE_EFFECT_IN_TEARDOWN' +
52+
(DEV ? `: ${rune} cannot be used inside an effect cleanup function.` : '')
53+
);
54+
}
55+
}
56+
3457
/**
3558
* @param {import("#client").Effect} effect
3659
* @param {import("#client").Reaction} parent_effect
@@ -105,18 +128,7 @@ export function effect_active() {
105128
* @param {() => void | (() => void)} fn
106129
*/
107130
export function user_effect(fn) {
108-
if (current_effect === null) {
109-
throw new Error(
110-
'ERR_SVELTE_ORPHAN_EFFECT' +
111-
(DEV ? ': The Svelte $effect rune can only be used during component initialisation.' : '')
112-
);
113-
}
114-
if (is_destroying_effect) {
115-
throw new Error(
116-
'ERR_SVELTE_EFFECT_IN_TEARDOWN' +
117-
(DEV ? ': The Svelte $effect rune can not be used in the teardown phase of an effect.' : '')
118-
);
119-
}
131+
validate_effect(current_effect, '$effect');
120132

121133
// Non-nested `$effect(...)` in a component should be deferred
122134
// until the component is mounted
@@ -140,23 +152,7 @@ export function user_effect(fn) {
140152
* @returns {import('#client').Effect}
141153
*/
142154
export function user_pre_effect(fn) {
143-
if (current_effect === null) {
144-
throw new Error(
145-
'ERR_SVELTE_ORPHAN_EFFECT' +
146-
(DEV
147-
? ': The Svelte $effect.pre rune can only be used during component initialisation.'
148-
: '')
149-
);
150-
}
151-
if (is_destroying_effect) {
152-
throw new Error(
153-
'ERR_SVELTE_EFFECT_IN_TEARDOWN' +
154-
(DEV
155-
? ': The Svelte $effect.pre rune can not be used in the teardown phase of an effect.'
156-
: '')
157-
);
158-
}
159-
155+
validate_effect(current_effect, '$effect.pre');
160156
return render_effect(fn);
161157
}
162158

0 commit comments

Comments
 (0)