Skip to content

Commit e42c7cd

Browse files
committed
fix: move logic to proxy inside set
1 parent 82d45a2 commit e42c7cd

File tree

9 files changed

+41
-32
lines changed

9 files changed

+41
-32
lines changed

packages/svelte/src/compiler/phases/3-transform/client/types.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export interface ClientTransformState extends TransformState {
3030
/** turn `foo` into e.g. `$.get(foo)` */
3131
read: (id: Identifier) => Expression;
3232
/** turn `foo = bar` into e.g. `$.set(foo, bar)` */
33-
assign?: (node: Identifier, value: Expression) => Expression;
33+
assign?: (node: Identifier, value: Expression, proxy?: boolean) => Expression;
3434
/** turn `foo.bar = baz` into e.g. `$.mutate(foo, $.get(foo).bar = baz);` */
3535
mutate?: (node: Identifier, mutation: AssignmentExpression | UpdateExpression) => Expression;
3636
/** turn `foo++` into e.g. `$.update(foo)` */

packages/svelte/src/compiler/phases/3-transform/client/visitors/AssignmentExpression.js

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -65,21 +65,22 @@ function build_assignment(operator, left, right, context) {
6565
context.visit(build_assignment_value(operator, left, right))
6666
);
6767

68-
if (
68+
const needs_proxy =
6969
private_state.kind === 'state' &&
7070
is_non_coercive_operator(operator) &&
71-
should_proxy(value, context.state.scope)
72-
) {
73-
value = build_proxy_reassignment(value, b.member(b.this, private_state.id));
74-
}
71+
should_proxy(value, context.state.scope);
7572

7673
if (context.state.in_constructor) {
7774
// inside the constructor, we can assign to `this.#foo.v` rather than using `$.set`,
7875
// since nothing is tracking the signal at this point
79-
return b.assignment(operator, /** @type {Pattern} */ (context.visit(left)), value);
76+
return b.assignment(
77+
operator,
78+
/** @type {Pattern} */ (context.visit(left)),
79+
needs_proxy ? build_proxy_reassignment(value, b.member(b.this, private_state.id)) : value
80+
);
8081
}
8182

82-
return b.call('$.set', left, value);
83+
return b.call('$.set', left, value, needs_proxy && b.true, dev && needs_proxy && b.true);
8384
}
8485
}
8586

@@ -113,19 +114,17 @@ function build_assignment(operator, left, right, context) {
113114
context.visit(build_assignment_value(operator, left, right))
114115
);
115116

116-
if (
117+
return transform.assign(
118+
object,
119+
value,
117120
!is_primitive &&
118-
binding.kind !== 'prop' &&
119-
binding.kind !== 'bindable_prop' &&
120-
binding.kind !== 'raw_state' &&
121-
context.state.analysis.runes &&
122-
should_proxy(right, context.state.scope) &&
123-
is_non_coercive_operator(operator)
124-
) {
125-
value = build_proxy_reassignment(value, object);
126-
}
127-
128-
return transform.assign(object, value);
121+
binding.kind !== 'prop' &&
122+
binding.kind !== 'bindable_prop' &&
123+
binding.kind !== 'raw_state' &&
124+
context.state.analysis.runes &&
125+
should_proxy(right, context.state.scope) &&
126+
is_non_coercive_operator(operator)
127+
);
129128
}
130129

131130
// mutation

packages/svelte/src/compiler/phases/3-transform/client/visitors/ClassBody.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { dev, is_ignored } from '../../../../state.js';
55
import * as b from '../../../../utils/builders.js';
66
import { regex_invalid_identifier_chars } from '../../../patterns.js';
77
import { get_rune } from '../../../scope.js';
8-
import { build_proxy_reassignment, should_proxy } from '../utils.js';
8+
import { should_proxy } from '../utils.js';
99

