From 5e02a98713a4991960c0284e7337c94e30b4fa21 Mon Sep 17 00:00:00 2001 From: paoloricciuti Date: Wed, 9 Apr 2025 23:45:40 +0200 Subject: [PATCH 1/5] fix: prevent ownership warnings if the fallback of a bindable is used --- .changeset/wise-turkeys-yell.md | 5 +++ .../client/visitors/shared/utils.js | 1 + .../svelte/src/internal/client/constants.js | 1 + .../src/internal/client/dev/ownership.js | 16 ++++++-- packages/svelte/src/internal/client/proxy.js | 13 ++++--- .../src/internal/client/reactivity/props.js | 37 ++++++++++++++++++- .../Child.svelte | 5 +++ .../Parent.svelte | 7 ++++ .../_config.js | 11 ++++++ .../main.svelte | 5 +++ .../Parent.svelte | 8 ++++ .../_config.js | 23 ++++++++++++ .../main.svelte | 5 +++ 13 files changed, 126 insertions(+), 11 deletions(-) create mode 100644 .changeset/wise-turkeys-yell.md create mode 100644 packages/svelte/tests/runtime-runes/samples/ownership-invalid-binding-bindable-fallback/Child.svelte create mode 100644 packages/svelte/tests/runtime-runes/samples/ownership-invalid-binding-bindable-fallback/Parent.svelte create mode 100644 packages/svelte/tests/runtime-runes/samples/ownership-invalid-binding-bindable-fallback/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/ownership-invalid-binding-bindable-fallback/main.svelte create mode 100644 packages/svelte/tests/runtime-runes/samples/ownership-invalid-mutation-bindable-fallback/Parent.svelte create mode 100644 packages/svelte/tests/runtime-runes/samples/ownership-invalid-mutation-bindable-fallback/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/ownership-invalid-mutation-bindable-fallback/main.svelte diff --git a/.changeset/wise-turkeys-yell.md b/.changeset/wise-turkeys-yell.md new file mode 100644 index 000000000000..cd5e103de3a6 --- /dev/null +++ b/.changeset/wise-turkeys-yell.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: prevent ownership warnings if the fallback of a bindable is used diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js index af6e56f70c81..819c22bd2f74 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js @@ -348,6 +348,7 @@ export function validate_mutation(node, context, expression) { b.literal(binding.prop_alias), b.array(path), expression, + binding.prop_alias != null && b.id(binding.prop_alias), loc && b.literal(loc.line), loc && b.literal(loc.column) ); diff --git a/packages/svelte/src/internal/client/constants.js b/packages/svelte/src/internal/client/constants.js index 7e5196c606b4..f67af2812220 100644 --- a/packages/svelte/src/internal/client/constants.js +++ b/packages/svelte/src/internal/client/constants.js @@ -23,5 +23,6 @@ export const EFFECT_HAS_DERIVED = 1 << 20; export const EFFECT_IS_UPDATING = 1 << 21; export const STATE_SYMBOL = Symbol('$state'); +export const BINDABLE_FALLBACK_SYMBOL = Symbol('bindable fallback'); export const LEGACY_PROPS = Symbol('legacy props'); export const LOADING_ATTR_SYMBOL = Symbol(''); diff --git a/packages/svelte/src/internal/client/dev/ownership.js b/packages/svelte/src/internal/client/dev/ownership.js index e28a40dd77ee..39bb6080919b 100644 --- a/packages/svelte/src/internal/client/dev/ownership.js +++ b/packages/svelte/src/internal/client/dev/ownership.js @@ -1,7 +1,7 @@ /** @typedef {{ file: string, line: number, column: number }} Location */ import { get_descriptor } from '../../shared/utils.js'; -import { LEGACY_PROPS, STATE_SYMBOL } from '../constants.js'; +import { BINDABLE_FALLBACK_SYMBOL, LEGACY_PROPS, STATE_SYMBOL } from '../constants.js'; import { FILENAME } from '../../../constants.js'; import { component_context } from '../context.js'; import * as w from '../warnings.js'; @@ -22,12 +22,13 @@ export function create_ownership_validator(props) { * @param {string} prop * @param {any[]} path * @param {any} result + * @param {any} prop_value * @param {number} line * @param {number} column */ - mutation: (prop, path, result, line, column) => { + mutation: (prop, path, result, prop_value, line, column) => { const name = path[0]; - if (is_bound(props, name) || !parent) { + if (is_bound(props, name) || !parent || prop_value()?.[BINDABLE_FALLBACK_SYMBOL]) { return result; } @@ -52,7 +53,14 @@ export function create_ownership_validator(props) { * @param {() => any} value */ binding: (key, child_component, value) => { - if (!is_bound(props, key) && parent && value()?.[STATE_SYMBOL]) { + var val; + if ( + !is_bound(props, key) && + parent && + // we do this trick to prevent calling the value function twice + (val = value())?.[STATE_SYMBOL] && + !val[BINDABLE_FALLBACK_SYMBOL] + ) { w.ownership_invalid_binding( component[FILENAME], key, diff --git a/packages/svelte/src/internal/client/proxy.js b/packages/svelte/src/internal/client/proxy.js index 5e0aa3dbc35f..d67d16fbc496 100644 --- a/packages/svelte/src/internal/client/proxy.js +++ b/packages/svelte/src/internal/client/proxy.js @@ -9,7 +9,7 @@ import { object_prototype } from '../shared/utils.js'; import { state as source, set } from './reactivity/sources.js'; -import { STATE_SYMBOL } from './constants.js'; +import { BINDABLE_FALLBACK_SYMBOL, STATE_SYMBOL } from './constants.js'; import { UNINITIALIZED } from '../../constants.js'; import * as e from './errors.js'; import { get_stack } from './dev/tracing.js'; @@ -64,10 +64,13 @@ export function proxy(value) { return new Proxy(/** @type {any} */ (value), { defineProperty(_, prop, descriptor) { if ( - !('value' in descriptor) || - descriptor.configurable === false || - descriptor.enumerable === false || - descriptor.writable === false + // we allow non enumerable/writable defines if the prop being set is our own symbol + // this should be fine for the invariants since the user can't get a handle to the symbol + (!DEV || prop !== BINDABLE_FALLBACK_SYMBOL) && + (!('value' in descriptor) || + descriptor.configurable === false || + descriptor.enumerable === false || + descriptor.writable === false) ) { // we disallow non-basic descriptors, because unless they are applied to the // target object — which we avoid, so that state can be forked — we will run diff --git a/packages/svelte/src/internal/client/reactivity/props.js b/packages/svelte/src/internal/client/reactivity/props.js index bd85b14df088..0e098d2f785a 100644 --- a/packages/svelte/src/internal/client/reactivity/props.js +++ b/packages/svelte/src/internal/client/reactivity/props.js @@ -7,13 +7,18 @@ import { PROPS_IS_RUNES, PROPS_IS_UPDATED } from '../../../constants.js'; -import { get_descriptor, is_function } from '../../shared/utils.js'; +import { define_property, get_descriptor, is_function } from '../../shared/utils.js'; import { mutable_source, set, source, update } from './sources.js'; import { derived, derived_safe_equal } from './deriveds.js'; import { get, captured_signals, untrack } from '../runtime.js'; import { safe_equals } from './equality.js'; import * as e from '../errors.js'; -import { LEGACY_DERIVED_PROP, LEGACY_PROPS, STATE_SYMBOL } from '../constants.js'; +import { + BINDABLE_FALLBACK_SYMBOL, + LEGACY_DERIVED_PROP, + LEGACY_PROPS, + STATE_SYMBOL +} from '../constants.js'; import { proxy } from '../proxy.js'; import { capture_store_binding } from './store.js'; import { legacy_mode_flag } from '../../flags/index.js'; @@ -304,6 +309,29 @@ export function prop(props, key, flags, fallback) { if (setter) setter(prop_value); } + /** + * @param {any} value + */ + function set_bindable_fallback(value) { + if (DEV && !setter && fallback_used && value != null && typeof value === 'object') { + // in dev we issue a warning if a bindable prop is passed with bindable + // to a child if the prop doesn't have a setter but if it's a fallback + // it's a false positive since the state it's actually created in this + // component so we store the fact that this is a bindable fallback with + // a symbol + define_property(value, BINDABLE_FALLBACK_SYMBOL, { + enumerable: false, + // it needs to be configurable or the proxy will complain when we return true + // for a non configurable property + configurable: true, + writable: false, + value: true + }); + } + } + + set_bindable_fallback(prop_value); + /** @type {() => V} */ var getter; if (runes) { @@ -399,6 +427,11 @@ export function prop(props, key, flags, fallback) { if (arguments.length > 0) { const new_value = mutation ? get(current_value) : runes && bindable ? proxy(value) : value; + // we only care to add the symbol if the original prop is reassigned + if (runes && bindable && !mutation) { + set_bindable_fallback(new_value); + } + if (!current_value.equals(new_value)) { from_child = true; set(inner_current_value, new_value); diff --git a/packages/svelte/tests/runtime-runes/samples/ownership-invalid-binding-bindable-fallback/Child.svelte b/packages/svelte/tests/runtime-runes/samples/ownership-invalid-binding-bindable-fallback/Child.svelte new file mode 100644 index 000000000000..78b82caed9ed --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/ownership-invalid-binding-bindable-fallback/Child.svelte @@ -0,0 +1,5 @@ + + +{test} diff --git a/packages/svelte/tests/runtime-runes/samples/ownership-invalid-binding-bindable-fallback/Parent.svelte b/packages/svelte/tests/runtime-runes/samples/ownership-invalid-binding-bindable-fallback/Parent.svelte new file mode 100644 index 000000000000..7bfb17aa6465 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/ownership-invalid-binding-bindable-fallback/Parent.svelte @@ -0,0 +1,7 @@ + + + diff --git a/packages/svelte/tests/runtime-runes/samples/ownership-invalid-binding-bindable-fallback/_config.js b/packages/svelte/tests/runtime-runes/samples/ownership-invalid-binding-bindable-fallback/_config.js new file mode 100644 index 000000000000..e93067eb9d34 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/ownership-invalid-binding-bindable-fallback/_config.js @@ -0,0 +1,11 @@ +import { test } from '../../test'; + +export default test({ + mode: ['client'], + compileOptions: { + dev: true + }, + async test({ warnings, assert }) { + assert.deepEqual(warnings, []); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/ownership-invalid-binding-bindable-fallback/main.svelte b/packages/svelte/tests/runtime-runes/samples/ownership-invalid-binding-bindable-fallback/main.svelte new file mode 100644 index 000000000000..282afb1771b0 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/ownership-invalid-binding-bindable-fallback/main.svelte @@ -0,0 +1,5 @@ + + + diff --git a/packages/svelte/tests/runtime-runes/samples/ownership-invalid-mutation-bindable-fallback/Parent.svelte b/packages/svelte/tests/runtime-runes/samples/ownership-invalid-mutation-bindable-fallback/Parent.svelte new file mode 100644 index 000000000000..7d6b248da736 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/ownership-invalid-mutation-bindable-fallback/Parent.svelte @@ -0,0 +1,8 @@ + + + + + +{test} \ No newline at end of file diff --git a/packages/svelte/tests/runtime-runes/samples/ownership-invalid-mutation-bindable-fallback/_config.js b/packages/svelte/tests/runtime-runes/samples/ownership-invalid-mutation-bindable-fallback/_config.js new file mode 100644 index 000000000000..9b4e3479ea8c --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/ownership-invalid-mutation-bindable-fallback/_config.js @@ -0,0 +1,23 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + mode: ['client'], + compileOptions: { + dev: true + }, + async test({ warnings, assert, target }) { + const [btn, btn2] = target.querySelectorAll('button'); + flushSync(() => { + btn2.click(); + }); + assert.deepEqual(warnings, []); + flushSync(() => { + btn.click(); + }); + flushSync(() => { + btn2.click(); + }); + assert.deepEqual(warnings, []); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/ownership-invalid-mutation-bindable-fallback/main.svelte b/packages/svelte/tests/runtime-runes/samples/ownership-invalid-mutation-bindable-fallback/main.svelte new file mode 100644 index 000000000000..282afb1771b0 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/ownership-invalid-mutation-bindable-fallback/main.svelte @@ -0,0 +1,5 @@ + + + From 4f7c3bdd42b57ebdb2d9e70dcf47956506a9292c Mon Sep 17 00:00:00 2001 From: paoloricciuti Date: Thu, 10 Apr 2025 09:46:01 +0200 Subject: [PATCH 2/5] fix: filter out symbol from own keys --- packages/svelte/src/internal/client/proxy.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/svelte/src/internal/client/proxy.js b/packages/svelte/src/internal/client/proxy.js index d67d16fbc496..0eda99efdb26 100644 --- a/packages/svelte/src/internal/client/proxy.js +++ b/packages/svelte/src/internal/client/proxy.js @@ -266,7 +266,9 @@ export function proxy(value) { var own_keys = Reflect.ownKeys(target).filter((key) => { var source = sources.get(key); - return source === undefined || source.v !== UNINITIALIZED; + return ( + source === undefined || source.v !== UNINITIALIZED || key !== BINDABLE_FALLBACK_SYMBOL + ); }); for (var [key, source] of sources) { From 7e95260c4484b6a07d01aaeab2c59036f4e8c0c6 Mon Sep 17 00:00:00 2001 From: paoloricciuti Date: Thu, 10 Apr 2025 09:55:33 +0200 Subject: [PATCH 3/5] fix: don't create sources for `BINDABLE_FALLBACK_SYMBOL` --- packages/svelte/src/internal/client/proxy.js | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/svelte/src/internal/client/proxy.js b/packages/svelte/src/internal/client/proxy.js index 0eda99efdb26..f539fa78055c 100644 --- a/packages/svelte/src/internal/client/proxy.js +++ b/packages/svelte/src/internal/client/proxy.js @@ -63,14 +63,17 @@ export function proxy(value) { return new Proxy(/** @type {any} */ (value), { defineProperty(_, prop, descriptor) { + // we allow non enumerable/writable defines if the prop being set is our own symbol + // this should be fine for the invariants since the user can't get a handle to the symbol + if (DEV && prop === BINDABLE_FALLBACK_SYMBOL) { + return Reflect.defineProperty(_, prop, descriptor); + } + if ( - // we allow non enumerable/writable defines if the prop being set is our own symbol - // this should be fine for the invariants since the user can't get a handle to the symbol - (!DEV || prop !== BINDABLE_FALLBACK_SYMBOL) && - (!('value' in descriptor) || - descriptor.configurable === false || - descriptor.enumerable === false || - descriptor.writable === false) + !('value' in descriptor) || + descriptor.configurable === false || + descriptor.enumerable === false || + descriptor.writable === false ) { // we disallow non-basic descriptors, because unless they are applied to the // target object — which we avoid, so that state can be forked — we will run @@ -126,6 +129,9 @@ export function proxy(value) { if (prop === STATE_SYMBOL) { return value; } + if (DEV && prop === BINDABLE_FALLBACK_SYMBOL) { + return Reflect.get(target, prop); + } var s = sources.get(prop); var exists = prop in target; From 8fda58a27dd4443acbc3fdd44383e5aa512aebcd Mon Sep 17 00:00:00 2001 From: paoloricciuti Date: Thu, 10 Apr 2025 12:13:55 +0200 Subject: [PATCH 4/5] fix: use strategy suggested by actually competent person aka @dummdidumm --- .../client/visitors/shared/utils.js | 1 - .../svelte/src/internal/client/constants.js | 1 - .../src/internal/client/dev/ownership.js | 22 +++++------- packages/svelte/src/internal/client/proxy.js | 15 ++------ .../src/internal/client/reactivity/props.js | 35 +------------------ 5 files changed, 12 insertions(+), 62 deletions(-) diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js index 819c22bd2f74..af6e56f70c81 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js @@ -348,7 +348,6 @@ export function validate_mutation(node, context, expression) { b.literal(binding.prop_alias), b.array(path), expression, - binding.prop_alias != null && b.id(binding.prop_alias), loc && b.literal(loc.line), loc && b.literal(loc.column) ); diff --git a/packages/svelte/src/internal/client/constants.js b/packages/svelte/src/internal/client/constants.js index f67af2812220..7e5196c606b4 100644 --- a/packages/svelte/src/internal/client/constants.js +++ b/packages/svelte/src/internal/client/constants.js @@ -23,6 +23,5 @@ export const EFFECT_HAS_DERIVED = 1 << 20; export const EFFECT_IS_UPDATING = 1 << 21; export const STATE_SYMBOL = Symbol('$state'); -export const BINDABLE_FALLBACK_SYMBOL = Symbol('bindable fallback'); export const LEGACY_PROPS = Symbol('legacy props'); export const LOADING_ATTR_SYMBOL = Symbol(''); diff --git a/packages/svelte/src/internal/client/dev/ownership.js b/packages/svelte/src/internal/client/dev/ownership.js index 39bb6080919b..3be354ba042a 100644 --- a/packages/svelte/src/internal/client/dev/ownership.js +++ b/packages/svelte/src/internal/client/dev/ownership.js @@ -1,7 +1,7 @@ /** @typedef {{ file: string, line: number, column: number }} Location */ import { get_descriptor } from '../../shared/utils.js'; -import { BINDABLE_FALLBACK_SYMBOL, LEGACY_PROPS, STATE_SYMBOL } from '../constants.js'; +import { LEGACY_PROPS, STATE_SYMBOL } from '../constants.js'; import { FILENAME } from '../../../constants.js'; import { component_context } from '../context.js'; import * as w from '../warnings.js'; @@ -22,13 +22,12 @@ export function create_ownership_validator(props) { * @param {string} prop * @param {any[]} path * @param {any} result - * @param {any} prop_value * @param {number} line * @param {number} column */ - mutation: (prop, path, result, prop_value, line, column) => { + mutation: (prop, path, result, line, column) => { const name = path[0]; - if (is_bound(props, name) || !parent || prop_value()?.[BINDABLE_FALLBACK_SYMBOL]) { + if (is_bound(props, name) || !parent) { return result; } @@ -53,14 +52,7 @@ export function create_ownership_validator(props) { * @param {() => any} value */ binding: (key, child_component, value) => { - var val; - if ( - !is_bound(props, key) && - parent && - // we do this trick to prevent calling the value function twice - (val = value())?.[STATE_SYMBOL] && - !val[BINDABLE_FALLBACK_SYMBOL] - ) { + if (!is_bound(props, key) && parent && value()?.[STATE_SYMBOL]) { w.ownership_invalid_binding( component[FILENAME], key, @@ -80,5 +72,9 @@ function is_bound(props, prop_name) { // Can be the case when someone does `mount(Component, props)` with `let props = $state({...})` // or `createClassComponent(Component, props)` const is_entry_props = STATE_SYMBOL in props || LEGACY_PROPS in props; - return !!get_descriptor(props, prop_name)?.set || (is_entry_props && prop_name in props); + return ( + !!get_descriptor(props, prop_name)?.set || + (is_entry_props && prop_name in props) || + !(prop_name in props) + ); } diff --git a/packages/svelte/src/internal/client/proxy.js b/packages/svelte/src/internal/client/proxy.js index f539fa78055c..5e0aa3dbc35f 100644 --- a/packages/svelte/src/internal/client/proxy.js +++ b/packages/svelte/src/internal/client/proxy.js @@ -9,7 +9,7 @@ import { object_prototype } from '../shared/utils.js'; import { state as source, set } from './reactivity/sources.js'; -import { BINDABLE_FALLBACK_SYMBOL, STATE_SYMBOL } from './constants.js'; +import { STATE_SYMBOL } from './constants.js'; import { UNINITIALIZED } from '../../constants.js'; import * as e from './errors.js'; import { get_stack } from './dev/tracing.js'; @@ -63,12 +63,6 @@ export function proxy(value) { return new Proxy(/** @type {any} */ (value), { defineProperty(_, prop, descriptor) { - // we allow non enumerable/writable defines if the prop being set is our own symbol - // this should be fine for the invariants since the user can't get a handle to the symbol - if (DEV && prop === BINDABLE_FALLBACK_SYMBOL) { - return Reflect.defineProperty(_, prop, descriptor); - } - if ( !('value' in descriptor) || descriptor.configurable === false || @@ -129,9 +123,6 @@ export function proxy(value) { if (prop === STATE_SYMBOL) { return value; } - if (DEV && prop === BINDABLE_FALLBACK_SYMBOL) { - return Reflect.get(target, prop); - } var s = sources.get(prop); var exists = prop in target; @@ -272,9 +263,7 @@ export function proxy(value) { var own_keys = Reflect.ownKeys(target).filter((key) => { var source = sources.get(key); - return ( - source === undefined || source.v !== UNINITIALIZED || key !== BINDABLE_FALLBACK_SYMBOL - ); + return source === undefined || source.v !== UNINITIALIZED; }); for (var [key, source] of sources) { diff --git a/packages/svelte/src/internal/client/reactivity/props.js b/packages/svelte/src/internal/client/reactivity/props.js index 0e098d2f785a..341d7c768ad0 100644 --- a/packages/svelte/src/internal/client/reactivity/props.js +++ b/packages/svelte/src/internal/client/reactivity/props.js @@ -13,12 +13,7 @@ import { derived, derived_safe_equal } from './deriveds.js'; import { get, captured_signals, untrack } from '../runtime.js'; import { safe_equals } from './equality.js'; import * as e from '../errors.js'; -import { - BINDABLE_FALLBACK_SYMBOL, - LEGACY_DERIVED_PROP, - LEGACY_PROPS, - STATE_SYMBOL -} from '../constants.js'; +import { LEGACY_DERIVED_PROP, LEGACY_PROPS, STATE_SYMBOL } from '../constants.js'; import { proxy } from '../proxy.js'; import { capture_store_binding } from './store.js'; import { legacy_mode_flag } from '../../flags/index.js'; @@ -309,29 +304,6 @@ export function prop(props, key, flags, fallback) { if (setter) setter(prop_value); } - /** - * @param {any} value - */ - function set_bindable_fallback(value) { - if (DEV && !setter && fallback_used && value != null && typeof value === 'object') { - // in dev we issue a warning if a bindable prop is passed with bindable - // to a child if the prop doesn't have a setter but if it's a fallback - // it's a false positive since the state it's actually created in this - // component so we store the fact that this is a bindable fallback with - // a symbol - define_property(value, BINDABLE_FALLBACK_SYMBOL, { - enumerable: false, - // it needs to be configurable or the proxy will complain when we return true - // for a non configurable property - configurable: true, - writable: false, - value: true - }); - } - } - - set_bindable_fallback(prop_value); - /** @type {() => V} */ var getter; if (runes) { @@ -427,11 +399,6 @@ export function prop(props, key, flags, fallback) { if (arguments.length > 0) { const new_value = mutation ? get(current_value) : runes && bindable ? proxy(value) : value; - // we only care to add the symbol if the original prop is reassigned - if (runes && bindable && !mutation) { - set_bindable_fallback(new_value); - } - if (!current_value.equals(new_value)) { from_child = true; set(inner_current_value, new_value); From 24d4df3ec64f1381414276a7a2679b1f5a3805c9 Mon Sep 17 00:00:00 2001 From: paoloricciuti Date: Thu, 10 Apr 2025 13:21:56 +0200 Subject: [PATCH 5/5] chore: rename function --- packages/svelte/src/internal/client/dev/ownership.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/svelte/src/internal/client/dev/ownership.js b/packages/svelte/src/internal/client/dev/ownership.js index 3be354ba042a..108c7adf9282 100644 --- a/packages/svelte/src/internal/client/dev/ownership.js +++ b/packages/svelte/src/internal/client/dev/ownership.js @@ -27,7 +27,7 @@ export function create_ownership_validator(props) { */ mutation: (prop, path, result, line, column) => { const name = path[0]; - if (is_bound(props, name) || !parent) { + if (is_bound_or_unset(props, name) || !parent) { return result; } @@ -52,7 +52,7 @@ export function create_ownership_validator(props) { * @param {() => any} value */ binding: (key, child_component, value) => { - if (!is_bound(props, key) && parent && value()?.[STATE_SYMBOL]) { + if (!is_bound_or_unset(props, key) && parent && value()?.[STATE_SYMBOL]) { w.ownership_invalid_binding( component[FILENAME], key, @@ -68,7 +68,7 @@ export function create_ownership_validator(props) { * @param {Record} props * @param {string} prop_name */ -function is_bound(props, prop_name) { +function is_bound_or_unset(props, prop_name) { // Can be the case when someone does `mount(Component, props)` with `let props = $state({...})` // or `createClassComponent(Component, props)` const is_entry_props = STATE_SYMBOL in props || LEGACY_PROPS in props;