Skip to content

Commit 69ee547

Browse files
authored
chore: simplify $inspect (#12065)
* simplify $inspect * tidy up * tidy up * unused * unused
1 parent 98d9074 commit 69ee547

File tree

9 files changed

+35
-149
lines changed

9 files changed

+35
-149
lines changed

packages/svelte/src/internal/client/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export const EFFECT_RAN = 1 << 14;
1616
export const EFFECT_TRANSPARENT = 1 << 15;
1717
/** Svelte 4 legacy mode props need to be handled with deriveds and be recognized elsewhere, hence the dedicated flag */
1818
export const LEGACY_DERIVED_PROP = 1 << 16;
19+
export const INSPECT_EFFECT = 1 << 17;
1920

2021
export const STATE_SYMBOL = Symbol('$state');
2122
export const STATE_FROZEN_SYMBOL = Symbol('$state.frozen');

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

Lines changed: 4 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,7 @@
1-
import { DEV } from 'esm-env';
21
import { snapshot } from '../proxy.js';
3-
import { render_effect, validate_effect } from '../reactivity/effects.js';
4-
import { deep_read, untrack } from '../runtime.js';
2+
import { inspect_effect, validate_effect } from '../reactivity/effects.js';
53
import { array_prototype, get_prototype_of, object_prototype } from '../utils.js';
64

7-
/** @type {Function | null} */
8-
export let inspect_fn = null;
9-
10-
/** @param {Function | null} fn */
11-
export function set_inspect_fn(fn) {
12-
inspect_fn = fn;
13-
}
14-
15-
/** @type {Array<import('#client').ValueDebug>} */
16-
export let inspect_captured_signals = [];
17-
185
/**
196
* @param {() => any[]} get_value
207
* @param {Function} [inspector]
@@ -25,32 +12,9 @@ export function inspect(get_value, inspector = console.log) {
2512

2613
let initial = true;
2714

28-
// we assign the function directly to signals, rather than just
29-
// calling `inspector` directly inside the effect, so that
30-
// we get useful stack traces
31-
var fn = () => {
32-
const value = untrack(() => deep_snapshot(get_value()));
33-
inspector(initial ? 'init' : 'update', ...value);
34-
};
35-
36-
render_effect(() => {
37-
inspect_fn = fn;
38-
deep_read(get_value());
39-
inspect_fn = null;
40-
41-
const signals = inspect_captured_signals.slice();
42-
inspect_captured_signals = [];
43-
44-
if (initial) {
45-
fn();
46-
initial = false;
47-
}
48-
49-
return () => {
50-
for (const s of signals) {
51-
s.inspect.delete(fn);
52-
}
53-
};
15+
inspect_effect(() => {
16+
inspector(initial ? 'init' : 'update', ...deep_snapshot(get_value()));
17+
initial = false;
5418
});
5519
}
5620

packages/svelte/src/internal/client/proxy.js

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
import { DEV } from 'esm-env';
2-
import {
3-
get,
4-
batch_inspect,
5-
current_component_context,
6-
untrack,
7-
current_effect
8-
} from './runtime.js';
2+
import { get, current_component_context, untrack, current_effect } from './runtime.js';
93
import {
104
array_prototype,
115
define_property,
@@ -230,11 +224,6 @@ const state_proxy_handler = {
230224
return value === UNINITIALIZED ? undefined : value;
231225
}
232226

233-
if (DEV) {
234-
if (typeof target[prop] === 'function' && prop !== Symbol.iterator) {
235-
return batch_inspect(target, prop, receiver);
236-
}
237-
}
238227
return Reflect.get(target, prop, receiver);
239228
},
240229

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

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { DEV } from 'esm-env';
21
import { CLEAN, DERIVED, DESTROYED, DIRTY, MAYBE_DIRTY, UNOWNED } from '../constants.js';
32
import {
43
current_reaction,
@@ -39,10 +38,6 @@ export function derived(fn) {
3938
version: 0
4039
};
4140

42-
if (DEV) {
43-
/** @type {import('#client').DerivedDebug} */ (signal).inspect = new Set();
44-
}
45-
4641
if (current_reaction !== null && (current_reaction.f & DERIVED) !== 0) {
4742
var current_derived = /** @type {import('#client').Derived<V>} */ (current_reaction);
4843
if (current_derived.deriveds === null) {
@@ -107,10 +102,6 @@ export function update_derived(derived, force_schedule) {
107102
derived.version = increment_version();
108103

109104
mark_reactions(derived, DIRTY, force_schedule);
110-
111-
if (DEV && force_schedule) {
112-
for (var fn of /** @type {import('#client').DerivedDebug} */ (derived).inspect) fn();
113-
}
114105
}
115106
}
116107

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ import {
3030
EFFECT_TRANSPARENT,
3131
DERIVED,
3232
UNOWNED,
33-
CLEAN
33+
CLEAN,
34+
INSPECT_EFFECT
3435
} from '../constants.js';
3536
import { set } from './sources.js';
3637
import { remove } from '../dom/reconciler.js';
@@ -204,6 +205,11 @@ export function user_pre_effect(fn) {
204205
return render_effect(fn);
205206
}
206207

208+
/** @param {() => void | (() => void)} fn */
209+
export function inspect_effect(fn) {
210+
return create_effect(INSPECT_EFFECT, fn, true);
211+
}
212+
207213
/**
208214
* Internal representation of `$effect.root(...)`
209215
* @param {() => void | (() => void)} fn

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import { mutable_source, set, source } from './sources.js';
1010
import { derived, derived_safe_equal } from './deriveds.js';
1111
import { get, is_signals_recorded, untrack, update } from '../runtime.js';
1212
import { safe_equals } from './equality.js';
13-
import { inspect_fn } from '../dev/inspect.js';
1413
import * as e from '../errors.js';
1514
import { LEGACY_DERIVED_PROP } from '../constants.js';
1615

@@ -308,7 +307,7 @@ export function prop(props, key, flags, fallback) {
308307

309308
// legacy nonsense — need to ensure the source is invalidated when necessary
310309
// also needed for when handling inspect logic so we can inspect the correct source signal
311-
if (is_signals_recorded || (DEV && inspect_fn)) {
310+
if (is_signals_recorded) {
312311
// set this so that we don't reset to the parent value if `d`
313312
// is invalidated because of `invalidate_inner_signals` (rather
314313
// than because the parent or child value changed)

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

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ import {
66
current_effect,
77
current_untracked_writes,
88
get,
9-
is_batching_effect,
109
is_runes,
1110
mark_reactions,
1211
schedule_effect,
1312
set_current_untracked_writes,
14-
set_last_inspected_signal,
1513
set_signal_status,
1614
untrack,
17-
increment_version
15+
increment_version,
16+
execute_effect,
17+
inspect_effects
1818
} from '../runtime.js';
1919
import { equals, safe_equals } from './equality.js';
2020
import { CLEAN, DERIVED, DIRTY, BRANCH_EFFECT } from '../constants.js';
@@ -23,25 +23,18 @@ import * as e from '../errors.js';
2323

2424
/**
2525
* @template V
26-
* @param {V} value
26+
* @param {V} v
2727
* @returns {import('#client').Source<V>}
2828
*/
2929
/*#__NO_SIDE_EFFECTS__*/
30-
export function source(value) {
31-
/** @type {import('#client').Source<V>} */
32-
const source = {
30+
export function source(v) {
31+
return {
3332
f: 0, // TODO ideally we could skip this altogether, but it causes type errors
33+
v,
3434
reactions: null,
35-
equals: equals,
36-
v: value,
35+
equals,
3736
version: 0
3837
};
39-
40-
if (DEV) {
41-
/** @type {import('#client').ValueDebug<V>} */ (source).inspect = new Set();
42-
}
43-
44-
return source;
4538
}
4639

4740
/**
@@ -129,11 +122,11 @@ export function set(source, value) {
129122
}
130123

131124
if (DEV) {
132-
if (is_batching_effect) {
133-
set_last_inspected_signal(/** @type {import('#client').ValueDebug} */ (source));
134-
} else {
135-
for (const fn of /** @type {import('#client').ValueDebug} */ (source).inspect) fn();
125+
for (const effect of inspect_effects) {
126+
execute_effect(effect);
136127
}
128+
129+
inspect_effects.clear();
137130
}
138131
}
139132

