From 376898f62d330ab887b9b7e46b2cd6a2650315d5 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Fri, 15 Mar 2024 23:15:43 +0100 Subject: [PATCH] runtime error when trying to bind: to non-bindable prop --- .../src/compiler/phases/3-transform/client/utils.js | 7 ++++++- packages/svelte/src/constants.js | 1 + .../svelte/src/internal/client/reactivity/props.js | 10 ++++++++++ .../samples/props-not-bindable/Counter.svelte | 5 +++++ .../samples/props-not-bindable/_config.js | 7 +++++++ .../samples/props-not-bindable/main.svelte | 7 +++++++ 6 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 packages/svelte/tests/runtime-runes/samples/props-not-bindable/Counter.svelte create mode 100644 packages/svelte/tests/runtime-runes/samples/props-not-bindable/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/props-not-bindable/main.svelte diff --git a/packages/svelte/src/compiler/phases/3-transform/client/utils.js b/packages/svelte/src/compiler/phases/3-transform/client/utils.js index cd274eef23..604bfdff6a 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/utils.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/utils.js @@ -5,7 +5,8 @@ import { PROPS_IS_LAZY_INITIAL, PROPS_IS_IMMUTABLE, PROPS_IS_RUNES, - PROPS_IS_UPDATED + PROPS_IS_UPDATED, + PROPS_IS_BINDABLE } from '../../../../constants.js'; /** @@ -639,6 +640,10 @@ export function get_prop_source(binding, state, name, initial) { flags |= PROPS_IS_RUNES; } + if (binding.kind === 'bindable_prop') { + flags |= PROPS_IS_BINDABLE; + } + if ( state.analysis.accessors || (state.analysis.immutable ? binding.reassigned : binding.mutated) diff --git a/packages/svelte/src/constants.js b/packages/svelte/src/constants.js index 7996e3b2fa..6f5c1673bc 100644 --- a/packages/svelte/src/constants.js +++ b/packages/svelte/src/constants.js @@ -11,6 +11,7 @@ export const PROPS_IS_IMMUTABLE = 1; export const PROPS_IS_RUNES = 1 << 1; export const PROPS_IS_UPDATED = 1 << 2; export const PROPS_IS_LAZY_INITIAL = 1 << 3; +export const PROPS_IS_BINDABLE = 1 << 4; /** List of Element events that will be delegated */ export const DelegatedEvents = [ diff --git a/packages/svelte/src/internal/client/reactivity/props.js b/packages/svelte/src/internal/client/reactivity/props.js index 586f0e64b1..56aa23101c 100644 --- a/packages/svelte/src/internal/client/reactivity/props.js +++ b/packages/svelte/src/internal/client/reactivity/props.js @@ -1,5 +1,6 @@ import { DEV } from 'esm-env'; import { + PROPS_IS_BINDABLE, PROPS_IS_IMMUTABLE, PROPS_IS_LAZY_INITIAL, PROPS_IS_RUNES, @@ -142,6 +143,15 @@ export function prop(props, key, flags, initial) { var prop_value = /** @type {V} */ (props[key]); var setter = get_descriptor(props, key)?.set; + if ((flags & PROPS_IS_BINDABLE) === 0 && setter) { + throw new Error( + 'ERR_SVELTE_NOT_BINDABLE' + + (DEV + ? `: Cannot bind:${key} because the property was not declared as bindable. To mark a property as bindable, use let \`{ ${key} } = $props.bindable()\` within the component.` + : '') + ); + } + if (prop_value === undefined && initial !== undefined) { if (setter && runes) { // TODO consolidate all these random runtime errors diff --git a/packages/svelte/tests/runtime-runes/samples/props-not-bindable/Counter.svelte b/packages/svelte/tests/runtime-runes/samples/props-not-bindable/Counter.svelte new file mode 100644 index 0000000000..4bc2db3968 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/props-not-bindable/Counter.svelte @@ -0,0 +1,5 @@ + + +{count} diff --git a/packages/svelte/tests/runtime-runes/samples/props-not-bindable/_config.js b/packages/svelte/tests/runtime-runes/samples/props-not-bindable/_config.js new file mode 100644 index 0000000000..e70b8067cc --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/props-not-bindable/_config.js @@ -0,0 +1,7 @@ +import { test } from '../../test'; + +export default test({ + error: + 'ERR_SVELTE_NOT_BINDABLE: Cannot bind:count because the property was not declared as bindable. To mark a property as bindable, use let `{ count } = $props.bindable()` within the component.', + html: `0` +}); diff --git a/packages/svelte/tests/runtime-runes/samples/props-not-bindable/main.svelte b/packages/svelte/tests/runtime-runes/samples/props-not-bindable/main.svelte new file mode 100644 index 0000000000..80242b75c6 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/props-not-bindable/main.svelte @@ -0,0 +1,7 @@ + + +