Skip to content

Commit 2d1f2c0

Browse files
committed
move proxy logic into props function
1 parent dd52427 commit 2d1f2c0

File tree

7 files changed

+47
-3
lines changed

7 files changed

+47
-3
lines changed

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import {
88
PROPS_IS_LAZY_INITIAL,
99
PROPS_IS_IMMUTABLE,
1010
PROPS_IS_RUNES,
11-
PROPS_IS_UPDATED
11+
PROPS_IS_UPDATED,
12+
PROPS_IS_BINDABLE
1213
} from '../../../../constants.js';
1314
import { dev } from '../../../state.js';
1415
import { get_value } from './visitors/shared/declarations.js';
@@ -168,6 +169,10 @@ export function get_prop_source(binding, state, name, initial) {
168169

169170
let flags = 0;
170171

172+
if (binding.kind === 'bindable_prop') {
173+
flags |= PROPS_IS_BINDABLE;
174+
}
175+
171176
if (state.analysis.immutable) {
172177
flags |= PROPS_IS_IMMUTABLE;
173178
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ export function build_assignment(operator, left, right, context) {
9999
if (
100100
!is_primitive &&
101101
binding.kind !== 'prop' &&
102+
binding.kind !== 'bindable_prop' &&
102103
context.state.analysis.runes &&
103104
should_proxy(value, context.state.scope)
104105
) {

packages/svelte/src/constants.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ export const EACH_ITEM_IMMUTABLE = 1 << 5;
1010
export const PROPS_IS_IMMUTABLE = 1;
1111
export const PROPS_IS_RUNES = 1 << 1;
1212
export const PROPS_IS_UPDATED = 1 << 2;
13-
export const PROPS_IS_LAZY_INITIAL = 1 << 3;
13+
export const PROPS_IS_BINDABLE = 1 << 3;
14+
export const PROPS_IS_LAZY_INITIAL = 1 << 4;
1415

1516
export const TRANSITION_IN = 1;
1617
export const TRANSITION_OUT = 1 << 1;

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/** @import { Source } from './types.js' */
22
import { DEV } from 'esm-env';
33
import {
4+
PROPS_IS_BINDABLE,
45
PROPS_IS_IMMUTABLE,
56
PROPS_IS_LAZY_INITIAL,
67
PROPS_IS_RUNES,
@@ -13,6 +14,7 @@ import { get, is_signals_recorded, untrack, update } from '../runtime.js';
1314
import { safe_equals } from './equality.js';
1415
import * as e from '../errors.js';
1516
import { LEGACY_DERIVED_PROP } from '../constants.js';
17+
import { proxy } from '../proxy.js';
1618

1719
/**
1820
* @param {((value?: number) => number)} fn
@@ -228,6 +230,7 @@ export function spread_props(...props) {
228230
export function prop(props, key, flags, fallback) {
229231
var immutable = (flags & PROPS_IS_IMMUTABLE) !== 0;
230232
var runes = (flags & PROPS_IS_RUNES) !== 0;
233+
var bindable = (flags & PROPS_IS_BINDABLE) !== 0;
231234
var lazy = (flags & PROPS_IS_LAZY_INITIAL) !== 0;
232235

233236
var prop_value = /** @type {V} */ (props[key]);
@@ -343,7 +346,7 @@ export function prop(props, key, flags, fallback) {
343346
}
344347

345348
if (arguments.length > 0) {
346-
const new_value = mutation ? get(current_value) : value;
349+
const new_value = mutation ? get(current_value) : bindable ? proxy(value) : value;
347350

348351
if (!current_value.equals(new_value)) {
349352
from_child = true;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<script>
2+
let { object = $bindable() } = $props();
3+
</script>
4+
5+
<button onclick={() => (object = { count: object.count + 1 })}>reassign</button>
6+
<button onclick={() => (object.count += 1)}>mutate</button>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { flushSync } from 'svelte';
2+
import { ok, test } from '../../test';
3+
4+
export default test({
5+
html: '<button>reassign</button> <button>mutate</button> <p>0</p>',
6+
test({ assert, target }) {
7+
const [reassign, mutate] = target.querySelectorAll('button');
8+
const output = target.querySelector('p');
9+
ok(output);
10+
11+
flushSync(() => mutate.click());
12+
assert.htmlEqual(output.innerHTML, '0');
13+
14+
flushSync(() => reassign.click());
15+
assert.htmlEqual(output.innerHTML, '2');
16+
17+
flushSync(() => mutate.click());
18+
assert.htmlEqual(output.innerHTML, '2');
19+
}
20+
});
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<script>
2+
import Child from './Child.svelte';
3+
4+
let object = $state.raw({ count: 0 });
5+
</script>
6+
7+
<Child bind:object />
8+
<p>{object.count}</p>

0 commit comments

Comments
 (0)