fix: exclude `bind:this` from reactive state validation (#12566)

pull/12579/head
Simon H 4 months ago committed by GitHub
parent 2ea2be3324
commit c0832fd85d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: exclude `bind:this` from reactive state validation

@ -2867,9 +2867,18 @@ export const template_visitors = {
BindDirective(node, context) { BindDirective(node, context) {
const { state, path, visit } = context; const { state, path, visit } = context;
const expression = node.expression; const expression = node.expression;
const property = binding_properties[node.name];
if ( if (
expression.type === 'MemberExpression' && expression.type === 'MemberExpression' &&
(node.name !== 'this' ||
path.some(
({ type }) =>
type === 'IfBlock' ||
type === 'EachBlock' ||
type === 'AwaitBlock' ||
type === 'KeyBlock'
)) &&
context.state.options.dev && context.state.options.dev &&
context.state.analysis.runes context.state.analysis.runes
) { ) {
@ -2900,8 +2909,7 @@ export const template_visitors = {
/** @type {CallExpression} */ /** @type {CallExpression} */
let call_expr; let call_expr;
const property = binding_properties[node.name]; if (property?.event) {
if (property && property.event) {
call_expr = b.call( call_expr = b.call(
'$.bind_property', '$.bind_property',
b.literal(node.name), b.literal(node.name),

@ -15,7 +15,8 @@ export const binding_properties = {
// media // media
currentTime: { currentTime: {
valid_elements: ['audio', 'video'], valid_elements: ['audio', 'video'],
omit_in_ssr: true omit_in_ssr: true,
bidirectional: true
}, },
duration: { duration: {
valid_elements: ['audio', 'video'], valid_elements: ['audio', 'video'],
@ -25,7 +26,8 @@ export const binding_properties = {
focused: {}, focused: {},
paused: { paused: {
valid_elements: ['audio', 'video'], valid_elements: ['audio', 'video'],
omit_in_ssr: true omit_in_ssr: true,
bidirectional: true
}, },
buffered: { buffered: {
valid_elements: ['audio', 'video'], valid_elements: ['audio', 'video'],
@ -41,15 +43,18 @@ export const binding_properties = {
}, },
volume: { volume: {
valid_elements: ['audio', 'video'], valid_elements: ['audio', 'video'],
omit_in_ssr: true omit_in_ssr: true,
bidirectional: true
}, },
muted: { muted: {
valid_elements: ['audio', 'video'], valid_elements: ['audio', 'video'],
omit_in_ssr: true omit_in_ssr: true,
bidirectional: true
}, },
playbackRate: { playbackRate: {
valid_elements: ['audio', 'video'], valid_elements: ['audio', 'video'],
omit_in_ssr: true omit_in_ssr: true,
bidirectional: true
}, },
seeking: { seeking: {
valid_elements: ['audio', 'video'], valid_elements: ['audio', 'video'],
@ -124,11 +129,13 @@ export const binding_properties = {
}, },
scrollX: { scrollX: {
valid_elements: ['svelte:window'], valid_elements: ['svelte:window'],
omit_in_ssr: true omit_in_ssr: true,
bidirectional: true
}, },
scrollY: { scrollY: {
valid_elements: ['svelte:window'], valid_elements: ['svelte:window'],
omit_in_ssr: true omit_in_ssr: true,
bidirectional: true
}, },
online: { online: {
valid_elements: ['svelte:window'], valid_elements: ['svelte:window'],
@ -180,23 +187,28 @@ export const binding_properties = {
omit_in_ssr: true // no corresponding attribute omit_in_ssr: true // no corresponding attribute
}, },
checked: { checked: {
valid_elements: ['input'] valid_elements: ['input'],
bidirectional: true
}, },
group: { group: {
valid_elements: ['input'] valid_elements: ['input'],
bidirectional: true
}, },
// various // various
this: { this: {
omit_in_ssr: true omit_in_ssr: true
}, },
innerText: { innerText: {
invalid_elements: ['svelte:window', 'svelte:document'] invalid_elements: ['svelte:window', 'svelte:document'],
bidirectional: true
}, },
innerHTML: { innerHTML: {
invalid_elements: ['svelte:window', 'svelte:document'] invalid_elements: ['svelte:window', 'svelte:document'],
bidirectional: true
}, },
textContent: { textContent: {
invalid_elements: ['svelte:window', 'svelte:document'] invalid_elements: ['svelte:window', 'svelte:document'],
bidirectional: true
}, },
open: { open: {
event: 'toggle', event: 'toggle',
@ -204,10 +216,12 @@ export const binding_properties = {
valid_elements: ['details'] valid_elements: ['details']
}, },
value: { value: {
valid_elements: ['input', 'textarea', 'select'] valid_elements: ['input', 'textarea', 'select'],
bidirectional: true
}, },
files: { files: {
valid_elements: ['input'], valid_elements: ['input'],
omit_in_ssr: true omit_in_ssr: true,
bidirectional: true
} }
}; };

@ -7,10 +7,11 @@ export default test({
async test({ assert, warnings }) { async test({ assert, warnings }) {
assert.deepEqual(warnings, [ assert.deepEqual(warnings, [
`\`bind:value={pojo.value}\` (main.svelte:50:7) is binding to a non-reactive property`, '`bind:value={pojo.value}` (main.svelte:50:7) is binding to a non-reactive property',
`\`bind:value={frozen.value}\` (main.svelte:51:7) is binding to a non-reactive property`, '`bind:value={frozen.value}` (main.svelte:51:7) is binding to a non-reactive property',
`\`bind:value={pojo.value}\` (main.svelte:52:7) is binding to a non-reactive property`, '`bind:value={pojo.value}` (main.svelte:52:7) is binding to a non-reactive property',
`\`bind:value={frozen.value}\` (main.svelte:53:7) is binding to a non-reactive property` '`bind:value={frozen.value}` (main.svelte:53:7) is binding to a non-reactive property',
'`bind:this={pojo.value}` (main.svelte:55:6) is binding to a non-reactive property'
]); ]);
} }
}); });

@ -51,6 +51,9 @@
<input bind:value={frozen.value} /> <input bind:value={frozen.value} />
<Child bind:value={pojo.value} /> <Child bind:value={pojo.value} />
<Child bind:value={frozen.value} /> <Child bind:value={frozen.value} />
{#if value}
<div bind:this={pojo.value}></div>
{/if}
<!-- should not warn --> <!-- should not warn -->
<input bind:value={reactive.value} /> <input bind:value={reactive.value} />
@ -59,3 +62,4 @@
<Child bind:value={reactive.value} /> <Child bind:value={reactive.value} />
<Child bind:value={accessors.value} /> <Child bind:value={accessors.value} />
<Child bind:value={proxy.value} /> <Child bind:value={proxy.value} />
<div bind:this={pojo.value}></div>

Loading…
Cancel
Save