mirror of https://github.com/sveltejs/svelte
commit
d7d7c314cf
@ -1,5 +0,0 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
chore: rebase batches after process, not during
|
||||
@ -0,0 +1,69 @@
|
||||
name: Autofix Lint
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
autofix-lint:
|
||||
permissions:
|
||||
contents: write # to push the generated types commit
|
||||
pull-requests: read # to resolve the PR head ref
|
||||
# prevents this action from running on forks
|
||||
if: |
|
||||
github.repository == 'sveltejs/svelte' &&
|
||||
(
|
||||
github.event_name == 'workflow_dispatch' ||
|
||||
(
|
||||
github.event.issue.pull_request != null &&
|
||||
github.event.comment.body == '/autofix' &&
|
||||
contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)
|
||||
)
|
||||
)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get PR ref
|
||||
if: github.event_name != 'workflow_dispatch'
|
||||
id: pr
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
script: |
|
||||
const { data: pull } = await github.rest.pulls.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: context.issue.number
|
||||
});
|
||||
if (pull.head.repo.full_name !== `${context.repo.owner}/${context.repo.repo}`) {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: 'Cannot autofix: this PR is from a forked repository. The autofix workflow can only push to branches within this repository.'
|
||||
});
|
||||
core.setFailed('PR is from a fork');
|
||||
}
|
||||
core.setOutput('ref', pull.head.ref);
|
||||
- uses: actions/checkout@v6
|
||||
if: github.event_name == 'workflow_dispatch' || steps.pr.outcome == 'success'
|
||||
with:
|
||||
ref: ${{ github.event_name == 'workflow_dispatch' && github.ref || steps.pr.outputs.ref }}
|
||||
- uses: pnpm/action-setup@v4.3.0
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 24
|
||||
cache: pnpm
|
||||
- run: pnpm install --frozen-lockfile
|
||||
- name: Build
|
||||
run: pnpm -F svelte build
|
||||
- name: Run prettier
|
||||
run: pnpm format
|
||||
- name: Commit changes
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git add -A
|
||||
git diff --staged --quiet || git commit -m "chore: autofix"
|
||||
git push origin HEAD
|
||||
@ -0,0 +1,7 @@
|
||||
<h1>Hello</h1>
|
||||
|
||||
<style>
|
||||
h1 {
|
||||
color: var(--color);
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,7 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
compileOptions: {
|
||||
hmr: true
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,5 @@
|
||||
<script>
|
||||
import Component from "./Component.svelte";
|
||||
</script>
|
||||
|
||||
<Component --color="red" />
|
||||
@ -0,0 +1,25 @@
|
||||
import { tick } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
compileOptions: {
|
||||
dev: true
|
||||
},
|
||||
async test({ assert, target }) {
|
||||
const button = /** @type {HTMLElement} */ (target.querySelector('button'));
|
||||
await tick();
|
||||
assert.htmlEqual(target.innerHTML, `<button>go</button><p>count1: 0, count2: 0</p>`);
|
||||
|
||||
button.click();
|
||||
await tick();
|
||||
assert.htmlEqual(target.innerHTML, `<button>go</button><p>count1: 1, count2: 1</p>`);
|
||||
|
||||
// additional tick necessary in legacy mode because it's using Promise.resolve() which finishes before the await in the component,
|
||||
// causing the cache to not be set yet, which would result in count2 becoming 2
|
||||
await tick();
|
||||
|
||||
button.click();
|
||||
await tick();
|
||||
assert.htmlEqual(target.innerHTML, `<button>go</button><p>count1: 2, count2: 1</p>`);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,18 @@
|
||||
<script>
|
||||
let count1 = $state(0);
|
||||
let count2 = $state(0);
|
||||
let cache = $state({});
|
||||
|
||||
async function go() {
|
||||
count1++;
|
||||
const value = cache.value ??= await get_value();
|
||||
}
|
||||
|
||||
function get_value() {
|
||||
count2++;
|
||||
return 42;
|
||||
}
|
||||
</script>
|
||||
|
||||
<button onclick={go}>go</button>
|
||||
<p>count1: {count1}, count2: {count2}</p>
|
||||
@ -0,0 +1,19 @@
|
||||
import { tick } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
compileOptions: {
|
||||
dev: true
|
||||
},
|
||||
async test({ assert, target }) {
|
||||
const button = /** @type {HTMLElement} */ (target.querySelector('button'));
|
||||
await tick();
|
||||
assert.htmlEqual(target.innerHTML, `<button>go</button><p>count1: 0, count2: 0</p>`);
|
||||
button.click();
|
||||
await tick();
|
||||
assert.htmlEqual(target.innerHTML, `<button>go</button><p>count1: 1, count2: 1</p>`);
|
||||
button.click();
|
||||
await tick();
|
||||
assert.htmlEqual(target.innerHTML, `<button>go</button><p>count1: 2, count2: 1</p>`);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,18 @@
|
||||
<script>
|
||||
let count1 = $state(0);
|
||||
let count2 = $state(0);
|
||||
let cache = $state({});
|
||||
|
||||
function go() {
|
||||
count1++;
|
||||
const value = cache.value ??= get_value();
|
||||
}
|
||||
|
||||
function get_value() {
|
||||
count2++;
|
||||
return 42;
|
||||
}
|
||||
</script>
|
||||
|
||||
<button onclick={go}>go</button>
|
||||
<p>count1: {count1}, count2: {count2}</p>
|
||||
@ -0,0 +1,29 @@
|
||||
import { tick } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
async test({ assert, target }) {
|
||||
await tick();
|
||||
const [a, b, resolve] = target.querySelectorAll('button');
|
||||
|
||||
a.click();
|
||||
await tick();
|
||||
b.click();
|
||||
await tick();
|
||||
resolve.click();
|
||||
await tick();
|
||||
resolve.click();
|
||||
await tick();
|
||||
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
<button>a</button>
|
||||
<button>b</button>
|
||||
<button>resolve</button>
|
||||
hi
|
||||
1
|
||||
`
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,21 @@
|
||||
<script>
|
||||
let a = $state(0);
|
||||
let b = $state(0);
|
||||
let a_b = $derived(a * b);
|
||||
|
||||
const queued = [];
|
||||
|
||||
function push(value) {
|
||||
if (!value) return value;
|
||||
return new Promise(resolve => {
|
||||
queued.push(() => resolve(value));
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<button onclick={() => (a++)}>a</button>
|
||||
<button onclick={() => (b++)}>b</button>
|
||||
<button onclick={() => (queued.shift()?.())}>resolve</button>
|
||||
<!-- a_b called in a block effect before being called in an async effect -->
|
||||
{#if a_b}hi{/if}
|
||||
{await push(a_b)}
|
||||
@ -0,0 +1,89 @@
|
||||
import { tick } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
async test({ assert, target }) {
|
||||
await tick();
|
||||
|
||||
const [increment, shift, pop] = target.querySelectorAll('button');
|
||||
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
<button>1</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
<p>1 = 1</p>
|
||||
`
|
||||
);
|
||||
|
||||
increment.click();
|
||||
await tick();
|
||||
increment.click();
|
||||
await tick();
|
||||
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
<button>3</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
<p>1 = 1</p>
|
||||
`
|
||||
);
|
||||
|
||||
shift.click();
|
||||
await tick();
|
||||
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
<button>3</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
<p>1 = 1</p>
|
||||
`
|
||||
);
|
||||
|
||||
shift.click();
|
||||
await tick();
|
||||
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
<button>3</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
<p>3 = 3</p>
|
||||
`
|
||||
);
|
||||
|
||||
increment.click();
|
||||
await tick();
|
||||
increment.click();
|
||||
await tick();
|
||||
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
<button>5</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
<p>3 = 3</p>
|
||||
`
|
||||
);
|
||||
|
||||
pop.click();
|
||||
await tick();
|
||||
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
<button>5</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
<p>5 = 5</p>
|
||||
`
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,36 @@
|
||||
<script>
|
||||
import { getAbortSignal } from 'svelte';
|
||||
|
||||
const queue = [];
|
||||
|
||||
function push(value) {
|
||||
if (value === 1) return 1;
|
||||
const d = Promise.withResolvers();
|
||||
|
||||
queue.push(() => d.resolve(value));
|
||||
|
||||
const signal = getAbortSignal();
|
||||
signal.onabort = () => d.reject(signal.reason);
|
||||
|
||||
return d.promise;
|
||||
}
|
||||
|
||||
function shift() {
|
||||
queue.shift()?.();
|
||||
}
|
||||
|
||||
function pop() {
|
||||
queue.pop()?.();
|
||||
}
|
||||
|
||||
let n = $state(1);
|
||||
</script>
|
||||
|
||||
<button onclick={() => n++}>
|
||||
{$state.eager(n)}
|
||||
</button>
|
||||
|
||||
<button onclick={shift}>shift</button>
|
||||
<button onclick={pop}>pop</button>
|
||||
|
||||
<p>{n} = {await push(n)}</p>
|
||||
@ -0,0 +1,32 @@
|
||||
import { tick } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
async test({ assert, target }) {
|
||||
const spam = /** @type {HTMLButtonElement} */ (target.querySelector('button.spam'));
|
||||
const resolve = /** @type {HTMLButtonElement} */ (target.querySelector('button.resolve'));
|
||||
|
||||
resolve.click();
|
||||
await tick();
|
||||
|
||||
for (let i = 0; i < 5; i += 1) {
|
||||
spam.click();
|
||||
await tick();
|
||||
}
|
||||
|
||||
for (let i = 0; i < 5; i += 1) {
|
||||
resolve.click();
|
||||
await tick();
|
||||
}
|
||||
|
||||
assert.equal(target.querySelectorAll('div').length, 1);
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
<button class="spam">Spam</button>
|
||||
<button class="resolve">Resolve</button>
|
||||
<div>5</div>
|
||||
`
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,28 @@
|
||||
<script>
|
||||
let value = $state({ id: '0' });
|
||||
const resolvers = [];
|
||||
|
||||
function wait() {
|
||||
const promise = Promise.withResolvers();
|
||||
resolvers.push(promise.resolve);
|
||||
return promise.promise;
|
||||
}
|
||||
|
||||
function spam() {
|
||||
value.id = `${Number(value.id) + 1}`;
|
||||
}
|
||||
</script>
|
||||
|
||||
<button class="spam" onclick={spam}>Spam</button>
|
||||
<button class="resolve" onclick={() => resolvers.shift()?.()}>Resolve</button>
|
||||
|
||||
<svelte:boundary>
|
||||
{#each [value.id] as s (s)}
|
||||
{await wait()}
|
||||
<div>{s}</div>
|
||||
{/each}
|
||||
|
||||
{#snippet pending()}
|
||||
<p>pending</p>
|
||||
{/snippet}
|
||||
</svelte:boundary>
|
||||
@ -0,0 +1,23 @@
|
||||
import { tick } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
async test({ assert, target }) {
|
||||
await tick();
|
||||
const [increment, shift] = target.querySelectorAll('button');
|
||||
|
||||
increment.click();
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`<button>clicks: 0 - 0 - 0</button> <button>shift</button> <p>true - true</p>`
|
||||
);
|
||||
|
||||
shift.click();
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`<button>clicks: 1 - 1 - 1</button> <button>shift</button> <p>false - false</p>`
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,22 @@
|
||||
<script>
|
||||
|
||||
let count = $state(0);
|
||||
const delayedCount = $derived(await push(count));
|
||||
const derivedCount = $derived(count);
|
||||
|
||||
let resolvers = [];
|
||||
|
||||
function push(value) {
|
||||
if (!value) return value;
|
||||
const { promise, resolve } = Promise.withResolvers();
|
||||
resolvers.push(() => resolve(value));
|
||||
return promise;
|
||||
}
|
||||
</script>
|
||||
|
||||
<button onclick={() => count += 1}>
|
||||
clicks: {count} - {delayedCount} - {derivedCount}
|
||||
</button>
|
||||
<button onclick={() => resolvers.shift()?.()}>shift</button>
|
||||
|
||||
<p>{$state.eager(count) !== count} - {$state.eager(derivedCount) !== derivedCount}</p>
|
||||
@ -0,0 +1,16 @@
|
||||
import { tick } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
async test({ assert, target, logs }) {
|
||||
const [btn] = target.querySelectorAll('button');
|
||||
|
||||
btn.click();
|
||||
await tick();
|
||||
assert.deepEqual(logs, [10]);
|
||||
|
||||
btn.click();
|
||||
await tick();
|
||||
assert.deepEqual(logs, [10, 10]);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,21 @@
|
||||
<script>
|
||||
import { fork } from 'svelte';
|
||||
|
||||
let s = $state(1);
|
||||
let d = $derived(s * 10);
|
||||
</script>
|
||||
|
||||
<button
|
||||
onclick={() => {
|
||||
const f = fork(() => {
|
||||
// d has not been read yet, so this write happens with an uninitialized old value
|
||||
s = 2;
|
||||
d = 99;
|
||||
});
|
||||
|
||||
f.discard();
|
||||
console.log(d);
|
||||
}}
|
||||
>
|
||||
test
|
||||
</button>
|
||||
@ -0,0 +1,10 @@
|
||||
import { tick } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
mode: ['hydrate'],
|
||||
async test({ assert, target }) {
|
||||
await tick();
|
||||
assert.htmlEqual(target.innerHTML, `<div><div><p>first test</p></div> other test</div>`);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,14 @@
|
||||
<script>
|
||||
function firstTest() {
|
||||
return Promise.resolve('<p>first test</p>');
|
||||
}
|
||||
|
||||
function otherTest() {
|
||||
return Promise.resolve('other test');
|
||||
}
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<div>{@html await firstTest()}</div>
|
||||
{await otherTest()}
|
||||
</div>
|
||||
@ -0,0 +1,7 @@
|
||||
<script>
|
||||
let data = $derived(await Promise.resolve('test'));
|
||||
</script>
|
||||
|
||||
<div data-resolved={data ? 'true' : 'false'}>
|
||||
{data}
|
||||
</div>
|
||||
@ -0,0 +1,7 @@
|
||||
<script>
|
||||
import Bound from './Bound.svelte';
|
||||
|
||||
let open;
|
||||
</script>
|
||||
|
||||
<Bound bind:open />
|
||||
@ -0,0 +1,10 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
// Tests that renderer.subsume (which is used when bindings are present) works correctly
|
||||
export default test({
|
||||
mode: ['hydrate'],
|
||||
html: '<div data-resolved="true">test</div>',
|
||||
async test({ assert, warnings }) {
|
||||
assert.deepEqual(warnings, []);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,7 @@
|
||||
<script lang="ts">
|
||||
import Async from './Async.svelte';
|
||||
import Binding from './Binding.svelte';
|
||||
</script>
|
||||
|
||||
<Async />
|
||||
<Binding />
|
||||
@ -0,0 +1,29 @@
|
||||
import { tick } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
async test({ assert, target }) {
|
||||
await tick();
|
||||
|
||||
const [a, b] = target.querySelectorAll('button');
|
||||
|
||||
assert.htmlEqual(target.innerHTML, `<button>a 0</button><button>b 0</button><p>hello</p>`);
|
||||
|
||||
a.click();
|
||||
await tick();
|
||||
assert.htmlEqual(target.innerHTML, `<button>a 0</button><button>b 0</button><p>hello</p>`);
|
||||
|
||||
a.click();
|
||||
await tick();
|
||||
assert.htmlEqual(target.innerHTML, `<button>a 2</button><button>b 0</button><p>hello</p>`);
|
||||
|
||||
a.click();
|
||||
await tick();
|
||||
assert.htmlEqual(target.innerHTML, `<button>a 2</button><button>b 0</button><p>hello</p>`);
|
||||
|
||||
// if we don't skip over the never-resolving promise in the `else` block, we will never update
|
||||
b.click();
|
||||
await tick();
|
||||
assert.htmlEqual(target.innerHTML, `<button>a 3</button><button>b 1</button><p>hello</p>`);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,14 @@
|
||||
<script>
|
||||
let a = $state(0);
|
||||
let b = $state(0);
|
||||
let show = $state(true);
|
||||
</script>
|
||||
|
||||
<button onclick={() => (a++, show = !show)}>a {a}</button>
|
||||
<button onclick={() => (b++, show = !show)}>b {b}</button>
|
||||
|
||||
{#if show}
|
||||
<p>hello</p>
|
||||
{:else}
|
||||
{await new Promise(() => {})}
|
||||
{/if}
|
||||
@ -0,0 +1,10 @@
|
||||
import { tick } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
ssrHtml: 'works',
|
||||
async test({ assert, target }) {
|
||||
await tick();
|
||||
assert.htmlEqual(target.innerHTML, 'works');
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,7 @@
|
||||
<script lang="ts">
|
||||
const test = async () => "test";
|
||||
await test();
|
||||
$inspect("inspect after await shouldnt break builds");
|
||||
</script>
|
||||
|
||||
works
|
||||
@ -0,0 +1,9 @@
|
||||
import { tick } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
async test({ assert, target }) {
|
||||
await tick();
|
||||
assert.htmlEqual(target.innerHTML, 'aaa 1');
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,10 @@
|
||||
<script>
|
||||
let name = $derived(await new Promise((a) => a('aaa')));
|
||||
function use() {
|
||||
return () => 1;
|
||||
}
|
||||
const aa = use();
|
||||
</script>
|
||||
|
||||
{name}
|
||||
{aa()}
|
||||
@ -0,0 +1,30 @@
|
||||
import { tick } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
async test({ assert, target }) {
|
||||
await tick();
|
||||
const [a_b, b, resolve] = target.querySelectorAll('button');
|
||||
|
||||
a_b.click();
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
'<button>a_b 0_0</button> <button>b 0</button> <button>resolve</button> 0'
|
||||
);
|
||||
|
||||
b.click();
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
'<button>a_b 0_0</button> <button>b 0</button> <button>resolve</button> 0'
|
||||
);
|
||||
|
||||
resolve.click();
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
'<button>a_b 1_2</button> <button>b 2</button> <button>resolve</button> 1'
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,17 @@
|
||||
<script>
|
||||
let a = $state(0);
|
||||
let b = $state(0);
|
||||
let deferreds = [];
|
||||
|
||||
function push(value) {
|
||||
if (!value) return value;
|
||||
return new Promise(resolve => {
|
||||
deferreds.push(() => resolve(value));
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<button onclick={() => {a++;b++}}>a_b {a}_{b}</button>
|
||||
<button onclick={() => (b++)}>b {b}</button>
|
||||
<button onclick={() => (deferreds.shift()?.())}>resolve</button>
|
||||
{await push(a)}
|
||||
@ -0,0 +1,107 @@
|
||||
import { tick } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
async test({ assert, target }) {
|
||||
await tick();
|
||||
const [a_b, a_c, b_d, shift, pop] = target.querySelectorAll('button');
|
||||
|
||||
a_b.click();
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 0 | b 0 | c 0 | d 0
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
|
||||
a_c.click();
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 0 | b 0 | c 0 | d 0
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
|
||||
b_d.click();
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 0 | b 0 | c 0 | d 0
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
|
||||
shift.click();
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 0 | b 0 | c 0 | d 0
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
|
||||
shift.click();
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 1 | b 1 | c 0 | d 0
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
|
||||
shift.click();
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 2 | b 1 | c 1 | d 0
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
|
||||
shift.click();
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 2 | b 2 | c 1 | d 1
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,26 @@
|
||||
<script>
|
||||
let a = $state(0);
|
||||
let b = $state(0);
|
||||
let c = $state(0);
|
||||
let d = $state(0);
|
||||
|
||||
const deferred = [];
|
||||
|
||||
function delay(value) {
|
||||
if (!value) return value;
|
||||
return new Promise((resolve) => deferred.push(() => resolve(value)));
|
||||
}
|
||||
</script>
|
||||
|
||||
a {await delay(a)} | b {await delay(b)} | c {c} | d {d}
|
||||
<button onclick={() => {a++;b++;}}>
|
||||
a and b
|
||||
</button>
|
||||
<button onclick={() => {a++;c++;}}>
|
||||
a and c
|
||||
</button>
|
||||
<button onclick={() => {b++;d++;}}>
|
||||
b and d
|
||||
</button>
|
||||
<button onclick={() => deferred.shift()?.()}>shift</button>
|
||||
<button onclick={() => deferred.pop()?.()}>pop</button>
|
||||
@ -0,0 +1,82 @@
|
||||
import { tick } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
skip: true, // TODO works on https://github.com/sveltejs/svelte/pull/17971
|
||||
async test({ assert, target }) {
|
||||
await tick();
|
||||
const [a_b, a_c, b_d, shift, pop] = target.querySelectorAll('button');
|
||||
|
||||
a_b.click();
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 0 | b 0 | c 0 | d 0
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
|
||||
a_c.click();
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 0 | b 0 | c 0 | d 0
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
|
||||
b_d.click();
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 0 | b 0 | c 0 | d 0
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
|
||||
pop.click(); // second b resolved, blocked on first batch because a still pending
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 0 | b 0 | c 0 | d 0
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
|
||||
for (let i = 0; i < 3; i++) {
|
||||
pop.click(); // second a resolved, first a/b now obsolete; empty queue
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 2 | b 2 | c 1 | d 1
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,26 @@
|
||||
<script>
|
||||
let a = $state(0);
|
||||
let b = $state(0);
|
||||
let c = $state(0);
|
||||
let d = $state(0);
|
||||
|
||||
const deferred = [];
|
||||
|
||||
function delay(value) {
|
||||
if (!value) return value;
|
||||
return new Promise((resolve) => deferred.push(() => resolve(value)));
|
||||
}
|
||||
</script>
|
||||
|
||||
a {await delay(a)} | b {await delay(b)} | c {c} | d {d}
|
||||
<button onclick={() => {a++;b++;}}>
|
||||
a and b
|
||||
</button>
|
||||
<button onclick={() => {a++;c++;}}>
|
||||
a and c
|
||||
</button>
|
||||
<button onclick={() => {b++;d++;}}>
|
||||
b and d
|
||||
</button>
|
||||
<button onclick={() => deferred.shift()?.()}>shift</button>
|
||||
<button onclick={() => deferred.pop()?.()}>pop</button>
|
||||
@ -0,0 +1,108 @@
|
||||
import { tick } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
skip: true, // TODO works on https://github.com/sveltejs/svelte/pull/17971
|
||||
async test({ assert, target }) {
|
||||
await tick();
|
||||
const [a_b, a_c, b_d, shift, pop] = target.querySelectorAll('button');
|
||||
|
||||
a_b.click();
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 0 | b 0 | c 0 | d 0
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
|
||||
a_c.click();
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 0 | b 0 | c 0 | d 0
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
|
||||
b_d.click();
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 0 | b 0 | c 0 | d 0
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
|
||||
shift.click(); // first a resolved, still pending: [b, a, b]
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 0 | b 0 | c 0 | d 0
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
|
||||
pop.click(); // second b resolved, still pending: [b, a]
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 0 | b 0 | c 0 | d 0
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
|
||||
shift.click(); // first b resolved, first + last batch settled, still pending: [a]
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 1 | b 2 | c 0 | d 1
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
|
||||
shift.click(); // all resolved
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 2 | b 2 | c 1 | d 1
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,26 @@
|
||||
<script>
|
||||
let a = $state(0);
|
||||
let b = $state(0);
|
||||
let c = $state(0);
|
||||
let d = $state(0);
|
||||
|
||||
const deferred = [];
|
||||
|
||||
function delay(value) {
|
||||
if (!value) return value;
|
||||
return new Promise((resolve) => deferred.push(() => resolve(value)));
|
||||
}
|
||||
</script>
|
||||
|
||||
a {await delay(a)} | b {await delay(b)} | c {c} | d {d}
|
||||
<button onclick={() => {a++;b++;}}>
|
||||
a and b
|
||||
</button>
|
||||
<button onclick={() => {a++;c++;}}>
|
||||
a and c
|
||||
</button>
|
||||
<button onclick={() => {b++;d++;}}>
|
||||
b and d
|
||||
</button>
|
||||
<button onclick={() => deferred.shift()?.()}>shift</button>
|
||||
<button onclick={() => deferred.pop()?.()}>pop</button>
|
||||
@ -0,0 +1,110 @@
|
||||
import { tick } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
skip: true, // TODO works on https://github.com/sveltejs/svelte/pull/17971
|
||||
async test({ assert, target }) {
|
||||
await tick();
|
||||
const [a_b, a_c, b_d, shift, pop] = target.querySelectorAll('button');
|
||||
|
||||
a_b.click();
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 0 | b 0 | c 0 | d 0
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
|
||||
a_c.click();
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 0 | b 0 | c 0 | d 0
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
|
||||
b_d.click();
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 0 | b 0 | c 0 | d 0
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
|
||||
shift.click(); // first a resolved, still pending: [b, a, b]
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 0 | b 0 | c 0 | d 0
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
|
||||
pop.click(); // second b resolved, still pending: [b, a]
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 0 | b 0 | c 0 | d 0
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
|
||||
pop.click(); // second a resolved, first a/b now obsolete
|
||||
// TODO would be nice to show final result here already, right now it doesn't because
|
||||
// we have no handle on the already resolved first a anymore
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 0 | b 0 | c 0 | d 0
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
|
||||
shift.click(); // queue empty
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
a 2 | b 2 | c 1 | d 1
|
||||
<button>a and b</button>
|
||||
<button>a and c</button>
|
||||
<button>b and d</button>
|
||||
<button>shift</button>
|
||||
<button>pop</button>
|
||||
`
|
||||
);
|
||||
}
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue