From 48549f7d005f388e1e26368daa65d058ed90dc61 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Tue, 9 Apr 2024 13:14:09 +0100 Subject: [PATCH] fix: improve internal proxied state signal heuristic (#11102) Fixes #11069 --- .changeset/four-mice-hammer.md | 5 +++++ packages/svelte/src/internal/client/proxy.js | 18 ++++++++++----- .../Child.svelte | 5 +++++ .../proxied-state-property-access/_config.js | 22 +++++++++++++++++++ .../proxied-state-property-access/main.svelte | 19 ++++++++++++++++ 5 files changed, 64 insertions(+), 5 deletions(-) create mode 100644 .changeset/four-mice-hammer.md create mode 100644 packages/svelte/tests/runtime-runes/samples/proxied-state-property-access/Child.svelte create mode 100644 packages/svelte/tests/runtime-runes/samples/proxied-state-property-access/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/proxied-state-property-access/main.svelte diff --git a/.changeset/four-mice-hammer.md b/.changeset/four-mice-hammer.md new file mode 100644 index 000000000000..22d1af592544 --- /dev/null +++ b/.changeset/four-mice-hammer.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: improve internal proxied state signal heuristic diff --git a/packages/svelte/src/internal/client/proxy.js b/packages/svelte/src/internal/client/proxy.js index bf4e15c5ffd5..6c6926241852 100644 --- a/packages/svelte/src/internal/client/proxy.js +++ b/packages/svelte/src/internal/client/proxy.js @@ -1,6 +1,11 @@ import { DEV } from 'esm-env'; -import { get, batch_inspect, current_component_context, untrack } from './runtime.js'; -import { effect_active } from './reactivity/effects.js'; +import { + get, + batch_inspect, + current_component_context, + untrack, + current_effect +} from './runtime.js'; import { array_prototype, define_property, @@ -206,7 +211,7 @@ const state_proxy_handler = { // but only if it's an own property and not a prototype property if ( s === undefined && - (effect_active() || updating_derived) && + (current_effect !== null || updating_derived) && (!(prop in target) || get_descriptor(target, prop)?.writable) ) { s = (metadata.i ? source : mutable_source)(proxy(target[prop], metadata.i, metadata.o)); @@ -250,7 +255,10 @@ const state_proxy_handler = { const has = Reflect.has(target, prop); let s = metadata.s.get(prop); - if (s !== undefined || (effect_active() && (!has || get_descriptor(target, prop)?.writable))) { + if ( + s !== undefined || + (current_effect !== null && (!has || get_descriptor(target, prop)?.writable)) + ) { if (s === undefined) { s = (metadata.i ? source : mutable_source)( has ? proxy(target[prop], metadata.i, metadata.o) : UNINITIALIZED @@ -273,7 +281,7 @@ const state_proxy_handler = { // we do so otherwise if we read it later, then the write won't be tracked and // the heuristics of effects will be different vs if we had read the proxied // object property before writing to that property. - if (s === undefined && effect_active()) { + if (s === undefined && current_effect !== null) { // the read creates a signal untrack(() => receiver[prop]); s = metadata.s.get(prop); diff --git a/packages/svelte/tests/runtime-runes/samples/proxied-state-property-access/Child.svelte b/packages/svelte/tests/runtime-runes/samples/proxied-state-property-access/Child.svelte new file mode 100644 index 000000000000..900577e32f4a --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/proxied-state-property-access/Child.svelte @@ -0,0 +1,5 @@ + + +Child: {settings.showInRgb} diff --git a/packages/svelte/tests/runtime-runes/samples/proxied-state-property-access/_config.js b/packages/svelte/tests/runtime-runes/samples/proxied-state-property-access/_config.js new file mode 100644 index 000000000000..ffccfd8e2009 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/proxied-state-property-access/_config.js @@ -0,0 +1,22 @@ +import { flushSync } from '../../../../src/index-client'; +import { test } from '../../test'; + +export default test({ + html: ` Child: true`, + + async test({ assert, target }) { + const btn = target.querySelector('button'); + + flushSync(() => { + btn?.click(); + }); + + assert.htmlEqual(target.innerHTML, ` Child: false`); + + flushSync(() => { + btn?.click(); + }); + + assert.htmlEqual(target.innerHTML, ` Child: true`); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/proxied-state-property-access/main.svelte b/packages/svelte/tests/runtime-runes/samples/proxied-state-property-access/main.svelte new file mode 100644 index 000000000000..f195c0c877ab --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/proxied-state-property-access/main.svelte @@ -0,0 +1,19 @@ + + + + + + +