mirror of https://github.com/sveltejs/svelte
fix: better binding interop between runes/non-runes components (#12123)
* Ensure binding from legacy component passed to runes component updates correctly. This is done by also using the `prop(..)` variant for a property if it's mutated in runes mode, and then figuring out at runtime whether or not the parent should be notified or not fixes #12032 * fix adjacent bug around wrong value getting return upon mutation * deduplicate * changeset * simplify * move comment * rename --------- Co-authored-by: Rich Harris <rich.harris@vercel.com>pull/12125/head
parent
6c66680919
commit
afe84450c6
@ -0,0 +1,5 @@
|
||||
---
|
||||
"svelte": patch
|
||||
---
|
||||
|
||||
fix: better binding interop between runes/non-runes components
|
@ -0,0 +1,8 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
mode: ['client'],
|
||||
test({ assert, logs }) {
|
||||
assert.deepEqual(logs, [true]);
|
||||
}
|
||||
});
|
@ -0,0 +1,4 @@
|
||||
<script>
|
||||
export let a = {};
|
||||
console.log((a.b = true));
|
||||
</script>
|
@ -0,0 +1,9 @@
|
||||
<script>
|
||||
let { object = $bindable(), primitive = $bindable() } = $props();
|
||||
</script>
|
||||
|
||||
{#if primitive}
|
||||
<button onclick={() => (primitive = 'bar')}>{primitive}</button>
|
||||
{:else}
|
||||
<button onclick={() => (object.value = 'bar')}>{object.value}</button>
|
||||
{/if}
|
@ -0,0 +1,9 @@
|
||||
<script>
|
||||
let { object = $bindable({}), primitive = $bindable('') } = $props();
|
||||
</script>
|
||||
|
||||
{#if primitive}
|
||||
<button onclick={() => (primitive = 'bar')}>{primitive}</button>
|
||||
{:else}
|
||||
<button onclick={() => (object.value = 'bar')}>{object.value}</button>
|
||||
{/if}
|
@ -0,0 +1,24 @@
|
||||
<svelte:options runes={false} />
|
||||
|
||||
<script>
|
||||
import Component1 from './Component1.svelte';
|
||||
import Component2 from './Component2.svelte';
|
||||
|
||||
let object1 = { value: 'foo' };
|
||||
let object2 = { value: 'foo' };
|
||||
|
||||
let primitive1 = 'foo';
|
||||
let primitive2 = 'foo';
|
||||
</script>
|
||||
|
||||
{object1.value}
|
||||
<Component1 bind:object={object1} />
|
||||
|
||||
{object2.value}
|
||||
<Component2 bind:object={object2} />
|
||||
|
||||
{primitive1}
|
||||
<Component1 bind:primitive={primitive1} />
|
||||
|
||||
{primitive2}
|
||||
<Component2 bind:primitive={primitive2} />
|
@ -0,0 +1,39 @@
|
||||
<script>
|
||||
import Component1 from './Component1.svelte';
|
||||
import Component2 from './Component2.svelte';
|
||||
|
||||
let object1 = $state({ value: 'foo' });
|
||||
let object2 = $state({ value: 'foo' });
|
||||
|
||||
class Frozen {
|
||||
constructor(value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
let object3 = $state(new Frozen('foo'));
|
||||
let object4 = $state(new Frozen('foo'));
|
||||
|
||||
let primitive1 = $state('foo');
|
||||
let primitive2 = $state('foo');
|
||||
</script>
|
||||
|
||||
{object1.value}
|
||||
<Component1 bind:object={object1} />
|
||||
|
||||
{object2.value}
|
||||
<Component2 bind:object={object2} />
|
||||
|
||||
<!-- force them into a different render effect so they don't coincidently update with the others -->
|
||||
{#if true}
|
||||
{object3.value}
|
||||
<Component1 bind:object={object3} />
|
||||
|
||||
{object4.value}
|
||||
<Component2 bind:object={object4} />
|
||||
{/if}
|
||||
|
||||
{primitive1}
|
||||
<Component1 bind:primitive={primitive1} />
|
||||
|
||||
{primitive2}
|
||||
<Component2 bind:primitive={primitive2} />
|
@ -0,0 +1,24 @@
|
||||
import { flushSync } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
mode: ['client'],
|
||||
async test({ assert, target }) {
|
||||
const buttons = target.querySelectorAll('button');
|
||||
|
||||
for (const button of buttons) {
|
||||
await button.click();
|
||||
flushSync();
|
||||
}
|
||||
flushSync();
|
||||
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
bar <button>bar</button> bar <button>bar</button> bar <button>bar</button> bar <button>bar</button>
|
||||
<hr>
|
||||
bar <button>bar</button> bar <button>bar</button> foo <button>foo</button> foo <button>foo</button> bar <button>bar</button> bar <button>bar</button>
|
||||
`
|
||||
);
|
||||
}
|
||||
});
|
@ -0,0 +1,10 @@
|
||||
<script>
|
||||
import Legacy from './Legacy.svelte';
|
||||
import Runes from './Runes.svelte';
|
||||
</script>
|
||||
|
||||
<Legacy />
|
||||
|
||||
<hr />
|
||||
|
||||
<Runes />
|
Loading…
Reference in new issue