Skip to content

Commit

Permalink
fix: improve prop binding warning validation for stores (sveltejs#12745)
Browse files Browse the repository at this point in the history
* fix: improve prop binding warning validation for stores

* ts

* address feedback

* add comment

* failing test

* fix/simplify

---------

Co-authored-by: Rich Harris <[email protected]>
  • Loading branch information
trueadm and Rich-Harris authored Aug 6, 2024
1 parent d06174e commit 1942f87
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 28 deletions.
5 changes: 5 additions & 0 deletions .changeset/healthy-dancers-play.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: improve prop binding warning validation for stores
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import * as b from '../../../../utils/builders.js';
import { binding_properties } from '../../../bindings.js';
import { build_setter } from '../utils.js';
import { build_attribute_value } from './shared/element.js';
import { build_bind_this, build_validate_binding } from './shared/utils.js';
import { build_bind_this, validate_binding } from './shared/utils.js';

/**
* @param {BindDirective} node
Expand All @@ -30,12 +30,10 @@ export function BindDirective(node, context) {
)) &&
!is_ignored(node, 'binding_property_non_reactive')
) {
context.state.init.push(
build_validate_binding(
context.state,
node,
/**@type {MemberExpression} */ (context.visit(expression))
)
validate_binding(
context.state,
node,
/**@type {MemberExpression} */ (context.visit(expression))
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { get_attribute_chunks } from '../../../../../utils/ast.js';
import * as b from '../../../../../utils/builders.js';
import { is_element_node } from '../../../../nodes.js';
import { create_derived, build_setter } from '../../utils.js';
import { build_bind_this, build_validate_binding } from '../shared/utils.js';
import { build_bind_this, validate_binding } from '../shared/utils.js';
import { build_attribute_value } from '../shared/element.js';
import { build_event_handler } from './events.js';

Expand Down Expand Up @@ -151,7 +151,7 @@ export function build_component(node, component_name, context, anchor = context.
context.state.analysis.runes &&
!is_ignored(node, 'binding_property_non_reactive')
) {
context.state.init.push(build_validate_binding(context.state, attribute, expression));
validate_binding(context.state, attribute, expression);
}

if (attribute.name === 'this') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,28 +204,30 @@ export function build_bind_this(expression, value, { state, visit }) {
* @param {BindDirective} binding
* @param {MemberExpression} expression
*/
export function build_validate_binding(state, binding, expression) {
const string = state.analysis.source.slice(binding.start, binding.end);

const get_object = b.thunk(/** @type {Expression} */ (expression.object));
const get_property = b.thunk(
/** @type {Expression} */ (
expression.computed
? expression.property
: b.literal(/** @type {Identifier} */ (expression.property).name)
)
);
export function validate_binding(state, binding, expression) {
// If we are referencing a $store.foo then we don't need to add validation
const left = object(binding.expression);
const left_binding = left && state.scope.get(left.name);
if (left_binding?.kind === 'store_sub') return;

const loc = locator(binding.start);

return b.stmt(
b.call(
'$.validate_binding',
b.literal(string),
get_object,
get_property,
loc && b.literal(loc.line),
loc && b.literal(loc.column)
state.init.push(
b.stmt(
b.call(
'$.validate_binding',
b.literal(state.analysis.source.slice(binding.start, binding.end)),
b.thunk(/** @type {Expression} */ (expression.object)),
b.thunk(
/** @type {Expression} */ (
expression.computed
? expression.property
: b.literal(/** @type {Identifier} */ (expression.property).name)
)
),
loc && b.literal(loc.line),
loc && b.literal(loc.column)
)
)
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<script>
let { value = $bindable() } = $props();
</script>

<input type="number" bind:value />
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { test } from '../../test';

export default test({
mode: ['client'],
compileOptions: {
dev: true
},
async test({ warnings, assert }) {
assert.deepEqual(warnings, []);
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<script>
import { writable } from 'svelte/store';
import Child from './Child.svelte';
let a = writable({ value: 0 });
let b = writable({ nested: { value: 0 } });
</script>

<Child bind:value={$a.value} />
<Child bind:value={$b.nested.value} />
<p>{$a.value}</p>
<p>{$b.nested.value}</p>

0 comments on commit 1942f87

Please sign in to comment.