Skip to content

Commit ae73afd

Browse files
committed
better warnings now that we have more info
1 parent 0dbba03 commit ae73afd

File tree

7 files changed

+20
-23
lines changed

7 files changed

+20
-23
lines changed

documentation/docs/98-reference/.generated/client-warnings.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ Tried to unmount a component that was not mounted
161161
### ownership_invalid_binding
162162

163163
```
164-
%parent% passed a value to %child% with `bind:`, but the value is owned by %owner%. Consider creating a binding between %owner% and %parent%
164+
%parent% passed property `%prop%` to %child% with `bind:`, but its parent component %owner% did not declare `%prop%` as a binding. Consider creating a binding between %owner% and %parent% (e.g. `bind:%prop%={...}` instead of `%prop%={...}`)
165165
```
166166

167167
Consider three components `GrandParent`, `Parent` and `Child`. If you do `<GrandParent bind:value>`, inside `GrandParent` pass on the variable via `<Parent {value} />` (note the missing `bind:`) and then do `<Child bind:value>` inside `Parent`, this warning is thrown.
@@ -171,11 +171,7 @@ To fix it, `bind:` to the value instead of just passing a property (i.e. in this
171171
### ownership_invalid_mutation
172172
173173
```
174-
Mutating a value outside the component that created it is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead
175-
```
176-
177-
```
178-
%component% mutated a value owned by %owner%. This is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead
174+
%component% mutated property `%prop%` from parent component %owner%, which did not declare it as a binding. This is strongly discouraged. Consider passing props to child components that mutate them with `bind:` (e.g. `bind:%prop%={...}` instead of `%prop%={...}`), or use a callback instead
179175
```
180176
181177
Consider the following code:

packages/svelte/messages/client-warnings/warnings.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,17 +132,15 @@ During development, this error is often preceeded by a `console.error` detailing
132132
133133
## ownership_invalid_binding
134134
135-
> %parent% passed a value to %child% with `bind:`, but the value is owned by %owner%. Consider creating a binding between %owner% and %parent%
135+
> %parent% passed property `%prop%` to %child% with `bind:`, but its parent component %owner% did not declare `%prop%` as a binding. Consider creating a binding between %owner% and %parent% (e.g. `bind:%prop%={...}` instead of `%prop%={...}`)
136136
137137
Consider three components `GrandParent`, `Parent` and `Child`. If you do `<GrandParent bind:value>`, inside `GrandParent` pass on the variable via `<Parent {value} />` (note the missing `bind:`) and then do `<Child bind:value>` inside `Parent`, this warning is thrown.
138138
139139
To fix it, `bind:` to the value instead of just passing a property (i.e. in this example do `<Parent bind:value />`).
140140
141141
## ownership_invalid_mutation
142142
143-
> Mutating a value outside the component that created it is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead
144-
145-
> %component% mutated a value owned by %owner%. This is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead
143+
> %component% mutated property `%prop%` from parent component %owner%, which did not declare it as a binding. This is strongly discouraged. Consider passing props to child components that mutate them with `bind:` (e.g. `bind:%prop%={...}` instead of `%prop%={...}`), or use a callback instead
146144
147145
Consider the following code:
148146

packages/svelte/src/internal/client/dev/ownership.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ export function create_ownership_validator(props) {
130130
*/
131131
mutation: (path, result) => {
132132
const prop_name = path[0];
133-
if (is_bound(prop_name)) {
133+
if (is_bound(prop_name) || !parent) {
134134
return result;
135135
}
136136

@@ -143,7 +143,7 @@ export function create_ownership_validator(props) {
143143
prop = prop[path[i]];
144144
}
145145

146-
w.ownership_invalid_mutation(component[FILENAME], parent[FILENAME]);
146+
w.ownership_invalid_mutation(component[FILENAME], prop_name, parent[FILENAME]);
147147

148148
return result;
149149
},
@@ -156,6 +156,7 @@ export function create_ownership_validator(props) {
156156
if (!is_bound(key) && parent && value()?.[STATE_SYMBOL]) {
157157
w.ownership_invalid_binding(
158158
component[FILENAME],
159+
key,
159160
child_component[FILENAME],
160161
parent[FILENAME]
161162
);

packages/svelte/src/internal/client/warnings.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -129,27 +129,29 @@ export function lifecycle_double_unmount() {
129129
}
130130

131131
/**
132-
* %parent% passed a value to %child% with `bind:`, but the value is owned by %owner%. Consider creating a binding between %owner% and %parent%
132+
* %parent% passed property `%prop%` to %child% with `bind:`, but its parent component %owner% did not declare `%prop%` as a binding. Consider creating a binding between %owner% and %parent% (e.g. `bind:%prop%={...}` instead of `%prop%={...}`)
133133
* @param {string} parent
134+
* @param {string} prop
134135
* @param {string} child
135136
* @param {string} owner
136137
*/
137-
export function ownership_invalid_binding(parent, child, owner) {
138+
export function ownership_invalid_binding(parent, prop, child, owner) {
138139
if (DEV) {
139-
console.warn(`%c[svelte] ownership_invalid_binding\n%c${parent} passed a value to ${child} with \`bind:\`, but the value is owned by ${owner}. Consider creating a binding between ${owner} and ${parent}\nhttps://svelte.dev/e/ownership_invalid_binding`, bold, normal);
140+
console.warn(`%c[svelte] ownership_invalid_binding\n%c${parent} passed property \`${prop}\` to ${child} with \`bind:\`, but its parent component ${owner} did not declare \`${prop}\` as a binding. Consider creating a binding between ${owner} and ${parent} (e.g. \`bind:${prop}={...}\` instead of \`${prop}={...}\`)\nhttps://svelte.dev/e/ownership_invalid_binding`, bold, normal);
140141
} else {
141142
console.warn(`https://svelte.dev/e/ownership_invalid_binding`);
142143
}
143144
}
144145

145146
/**
146-
* %component% mutated a value owned by %owner%. This is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead
147-
* @param {string | undefined | null} [component]
148-
* @param {string | undefined | null} [owner]
147+
* %component% mutated property `%prop%` from parent component %owner%, which did not declare it as a binding. This is strongly discouraged. Consider passing props to child components that mutate them with `bind:` (e.g. `bind:%prop%={...}` instead of `%prop%={...}`), or use a callback instead
148+
* @param {string} component
149+
* @param {string} prop
150+
* @param {string} owner
149151
*/
150-
export function ownership_invalid_mutation(component, owner) {
152+
export function ownership_invalid_mutation(component, prop, owner) {
151153
if (DEV) {
152-
console.warn(`%c[svelte] ownership_invalid_mutation\n%c${component ? `${component} mutated a value owned by ${owner}. This is strongly discouraged. Consider passing values to child components with \`bind:\`, or use a callback instead` : 'Mutating a value outside the component that created it is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead'}\nhttps://svelte.dev/e/ownership_invalid_mutation`, bold, normal);
154+
console.warn(`%c[svelte] ownership_invalid_mutation\n%c${component} mutated property \`${prop}\` from parent component ${owner}, which did not declare it as a binding. This is strongly discouraged. Consider passing props to child components that mutate them with \`bind:\` (e.g. \`bind:${prop}={...}\` instead of \`${prop}={...}\`), or use a callback instead\nhttps://svelte.dev/e/ownership_invalid_mutation`, bold, normal);
153155
} else {
154156
console.warn(`https://svelte.dev/e/ownership_invalid_mutation`);
155157
}

packages/svelte/tests/runtime-runes/samples/non-local-mutation-discouraged/_config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export default test({
1010

1111
test({ assert, target, warnings }) {
1212
const warning =
13-
'Counter.svelte mutated a value owned by main.svelte. This is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead';
13+
'Counter.svelte mutated property `object` from parent component main.svelte, which did not declare it as a binding. This is strongly discouraged. Consider passing props to child components that mutate them with `bind:` (e.g. `bind:object={...}` instead of `object={...}`), or use a callback instead';
1414
const [btn1, btn2] = target.querySelectorAll('button');
1515

1616
btn1.click();

packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-2/_config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ export default test({
88
},
99

1010
warnings: [
11-
'Intermediate.svelte passed a value to Counter.svelte with `bind:`, but the value is owned by main.svelte. Consider creating a binding between main.svelte and Intermediate.svelte'
11+
'Intermediate.svelte passed property `object` to Counter.svelte with `bind:`, but its parent component main.svelte did not declare `object` as a binding. Consider creating a binding between main.svelte and Intermediate.svelte (e.g. `bind:object={...}` instead of `object={...}`)'
1212
]
1313
});

packages/svelte/tests/runtime-runes/samples/non-local-mutation-with-binding-3/_config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export default test({
3333
assert.htmlEqual(target.innerHTML, `<button>clicks: 1</button><button>clicks: 1</button>`);
3434

3535
assert.deepEqual(warnings, [
36-
'Counter.svelte mutated a value owned by main.svelte. This is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead'
36+
'Counter.svelte mutated property `notshared` from parent component main.svelte, which did not declare it as a binding. This is strongly discouraged. Consider passing props to child components that mutate them with `bind:` (e.g. `bind:notshared={...}` instead of `notshared={...}`), or use a callback instead'
3737
]);
3838
}
3939
});

0 commit comments

Comments
 (0)