mirror of https://github.com/sveltejs/svelte
commit
c8d764e39b
@ -0,0 +1,5 @@
|
||||
---
|
||||
"svelte": patch
|
||||
---
|
||||
|
||||
fix: wait a microtask for await blocks to reduce UI churn
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
"svelte": patch
|
||||
---
|
||||
|
||||
fix: ensure state update expressions are serialised correctly
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
"svelte": patch
|
||||
---
|
||||
|
||||
fix: repair each block length even without an else
|
@ -1,24 +1,58 @@
|
||||
import { kairo_avoidable } from './benchmarks/kairo/kairo_avoidable.js';
|
||||
import { kairo_broad } from './benchmarks/kairo/kairo_broad.js';
|
||||
import { kairo_deep } from './benchmarks/kairo/kairo_deep.js';
|
||||
import { kairo_diamond } from './benchmarks/kairo/kairo_diamond.js';
|
||||
import { kairo_mux } from './benchmarks/kairo/kairo_mux.js';
|
||||
import { kairo_repeated } from './benchmarks/kairo/kairo_repeated.js';
|
||||
import { kairo_triangle } from './benchmarks/kairo/kairo_triangle.js';
|
||||
import { kairo_unstable } from './benchmarks/kairo/kairo_unstable.js';
|
||||
import { mol_bench } from './benchmarks/mol_bench.js';
|
||||
import {
|
||||
kairo_avoidable_owned,
|
||||
kairo_avoidable_unowned
|
||||
} from './benchmarks/kairo/kairo_avoidable.js';
|
||||
import { kairo_broad_owned, kairo_broad_unowned } from './benchmarks/kairo/kairo_broad.js';
|
||||
import { kairo_deep_owned, kairo_deep_unowned } from './benchmarks/kairo/kairo_deep.js';
|
||||
import { kairo_diamond_owned, kairo_diamond_unowned } from './benchmarks/kairo/kairo_diamond.js';
|
||||
import { kairo_mux_unowned, kairo_mux_owned } from './benchmarks/kairo/kairo_mux.js';
|
||||
import { kairo_repeated_unowned, kairo_repeated_owned } from './benchmarks/kairo/kairo_repeated.js';
|
||||
import { kairo_triangle_owned, kairo_triangle_unowned } from './benchmarks/kairo/kairo_triangle.js';
|
||||
import { kairo_unstable_owned, kairo_unstable_unowned } from './benchmarks/kairo/kairo_unstable.js';
|
||||
import { mol_bench_owned, mol_bench_unowned } from './benchmarks/mol_bench.js';
|
||||
import {
|
||||
sbench_create_0to1,
|
||||
sbench_create_1000to1,
|
||||
sbench_create_1to1,
|
||||
sbench_create_1to1000,
|
||||
sbench_create_1to2,
|
||||
sbench_create_1to4,
|
||||
sbench_create_1to8,
|
||||
sbench_create_2to1,
|
||||
sbench_create_4to1,
|
||||
sbench_create_signals
|
||||
} from './benchmarks/sbench.js';
|
||||
|
||||
// This benchmark has been adapted from the js-reactivity-benchmark (https://github.com/milomg/js-reactivity-benchmark)
|
||||
// Not all tests are the same, and many parts have been tweaked to capture different data.
|
||||
|
||||
export const benchmarks = [
|
||||
kairo_avoidable,
|
||||
kairo_broad,
|
||||
kairo_deep,
|
||||
kairo_diamond,
|
||||
kairo_triangle,
|
||||
kairo_mux,
|
||||
kairo_repeated,
|
||||
kairo_unstable,
|
||||
mol_bench
|
||||
sbench_create_signals,
|
||||
sbench_create_0to1,
|
||||
sbench_create_1to1,
|
||||
sbench_create_2to1,
|
||||
sbench_create_4to1,
|
||||
sbench_create_1000to1,
|
||||
sbench_create_1to2,
|
||||
sbench_create_1to4,
|
||||
sbench_create_1to8,
|
||||
sbench_create_1to1000,
|
||||
kairo_avoidable_owned,
|
||||
kairo_avoidable_unowned,
|
||||
kairo_broad_owned,
|
||||
kairo_broad_unowned,
|
||||
kairo_deep_owned,
|
||||
kairo_deep_unowned,
|
||||
kairo_diamond_owned,
|
||||
kairo_diamond_unowned,
|
||||
kairo_triangle_owned,
|
||||
kairo_triangle_unowned,
|
||||
kairo_mux_owned,
|
||||
kairo_mux_unowned,
|
||||
kairo_repeated_owned,
|
||||
kairo_repeated_unowned,
|
||||
kairo_unstable_owned,
|
||||
kairo_unstable_unowned,
|
||||
mol_bench_owned,
|
||||
mol_bench_unowned
|
||||
];
|
||||
|
@ -0,0 +1,339 @@
|
||||
import { fastest_test } from '../utils.js';
|
||||
import * as $ from '../../packages/svelte/src/internal/client/index.js';
|
||||
|
||||
const COUNT = 1e5;
|
||||
|
||||
/**
|
||||
* @param {number} n
|
||||
* @param {any[]} sources
|
||||
*/
|
||||
function create_data_signals(n, sources) {
|
||||
for (let i = 0; i < n; i++) {
|
||||
sources[i] = $.source(i);
|
||||
}
|
||||
return sources;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} i
|
||||
*/
|
||||
function create_computation_0(i) {
|
||||
$.derived(() => i);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} s1
|
||||
*/
|
||||
function create_computation_1(s1) {
|
||||
$.derived(() => $.get(s1));
|
||||
}
|
||||
/**
|
||||
* @param {any} s1
|
||||
* @param {any} s2
|
||||
*/
|
||||
function create_computation_2(s1, s2) {
|
||||
$.derived(() => $.get(s1) + $.get(s2));
|
||||
}
|
||||
|
||||
function create_computation_1000(ss, offset) {
|
||||
$.derived(() => {
|
||||
let sum = 0;
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
sum += $.get(ss[offset + i]);
|
||||
}
|
||||
return sum;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} n
|
||||
*/
|
||||
function create_computations_0to1(n) {
|
||||
for (let i = 0; i < n; i++) {
|
||||
create_computation_0(i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} n
|
||||
* @param {any[]} sources
|
||||
*/
|
||||
function create_computations_1to1(n, sources) {
|
||||
for (let i = 0; i < n; i++) {
|
||||
const source = sources[i];
|
||||
create_computation_1(source);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} n
|
||||
* @param {any[]} sources
|
||||
*/
|
||||
function create_computations_2to1(n, sources) {
|
||||
for (let i = 0; i < n; i++) {
|
||||
create_computation_2(sources[i * 2], sources[i * 2 + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
function create_computation_4(s1, s2, s3, s4) {
|
||||
$.derived(() => $.get(s1) + $.get(s2) + $.get(s3) + $.get(s4));
|
||||
}
|
||||
|
||||
function create_computations_1000to1(n, sources) {
|
||||
for (let i = 0; i < n; i++) {
|
||||
create_computation_1000(sources, i * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
function create_computations_1to2(n, sources) {
|
||||
for (let i = 0; i < n / 2; i++) {
|
||||
const source = sources[i];
|
||||
create_computation_1(source);
|
||||
create_computation_1(source);
|
||||
}
|
||||
}
|
||||
|
||||
function create_computations_1to4(n, sources) {
|
||||
for (let i = 0; i < n / 4; i++) {
|
||||
const source = sources[i];
|
||||
create_computation_1(source);
|
||||
create_computation_1(source);
|
||||
create_computation_1(source);
|
||||
create_computation_1(source);
|
||||
}
|
||||
}
|
||||
|
||||
function create_computations_1to8(n, sources) {
|
||||
for (let i = 0; i < n / 8; i++) {
|
||||
const source = sources[i];
|
||||
create_computation_1(source);
|
||||
create_computation_1(source);
|
||||
create_computation_1(source);
|
||||
create_computation_1(source);
|
||||
create_computation_1(source);
|
||||
create_computation_1(source);
|
||||
create_computation_1(source);
|
||||
create_computation_1(source);
|
||||
}
|
||||
}
|
||||
|
||||
function create_computations_1to1000(n, sources) {
|
||||
for (let i = 0; i < n / 1000; i++) {
|
||||
const source = sources[i];
|
||||
for (let j = 0; j < 1000; j++) {
|
||||
create_computation_1(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function create_computations_4to1(n, sources) {
|
||||
for (let i = 0; i < n; i++) {
|
||||
create_computation_4(
|
||||
sources[i * 4],
|
||||
sources[i * 4 + 1],
|
||||
sources[i * 4 + 2],
|
||||
sources[i * 4 + 3]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} fn
|
||||
* @param {number} count
|
||||
* @param {number} scount
|
||||
*/
|
||||
function bench(fn, count, scount) {
|
||||
let sources = create_data_signals(scount, []);
|
||||
|
||||
fn(count, sources);
|
||||
}
|
||||
|
||||
export async function sbench_create_signals() {
|
||||
// Do 3 loops to warm up JIT
|
||||
for (let i = 0; i < 3; i++) {
|
||||
bench(create_data_signals, COUNT, COUNT);
|
||||
}
|
||||
|
||||
const { timing } = await fastest_test(10, () => {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
bench(create_data_signals, COUNT, COUNT);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
benchmark: 'sbench_create_signals',
|
||||
time: timing.time.toFixed(2),
|
||||
gc_time: timing.gc_time.toFixed(2)
|
||||
};
|
||||
}
|
||||
|
||||
export async function sbench_create_0to1() {
|
||||
// Do 3 loops to warm up JIT
|
||||
for (let i = 0; i < 3; i++) {
|
||||
bench(create_computations_0to1, COUNT, 0);
|
||||
}
|
||||
|
||||
const { timing } = await fastest_test(10, () => {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
bench(create_computations_0to1, COUNT, 0);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
benchmark: 'sbench_create_0to1',
|
||||
time: timing.time.toFixed(2),
|
||||
gc_time: timing.gc_time.toFixed(2)
|
||||
};
|
||||
}
|
||||
|
||||
export async function sbench_create_1to1() {
|
||||
// Do 3 loops to warm up JIT
|
||||
for (let i = 0; i < 3; i++) {
|
||||
bench(create_computations_1to1, COUNT, COUNT);
|
||||
}
|
||||
|
||||
const { timing } = await fastest_test(10, () => {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
bench(create_computations_1to1, COUNT, COUNT);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
benchmark: 'sbench_create_1to1',
|
||||
time: timing.time.toFixed(2),
|
||||
gc_time: timing.gc_time.toFixed(2)
|
||||
};
|
||||
}
|
||||
|
||||
export async function sbench_create_2to1() {
|
||||
// Do 3 loops to warm up JIT
|
||||
for (let i = 0; i < 3; i++) {
|
||||
bench(create_computations_2to1, COUNT / 2, COUNT);
|
||||
}
|
||||
|
||||
const { timing } = await fastest_test(10, () => {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
bench(create_computations_2to1, COUNT / 2, COUNT);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
benchmark: 'sbench_create_2to1',
|
||||
time: timing.time.toFixed(2),
|
||||
gc_time: timing.gc_time.toFixed(2)
|
||||
};
|
||||
}
|
||||
|
||||
export async function sbench_create_4to1() {
|
||||
// Do 3 loops to warm up JIT
|
||||
for (let i = 0; i < 3; i++) {
|
||||
bench(create_computations_4to1, COUNT / 4, COUNT);
|
||||
}
|
||||
|
||||
const { timing } = await fastest_test(10, () => {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
bench(create_computations_4to1, COUNT / 4, COUNT);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
benchmark: 'sbench_create_4to1',
|
||||
time: timing.time.toFixed(2),
|
||||
gc_time: timing.gc_time.toFixed(2)
|
||||
};
|
||||
}
|
||||
|
||||
export async function sbench_create_1000to1() {
|
||||
// Do 3 loops to warm up JIT
|
||||
for (let i = 0; i < 3; i++) {
|
||||
bench(create_computations_1000to1, COUNT / 1000, COUNT);
|
||||
}
|
||||
|
||||
const { timing } = await fastest_test(10, () => {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
bench(create_computations_1000to1, COUNT / 1000, COUNT);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
benchmark: 'sbench_create_1000to1',
|
||||
time: timing.time.toFixed(2),
|
||||
gc_time: timing.gc_time.toFixed(2)
|
||||
};
|
||||
}
|
||||
|
||||
export async function sbench_create_1to2() {
|
||||
// Do 3 loops to warm up JIT
|
||||
for (let i = 0; i < 3; i++) {
|
||||
bench(create_computations_1to2, COUNT, COUNT / 2);
|
||||
}
|
||||
|
||||
const { timing } = await fastest_test(10, () => {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
bench(create_computations_1to2, COUNT, COUNT / 2);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
benchmark: 'sbench_create_1to2',
|
||||
time: timing.time.toFixed(2),
|
||||
gc_time: timing.gc_time.toFixed(2)
|
||||
};
|
||||
}
|
||||
|
||||
export async function sbench_create_1to4() {
|
||||
// Do 3 loops to warm up JIT
|
||||
for (let i = 0; i < 3; i++) {
|
||||
bench(create_computations_1to4, COUNT, COUNT / 4);
|
||||
}
|
||||
|
||||
const { timing } = await fastest_test(10, () => {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
bench(create_computations_1to4, COUNT, COUNT / 4);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
benchmark: 'sbench_create_1to4',
|
||||
time: timing.time.toFixed(2),
|
||||
gc_time: timing.gc_time.toFixed(2)
|
||||
};
|
||||
}
|
||||
|
||||
export async function sbench_create_1to8() {
|
||||
// Do 3 loops to warm up JIT
|
||||
for (let i = 0; i < 3; i++) {
|
||||
bench(create_computations_1to8, COUNT, COUNT / 8);
|
||||
}
|
||||
|
||||
const { timing } = await fastest_test(10, () => {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
bench(create_computations_1to8, COUNT, COUNT / 8);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
benchmark: 'sbench_create_1to8',
|
||||
time: timing.time.toFixed(2),
|
||||
gc_time: timing.gc_time.toFixed(2)
|
||||
};
|
||||
}
|
||||
|
||||
export async function sbench_create_1to1000() {
|
||||
// Do 3 loops to warm up JIT
|
||||
for (let i = 0; i < 3; i++) {
|
||||
bench(create_computations_1to1000, COUNT, COUNT / 1000);
|
||||
}
|
||||
|
||||
const { timing } = await fastest_test(10, () => {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
bench(create_computations_1to1000, COUNT, COUNT / 1000);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
benchmark: 'sbench_create_1to1000',
|
||||
time: timing.time.toFixed(2),
|
||||
gc_time: timing.gc_time.toFixed(2)
|
||||
};
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
import { assert_ok, test } from '../../test';
|
||||
|
||||
export default test({
|
||||
server_props: {
|
||||
items: []
|
||||
},
|
||||
|
||||
props: {
|
||||
items: [{ name: 'a' }]
|
||||
},
|
||||
|
||||
snapshot(target) {
|
||||
const ul = target.querySelector('ul');
|
||||
assert_ok(ul);
|
||||
|
||||
return {
|
||||
ul
|
||||
};
|
||||
}
|
||||
});
|
@ -0,0 +1,9 @@
|
||||
<!--ssr:0--><ul><!--ssr:1--><!--ssr:7--><li>a</li><!--ssr:7--><!--ssr:1--></ul>
|
||||
<ul><!--ssr:2--><!--ssr:9--><li>a</li><!--ssr:9--><!--ssr:2--></ul>
|
||||
<ul><!--ssr:3--><!--ssr:11--><li>a</li><!--ssr:11--><!--ssr:3--></ul>
|
||||
<!--ssr:4--><!--ssr:13--><li>a</li>
|
||||
<li>a</li><!--ssr:13--><!--ssr:4-->
|
||||
<!--ssr:5--><!--ssr:15--><li>a</li>
|
||||
<li>a</li><!--ssr:15--><!--ssr:5-->
|
||||
<!--ssr:6--><!--ssr:17--><li>a</li>
|
||||
<li>a</li><!--ssr:17--><!--ssr:6--><!--ssr:0--></div>
|
@ -0,0 +1,32 @@
|
||||
<script>
|
||||
let { items } = $props();
|
||||
</script>
|
||||
|
||||
<ul>
|
||||
{#each items as item}
|
||||
<li>{item.name}</li>
|
||||
{/each}
|
||||
</ul>
|
||||
<ul>
|
||||
{#each items as item (item)}
|
||||
<li>{item.name}</li>
|
||||
{/each}
|
||||
</ul>
|
||||
<ul>
|
||||
{#each items as item (item.name)}
|
||||
<li>{item.name}</li>
|
||||
{/each}
|
||||
</ul>
|
||||
|
||||
{#each items as item}
|
||||
<li>{item.name}</li>
|
||||
<li>{item.name}</li>
|
||||
{/each}
|
||||
{#each items as item (item)}
|
||||
<li>{item.name}</li>
|
||||
<li>{item.name}</li>
|
||||
{/each}
|
||||
{#each items as item (item.name)}
|
||||
<li>{item.name}</li>
|
||||
<li>{item.name}</li>
|
||||
{/each}
|
@ -0,0 +1,24 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
async test({ assert, target, logs }) {
|
||||
const [b1, b2] = target.querySelectorAll('button');
|
||||
|
||||
b1.click();
|
||||
await Promise.resolve();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`<p>pending</p><button>Show Promise A</button><button>Show Promise B</button>`
|
||||
);
|
||||
|
||||
b2.click();
|
||||
await Promise.resolve();
|
||||
await Promise.resolve();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`<p>pending</p><button>Show Promise A</button><button>Show Promise B</button>`
|
||||
);
|
||||
|
||||
assert.deepEqual(logs, ['rendering pending block']);
|
||||
}
|
||||
});
|
@ -0,0 +1,17 @@
|
||||
<script>
|
||||
const a = new Promise(() => {});
|
||||
const b = new Promise(() => {});
|
||||
|
||||
let promise = $state(a);
|
||||
</script>
|
||||
|
||||
{#await promise}
|
||||
{console.log('rendering pending block')}
|
||||
<p>pending</p>
|
||||
{:then value}
|
||||
{console.log('rendering then block')}
|
||||
<p>then {value}</p>
|
||||
{/await}
|
||||
|
||||
<button onclick={() => (promise = a)}>Show Promise A</button>
|
||||
<button onclick={() => (promise = b)}>Show Promise B</button>
|
@ -0,0 +1,21 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
async test({ assert, target, logs }) {
|
||||
const [b1, b2, b3, b4] = target.querySelectorAll('button');
|
||||
b1.click();
|
||||
await Promise.resolve();
|
||||
b2.click();
|
||||
await Promise.resolve();
|
||||
await Promise.resolve();
|
||||
await Promise.resolve();
|
||||
b3.click();
|
||||
await Promise.resolve();
|
||||
await Promise.resolve();
|
||||
await Promise.resolve();
|
||||
b4.click();
|
||||
await Promise.resolve();
|
||||
await Promise.resolve();
|
||||
assert.deepEqual(logs, ['pending', 'a', 'b', 'c', 'pending']);
|
||||
}
|
||||
});
|
@ -0,0 +1,21 @@
|
||||
<script>
|
||||
const promise_a = Promise.resolve('a');
|
||||
const promise_b = Promise.resolve('b');
|
||||
const promise_c = Promise.resolve('c');
|
||||
const promise_d = new Promise(() => {});
|
||||
|
||||
let current_promise = $state(promise_a);
|
||||
</script>
|
||||
|
||||
{#await current_promise}
|
||||
{console.log('pending')}
|
||||
{:then value}
|
||||
{console.log(value)}
|
||||
{:catch}
|
||||
{console.log('error')}
|
||||
{/await}
|
||||
|
||||
<button onclick={()=>{current_promise = promise_a}}>Show Promise A</button>
|
||||
<button onclick={()=>{current_promise = promise_b}}>Show Promise B</button>
|
||||
<button onclick={()=>{current_promise = promise_c}}>Show Promise C</button>
|
||||
<button onclick={()=>{current_promise = promise_d}}>Show Promise D</button>
|
@ -0,0 +1,27 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
async test({ assert, target, logs }) {
|
||||
const [b1, b2] = target.querySelectorAll('button');
|
||||
b1.click();
|
||||
await Promise.resolve();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`<p>then a</p><button>Show Promise A</button><button>Show Promise B</button>`
|
||||
);
|
||||
b2.click();
|
||||
await Promise.resolve();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`<p>then a</p><button>Show Promise A</button><button>Show Promise B</button>`
|
||||
);
|
||||
await Promise.resolve();
|
||||
await Promise.resolve();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`<p>then b</p><button>Show Promise A</button><button>Show Promise B</button>`
|
||||
);
|
||||
|
||||
assert.deepEqual(logs, ['rendering pending block', 'rendering then block']);
|
||||
}
|
||||
});
|
@ -0,0 +1,17 @@
|
||||
<script>
|
||||
const a = Promise.resolve('a');
|
||||
const b = Promise.resolve('b');
|
||||
|
||||
let promise = $state(a);
|
||||
</script>
|
||||
|
||||
{#await promise}
|
||||
{console.log('rendering pending block')}
|
||||
<p>pending</p>
|
||||
{:then value}
|
||||
{console.log('rendering then block')}
|
||||
<p>then {value}</p>
|
||||
{/await}
|
||||
|
||||
<button onclick={() => (promise = a)}>Show Promise A</button>
|
||||
<button onclick={() => (promise = b)}>Show Promise B</button>
|
@ -0,0 +1,7 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
test({ assert, logs }) {
|
||||
assert.deepEqual(logs, [1, 1, 1, 1]);
|
||||
}
|
||||
});
|
@ -0,0 +1,9 @@
|
||||
<script>
|
||||
let x = $state(0);
|
||||
let o = $state({ x: 0 });
|
||||
|
||||
console.log(++x);
|
||||
console.log(x++);
|
||||
console.log(++o.x);
|
||||
console.log(o.x++);
|
||||
</script>
|
Loading…
Reference in new issue