`/`` for a11y role checks
diff --git a/.changeset/forty-worlds-attack.md b/.changeset/forty-worlds-attack.md
deleted file mode 100644
index 52bb3644c0..0000000000
--- a/.changeset/forty-worlds-attack.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'svelte': patch
----
-
-fix: add vite-ignore comment inside dynamic crypto import
diff --git a/.changeset/loud-bottles-own.md b/.changeset/loud-bottles-own.md
deleted file mode 100644
index 493dc6c47f..0000000000
--- a/.changeset/loud-bottles-own.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'svelte': patch
----
-
-chore: wrap JSDoc URLs in `@see` and `@link` tags
diff --git a/.changeset/orange-ants-greet.md b/.changeset/orange-ants-greet.md
deleted file mode 100644
index 6f7c684fee..0000000000
--- a/.changeset/orange-ants-greet.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'svelte': minor
----
-
-feat: allow use of createContext when instantiating components programmatically
diff --git a/.changeset/poor-students-nail.md b/.changeset/poor-students-nail.md
deleted file mode 100644
index cee650c002..0000000000
--- a/.changeset/poor-students-nail.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"svelte": patch
----
-
-fix: properly hydrate already-resolved async blocks
diff --git a/.changeset/sharp-snakes-poke.md b/.changeset/sharp-snakes-poke.md
deleted file mode 100644
index 7f7f8aa7b2..0000000000
--- a/.changeset/sharp-snakes-poke.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'svelte': patch
----
-
-fix: emit `each_key_duplicate` error in production
diff --git a/.changeset/tiny-owls-pay.md b/.changeset/tiny-owls-pay.md
deleted file mode 100644
index ac25500258..0000000000
--- a/.changeset/tiny-owls-pay.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'svelte': patch
----
-
-fix: exit resolved async blocks on correct node when hydrating
diff --git a/.oxlintrc.json b/.oxlintrc.json
index f3cf53d67d..debe49a196 100644
--- a/.oxlintrc.json
+++ b/.oxlintrc.json
@@ -120,6 +120,7 @@
"coverage/**",
"playgrounds/sandbox/**",
"*.config.js",
+ "vitest-xhtml-environment.ts",
"documentation",
"tmp/**"
],
diff --git a/documentation/docs/03-template-syntax/09-@attach.md b/documentation/docs/03-template-syntax/09-@attach.md
index b25fbb32a6..8814ead487 100644
--- a/documentation/docs/03-template-syntax/09-@attach.md
+++ b/documentation/docs/03-template-syntax/09-@attach.md
@@ -82,6 +82,14 @@ Attachments can also be created inline ([demo](/playground/untitled#H4sIAAAAAAAA
> [!NOTE]
> The nested effect runs whenever `color` changes, while the outer effect (where `canvas.getContext(...)` is called) only runs once, since it doesn't read any reactive state.
+## Conditional attachments
+
+Falsy values like `false` or `undefined` are treated as no attachment, enabling conditional usage:
+
+```svelte
+
...
+```
+
## Passing attachments to components
When used on a component, `{@attach ...}` will create a prop whose key is a [`Symbol`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol). If the component then [spreads](/tutorial/svelte/spread-props) props onto an element, the element will receive those attachments.
diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md
index a71effd5dd..b251e778ef 100644
--- a/packages/svelte/CHANGELOG.md
+++ b/packages/svelte/CHANGELOG.md
@@ -1,5 +1,31 @@
# svelte
+## 5.50.0
+
+### Minor Changes
+
+- feat: allow use of createContext when instantiating components programmatically ([#17575](https://github.com/sveltejs/svelte/pull/17575))
+
+### Patch Changes
+
+- fix: ensure infinite effect loops are cleared after flushing ([#17601](https://github.com/sveltejs/svelte/pull/17601))
+
+- fix: allow `{#key NaN}` ([#17642](https://github.com/sveltejs/svelte/pull/17642))
+
+- fix: detect store in each block expression regardless of AST shape ([#17636](https://github.com/sveltejs/svelte/pull/17636))
+
+- fix: treat `
`/`` for a11y role checks ([#17638](https://github.com/sveltejs/svelte/pull/17638))
+
+- fix: add vite-ignore comment inside dynamic crypto import ([#17623](https://github.com/sveltejs/svelte/pull/17623))
+
+- chore: wrap JSDoc URLs in `@see` and `@link` tags ([#17617](https://github.com/sveltejs/svelte/pull/17617))
+
+- fix: properly hydrate already-resolved async blocks ([#17641](https://github.com/sveltejs/svelte/pull/17641))
+
+- fix: emit `each_key_duplicate` error in production ([#16724](https://github.com/sveltejs/svelte/pull/16724))
+
+- fix: exit resolved async blocks on correct node when hydrating ([#17640](https://github.com/sveltejs/svelte/pull/17640))
+
## 5.49.2
### Patch Changes
diff --git a/packages/svelte/package.json b/packages/svelte/package.json
index 48f492783f..82d0d1a8ed 100644
--- a/packages/svelte/package.json
+++ b/packages/svelte/package.json
@@ -2,7 +2,7 @@
"name": "svelte",
"description": "Cybernetically enhanced web apps",
"license": "MIT",
- "version": "5.49.2",
+ "version": "5.50.0",
"type": "module",
"types": "./types/index.d.ts",
"engines": {
diff --git a/packages/svelte/src/version.js b/packages/svelte/src/version.js
index 31538c3fe7..3aefb2e1f6 100644
--- a/packages/svelte/src/version.js
+++ b/packages/svelte/src/version.js
@@ -4,5 +4,5 @@
* The current version, as set in package.json.
* @type {string}
*/
-export const VERSION = '5.49.2';
+export const VERSION = '5.50.0';
export const PUBLIC_VERSION = '5';
diff --git a/packages/svelte/tests/html_equal.js b/packages/svelte/tests/html_equal.js
index 76a4a957a5..cdb8f52e37 100644
--- a/packages/svelte/tests/html_equal.js
+++ b/packages/svelte/tests/html_equal.js
@@ -9,7 +9,9 @@ function clean_children(node, opts) {
let previous = null;
let has_element_children = false;
let template =
- node.nodeName === 'TEMPLATE' ? /** @type {HTMLTemplateElement} */ (node) : undefined;
+ node.nodeName.toUpperCase() === 'TEMPLATE'
+ ? /** @type {HTMLTemplateElement} */ (node)
+ : undefined;
if (template) {
const div = document.createElement('div');
@@ -23,22 +25,20 @@ function clean_children(node, opts) {
});
attributes.forEach((attr) => {
- node.removeAttribute(attr.name);
+ if (attr.name !== 'xmlns') node.removeAttribute(attr.name);
});
- attributes.forEach((attr) => {
+ attributes.forEach(({ name, value }) => {
// Strip out the special onload/onerror hydration events from the test output
- if ((attr.name === 'onload' || attr.name === 'onerror') && attr.value === 'this.__e=event') {
+ if (['onload', 'onerror', 'xmlns'].includes(name) && value === 'this.__e=event') {
return;
}
- let value = attr.value;
-
- if (attr.name === 'class') {
+ if (name === 'class') {
value = value.replace(/svelte-\w+/, 'svelte-xyz123');
}
- node.setAttribute(attr.name, value);
+ node.setAttribute(name, value);
});
for (let child of [...node.childNodes]) {
diff --git a/packages/svelte/tests/runtime-xhtml/samples/attribute-quotes/_config.js b/packages/svelte/tests/runtime-xhtml/samples/attribute-quotes/_config.js
new file mode 100644
index 0000000000..f47bee71df
--- /dev/null
+++ b/packages/svelte/tests/runtime-xhtml/samples/attribute-quotes/_config.js
@@ -0,0 +1,3 @@
+import { test } from '../../test';
+
+export default test({});
diff --git a/packages/svelte/tests/runtime-xhtml/samples/attribute-quotes/main.svelte b/packages/svelte/tests/runtime-xhtml/samples/attribute-quotes/main.svelte
new file mode 100644
index 0000000000..82db611c12
--- /dev/null
+++ b/packages/svelte/tests/runtime-xhtml/samples/attribute-quotes/main.svelte
@@ -0,0 +1,2 @@
+
+
diff --git a/packages/svelte/tests/runtime-xhtml/samples/autoclosed-tags/_config.js b/packages/svelte/tests/runtime-xhtml/samples/autoclosed-tags/_config.js
new file mode 100644
index 0000000000..f47bee71df
--- /dev/null
+++ b/packages/svelte/tests/runtime-xhtml/samples/autoclosed-tags/_config.js
@@ -0,0 +1,3 @@
+import { test } from '../../test';
+
+export default test({});
diff --git a/packages/svelte/tests/runtime-xhtml/samples/autoclosed-tags/main.svelte b/packages/svelte/tests/runtime-xhtml/samples/autoclosed-tags/main.svelte
new file mode 100644
index 0000000000..18a4463ce1
--- /dev/null
+++ b/packages/svelte/tests/runtime-xhtml/samples/autoclosed-tags/main.svelte
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/packages/svelte/tests/runtime-xhtml/samples/boolean-attributes/_config.js b/packages/svelte/tests/runtime-xhtml/samples/boolean-attributes/_config.js
new file mode 100644
index 0000000000..f965e04b02
--- /dev/null
+++ b/packages/svelte/tests/runtime-xhtml/samples/boolean-attributes/_config.js
@@ -0,0 +1,5 @@
+import { test } from '../../test';
+
+export default test({
+ skip: true
+});
diff --git a/packages/svelte/tests/runtime-xhtml/samples/boolean-attributes/main.svelte b/packages/svelte/tests/runtime-xhtml/samples/boolean-attributes/main.svelte
new file mode 100644
index 0000000000..3d2fc88d10
--- /dev/null
+++ b/packages/svelte/tests/runtime-xhtml/samples/boolean-attributes/main.svelte
@@ -0,0 +1 @@
+
diff --git a/packages/svelte/tests/runtime-xhtml/samples/comment-marker/_config.js b/packages/svelte/tests/runtime-xhtml/samples/comment-marker/_config.js
new file mode 100644
index 0000000000..f47bee71df
--- /dev/null
+++ b/packages/svelte/tests/runtime-xhtml/samples/comment-marker/_config.js
@@ -0,0 +1,3 @@
+import { test } from '../../test';
+
+export default test({});
diff --git a/packages/svelte/tests/runtime-xhtml/samples/comment-marker/main.svelte b/packages/svelte/tests/runtime-xhtml/samples/comment-marker/main.svelte
new file mode 100644
index 0000000000..8dd87ce81e
--- /dev/null
+++ b/packages/svelte/tests/runtime-xhtml/samples/comment-marker/main.svelte
@@ -0,0 +1 @@
+{#each [1,2] as i}{i}{/each}
diff --git a/packages/svelte/tests/runtime-xhtml/samples/is-xhtml/_config.js b/packages/svelte/tests/runtime-xhtml/samples/is-xhtml/_config.js
new file mode 100644
index 0000000000..52dddb4ad7
--- /dev/null
+++ b/packages/svelte/tests/runtime-xhtml/samples/is-xhtml/_config.js
@@ -0,0 +1,8 @@
+import { test } from '../../test';
+
+export default test({
+ mode: ['client'],
+ test({ assert, target }) {
+ assert.htmlEqual(target.innerHTML, `