Skip to content

Commit 3bb2311

Browse files
trueadmRich-Harris
andauthored
fix: loosen proxy signal creation heuristics (#11109)
* fix: loosen proxy signal creation heuristics * tighten up test * update comment * no need to create a source outside an effect here, because it can't result in a reference * preserve reference to props.$$events --------- Co-authored-by: Rich Harris <[email protected]>
1 parent 27891cb commit 3bb2311

File tree

5 files changed

+18
-17
lines changed

5 files changed

+18
-17
lines changed

.changeset/early-months-whisper.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: loosen proxy signal creation heuristics

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

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import {
1919
import { add_owner, check_ownership, strip_owner } from './dev/ownership.js';
2020
import { mutable_source, source, set } from './reactivity/sources.js';
2121
import { STATE_SYMBOL } from './constants.js';
22-
import { updating_derived } from './reactivity/deriveds.js';
2322
import { UNINITIALIZED } from '../../constants.js';
2423

2524
/**
@@ -207,13 +206,8 @@ const state_proxy_handler = {
207206
const metadata = target[STATE_SYMBOL];
208207
let s = metadata.s.get(prop);
209208

210-
// if we're reading a property in a reactive context, create a source,
211-
// but only if it's an own property and not a prototype property
212-
if (
213-
s === undefined &&
214-
(current_effect !== null || updating_derived) &&
215-
(!(prop in target) || get_descriptor(target, prop)?.writable)
216-
) {
209+
// create a source, but only if it's an own property and not a prototype property
210+
if (s === undefined && (!(prop in target) || get_descriptor(target, prop)?.writable)) {
217211
s = (metadata.i ? source : mutable_source)(proxy(target[prop], metadata.i, metadata.o));
218212
metadata.s.set(prop, s);
219213
}
@@ -281,7 +275,7 @@ const state_proxy_handler = {
281275
// we do so otherwise if we read it later, then the write won't be tracked and
282276
// the heuristics of effects will be different vs if we had read the proxied
283277
// object property before writing to that property.
284-
if (s === undefined && current_effect !== null) {
278+
if (s === undefined) {
285279
// the read creates a signal
286280
untrack(() => receiver[prop]);
287281
s = metadata.s.get(prop);

packages/svelte/src/legacy/legacy-client.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export function asClassComponent(component) {
5353

5454
class Svelte4Component {
5555
/** @type {any} */
56-
#events = {};
56+
#events;
5757

5858
/** @type {Record<string, any>} */
5959
#instance;
@@ -70,7 +70,7 @@ class Svelte4Component {
7070
// Using proxy state here isn't completely mirroring the Svelte 4 behavior, because mutations to a property
7171
// cause fine-grained updates to only the places where that property is used, and not the entire property.
7272
// Reactive statements and actions (the things where this matters) are handling this properly regardless, so it should be fine in practise.
73-
const props = proxy({ ...(options.props || {}), $$events: this.#events }, false);
73+
const props = proxy({ ...(options.props || {}), $$events: {} }, false);
7474
this.#instance = (options.hydrate ? hydrate : mount)(options.component, {
7575
target: options.target,
7676
props,
@@ -79,6 +79,8 @@ class Svelte4Component {
7979
recover: options.recover
8080
});
8181

82+
this.#events = props.$$events;
83+
8284
for (const key of Object.keys(this.#instance)) {
8385
if (key === '$set' || key === '$destroy' || key === '$on') continue;
8486
define_property(this, key, {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script>
2-
const { settings } = $props();
2+
import { settings } from './main.svelte';
33
</script>
44

55
Child: {settings.showInRgb}
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
<script context="module">
2-
export const context = $state({
2+
const context = $state({
33
settings: {
44
showInRgb: true
55
}
6-
})
6+
});
7+
8+
export const settings = context.settings;
79
</script>
810

911
<script>
1012
import Child from './Child.svelte';
11-
12-
const { settings } = context
1313
</script>
1414

1515
<button onclick={() => settings.showInRgb = !settings.showInRgb}>
1616
click {settings.showInRgb}
1717
</button>
1818

19-
<Child settings={settings} />
19+
<Child />

0 commit comments

Comments
 (0)