1010
/**
1111
* @param {ClassBody} node
@@ -160,7 +160,7 @@ export function ClassBody(node, context) {
160160
'set',
161161
definition.key,
162162
[value],
163-
[b.stmt(b.call('$.set', member, build_proxy_reassignment(value, prev)))]
163+
[b.stmt(b.call('$.set', member, value, b.true, dev && b.true))]
164164
)
165165
);
166166
}

packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/declarations.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
/** @import { Identifier } from 'estree' */
22
/** @import { ComponentContext, Context } from '../../types' */
3-
import { is_state_source } from '../../utils.js';
3+
import { is_state_source, should_proxy } from '../../utils.js';
44
import * as b from '../../../../../utils/builders.js';
5+
import { dev } from '../../../../../state.js';
56

67
/**
78
* Turns `foo` into `$.get(foo)`
@@ -24,8 +25,8 @@ export function add_state_transformers(context) {
2425
) {
2526
context.state.transform[name] = {
2627
read: binding.declaration_kind === 'var' ? (node) => b.call('$.safe_get', node) : get_value,
27-
assign: (node, value) => {
28-
let call = b.call('$.set', node, value);
28+
assign: (node, value, proxy = false) => {
29+
let call = b.call('$.set', node, value, proxy && b.true, dev && proxy && b.true);
2930

3031
if (context.state.scope.get(`$${node.name}`)?.kind === 'store_sub') {
3132
call = b.call('$.store_unsub', call, b.literal(`$${node.name}`), b.id('$$stores'));

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import {
3434
import * as e from '../errors.js';
3535
import { legacy_mode_flag, tracing_mode_flag } from '../../flags/index.js';
3636
import { get_stack } from '../dev/tracing.js';
37+
import { proxy } from '../proxy.js';
3738

3839
export let inspect_effects = new Set();
3940

@@ -154,9 +155,11 @@ export function mutate(source, value) {
154155
* @template V
155156
* @param {Source<V>} source
156157
* @param {V} value
158+
* @param {boolean} [should_proxy]
159+
* @param {boolean} [needs_previous]
157160
* @returns {V}
158161
*/
159-
export function set(source, value) {
162+
export function set(source, value, should_proxy = false, needs_previous = false) {
160163
if (
161164
active_reaction !== null &&
162165
is_runes() &&
@@ -168,7 +171,13 @@ export function set(source, value) {
168171
e.state_unsafe_mutation();
169172
}
170173

171-
return internal_set(source, value);
174+
let new_value = should_proxy
175+
? needs_previous
176+
? proxy(value, source.o, null, source)
177+
: proxy(value, source.o)
178+
: value;
179+
180+
return internal_set(source, new_value);
172181
}
173182

174183
/**

packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/client/index.svelte.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export default function Bind_component_snippet($$anchor) {
2323
return $.get(value);
2424
},
2525
set value($$value) {
26-
$.set(value, $.proxy($$value, $.get_options(value)));
26+
$.set(value, $$value, true);
2727
}
2828
});
2929

packages/svelte/tests/snapshot/samples/class-state-field-constructor-assignment/_expected/client/index.svelte.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export default function Class_state_field_constructor_assignment($$anchor, $$pro
1212
}
1313

1414
set a(value) {
15-
$.set(this.#a, $.proxy(value, $.get_options(this.#a)));
15+
$.set(this.#a, value, true);
1616
}
1717

1818
#b = $.state();

packages/svelte/tests/snapshot/samples/destructured-assignments/_expected/client/index.svelte.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ let d = 4;
88

99
export function update(array) {
1010
(
11-
$.set(a, $.proxy(array[0], $.get_options(a))),
12-
$.set(b, $.proxy(array[1], $.get_options(b)))
11+
$.set(a, array[0], true),
12+
$.set(b, array[1], true)
1313
);
1414

1515
[c, d] = array;

packages/svelte/tests/snapshot/samples/function-prop-no-getter/_expected/client/index.svelte.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export default function Function_prop_no_getter($$anchor) {
1313
Button($$anchor, {
1414
onmousedown: () => $.set(count, $.get(count) + 1),
1515
onmouseup,
16-
onmouseenter: () => $.set(count, $.proxy(plusOne($.get(count)), $.get_options(count))),
16+
onmouseenter: () => $.set(count, plusOne($.get(count)), true),
1717
children: ($$anchor, $$slotProps) => {
1818
$.next();
1919

0 commit comments

Comments
 (0)