packages/svelte/src/internal/client/reactivity/types.d.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,6 @@ export interface Effect extends Reaction {
5353
component_function?: any;
5454
}
5555

56-
export interface ValueDebug<V = unknown> extends Value<V> {
57-
inspect: Set<Function>;
58-
}
59-
60-
export interface DerivedDebug<V = unknown> extends Derived<V>, ValueDebug<V> {}
61-
6256
export type Source<V = unknown> = Value<V>;
6357

6458
export type MaybeSource<T = unknown> = T | Source<T>;

packages/svelte/src/internal/client/runtime.js

Lines changed: 9 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ import {
2929
ROOT_EFFECT,
3030
LEGACY_DERIVED_PROP,
3131
DISCONNECTED,
32-
STATE_FROZEN_SYMBOL
32+
STATE_FROZEN_SYMBOL,
33+
INSPECT_EFFECT
3334
} from './constants.js';
3435
import { flush_tasks } from './dom/task.js';
3536
import { add_owner } from './dev/ownership.js';
3637
import { mutate, set, source } from './reactivity/sources.js';
3738
import { update_derived } from './reactivity/deriveds.js';
38-
import { inspect_captured_signals, inspect_fn, set_inspect_fn } from './dev/inspect.js';
3939
import * as e from './errors.js';
4040
import { lifecycle_outside_component } from '../shared/errors.js';
4141

