mirror of https://github.com/sveltejs/svelte
				
				
				
			fix: run effect roots in tree order (#15446)
	
		
	
				
					
				
			* process effect roots in tree order * bring test over * add test * changeset * tidypull/15447/head
							parent
							
								
									e591e872aa
								
							
						
					
					
						commit
						3fc2007836
					
				@ -0,0 +1,5 @@
 | 
				
			||||
---
 | 
				
			||||
'svelte': patch
 | 
				
			||||
---
 | 
				
			||||
 | 
				
			||||
fix: run effect roots in tree order
 | 
				
			||||
@ -0,0 +1,17 @@
 | 
				
			||||
import { flushSync } from 'svelte';
 | 
				
			||||
import { test } from '../../test';
 | 
				
			||||
 | 
				
			||||
export default test({
 | 
				
			||||
	async test({ assert, target, logs }) {
 | 
				
			||||
		const [b1, b2] = target.querySelectorAll('button');
 | 
				
			||||
 | 
				
			||||
		flushSync(() => b1.click());
 | 
				
			||||
		assert.deepEqual(logs, [0, 1]);
 | 
				
			||||
 | 
				
			||||
		flushSync(() => b1.click());
 | 
				
			||||
		assert.deepEqual(logs, [0, 1, 2]);
 | 
				
			||||
 | 
				
			||||
		flushSync(() => b2.click());
 | 
				
			||||
		assert.deepEqual(logs, [0, 1, 2]);
 | 
				
			||||
	}
 | 
				
			||||
});
 | 
				
			||||
@ -0,0 +1,23 @@
 | 
				
			||||
<script>
 | 
				
			||||
	let obj = $state({ count: 0 });
 | 
				
			||||
 | 
				
			||||
	$effect.root(() => {
 | 
				
			||||
		let teardown;
 | 
				
			||||
 | 
				
			||||
		$effect.pre(() => {
 | 
				
			||||
			if (obj) {
 | 
				
			||||
				teardown ??= $effect.root(() => {
 | 
				
			||||
					$effect.pre(() => {
 | 
				
			||||
						console.log(obj.count);
 | 
				
			||||
					});
 | 
				
			||||
				});
 | 
				
			||||
			} else {
 | 
				
			||||
				teardown?.();
 | 
				
			||||
				teardown = null;
 | 
				
			||||
			}
 | 
				
			||||
		});
 | 
				
			||||
	});
 | 
				
			||||
</script>
 | 
				
			||||
 | 
				
			||||
<button onclick={() => ((obj ??= { count: 0 }).count += 1)}>+1</button>
 | 
				
			||||
<button onclick={() => (obj = null)}>null</button>
 | 
				
			||||
@ -0,0 +1,13 @@
 | 
				
			||||
import { flushSync } from 'svelte';
 | 
				
			||||
import { test } from '../../test';
 | 
				
			||||
 | 
				
			||||
export default test({
 | 
				
			||||
	async test({ assert, target }) {
 | 
				
			||||
		let [, btn2] = target.querySelectorAll('button');
 | 
				
			||||
 | 
				
			||||
		btn2.click();
 | 
				
			||||
		flushSync();
 | 
				
			||||
 | 
				
			||||
		assert.htmlEqual(target.innerHTML, `<button>Set data</button><button>Clear data</button>`);
 | 
				
			||||
	}
 | 
				
			||||
});
 | 
				
			||||
@ -0,0 +1,11 @@
 | 
				
			||||
<script>
 | 
				
			||||
	import { toStore } from 'svelte/store'
 | 
				
			||||
 | 
				
			||||
	let { data } = $props()
 | 
				
			||||
	const currentValue = toStore(() => data.value)
 | 
				
			||||
</script>
 | 
				
			||||
 | 
				
			||||
<p>
 | 
				
			||||
	Current value:
 | 
				
			||||
	<span>{$currentValue}</span>
 | 
				
			||||
</p>
 | 
				
			||||
@ -0,0 +1,15 @@
 | 
				
			||||
<script>
 | 
				
			||||
	import Child from './child.svelte'
 | 
				
			||||
 | 
				
			||||
	let data = $state({ value: 'hello' });
 | 
				
			||||
 | 
				
			||||
	const setData = () => (data = { value: 'hello' })
 | 
				
			||||
	const clearData = () => (data = undefined)
 | 
				
			||||
</script>
 | 
				
			||||
 | 
				
			||||
<button onclick={setData}>Set data</button>
 | 
				
			||||
<button onclick={clearData}>Clear data</button>
 | 
				
			||||
 | 
				
			||||
{#if data}
 | 
				
			||||
  <Child {data} />
 | 
				
			||||
{/if}
 | 
				
			||||
					Loading…
					
					
				
		Reference in new issue