mirror of https://github.com/sveltejs/svelte
				
				
				
			fix: widen ownership upon property access if necessary (#13175)
	
		
	
				
					
				
			In case of something like `foo = bar.map(...)`, foo would have ownership of the array itself, while the individual items would have ownership of the component that created the proxy. That means if we later do `foo[0].baz = 42`, we could get a false-positive ownership violation, since the two proxies are not connected to each other via the parent relationship. For this reason, we need to widen the ownership of the children upon access when we detect they are not connected. Fixes #13137pull/13198/head
							parent
							
								
									fd7e8b70cf
								
							
						
					
					
						commit
						3808935f51
					
				@ -0,0 +1,5 @@
 | 
				
			||||
---
 | 
				
			||||
'svelte': patch
 | 
				
			||||
---
 | 
				
			||||
 | 
				
			||||
fix: widen ownership upon property access if necessary
 | 
				
			||||
@ -0,0 +1,13 @@
 | 
				
			||||
<script>
 | 
				
			||||
	import Component2 from './Component2.svelte';
 | 
				
			||||
 | 
				
			||||
	let { rows = $bindable([]) } = $props();
 | 
				
			||||
 | 
				
			||||
	let rows2 = $state([]);
 | 
				
			||||
 | 
				
			||||
	$effect(() => {
 | 
				
			||||
		rows2 = rows.slice();
 | 
				
			||||
	});
 | 
				
			||||
</script>
 | 
				
			||||
 | 
				
			||||
<Component2 bind:rows={rows2} />
 | 
				
			||||
@ -0,0 +1,7 @@
 | 
				
			||||
<script>
 | 
				
			||||
	let { rows = $bindable([]) } = $props();
 | 
				
			||||
</script>
 | 
				
			||||
 | 
				
			||||
{#if rows.length}
 | 
				
			||||
	<input type="checkbox" bind:checked={rows[0].check} />
 | 
				
			||||
{/if}
 | 
				
			||||
@ -0,0 +1,22 @@
 | 
				
			||||
import { flushSync } from 'svelte';
 | 
				
			||||
import { ok, test } from '../../test';
 | 
				
			||||
 | 
				
			||||
// Tests that proxies widen ownership correctly even if not directly connected to each other
 | 
				
			||||
export default test({
 | 
				
			||||
	compileOptions: {
 | 
				
			||||
		dev: true
 | 
				
			||||
	},
 | 
				
			||||
 | 
				
			||||
	test({ assert, target, warnings }) {
 | 
				
			||||
		const input = target.querySelector('input');
 | 
				
			||||
		ok(input);
 | 
				
			||||
 | 
				
			||||
		input.checked = true;
 | 
				
			||||
		input.dispatchEvent(new Event('input', { bubbles: true }));
 | 
				
			||||
		flushSync();
 | 
				
			||||
 | 
				
			||||
		assert.deepEqual(warnings, []);
 | 
				
			||||
	},
 | 
				
			||||
 | 
				
			||||
	warnings: []
 | 
				
			||||
});
 | 
				
			||||
@ -0,0 +1,7 @@
 | 
				
			||||
<script>
 | 
				
			||||
	import Component1 from './Component1.svelte';
 | 
				
			||||
 | 
				
			||||
	let rows = $state([{}]);
 | 
				
			||||
</script>
 | 
				
			||||
 | 
				
			||||
<Component1 bind:rows />
 | 
				
			||||
					Loading…
					
					
				
		Reference in new issue