Skip to content

Commit 31cfc1c

Browse files
committed
inelegant fix
1 parent c2bc9bb commit 31cfc1c

File tree

2 files changed

+39
-10
lines changed

2 files changed

+39
-10
lines changed

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

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,23 @@ export function proxy(value, parent = null, prev) {
4545
var reaction = active_reaction;
4646

4747
/** @param {any} value */
48-
var child = (value) => {
48+
var child_source = (value) => {
4949
var previous_reaction = active_reaction;
5050
set_active_reaction(reaction);
5151
var s = source(value, stack);
5252
set_active_reaction(previous_reaction);
5353
return s;
5454
};
5555

56+
/** @param {any} value */
57+
var child_proxy = (value) => {
58+
var previous_reaction = active_reaction;
59+
set_active_reaction(reaction);
60+
var p = proxy(value, metadata);
61+
set_active_reaction(previous_reaction);
62+
return p;
63+
};
64+
5665
if (is_proxied_array) {
5766
// We need to create the length source eagerly to ensure that
5867
// mutations to the array are properly synced with our proxy
@@ -102,10 +111,10 @@ export function proxy(value, parent = null, prev) {
102111
var s = sources.get(prop);
103112

104113
if (s === undefined) {
105-
s = child(descriptor.value);
114+
s = child_source(descriptor.value);
106115
sources.set(prop, s);
107116
} else {
108-
set(s, proxy(descriptor.value, metadata));
117+
set(s, child_proxy(descriptor.value));
109118
}
110119

111120
return true;
@@ -116,7 +125,7 @@ export function proxy(value, parent = null, prev) {
116125

117126
if (s === undefined) {
118127
if (prop in target) {
119-
sources.set(prop, child(UNINITIALIZED));
128+
sources.set(prop, child_source(UNINITIALIZED));
120129
}
121130
} else {
122131
// When working with arrays, we need to also ensure we update the length when removing
@@ -150,7 +159,7 @@ export function proxy(value, parent = null, prev) {
150159

151160
// create a source, but only if it's an own property and not a prototype property
152161
if (s === undefined && (!exists || get_descriptor(target, prop)?.writable)) {
153-
s = child(proxy(exists ? target[prop] : UNINITIALIZED, metadata));
162+
s = child_source(child_proxy(exists ? target[prop] : UNINITIALIZED));
154163
sources.set(prop, s);
155164
}
156165

@@ -218,7 +227,7 @@ export function proxy(value, parent = null, prev) {
218227
(active_effect !== null && (!has || get_descriptor(target, prop)?.writable))
219228
) {
220229
if (s === undefined) {
221-
s = child(has ? proxy(target[prop], metadata) : UNINITIALIZED);
230+
s = child_source(has ? child_proxy(target[prop]) : UNINITIALIZED);
222231
sources.set(prop, s);
223232
}
224233

@@ -245,7 +254,7 @@ export function proxy(value, parent = null, prev) {
245254
// If the item exists in the original, we need to create a uninitialized source,
246255
// else a later read of the property would result in a source being created with
247256
// the value of the original item at that index.
248-
other_s = child(UNINITIALIZED);
257+
other_s = child_source(UNINITIALIZED);
249258
sources.set(i + '', other_s);
250259
}
251260
}
@@ -257,13 +266,13 @@ export function proxy(value, parent = null, prev) {
257266
// object property before writing to that property.
258267
if (s === undefined) {
259268
if (!has || get_descriptor(target, prop)?.writable) {
260-
s = child(undefined);
261-
set(s, proxy(value, metadata));
269+
s = child_source(undefined);
270+
set(s, child_proxy(value));
262271
sources.set(prop, s);
263272
}
264273
} else {
265274
has = s.v !== UNINITIALIZED;
266-
set(s, proxy(value, metadata));
275+
set(s, child_proxy(value));
267276
}
268277

269278
if (DEV) {

packages/svelte/tests/signals/test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,26 @@ describe('signals', () => {
492492
};
493493
});
494494

495+
test('schedules rerun when updating deeply nested value', (runes) => {
496+
if (!runes) return () => {};
497+
498+
const value = proxy({ a: { b: { c: 0 } } });
499+
user_effect(() => {
500+
value.a.b.c += 1;
501+
});
502+
503+
return () => {
504+
let errored = false;
505+
try {
506+
flushSync();
507+
} catch (e: any) {
508+
assert.include(e.message, 'effect_update_depth_exceeded');
509+
errored = true;
510+
}
511+
assert.equal(errored, true);
512+
};
513+
});
514+
495515
test('schedules rerun when writing to signal before reading it', (runes) => {
496516
if (!runes) return () => {};
497517

0 commit comments

Comments
 (0)