diff --git a/packages/svelte/src/compiler/phases/1-parse/state/element.js b/packages/svelte/src/compiler/phases/1-parse/state/element.js
index d94d8180e7a9..7e75b3a3b0e9 100644
--- a/packages/svelte/src/compiler/phases/1-parse/state/element.js
+++ b/packages/svelte/src/compiler/phases/1-parse/state/element.js
@@ -151,7 +151,8 @@ export default function element(parser) {
svg: false,
mathml: false,
scoped: false,
- has_spread: false
+ has_spread: false,
+ auto_opens: null
},
parent: null
}
diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js
index d004da04110b..eaea0390f206 100644
--- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js
+++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js
@@ -281,6 +281,10 @@ export function RegularElement(node, context) {
context.state.template.push('>');
+ if (node.metadata.auto_opens !== null) {
+ context.state.template.push(node.metadata.auto_opens);
+ }
+
/** @type {SourceLocation[]} */
const child_locations = [];
@@ -347,10 +351,21 @@ export function RegularElement(node, context) {
arg = b.member(arg, 'content');
}
- process_children(trimmed, () => b.call('$.child', arg), true, {
- ...context,
- state: child_state
- });
+ process_children(
+ trimmed, // TODO: this doesn't work when the table is a sibling, as the expression is then not used
+ () => {
+ let call = b.call('$.child', arg);
+ for (let i = (node.metadata.auto_opens?.split('<').length ?? 1) - 1; i > 0; i--) {
+ call = b.call('$.child', call);
+ }
+ return call;
+ },
+ true,
+ {
+ ...context,
+ state: child_state
+ }
+ );
if (needs_reset) {
child_state.init.push(b.stmt(b.call('$.reset', context.state.node)));
diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/RegularElement.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/RegularElement.js
index af50695efa62..b55b131e69be 100644
--- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/RegularElement.js
+++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/RegularElement.js
@@ -37,6 +37,10 @@ export function RegularElement(node, context) {
return;
}
+ if (node.metadata.auto_opens !== null) {
+ context.state.template.push(b.literal(node.metadata.auto_opens));
+ }
+
const { hoisted, trimmed } = clean_nodes(
node,
node.fragment.nodes,
diff --git a/packages/svelte/src/compiler/types/template.d.ts b/packages/svelte/src/compiler/types/template.d.ts
index 9da0320432d4..52f0b51db954 100644
--- a/packages/svelte/src/compiler/types/template.d.ts
+++ b/packages/svelte/src/compiler/types/template.d.ts
@@ -302,7 +302,10 @@ export namespace AST {
mathml: boolean;
/** `true` if contains a SpreadAttribute */
has_spread: boolean;
+ /** `true` if should get a hash on the `class` attribute */
scoped: boolean;
+ /** Contains a string of the tag(s) that are implicitly opened after this element */
+ auto_opens: string | null;
};
}
diff --git a/packages/svelte/tests/runtime-runes/samples/invalid-html-table-autorepair/_config.js b/packages/svelte/tests/runtime-runes/samples/invalid-html-table-autorepair/_config.js
new file mode 100644
index 000000000000..7fd3ad36aa91
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/invalid-html-table-autorepair/_config.js
@@ -0,0 +1,57 @@
+import { test } from '../../test';
+
+let console_error = console.error;
+
+/**
+ * @type {any[]}
+ */
+const log = [];
+
+export default test({
+ solo: true,
+ compileOptions: {
+ dev: true // enable validation to ensure it doesn't throw
+ },
+
+ html: `
+
+
+
+
+
+ | works2 |
+
+
+ | works3 |
+
+
+
+
+
+
+
+ | works4 |
+
+
+
+
+ | works5 |
+
+
+
+
+
+`
+});
diff --git a/packages/svelte/tests/runtime-runes/samples/invalid-html-table-autorepair/main.svelte b/packages/svelte/tests/runtime-runes/samples/invalid-html-table-autorepair/main.svelte
new file mode 100644
index 000000000000..0465cc2719d8
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/invalid-html-table-autorepair/main.svelte
@@ -0,0 +1,28 @@
+
+
+
+ {#each ['works2', 'works3'] as cell}
+
+ | {cell} |
+
+ {/each}
+
+
+
+
+ | works4 |
+
+
+
+ | works5 |
+
+
+
+
+