From ee2edae09f6e080ccc92703864a463e31b4bb3b3 Mon Sep 17 00:00:00 2001
From: jhefferman-sfdc <83669775+jhefferman-sfdc@users.noreply.github.com>
Date: Tue, 10 Dec 2024 09:48:59 -0700
Subject: [PATCH] fix(ssr): correctly render foreign namespace element closing
tags (#4992)
* fix: correctly render foreign element closing tags
* fix: properly handle scoped class for void and foreign elements
* fix: address review comments
* fix: remove math example for now
* fix: ignore UNKNOWN_HTML_TAG_IN_TEMPLATE warning to allow for MathML test
* fix: update tag warning suppression to reference issue
* fix: simpler MathML example
---
.../src/__tests__/fixtures.spec.ts | 4 +-
.../fixtures/render-correct-tags/error.txt | 0
.../render-correct-tags/expected.html | 39 +++++++++++++++++++
.../fixtures/render-correct-tags/index.js | 3 ++
.../modules/x/elements/elements.html | 30 ++++++++++++++
.../modules/x/elements/elements.js | 5 +++
.../modules/x/elements/elements.scoped.css | 3 ++
.../src/__tests__/utils/expected-failures.ts | 2 -
.../compile-template/transformers/element.ts | 14 +++----
9 files changed, 90 insertions(+), 10 deletions(-)
create mode 100644 packages/@lwc/engine-server/src/__tests__/fixtures/render-correct-tags/error.txt
create mode 100644 packages/@lwc/engine-server/src/__tests__/fixtures/render-correct-tags/expected.html
create mode 100644 packages/@lwc/engine-server/src/__tests__/fixtures/render-correct-tags/index.js
create mode 100644 packages/@lwc/engine-server/src/__tests__/fixtures/render-correct-tags/modules/x/elements/elements.html
create mode 100644 packages/@lwc/engine-server/src/__tests__/fixtures/render-correct-tags/modules/x/elements/elements.js
create mode 100644 packages/@lwc/engine-server/src/__tests__/fixtures/render-correct-tags/modules/x/elements/elements.scoped.css
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 f0c45d0a3d..6902462327 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',
@@ -32,7 +31,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);
};