mirror of https://github.com/sveltejs/svelte
commit
ee30cc9214
@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
'svelte': patch
|
|
||||||
---
|
|
||||||
|
|
||||||
fix: `append_styles` in an effect to make them available on mount
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
'svelte': patch
|
|
||||||
---
|
|
||||||
|
|
||||||
chore: remove `parser.template_untrimmed`
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
'svelte': patch
|
|
||||||
---
|
|
||||||
|
|
||||||
fix: always inject styles when compiling as a custom element
|
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
/** @import { AST } from '#compiler' */
|
||||||
|
/** @import { Context } from '../types.js' */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {AST.Fragment} node
|
||||||
|
* @param {Context} context
|
||||||
|
*/
|
||||||
|
export function Fragment(node, context) {
|
||||||
|
context.next({ ...context.state, fragment: node });
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
/** @import { Expression, ForOfStatement, Pattern, Statement, VariableDeclaration } from 'estree' */
|
||||||
|
/** @import { ComponentContext } from '../types' */
|
||||||
|
import * as b from '#compiler/builders';
|
||||||
|
import { dev, is_ignored } from '../../../../state.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ForOfStatement} node
|
||||||
|
* @param {ComponentContext} context
|
||||||
|
*/
|
||||||
|
export function ForOfStatement(node, context) {
|
||||||
|
if (node.await && dev && !is_ignored(node, 'await_reactivity_loss')) {
|
||||||
|
const left = /** @type {VariableDeclaration | Pattern} */ (context.visit(node.left));
|
||||||
|
const argument = /** @type {Expression} */ (context.visit(node.right));
|
||||||
|
const body = /** @type {Statement} */ (context.visit(node.body));
|
||||||
|
const right = b.call('$.for_await_track_reactivity_loss', argument);
|
||||||
|
return b.for_of(left, right, body, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.next();
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
error: {
|
||||||
|
code: 'snippet_invalid_export',
|
||||||
|
message:
|
||||||
|
'An exported snippet can only reference things declared in a `<script module>`, or other exportable snippets',
|
||||||
|
position: [26, 29]
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
<script module>
|
||||||
|
export { foo }
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
let x = 42;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#snippet foo()}
|
||||||
|
{x}
|
||||||
|
{/snippet}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
<p>nested</p>
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
errors: [
|
||||||
|
'Failed to hydrate: ',
|
||||||
|
new DOMException("Node can't be inserted in a #text parent.", 'HierarchyRequestError')
|
||||||
|
]
|
||||||
|
});
|
||||||
@ -0,0 +1 @@
|
|||||||
|
<main><p>nested</p><!----></main>
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
<!--[-->
|
||||||
|
<main><p>nested</p><!----></main><!--]-->
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
<script>
|
||||||
|
import Nested from './Nested.svelte';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<Nested />
|
||||||
|
</main>
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
import { flushSync } from 'svelte';
|
||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
test({ target, assert }) {
|
||||||
|
const input = target.querySelector('input');
|
||||||
|
const button = target.querySelector('button');
|
||||||
|
|
||||||
|
assert.equal(input?.step, 'any');
|
||||||
|
|
||||||
|
button?.click();
|
||||||
|
flushSync();
|
||||||
|
assert.equal(input?.step, '10');
|
||||||
|
|
||||||
|
button?.click();
|
||||||
|
flushSync();
|
||||||
|
assert.equal(input?.step, 'any');
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
<script>
|
||||||
|
let step = "any";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<input type="range" {...{step}} />
|
||||||
|
<button onclick={() => step = step === "any" ? 10 : "any"}>change step</button>
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
import { ok, test } from '../../test';
|
||||||
|
import { flushSync } from 'svelte';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
async test({ assert, target, errors }) {
|
||||||
|
const btn = target.querySelector('button');
|
||||||
|
flushSync(() => {
|
||||||
|
btn?.click();
|
||||||
|
});
|
||||||
|
assert.deepEqual(errors, []);
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { getAbortSignal } from "svelte";
|
||||||
|
|
||||||
|
let aborted = $state(0);
|
||||||
|
|
||||||
|
let count = $state(0);
|
||||||
|
|
||||||
|
let der = $derived.by(()=>{
|
||||||
|
const signal = getAbortSignal();
|
||||||
|
|
||||||
|
signal.addEventListener("abort", () => {
|
||||||
|
try{
|
||||||
|
aborted++;
|
||||||
|
}catch(e){
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return count;
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{der}
|
||||||
|
|
||||||
|
<button onclick={() => count++}></button>
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
import { tick } from 'svelte';
|
||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
async test({ assert, target }) {
|
||||||
|
const [reset, one, two, reject] = target.querySelectorAll('button');
|
||||||
|
|
||||||
|
await tick();
|
||||||
|
assert.htmlEqual(
|
||||||
|
target.innerHTML,
|
||||||
|
'<button>reset</button><button>one</button><button>two</button><button>reject</button> waiting'
|
||||||
|
);
|
||||||
|
|
||||||
|
one.click();
|
||||||
|
await tick();
|
||||||
|
assert.htmlEqual(
|
||||||
|
target.innerHTML,
|
||||||
|
'<button>reset</button><button>one</button><button>two</button><button>reject</button> one_res'
|
||||||
|
);
|
||||||
|
|
||||||
|
reset.click();
|
||||||
|
await tick();
|
||||||
|
assert.htmlEqual(
|
||||||
|
target.innerHTML,
|
||||||
|
'<button>reset</button><button>one</button><button>two</button><button>reject</button> waiting'
|
||||||
|
);
|
||||||
|
|
||||||
|
two.click();
|
||||||
|
await tick();
|
||||||
|
assert.htmlEqual(
|
||||||
|
target.innerHTML,
|
||||||
|
'<button>reset</button><button>one</button><button>two</button><button>reject</button> two_res'
|
||||||
|
);
|
||||||
|
|
||||||
|
reset.click();
|
||||||
|
reject.click();
|
||||||
|
await tick();
|
||||||
|
assert.htmlEqual(
|
||||||
|
target.innerHTML,
|
||||||
|
'<button>reset</button><button>one</button><button>two</button><button>reject</button> reject_catch'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
<script>
|
||||||
|
let deferred = $state(Promise.withResolvers());
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button onclick={() => deferred = Promise.withResolvers()}>reset</button>
|
||||||
|
<button onclick={() => deferred.resolve("one")}>one</button>
|
||||||
|
<button onclick={() => deferred.resolve("two")}>two</button>
|
||||||
|
<button onclick={() => deferred.reject("reject")}>reject</button>
|
||||||
|
|
||||||
|
<svelte:boundary>
|
||||||
|
{#await await deferred.promise + "_res"}
|
||||||
|
waiting
|
||||||
|
{:then res}
|
||||||
|
{res}
|
||||||
|
{:catch err}
|
||||||
|
{err}_catch
|
||||||
|
{/await}
|
||||||
|
|
||||||
|
{#snippet pending()}
|
||||||
|
<p>pending</p>
|
||||||
|
{/snippet}
|
||||||
|
</svelte:boundary>
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
import { tick } from 'svelte';
|
||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
html: `<h1>Loading...</h1>`,
|
||||||
|
|
||||||
|
async test({ assert, target }) {
|
||||||
|
await tick();
|
||||||
|
|
||||||
|
assert.htmlEqual(target.innerHTML, `<h1>Hello, world!</h1>`);
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
<script>
|
||||||
|
let name = $state('world');
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:boundary>
|
||||||
|
{#snippet pending()}
|
||||||
|
<h1>Loading...</h1>
|
||||||
|
{/snippet}
|
||||||
|
|
||||||
|
{#snippet greet()}
|
||||||
|
{@const greeting = await `Hello, ${name}!`}
|
||||||
|
<h1>{greeting}</h1>
|
||||||
|
{/snippet}
|
||||||
|
|
||||||
|
{@render greet()}
|
||||||
|
</svelte:boundary>
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
import { tick } from 'svelte';
|
||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
compileOptions: {
|
||||||
|
dev: true
|
||||||
|
},
|
||||||
|
|
||||||
|
html: `<button>a</button><button>b</button><p>pending</p>`,
|
||||||
|
|
||||||
|
async test({ assert, target, warnings }) {
|
||||||
|
await tick();
|
||||||
|
assert.htmlEqual(target.innerHTML, '<button>a</button><button>b</button><h1>3</h1>');
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
warnings[0],
|
||||||
|
'Detected reactivity loss when reading `values[1]`. This happens when state is read in an async function after an earlier `await`'
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal(warnings[1].name, 'TracedAtError');
|
||||||
|
|
||||||
|
assert.equal(warnings.length, 2);
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
<script>
|
||||||
|
let values = $state([1, 2]);
|
||||||
|
|
||||||
|
async function get_total() {
|
||||||
|
let total = 0;
|
||||||
|
|
||||||
|
for await (const n of values) {
|
||||||
|
total += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button onclick={() => values[0]++}>a</button>
|
||||||
|
<button onclick={() => values[1]++}>b</button>
|
||||||
|
|
||||||
|
<svelte:boundary>
|
||||||
|
<h1>{await get_total()}</h1>
|
||||||
|
|
||||||
|
{#snippet pending()}
|
||||||
|
<p>pending</p>
|
||||||
|
{/snippet}
|
||||||
|
</svelte:boundary>
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
<script>
|
||||||
|
let { data } = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#each data.obj.arr as i}
|
||||||
|
<p>{i}</p>
|
||||||
|
{/each}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
<p>Comp 2</p>
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
import { flushSync } from 'svelte';
|
||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
async test({ assert, target }) {
|
||||||
|
const [btn] = target.querySelectorAll('button');
|
||||||
|
btn.click();
|
||||||
|
flushSync();
|
||||||
|
assert.htmlEqual(target.innerHTML, `<button>Change</button> <p>Comp 2</p>`);
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
<script>
|
||||||
|
import Comp_1 from './Comp-1.svelte';
|
||||||
|
import Comp_2 from './Comp-2.svelte';
|
||||||
|
|
||||||
|
let Comp = $state.raw(Comp_1);
|
||||||
|
let data = $state.raw({ obj: { arr: [1, 2, 3] } });
|
||||||
|
|
||||||
|
function change() {
|
||||||
|
Comp = Comp_2;
|
||||||
|
data = {};
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button onclick={change}>Change</button>
|
||||||
|
|
||||||
|
<Comp {data} />
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue