diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/attribute-class/with-scoped-styles-only-in-child/dynamic/expected.html b/packages/@lwc/engine-server/src/__tests__/fixtures/attribute-class/with-scoped-styles-only-in-child/dynamic/expected.html index 9627366d70..981f56e801 100644 --- a/packages/@lwc/engine-server/src/__tests__/fixtures/attribute-class/with-scoped-styles-only-in-child/dynamic/expected.html +++ b/packages/@lwc/engine-server/src/__tests__/fixtures/attribute-class/with-scoped-styles-only-in-child/dynamic/expected.html @@ -221,5 +221,18 @@ + + + \ No newline at end of file diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/attribute-class/with-scoped-styles-only-in-child/dynamic/modules/x/parent/parent.html b/packages/@lwc/engine-server/src/__tests__/fixtures/attribute-class/with-scoped-styles-only-in-child/dynamic/modules/x/parent/parent.html index ceb3187e70..6589394e6a 100644 --- a/packages/@lwc/engine-server/src/__tests__/fixtures/attribute-class/with-scoped-styles-only-in-child/dynamic/modules/x/parent/parent.html +++ b/packages/@lwc/engine-server/src/__tests__/fixtures/attribute-class/with-scoped-styles-only-in-child/dynamic/modules/x/parent/parent.html @@ -16,4 +16,5 @@ + diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/attribute-class/with-scoped-styles-only-in-child/dynamic/modules/x/parent/parent.js b/packages/@lwc/engine-server/src/__tests__/fixtures/attribute-class/with-scoped-styles-only-in-child/dynamic/modules/x/parent/parent.js index 879d633a22..611eb57566 100644 --- a/packages/@lwc/engine-server/src/__tests__/fixtures/attribute-class/with-scoped-styles-only-in-child/dynamic/modules/x/parent/parent.js +++ b/packages/@lwc/engine-server/src/__tests__/fixtures/attribute-class/with-scoped-styles-only-in-child/dynamic/modules/x/parent/parent.js @@ -21,4 +21,7 @@ export default class extends LightningElement { isUppercase = 'FOO BaR'; isTabs = '\tfoo\t'; isNewlines = '\nfoo\n'; + // Skipping `>` because it messes up `formatHTML()`, and the important thing is checking + // that we are calling `htmlEscape()` in attribute mode, so checking `<` is sufficient. + hasEscapableCharacters = `"'<&`; } 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 4c95be787f..176201c883 100644 --- a/packages/@lwc/ssr-compiler/src/__tests__/utils/expected-failures.ts +++ b/packages/@lwc/ssr-compiler/src/__tests__/utils/expected-failures.ts @@ -8,8 +8,6 @@ // We should slowly drive down these test failures or at least document where we expect the failures // TODO [#4815]: enable all SSR v2 tests export const expectedFailures = new Set([ - 'attribute-class/with-scoped-styles-only-in-child/dynamic/index.js', - 'attribute-class/with-scoped-styles/dynamic/index.js', 'attribute-global-html/as-component-prop/undeclared/index.js', 'attribute-global-html/as-component-prop/without-@api/index.js', 'exports/component-as-default/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 84f8f8dfba..66341e2355 100644 --- a/packages/@lwc/ssr-compiler/src/compile-template/transformers/element.ts +++ b/packages/@lwc/ssr-compiler/src/compile-template/transformers/element.ts @@ -81,9 +81,17 @@ const bYieldClassDynamicValue = esTemplateWithYield` const attrValue = normalizeClass(${/* attribute value expression */ is.expression}); const shouldRenderScopeToken = hasScopedStylesheets || hasScopedStaticStylesheets(Cmp); + // Concatenate the scope token with the class attribute value as necessary. + // If either is missing, render the other alone. + let combinedValue = shouldRenderScopeToken ? stylesheetScopeToken : ''; if (attrValue) { - const prefix = shouldRenderScopeToken ? stylesheetScopeToken + ' ' : ''; - yield \` class="\${prefix}\${htmlEscape(String(attrValue), true)}"\`; + if (combinedValue) { + combinedValue += ' '; + } + combinedValue += htmlEscape(String(attrValue), true); + } + if (combinedValue) { + yield \` class="\${combinedValue}"\`; } } `;