@@ -63,9 +63,7 @@ export function set_is_destroying_effect(value) {
6363
is_destroying_effect = value;
6464
}
6565

66-
// Used for $inspect
67-
export let is_batching_effect = false;
68-
let is_inspecting_signal = false;
66+
export let inspect_effects = new Set();
6967

7068
// Handle effect queues
7169

@@ -106,14 +104,6 @@ export function set_current_untracked_writes(value) {
106104
current_untracked_writes = value;
107105
}
108106

109-
/** @type {null | import('#client').ValueDebug} */
110-
export let last_inspected_signal = null;
111-
112-
/** @param {null | import('#client').ValueDebug} signal */
113-
export function set_last_inspected_signal(signal) {
114-
last_inspected_signal = signal;
115-
}
116-
117107
/** @type {number} Used by sources and deriveds for handling updates to unowned deriveds */
118108
let current_version = 0;
119109

@@ -159,38 +149,6 @@ export function is_runes() {
159149
return current_component_context !== null && current_component_context.l === null;
160150
}
161151

162-
/**
163-
* @param {import('#client').ProxyStateObject} target
164-
* @param {string | symbol} prop
165-
* @param {any} receiver
166-
*/
167-
export function batch_inspect(target, prop, receiver) {
168-
const value = Reflect.get(target, prop, receiver);
169-
/**
170-
* @this {any}
171-
*/
172-
return function () {
173-
const previously_batching_effect = is_batching_effect;
174-
is_batching_effect = true;
175-
try {
176-
return Reflect.apply(value, this, arguments);
177-
} finally {
178-
is_batching_effect = previously_batching_effect;
179-
if (last_inspected_signal !== null && !is_inspecting_signal) {
180-
is_inspecting_signal = true;
181-
try {
182-
for (const fn of last_inspected_signal.inspect) {
183-
fn();
184-
}
185-
} finally {
186-
is_inspecting_signal = false;
187-
}
188-
last_inspected_signal = null;
189-
}
190-
}
191-
};
192-
}
193-
194152
/**
195153
* Determines whether a derived or effect is dirty.
196154
* If it is MAYBE_DIRTY, will set the status to CLEAN
@@ -793,12 +751,6 @@ export async function tick() {
793751
* @returns {V}
794752
*/
795753
export function get(signal) {
796-
if (DEV && inspect_fn) {
797-
var s = /** @type {import('#client').ValueDebug} */ (signal);
798-
s.inspect.add(inspect_fn);
799-
inspect_captured_signals.push(s);
800-
}
801-
802754
const flags = signal.f;
803755
if ((flags & DESTROYED) !== 0) {
804756
return signal.v;
@@ -846,15 +798,7 @@ export function get(signal) {
846798
(flags & DERIVED) !== 0 &&
847799
check_dirtiness(/** @type {import('#client').Derived} */ (signal))
848800
) {
849-
if (DEV) {
850-
// we want to avoid tracking indirect dependencies
851-
const previous_inspect_fn = inspect_fn;
852-
set_inspect_fn(null);
853-
update_derived(/** @type {import('#client').Derived} **/ (signal), false);
854-
set_inspect_fn(previous_inspect_fn);
855-
} else {
856-
update_derived(/** @type {import('#client').Derived} **/ (signal), false);
857-
}
801+
update_derived(/** @type {import('#client').Derived} **/ (signal), false);
858802
}
859803

860804
return signal.v;
@@ -914,6 +858,11 @@ export function mark_reactions(signal, to_status, force_schedule) {
914858
var reaction = reactions[i];
915859
var flags = reaction.f;
916860

861+
if (DEV && (flags & INSPECT_EFFECT) !== 0) {
862+
inspect_effects.add(reaction);
863+
continue;
864+
}
865+
917866
// We skip any effects that are already dirty. Additionally, we also
918867
// skip if the reaction is the same as the current effect (except if we're not in runes or we
919868
// are in force schedule mode).

0 commit comments

Comments
 (0)