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; }
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
<svelte:head><meta name="x" content="y" /></svelte:head>
|
||||
|
||||
<style>
|
||||
:export { foo: red; }
|
||||
:is(:global(td), :global(th)) { color: red; }
|
||||
</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