mirror of https://github.com/sveltejs/svelte
				
				
				
			
						commit
						203c321b4b
					
				@ -1,5 +0,0 @@
 | 
				
			|||||||
---
 | 
					 | 
				
			||||||
'svelte': patch
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fix: don't set state withing `with_parent` in proxy
 | 
					 | 
				
			||||||
@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					'svelte': patch
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fix: untrack `$inspect.with` and add check for unsafe mutation
 | 
				
			||||||
@ -1,21 +1,14 @@
 | 
				
			|||||||
/** @import { Expression } from 'estree' */
 | 
					 | 
				
			||||||
/** @import { AST } from '#compiler' */
 | 
					/** @import { AST } from '#compiler' */
 | 
				
			||||||
/** @import { ComponentContext } from '../types' */
 | 
					/** @import { ComponentContext } from '../types' */
 | 
				
			||||||
import * as b from '../../../../utils/builders.js';
 | 
					import * as b from '../../../../utils/builders.js';
 | 
				
			||||||
 | 
					import { build_expression } from './shared/utils.js';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @param {AST.AttachTag} node
 | 
					 * @param {AST.AttachTag} node
 | 
				
			||||||
 * @param {ComponentContext} context
 | 
					 * @param {ComponentContext} context
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export function AttachTag(node, context) {
 | 
					export function AttachTag(node, context) {
 | 
				
			||||||
	context.state.init.push(
 | 
						const expression = build_expression(context, node.expression, node.metadata.expression);
 | 
				
			||||||
		b.stmt(
 | 
						context.state.init.push(b.stmt(b.call('$.attach', context.state.node, b.thunk(expression))));
 | 
				
			||||||
			b.call(
 | 
					 | 
				
			||||||
				'$.attach',
 | 
					 | 
				
			||||||
				context.state.node,
 | 
					 | 
				
			||||||
				b.thunk(/** @type {Expression} */ (context.visit(node.expression)))
 | 
					 | 
				
			||||||
			)
 | 
					 | 
				
			||||||
		)
 | 
					 | 
				
			||||||
	);
 | 
					 | 
				
			||||||
	context.next();
 | 
						context.next();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
						span[class].svelte-xyz { color: green }
 | 
				
			||||||
 | 
						div[style].svelte-xyz { color: green }
 | 
				
			||||||
@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					<span class:foo={true}></span>
 | 
				
			||||||
 | 
					<div style:--foo="bar"></div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style>
 | 
				
			||||||
 | 
						span[class] { color: green }
 | 
				
			||||||
 | 
						div[style] { color: green }
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					import { test } from '../../test';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default test({
 | 
				
			||||||
 | 
						warnings: [
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								code: 'css_unused_selector',
 | 
				
			||||||
 | 
								message: 'Unused CSS selector ".forth"\nhttps://svelte.dev/e/css_unused_selector',
 | 
				
			||||||
 | 
								start: {
 | 
				
			||||||
 | 
									line: 8,
 | 
				
			||||||
 | 
									column: 2,
 | 
				
			||||||
 | 
									character: 190
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								end: {
 | 
				
			||||||
 | 
									line: 8,
 | 
				
			||||||
 | 
									column: 8,
 | 
				
			||||||
 | 
									character: 196
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						]
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					  .zero.first.svelte-xyz { color: green }
 | 
				
			||||||
 | 
					  .second.svelte-xyz { color: green }
 | 
				
			||||||
 | 
					  .third.svelte-xyz { color: green }
 | 
				
			||||||
 | 
					  /* (unused) .forth { color: red }*/
 | 
				
			||||||
@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					<div class="zero" class:first={true}></div>
 | 
				
			||||||
 | 
					<div class:second={true} class:third={true}></div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style>
 | 
				
			||||||
 | 
					  .zero.first { color: green }
 | 
				
			||||||
 | 
					  .second { color: green }
 | 
				
			||||||
 | 
					  .third { color: green }
 | 
				
			||||||
 | 
					  .forth { color: red }
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					import { test } from '../../test';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default test({
 | 
				
			||||||
 | 
						server_props: {
 | 
				
			||||||
 | 
							browser: false
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						props: {
 | 
				
			||||||
 | 
							browser: true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<!--[--><div></div><!--]-->
 | 
				
			||||||
@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
						const { browser } = $props();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const attributes = {
 | 
				
			||||||
 | 
							"data-test": browser ? undefined : ""
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div {...attributes}></div>
 | 
				
			||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					import { flushSync } from 'svelte';
 | 
				
			||||||
 | 
					import { test } from '../../test';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default test({
 | 
				
			||||||
 | 
						test({ assert, target }) {
 | 
				
			||||||
 | 
							const button = target.querySelector('button');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							assert.htmlEqual(target.innerHTML, `<div></div><button>inc</button> [0,0,0,0,0,0,0,0,0]`);
 | 
				
			||||||
 | 
							flushSync(() => button?.click());
 | 
				
			||||||
 | 
							assert.htmlEqual(target.innerHTML, `<div></div><button>inc</button> [0,0,0,0,0,0,0,0,0]`);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
					    let a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0, h = 0, i = 0;
 | 
				
			||||||
 | 
					    function inc() {
 | 
				
			||||||
 | 
					        a++;
 | 
				
			||||||
 | 
					        b++;
 | 
				
			||||||
 | 
					        c++;
 | 
				
			||||||
 | 
					        d++;
 | 
				
			||||||
 | 
					        e++;
 | 
				
			||||||
 | 
					        f++;
 | 
				
			||||||
 | 
					        g++;
 | 
				
			||||||
 | 
					        h++;
 | 
				
			||||||
 | 
					        i++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#if a = 0}{/if}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#each [b = 0] as x}{x,''}{/each}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#key c = 0}{/key}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#await d = 0}{/await}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#snippet snip()}{/snippet}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{@render (e = 0, snip)()}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{@html f = 0, ''}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div {@attach !!(g = 0)}></div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#key 1}
 | 
				
			||||||
 | 
					    {@const x = (h = 0)}
 | 
				
			||||||
 | 
					    {x, ''}
 | 
				
			||||||
 | 
					{/key}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#if 1}
 | 
				
			||||||
 | 
					    {@const x = (i = 0)}
 | 
				
			||||||
 | 
					    {x, ''}
 | 
				
			||||||
 | 
					{/if}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<button on:click={inc}>inc</button>
 | 
				
			||||||
 | 
					[{a},{b},{c},{d},{e},{f},{g},{h},{i}]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					import { flushSync } from 'svelte';
 | 
				
			||||||
 | 
					import { test } from '../../test';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default test({
 | 
				
			||||||
 | 
						test({ assert, target }) {
 | 
				
			||||||
 | 
							const button = target.querySelector('button');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							assert.htmlEqual(target.innerHTML, `<div></div><button data-foo="true">inc</button> 12 - 12`);
 | 
				
			||||||
 | 
							flushSync(() => button?.click());
 | 
				
			||||||
 | 
							assert.htmlEqual(target.innerHTML, `<div></div><button data-foo="true">inc</button> 13 - 12`);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
					    let count1 = 1;
 | 
				
			||||||
 | 
					    let count2 = 1;
 | 
				
			||||||
 | 
					    function fn(ret) {
 | 
				
			||||||
 | 
					        if (count1 > 100) return ret;
 | 
				
			||||||
 | 
					        count1++;
 | 
				
			||||||
 | 
					        count2++;
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#if fn(false)}{:else if fn(true)}{/if}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#each fn([]) as x}{x, ''}{/each}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#key fn(1)}{/key}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#await fn(Promise.resolve())}{/await}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#snippet snip()}{/snippet}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{@render fn(snip)()}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{@html fn('')}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div {@attach fn(() => {})}></div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#key 1}
 | 
				
			||||||
 | 
					    {@const x = fn('')}
 | 
				
			||||||
 | 
					    {x}
 | 
				
			||||||
 | 
					{/key}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<button data-foo={fn(true)} on:click={() => count1++}>{fn('inc')}</button>
 | 
				
			||||||
 | 
					{count1} - {count2}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					import { flushSync } from 'svelte';
 | 
				
			||||||
 | 
					import { test } from '../../test';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default test({
 | 
				
			||||||
 | 
						test({ assert, target }) {
 | 
				
			||||||
 | 
							const button = target.querySelector('button');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							assert.htmlEqual(target.innerHTML, `<div></div><button>inc</button> 10 - 10`);
 | 
				
			||||||
 | 
							flushSync(() => button?.click());
 | 
				
			||||||
 | 
							assert.htmlEqual(target.innerHTML, `<div></div><button>inc</button> 11 - 10`);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@ -0,0 +1,46 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
					    let count1 = 1;
 | 
				
			||||||
 | 
					    let count2 = 1;
 | 
				
			||||||
 | 
					    function fn(ret) {
 | 
				
			||||||
 | 
					        if (count1 > 100) return ret;
 | 
				
			||||||
 | 
					        count1++;
 | 
				
			||||||
 | 
					        count2++;
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const obj = {
 | 
				
			||||||
 | 
					        get true() { return fn(true) },
 | 
				
			||||||
 | 
					        get false() { return fn(false) },
 | 
				
			||||||
 | 
					        get array() { return fn([]) },
 | 
				
			||||||
 | 
					        get string() { return fn('') },
 | 
				
			||||||
 | 
					        get promise() { return fn(Promise.resolve()) },
 | 
				
			||||||
 | 
					        get snippet() { return fn(snip) },
 | 
				
			||||||
 | 
					        get attachment() { return fn(() => {}) },
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#if obj.false}{:else if obj.true}{/if}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#each obj.array as x}{x, ''}{/each}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#key obj.string}{/key}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#await obj.promise}{/await}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#snippet snip()}{/snippet}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{@render obj.snippet()}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{@html obj.string}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div {@attach obj.attachment}></div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#key 1}
 | 
				
			||||||
 | 
					    {@const x = obj.string}
 | 
				
			||||||
 | 
					    {x}
 | 
				
			||||||
 | 
					{/key}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<button on:click={() => count1++}>inc</button>
 | 
				
			||||||
 | 
					{count1} - {count2}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					import { flushSync } from 'svelte';
 | 
				
			||||||
 | 
					import { test } from '../../test';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default test({
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Ensure that sorting an array inside an $effect works correctly
 | 
				
			||||||
 | 
						 * and re-runs when the array changes (e.g., when items are added).
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						test({ assert, target }) {
 | 
				
			||||||
 | 
							const button = target.querySelector('button');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// initial render — array should be sorted
 | 
				
			||||||
 | 
							assert.htmlEqual(
 | 
				
			||||||
 | 
								target.innerHTML,
 | 
				
			||||||
 | 
								`
 | 
				
			||||||
 | 
									<button>add item</button>
 | 
				
			||||||
 | 
									<p>0</p>
 | 
				
			||||||
 | 
									<p>50</p>
 | 
				
			||||||
 | 
									<p>100</p>
 | 
				
			||||||
 | 
								`
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// add first item (20); effect should re-run and sort the array
 | 
				
			||||||
 | 
							flushSync(() => button?.click());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							assert.htmlEqual(
 | 
				
			||||||
 | 
								target.innerHTML,
 | 
				
			||||||
 | 
								`
 | 
				
			||||||
 | 
									<button>add item</button>
 | 
				
			||||||
 | 
									<p>0</p>
 | 
				
			||||||
 | 
									<p>20</p>
 | 
				
			||||||
 | 
									<p>50</p>
 | 
				
			||||||
 | 
									<p>100</p>
 | 
				
			||||||
 | 
								`
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// add second item (80); effect should re-run and sort the array
 | 
				
			||||||
 | 
							flushSync(() => button?.click());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							assert.htmlEqual(
 | 
				
			||||||
 | 
								target.innerHTML,
 | 
				
			||||||
 | 
								`
 | 
				
			||||||
 | 
									<button>add item</button>
 | 
				
			||||||
 | 
									<p>0</p>
 | 
				
			||||||
 | 
									<p>20</p>
 | 
				
			||||||
 | 
									<p>50</p>
 | 
				
			||||||
 | 
									<p>80</p>
 | 
				
			||||||
 | 
									<p>100</p>
 | 
				
			||||||
 | 
								`
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
						let arr = $state([100, 0, 50]);
 | 
				
			||||||
 | 
						let nextValues = [20, 80];
 | 
				
			||||||
 | 
						let valueIndex = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						$effect(() => {
 | 
				
			||||||
 | 
							arr.sort((a, b) => a - b);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						function addItem() {
 | 
				
			||||||
 | 
							if (valueIndex < nextValues.length) {
 | 
				
			||||||
 | 
								arr.push(nextValues[valueIndex]);
 | 
				
			||||||
 | 
								valueIndex++;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<button onclick={addItem}>add item</button>
 | 
				
			||||||
 | 
					{#each arr as x}
 | 
				
			||||||
 | 
						<p>{x}</p>
 | 
				
			||||||
 | 
					{/each}
 | 
				
			||||||
@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
						const { children } = $props()
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{@render children()}
 | 
				
			||||||
@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					import { test } from '../../test';
 | 
				
			||||||
 | 
					import { flushSync } from 'svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default test({
 | 
				
			||||||
 | 
						async test({ assert, target }) {
 | 
				
			||||||
 | 
							assert.htmlEqual(target.innerHTML, 'test');
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
						import A from './A.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const B = $derived(A);
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<B>
 | 
				
			||||||
 | 
						<B>test</B>
 | 
				
			||||||
 | 
					</B>
 | 
				
			||||||
@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					import { flushSync } from 'svelte';
 | 
				
			||||||
 | 
					import { test } from '../../test';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default test({
 | 
				
			||||||
 | 
						test({ assert, target }) {
 | 
				
			||||||
 | 
							const [change, increment] = target.querySelectorAll('button');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							increment.click();
 | 
				
			||||||
 | 
							flushSync();
 | 
				
			||||||
 | 
							assert.htmlEqual(target.innerHTML, '<button>change handlers</button><button>1 / 1</button>');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							change.click();
 | 
				
			||||||
 | 
							flushSync();
 | 
				
			||||||
 | 
							increment.click();
 | 
				
			||||||
 | 
							flushSync();
 | 
				
			||||||
 | 
							assert.htmlEqual(target.innerHTML, '<button>change handlers</button><button>3 / 3</button>');
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
						let delegated = $state(0);
 | 
				
			||||||
 | 
						let non_delegated = $state(0);
 | 
				
			||||||
 | 
						let attrs = $state({
 | 
				
			||||||
 | 
							onclick: () => {
 | 
				
			||||||
 | 
								delegated += 1;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							onclickcapture: () => {
 | 
				
			||||||
 | 
								non_delegated += 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<button
 | 
				
			||||||
 | 
						onclick={() =>
 | 
				
			||||||
 | 
							(attrs = {
 | 
				
			||||||
 | 
								onclick: () => {
 | 
				
			||||||
 | 
									delegated += 2;
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								onclickcapture: () => {
 | 
				
			||||||
 | 
									non_delegated += 2;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})}
 | 
				
			||||||
 | 
					>
 | 
				
			||||||
 | 
						change handlers
 | 
				
			||||||
 | 
					</button>
 | 
				
			||||||
 | 
					<button {...attrs}>{delegated} / {non_delegated}</button>
 | 
				
			||||||
@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					import { flushSync } from 'svelte';
 | 
				
			||||||
 | 
					import { test } from '../../test';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default test({
 | 
				
			||||||
 | 
						compileOptions: {
 | 
				
			||||||
 | 
							dev: true
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						error: 'state_unsafe_mutation'
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
						let a = $state(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						let b = $state(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						$inspect(a).with((...args)=>{
 | 
				
			||||||
 | 
							console.log(...args);
 | 
				
			||||||
 | 
							b++;
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					import { flushSync } from 'svelte';
 | 
				
			||||||
 | 
					import { test } from '../../test';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default test({
 | 
				
			||||||
 | 
						compileOptions: {
 | 
				
			||||||
 | 
							dev: true
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						async test({ assert, target, logs }) {
 | 
				
			||||||
 | 
							const [a, b] = target.querySelectorAll('button');
 | 
				
			||||||
 | 
							assert.deepEqual(logs, ['init', 0]);
 | 
				
			||||||
 | 
							flushSync(() => {
 | 
				
			||||||
 | 
								b?.click();
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
							assert.deepEqual(logs, ['init', 0]);
 | 
				
			||||||
 | 
							flushSync(() => {
 | 
				
			||||||
 | 
								a?.click();
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
							assert.deepEqual(logs, ['init', 0, 'update', 1]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
						let a = $state(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						let b = $state(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						$inspect(a).with((...args)=>{
 | 
				
			||||||
 | 
							console.log(...args);
 | 
				
			||||||
 | 
							b;
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<button onclick={()=>a++}></button>
 | 
				
			||||||
 | 
					<button onclick={()=>b++}></button>
 | 
				
			||||||
					Loading…
					
					
				
		Reference in new issue