mirror of https://github.com/sveltejs/svelte
commit
894f376b37
@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
'svelte': patch
|
|
||||||
---
|
|
||||||
|
|
||||||
fix: cancel deferred event listeners during cleanup
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
'svelte': patch
|
|
||||||
---
|
|
||||||
|
|
||||||
fix: preserve global CSS in components without scopable elements
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
'svelte': patch
|
|
||||||
---
|
|
||||||
|
|
||||||
fix: reduce SSR render result garbage collection
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
'svelte': patch
|
|
||||||
---
|
|
||||||
|
|
||||||
fix: resolve the fallback of an each block in the enclosing scope
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
'svelte': patch
|
|
||||||
---
|
|
||||||
|
|
||||||
perf: speed up parser interactions with Acorn or avoid them where possible
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
'svelte': patch
|
|
||||||
---
|
|
||||||
|
|
||||||
fix: prevent effect tree of batches from interfering with each other
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
'svelte': patch
|
|
||||||
---
|
|
||||||
|
|
||||||
fix: serialize input default values during server rendering
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
'svelte': patch
|
|
||||||
---
|
|
||||||
|
|
||||||
fix: remove `WAS_MARKED` flag in favor of `Set`
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
'svelte': patch
|
|
||||||
---
|
|
||||||
|
|
||||||
fix: throw `set_context_after_init` when `setContext` is called after an `await` during SSR
|
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: don't overwrite an unchanged spread `value`, preserving incomplete number input
|
||||||
@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
'svelte': patch
|
|
||||||
---
|
|
||||||
|
|
||||||
fix: keep `$state.eager` when used as a variable initializer
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
'svelte': patch
|
|
||||||
---
|
|
||||||
|
|
||||||
perf: avoid regex matching in parser where possible
|
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: prevent hydration mismatch recovery from being intercepted by error boundaries
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: preserve dynamic element connections during hydration
|
||||||
@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
'svelte': patch
|
|
||||||
---
|
|
||||||
|
|
||||||
fix: in non-async mode, only push variable to current_sources when active_reaction is updating
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
'svelte': patch
|
|
||||||
---
|
|
||||||
|
|
||||||
fix: recognise `aria-braillelabel` and `aria-brailleroledescription` as known ARIA attributes
|
|
||||||
@ -1,2 +1 @@
|
|||||||
:export { foo: red; }
|
|
||||||
:is(td, th) { color: red; }
|
:is(td, th) { color: red; }
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
<svelte:head><meta name="x" content="y" /></svelte:head>
|
<svelte:head><meta name="x" content="y" /></svelte:head>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
:export { foo: red; }
|
|
||||||
:is(:global(td), :global(th)) { color: red; }
|
:is(:global(td), :global(th)) { color: red; }
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -0,0 +1,5 @@
|
|||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
expect_hydration_error: true
|
||||||
|
});
|
||||||
@ -0,0 +1 @@
|
|||||||
|
<!----><p><p>Valid HTML fragment</p><!----></p><!---->
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
<svelte:boundary>
|
||||||
|
<p>{@html '<p>Valid HTML fragment</p>'}</p>
|
||||||
|
|
||||||
|
{#snippet failed()}
|
||||||
|
<p>boundary fallback</p>
|
||||||
|
{/snippet}
|
||||||
|
</svelte:boundary>
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import { test } from '../../test';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
server_props: { condition: false },
|
||||||
|
props: { condition: true },
|
||||||
|
|
||||||
|
snapshot(target) {
|
||||||
|
return { element: target.querySelector('div'), sibling: target.querySelector(':scope > p') };
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
<div><p>client</p></div>
|
||||||
|
<p>after</p>
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
<script>
|
||||||
|
export let condition;
|
||||||
|
export let tag = 'div';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:element this={tag}>
|
||||||
|
{#if condition}<p>client</p>{:else}<span>server</span>{/if}
|
||||||
|
</svelte:element>
|
||||||
|
<p>after</p>
|
||||||
@ -0,0 +1,71 @@
|
|||||||
|
import { flushSync } from 'svelte';
|
||||||
|
import { assert_ok, test } from '../../assert';
|
||||||
|
|
||||||
|
/** @type {Record<string, number>} */
|
||||||
|
const connections = {};
|
||||||
|
/** @type {string[]} */
|
||||||
|
const disconnections = [];
|
||||||
|
/** @type {Element[]} */
|
||||||
|
let claimed;
|
||||||
|
/** @type {MutationObserver} */
|
||||||
|
let observer;
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
before_test() {
|
||||||
|
const target = document.querySelector('main');
|
||||||
|
assert_ok(target);
|
||||||
|
claimed = Array.from(target.children);
|
||||||
|
customElements.define(
|
||||||
|
'connection-probe',
|
||||||
|
class extends HTMLElement {
|
||||||
|
connectedCallback() {
|
||||||
|
connections[this.id] = (connections[this.id] || 0) + 1;
|
||||||
|
}
|
||||||
|
disconnectedCallback() {
|
||||||
|
disconnections.push(this.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
observer = new MutationObserver(() => {});
|
||||||
|
observer.observe(target, { childList: true });
|
||||||
|
},
|
||||||
|
|
||||||
|
test({ assert, component, target }) {
|
||||||
|
const removed = observer.takeRecords().flatMap((record) => Array.from(record.removedNodes));
|
||||||
|
observer.disconnect();
|
||||||
|
assert.deepEqual(
|
||||||
|
removed
|
||||||
|
.filter((node) => node instanceof Element)
|
||||||
|
.filter((node) => claimed.includes(node))
|
||||||
|
.map((node) => node.id),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
assert.deepEqual(connections, { child: 1, custom: 1 });
|
||||||
|
assert.deepEqual(disconnections, []);
|
||||||
|
|
||||||
|
flushSync(() => {
|
||||||
|
component.tag = 'section';
|
||||||
|
component.empty_tag = 'span';
|
||||||
|
component.void_tag = 'hr';
|
||||||
|
component.custom_tag = 'aside';
|
||||||
|
});
|
||||||
|
assert.equal(target.querySelector('#parent')?.tagName, 'SECTION');
|
||||||
|
assert.equal(target.querySelector('#empty')?.tagName, 'SPAN');
|
||||||
|
assert.equal(target.querySelector('#void')?.tagName, 'HR');
|
||||||
|
assert.equal(target.querySelector('#custom')?.tagName, 'ASIDE');
|
||||||
|
assert.deepEqual(connections, { child: 2, custom: 1 });
|
||||||
|
assert.deepEqual(disconnections, ['child', 'custom']);
|
||||||
|
|
||||||
|
flushSync(() => {
|
||||||
|
component.tag = null;
|
||||||
|
});
|
||||||
|
assert.equal(target.querySelector('#parent'), null);
|
||||||
|
assert.deepEqual(disconnections, ['child', 'custom', 'child']);
|
||||||
|
|
||||||
|
flushSync(() => {
|
||||||
|
component.tag = 'div';
|
||||||
|
});
|
||||||
|
assert.equal(target.querySelector('#parent')?.tagName, 'DIV');
|
||||||
|
assert.deepEqual(connections, { child: 3, custom: 1 });
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
<script>
|
||||||
|
export let tag = 'div';
|
||||||
|
export let empty_tag = 'div';
|
||||||
|
export let void_tag = 'input';
|
||||||
|
export let custom_tag = 'connection-probe';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:element this={tag} id="parent"><connection-probe id="child"></connection-probe></svelte:element>
|
||||||
|
<svelte:element this={empty_tag} id="empty" />
|
||||||
|
<svelte:element this={void_tag} id="void" />
|
||||||
|
<svelte:element this={custom_tag} id="custom" />
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
import { flushSync } from 'svelte';
|
||||||
|
import { ok, test } from '../../assert';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
async test({ assert, target }) {
|
||||||
|
const input = target.querySelector('input');
|
||||||
|
ok(input);
|
||||||
|
|
||||||
|
input.focus();
|
||||||
|
|
||||||
|
// we need to use `document.execCommand('insertText', false, ...)` to simulate user input
|
||||||
|
// because directly setting an invalid value to `input.value` would simply clear the input
|
||||||
|
// and dispatching an event would not update the input correctly
|
||||||
|
document.execCommand('insertText', false, '1');
|
||||||
|
flushSync();
|
||||||
|
// `1e` is incomplete on every platform, unlike `1.` which Chromium on Linux accepts as `1`
|
||||||
|
document.execCommand('insertText', false, 'e');
|
||||||
|
flushSync();
|
||||||
|
|
||||||
|
assert.equal(input.value, '');
|
||||||
|
assert.equal(input.validity.badInput, true);
|
||||||
|
|
||||||
|
document.execCommand('insertText', false, '5');
|
||||||
|
flushSync();
|
||||||
|
|
||||||
|
assert.equal(input.value, '1e5');
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
<script>
|
||||||
|
let value = $state('');
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<input {...{ type: 'number', value }} oninput={(e) => (value = e.currentTarget.value)} />
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
import { test } from '../../test';
|
||||||
|
import { tick } from 'svelte';
|
||||||
|
|
||||||
|
export default test({
|
||||||
|
html: `<button>add y</button><button>delete y</button><p>false</p>`,
|
||||||
|
|
||||||
|
async test({ assert, target }) {
|
||||||
|
const [add, remove] = target.querySelectorAll('button');
|
||||||
|
|
||||||
|
add.click();
|
||||||
|
await tick();
|
||||||
|
assert.htmlEqual(
|
||||||
|
target.innerHTML,
|
||||||
|
`<button>add y</button><button>delete y</button><p>true</p>`
|
||||||
|
);
|
||||||
|
|
||||||
|
remove.click();
|
||||||
|
await tick();
|
||||||
|
assert.htmlEqual(
|
||||||
|
target.innerHTML,
|
||||||
|
`<button>add y</button><button>delete y</button><p>false</p>`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
<script>
|
||||||
|
let state = $state({});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button onclick={() => (state.y = true)}>add y</button>
|
||||||
|
<button onclick={() => delete state.y}>delete y</button>
|
||||||
|
<p>{Object.hasOwn(state, 'y')}</p>
|
||||||
Loading…
Reference in new issue