diff --git a/packages/svelte/src/internal/client/constants.js b/packages/svelte/src/internal/client/constants.js index a4840ce4eb..5f24792eae 100644 --- a/packages/svelte/src/internal/client/constants.js +++ b/packages/svelte/src/internal/client/constants.js @@ -22,6 +22,7 @@ export const HEAD_EFFECT = 1 << 19; export const EFFECT_HAS_DERIVED = 1 << 20; export const STATE_SYMBOL = Symbol('$state'); +export const PROXY_ONCHANGE_SYMBOL = Symbol('proxy onchange'); export const STATE_SYMBOL_METADATA = Symbol('$state metadata'); export const LEGACY_PROPS = Symbol('legacy props'); export const LOADING_ATTR_SYMBOL = Symbol(''); diff --git a/packages/svelte/src/internal/client/proxy.js b/packages/svelte/src/internal/client/proxy.js index c6e304fbf2..406b279df3 100644 --- a/packages/svelte/src/internal/client/proxy.js +++ b/packages/svelte/src/internal/client/proxy.js @@ -10,7 +10,7 @@ import { } from '../shared/utils.js'; import { check_ownership, widen_ownership } from './dev/ownership.js'; import { source, set, state, batch_onchange } from './reactivity/sources.js'; -import { STATE_SYMBOL, STATE_SYMBOL_METADATA } from './constants.js'; +import { PROXY_ONCHANGE_SYMBOL, STATE_SYMBOL, STATE_SYMBOL_METADATA } from './constants.js'; import { UNINITIALIZED } from '../../constants.js'; import * as e from './errors.js'; import { get_stack } from './dev/tracing.js'; @@ -33,7 +33,13 @@ export function proxy(value, options, parent = null, prev) { stack = get_stack('CreatedAt'); } // if non-proxyable, or is already a proxy, return `value` - if (typeof value !== 'object' || value === null || STATE_SYMBOL in value) { + if (typeof value !== 'object' || value === null) { + return value; + } + + if (STATE_SYMBOL in value) { + // @ts-ignore + value[PROXY_ONCHANGE_SYMBOL] = options?.onchange; return value; } @@ -237,6 +243,14 @@ export function proxy(value, options, parent = null, prev) { }, set(target, prop, value, receiver) { + if (prop === PROXY_ONCHANGE_SYMBOL && options?.onchange != null) { + const old_onchange = options.onchange; + options.onchange = () => { + old_onchange(); + value(); + }; + return true; + } var s = sources.get(prop); var has = prop in target;