Skip to content

Commit 48549f7

Browse files
authored
fix: improve internal proxied state signal heuristic (#11102)
Fixes #11069
1 parent d2b6159 commit 48549f7

File tree

5 files changed

+64
-5
lines changed

5 files changed

+64
-5
lines changed

.changeset/four-mice-hammer.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"svelte": patch
3+
---
4+
5+
fix: improve internal proxied state signal heuristic

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

+13-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import { DEV } from 'esm-env';
2-
import { get, batch_inspect, current_component_context, untrack } from './runtime.js';
3-
import { effect_active } from './reactivity/effects.js';
2+
import {
3+
get,
4+
batch_inspect,
5+
current_component_context,
6+
untrack,
7+
current_effect
8+
} from './runtime.js';
49
import {
510
array_prototype,
611
define_property,
@@ -206,7 +211,7 @@ const state_proxy_handler = {
206211
// but only if it's an own property and not a prototype property
207212
if (
208213
s === undefined &&
209-
(effect_active() || updating_derived) &&
214+
(current_effect !== null || updating_derived) &&
210215
(!(prop in target) || get_descriptor(target, prop)?.writable)
211216
) {
212217
s = (metadata.i ? source : mutable_source)(proxy(target[prop], metadata.i, metadata.o));
@@ -250,7 +255,10 @@ const state_proxy_handler = {
250255
const has = Reflect.has(target, prop);
251256

252257
let s = metadata.s.get(prop);
253-
if (s !== undefined || (effect_active() && (!has || get_descriptor(target, prop)?.writable))) {
258+
if (
259+
s !== undefined ||
260+
(current_effect !== null && (!has || get_descriptor(target, prop)?.writable))
261+
) {
254262
if (s === undefined) {
255263
s = (metadata.i ? source : mutable_source)(
256264
has ? proxy(target[prop], metadata.i, metadata.o) : UNINITIALIZED
@@ -273,7 +281,7 @@ const state_proxy_handler = {
273281
// we do so otherwise if we read it later, then the write won't be tracked and
274282
// the heuristics of effects will be different vs if we had read the proxied
275283
// object property before writing to that property.
276-
if (s === undefined && effect_active()) {
284+
if (s === undefined && current_effect !== null) {
277285
// the read creates a signal
278286
untrack(() => receiver[prop]);
279287
s = metadata.s.get(prop);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<script>
2+
const { settings } = $props();
3+
</script>
4+
5+
Child: {settings.showInRgb}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { flushSync } from '../../../../src/index-client';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
html: `<button>click true</button> Child: true`,
6+
7+
async test({ assert, target }) {
8+
const btn = target.querySelector('button');
9+
10+
flushSync(() => {
11+
btn?.click();
12+
});
13+
14+
assert.htmlEqual(target.innerHTML, `<button>click false</button> Child: false`);
15+
16+
flushSync(() => {
17+
btn?.click();
18+
});
19+
20+
assert.htmlEqual(target.innerHTML, `<button>click true</button> Child: true`);
21+
}
22+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<script context="module">
2+
export const context = $state({
3+
settings: {
4+
showInRgb: true
5+
}
6+
})
7+
</script>
8+
9+
<script>
10+
import Child from './Child.svelte';
11+
12+
const { settings } = context
13+
</script>
14+
15+
<button onclick={() => settings.showInRgb = !settings.showInRgb}>
16+
click {settings.showInRgb}
17+
</button>
18+
19+
<Child settings={settings} />

0 commit comments

Comments
 (0)