mirror of https://github.com/sveltejs/svelte
				
				
				
			fix: on teardown, use the last known value for the signal before the set (#15469)
	
		
	
				
					
				
			* fix: on teardown, use the last known value for the signal before the se * fix: on teardown, use the last known value for the signal before the se * fix: on teardown, use the last known value for the signal before the se * fix: on teardown, use the last known value for the signal before the se * fix: on teardown, use the last known value for the signal before the se * Update packages/svelte/src/internal/client/reactivity/props.js Co-authored-by: Rich Harris <rich.harris@vercel.com> * Update packages/svelte/src/internal/client/reactivity/props.js Co-authored-by: Rich Harris <rich.harris@vercel.com> * Update packages/svelte/src/internal/client/reactivity/props.js Co-authored-by: Rich Harris <rich.harris@vercel.com> * lint * lint * lint * Update .changeset/sharp-elephants-invite.md --------- Co-authored-by: Rich Harris <rich.harris@vercel.com>pull/15493/head
							parent
							
								
									1cc5bcdc99
								
							
						
					
					
						commit
						110d42062f
					
				| @ -0,0 +1,5 @@ | ||||
| --- | ||||
| 'svelte': minor | ||||
| --- | ||||
| 
 | ||||
| fix: make values consistent between effects and their cleanup functions | ||||
| @ -0,0 +1,11 @@ | ||||
| <script> | ||||
| 	import { onDestroy } from 'svelte'; | ||||
| 
 | ||||
| 	export let my_prop; | ||||
| 
 | ||||
| 	onDestroy(() => { | ||||
| 		console.log(my_prop.foo); | ||||
| 	}); | ||||
| </script> | ||||
| 
 | ||||
| {my_prop.foo} | ||||
| @ -0,0 +1,14 @@ | ||||
| import { test } from '../../test'; | ||||
| import { flushSync } from 'svelte'; | ||||
| 
 | ||||
| export default test({ | ||||
| 	async test({ assert, target, logs }) { | ||||
| 		const [btn1] = target.querySelectorAll('button'); | ||||
| 
 | ||||
| 		flushSync(() => { | ||||
| 			btn1.click(); | ||||
| 		}); | ||||
| 
 | ||||
| 		assert.deepEqual(logs, ['bar']); | ||||
| 	} | ||||
| }); | ||||
| @ -0,0 +1,15 @@ | ||||
| <script> | ||||
| 	import Component from './Component.svelte'; | ||||
| 
 | ||||
| 	let value = { foo: 'bar' }; | ||||
| </script> | ||||
| 
 | ||||
| <button | ||||
| 	onclick={() => { | ||||
| 		value = undefined; | ||||
| 	}}>Reset value</button | ||||
| > | ||||
| 
 | ||||
| {#if value !== undefined} | ||||
| 	<Component my_prop={value} /> | ||||
| {/if} | ||||
| @ -0,0 +1,5 @@ | ||||
| <script lang="ts"> | ||||
| 	export let ref; | ||||
| </script> | ||||
| 
 | ||||
| <input bind:this={ref} /> | ||||
| @ -0,0 +1,11 @@ | ||||
| import { test } from '../../test'; | ||||
| import { flushSync } from 'svelte'; | ||||
| 
 | ||||
| export default test({ | ||||
| 	async test({ target }) { | ||||
| 		const [btn1] = target.querySelectorAll('button'); | ||||
| 
 | ||||
| 		btn1.click(); | ||||
| 		flushSync(); | ||||
| 	} | ||||
| }); | ||||
| @ -0,0 +1,16 @@ | ||||
| <script> | ||||
| 	import Component from './Component.svelte'; | ||||
| 	let state = { title: 'foo' }; | ||||
| </script> | ||||
| 
 | ||||
| {#if state} | ||||
| 	{@const attributes = { title: state.title }} | ||||
| 	<Component {...attributes} /> | ||||
| {/if} | ||||
| <button | ||||
| 	onclick={() => { | ||||
| 		state = undefined; | ||||
| 	}} | ||||
| > | ||||
| 	Del | ||||
| </button> | ||||
| @ -0,0 +1,12 @@ | ||||
| <script> | ||||
| 	import { onDestroy } from "svelte"; | ||||
| 	export let checked; | ||||
| 	export let count; | ||||
| 	onDestroy(() => { | ||||
| 		console.log(count, checked); | ||||
| 	}); | ||||
| </script> | ||||
| 
 | ||||
| <p>{count}</p> | ||||
| 
 | ||||
| <button onclick={()=> count-- }></button> | ||||
| @ -0,0 +1,68 @@ | ||||
| import { test } from '../../test'; | ||||
| import { flushSync } from 'svelte'; | ||||
| 
 | ||||
| export default test({ | ||||
| 	async test({ assert, target, logs }) { | ||||
| 		const [btn1, btn2, btn3] = target.querySelectorAll('button'); | ||||
| 		let ps = [...target.querySelectorAll('p')]; | ||||
| 
 | ||||
| 		for (const p of ps) { | ||||
| 			assert.equal(p.innerHTML, '0'); | ||||
| 		} | ||||
| 
 | ||||
| 		flushSync(() => { | ||||
| 			btn1.click(); | ||||
| 		}); | ||||
| 
 | ||||
| 		// prop update normally if we are not unmounting
 | ||||
| 		for (const p of ps) { | ||||
| 			assert.equal(p.innerHTML, '1'); | ||||
| 		} | ||||
| 
 | ||||
| 		flushSync(() => { | ||||
| 			btn3.click(); | ||||
| 		}); | ||||
| 
 | ||||
| 		// binding still works and update the value correctly
 | ||||
| 		for (const p of ps) { | ||||
| 			assert.equal(p.innerHTML, '0'); | ||||
| 		} | ||||
| 
 | ||||
| 		flushSync(() => { | ||||
| 			btn1.click(); | ||||
| 		}); | ||||
| 
 | ||||
| 		flushSync(() => { | ||||
| 			btn1.click(); | ||||
| 		}); | ||||
| 
 | ||||
| 		console.warn(logs); | ||||
| 
 | ||||
| 		// the five components guarded by `count < 2` unmount and log
 | ||||
| 		assert.deepEqual(logs, [1, true, 1, true, 1, true, 1, true, 1, true]); | ||||
| 
 | ||||
| 		flushSync(() => { | ||||
| 			btn2.click(); | ||||
| 		}); | ||||
| 
 | ||||
| 		// the three components guarded by `show` unmount and log
 | ||||
| 		assert.deepEqual(logs, [ | ||||
| 			1, | ||||
| 			true, | ||||
| 			1, | ||||
| 			true, | ||||
| 			1, | ||||
| 			true, | ||||
| 			1, | ||||
| 			true, | ||||
| 			1, | ||||
| 			true, | ||||
| 			2, | ||||
| 			true, | ||||
| 			2, | ||||
| 			true, | ||||
| 			2, | ||||
| 			true | ||||
| 		]); | ||||
| 	} | ||||
| }); | ||||
| @ -0,0 +1,41 @@ | ||||
| <script> | ||||
| 	import Component from "./Component.svelte"; | ||||
| 	let show = true; | ||||
| 	let count = 0; | ||||
| 	$: spread = { checked: show, count }; | ||||
| </script> | ||||
| 
 | ||||
| <button onclick={()=> count++ }></button> | ||||
| <button onclick={()=> show = !show }></button> | ||||
| 
 | ||||
| <!-- count with bind --> | ||||
| {#if count < 2} | ||||
| 	<Component bind:count bind:checked={show} /> | ||||
| {/if} | ||||
| 
 | ||||
| <!-- spread syntax --> | ||||
| {#if count < 2} | ||||
| 	<Component {...spread} /> | ||||
| {/if} | ||||
| 
 | ||||
| <!-- normal prop --> | ||||
| {#if count < 2} | ||||
| 	<Component {count} checked={show} /> | ||||
| {/if} | ||||
| 
 | ||||
| <!-- prop only accessed in destroy --> | ||||
| {#if show} | ||||
| 	<Component {count} checked={show} /> | ||||
| {/if} | ||||
| 
 | ||||
| <!-- dynamic component --> | ||||
| <svelte:component this={count < 2 ? Component : undefined} {count} checked={show} /> | ||||
| 
 | ||||
| <!-- dynamic component spread --> | ||||
| <svelte:component this={count < 2 ? Component : undefined} {...spread} /> | ||||
| 
 | ||||
| <!-- dynamic component with prop only accessed on destroy --> | ||||
| <svelte:component this={show ? Component : undefined} {count} checked={show} /> | ||||
| 
 | ||||
| <!-- dynamic component with prop only accessed on destroy spread --> | ||||
| <svelte:component this={show ? Component : undefined} {...spread} /> | ||||
					Loading…
					
					
				
		Reference in new issue