diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures.spec.ts b/packages/@lwc/engine-server/src/__tests__/fixtures.spec.ts
index 3c542787c5..0889ac7a4a 100755
--- a/packages/@lwc/engine-server/src/__tests__/fixtures.spec.ts
+++ b/packages/@lwc/engine-server/src/__tests__/fixtures.spec.ts
@@ -80,7 +80,9 @@ async function compileFixture({
// IGNORED_SLOT_ATTRIBUTE_IN_CHILD is fine; it is used in some of these tests
message.includes('LWC1201') ||
message.includes('-h-t-m-l') ||
- code === 'CIRCULAR_DEPENDENCY';
+ code === 'CIRCULAR_DEPENDENCY' ||
+ // TODO [#5010]: template-compiler -> index -> validateElement generates UNKNOWN_HTML_TAG_IN_TEMPLATE for MathML elements
+ message.includes('LWC1123');
if (!shouldIgnoreWarning) {
throw new Error(message);
}
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/render-correct-tags/error.txt b/packages/@lwc/engine-server/src/__tests__/fixtures/render-correct-tags/error.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/render-correct-tags/expected.html b/packages/@lwc/engine-server/src/__tests__/fixtures/render-correct-tags/expected.html
new file mode 100644
index 0000000000..862326ccfa
--- /dev/null
+++ b/packages/@lwc/engine-server/src/__tests__/fixtures/render-correct-tags/expected.html
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/render-correct-tags/index.js b/packages/@lwc/engine-server/src/__tests__/fixtures/render-correct-tags/index.js
new file mode 100644
index 0000000000..99eaa6cf88
--- /dev/null
+++ b/packages/@lwc/engine-server/src/__tests__/fixtures/render-correct-tags/index.js
@@ -0,0 +1,3 @@
+export const tagName = 'x-elements';
+export { default } from 'x/elements';
+export * from 'x/elements';
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/render-correct-tags/modules/x/elements/elements.html b/packages/@lwc/engine-server/src/__tests__/fixtures/render-correct-tags/modules/x/elements/elements.html
new file mode 100644
index 0000000000..00c96652f4
--- /dev/null
+++ b/packages/@lwc/engine-server/src/__tests__/fixtures/render-correct-tags/modules/x/elements/elements.html
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/render-correct-tags/modules/x/elements/elements.js b/packages/@lwc/engine-server/src/__tests__/fixtures/render-correct-tags/modules/x/elements/elements.js
new file mode 100644
index 0000000000..c9952ab5c6
--- /dev/null
+++ b/packages/@lwc/engine-server/src/__tests__/fixtures/render-correct-tags/modules/x/elements/elements.js
@@ -0,0 +1,5 @@
+import { LightningElement, api } from 'lwc';
+
+export default class extends LightningElement {
+ @api foreignNamespaceInnerHtml = '';
+}
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/render-correct-tags/modules/x/elements/elements.scoped.css b/packages/@lwc/engine-server/src/__tests__/fixtures/render-correct-tags/modules/x/elements/elements.scoped.css
new file mode 100644
index 0000000000..dd8d0c84a6
--- /dev/null
+++ b/packages/@lwc/engine-server/src/__tests__/fixtures/render-correct-tags/modules/x/elements/elements.scoped.css
@@ -0,0 +1,3 @@
+:host {
+ background: blue;
+}
diff --git a/packages/@lwc/ssr-compiler/src/__tests__/utils/expected-failures.ts b/packages/@lwc/ssr-compiler/src/__tests__/utils/expected-failures.ts
index ac9356a663..ae70963c5f 100644
--- a/packages/@lwc/ssr-compiler/src/__tests__/utils/expected-failures.ts
+++ b/packages/@lwc/ssr-compiler/src/__tests__/utils/expected-failures.ts
@@ -14,7 +14,6 @@ export const expectedFailures = new Set([
'attribute-component-global-html/index.js',
'attribute-global-html/as-component-prop/undeclared/index.js',
'attribute-global-html/as-component-prop/without-@api/index.js',
- 'attribute-namespace/index.js',
'attribute-style/basic/index.js',
'attribute-style/dynamic/index.js',
'exports/component-as-default/index.js',
@@ -35,7 +34,6 @@ export const expectedFailures = new Set([
'superclass/render-in-superclass/no-template-in-subclass/index.js',
'superclass/render-in-superclass/unused-default-in-subclass/index.js',
'superclass/render-in-superclass/unused-default-in-superclass/index.js',
- 'svgs/index.js',
'wire/errors/throws-on-computed-key/index.js',
'wire/errors/throws-when-colliding-prop-then-method/index.js',
'wire/errors/throws-when-computed-prop-is-expression/index.js',
diff --git a/packages/@lwc/ssr-compiler/src/compile-template/transformers/element.ts b/packages/@lwc/ssr-compiler/src/compile-template/transformers/element.ts
index 7c39a30d1a..b41fd77360 100644
--- a/packages/@lwc/ssr-compiler/src/compile-template/transformers/element.ts
+++ b/packages/@lwc/ssr-compiler/src/compile-template/transformers/element.ts
@@ -227,10 +227,6 @@ export const Element: Transformer = fu
return result;
});
- if (isVoidElement(node.name, HTML_NAMESPACE)) {
- return [bYield(b.literal(`<${node.name}`)), ...yieldAttrsAndProps, bYield(b.literal(`>`))];
- }
-
let childContent: EsStatement[];
// An element can have children or lwc:inner-html, but not both
// If it has both, the template compiler will throw an error before reaching here
@@ -246,13 +242,17 @@ export const Element: Transformer = fu
childContent = [];
}
+ const isForeignSelfClosingElement =
+ node.namespace !== HTML_NAMESPACE && childContent.length === 0;
+ const isSelfClosingElement =
+ isVoidElement(node.name, HTML_NAMESPACE) || isForeignSelfClosingElement;
+
return [
bYield(b.literal(`<${node.name}`)),
// If we haven't already prefixed the scope token to an existing class, add an explicit class here
...(hasClassAttribute ? [] : [bConditionallyYieldScopeTokenClass()]),
...yieldAttrsAndProps,
- bYield(b.literal(`>`)),
- ...childContent,
- bYield(b.literal(`${node.name}>`)),
+ bYield(b.literal(isForeignSelfClosingElement ? `/>` : `>`)),
+ ...(isSelfClosingElement ? [] : [...childContent, bYield(b.literal(`${node.name}>`))]),
].filter(Boolean);
};