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 ce2037c3a3..9c410df499 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
@@ -17,7 +17,7 @@
-
+
@@ -29,7 +29,7 @@
-
+
@@ -41,7 +41,7 @@
-
+
@@ -53,7 +53,7 @@
-
+
@@ -65,7 +65,7 @@
-
+
@@ -77,7 +77,7 @@
-
+
@@ -89,7 +89,7 @@
-
+
@@ -101,7 +101,7 @@
-
+
@@ -113,7 +113,7 @@
-
+
@@ -125,7 +125,7 @@
-
+
@@ -137,7 +137,7 @@
-
+
@@ -149,7 +149,7 @@
-
+
@@ -161,7 +161,7 @@
-
+
@@ -173,7 +173,7 @@
-
+
@@ -185,7 +185,7 @@
-
+
@@ -197,7 +197,7 @@
-
+
@@ -209,7 +209,7 @@
-
+
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/attribute-class/with-scoped-styles-only-in-child/static/expected.html b/packages/@lwc/engine-server/src/__tests__/fixtures/attribute-class/with-scoped-styles-only-in-child/static/expected.html
index cab0de7c37..9031b13e0a 100644
--- a/packages/@lwc/engine-server/src/__tests__/fixtures/attribute-class/with-scoped-styles-only-in-child/static/expected.html
+++ b/packages/@lwc/engine-server/src/__tests__/fixtures/attribute-class/with-scoped-styles-only-in-child/static/expected.html
@@ -13,7 +13,7 @@
-
+
@@ -21,7 +21,7 @@
-
+
@@ -29,7 +29,7 @@
-
+
@@ -37,7 +37,7 @@
-
+
@@ -45,7 +45,7 @@
-
+
@@ -53,7 +53,7 @@
-
+
@@ -61,7 +61,7 @@
-
+
@@ -69,7 +69,7 @@
-
+
@@ -77,7 +77,7 @@
-
+
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/attribute-class/with-scoped-styles/dynamic/expected.html b/packages/@lwc/engine-server/src/__tests__/fixtures/attribute-class/with-scoped-styles/dynamic/expected.html
index 2d2fe174c0..ab4c66fc72 100644
--- a/packages/@lwc/engine-server/src/__tests__/fixtures/attribute-class/with-scoped-styles/dynamic/expected.html
+++ b/packages/@lwc/engine-server/src/__tests__/fixtures/attribute-class/with-scoped-styles/dynamic/expected.html
@@ -27,13 +27,13 @@
-
+
-
+
@@ -41,13 +41,13 @@
-
+
-
+
@@ -55,13 +55,13 @@
-
+
-
+
@@ -69,13 +69,13 @@
-
+
-
+
@@ -83,13 +83,13 @@
-
+
-
+
@@ -97,13 +97,13 @@
-
+
-
+
@@ -111,13 +111,13 @@
-
+
-
+
@@ -125,13 +125,13 @@
-
+
-
+
@@ -139,13 +139,13 @@
-
+
-
+
@@ -153,13 +153,13 @@
-
+
-
+
@@ -167,13 +167,13 @@
-
+
-
+
@@ -181,13 +181,13 @@
-
+
-
+
@@ -195,13 +195,13 @@
-
+
-
+
@@ -209,13 +209,13 @@
-
+
-
+
@@ -223,13 +223,13 @@
-
+
-
+
@@ -237,13 +237,13 @@
-
+
-
+
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/attribute-class/with-scoped-styles/static/expected.html b/packages/@lwc/engine-server/src/__tests__/fixtures/attribute-class/with-scoped-styles/static/expected.html
index 7e9e5c654e..b7c8d32b85 100644
--- a/packages/@lwc/engine-server/src/__tests__/fixtures/attribute-class/with-scoped-styles/static/expected.html
+++ b/packages/@lwc/engine-server/src/__tests__/fixtures/attribute-class/with-scoped-styles/static/expected.html
@@ -16,55 +16,55 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/packages/@lwc/integration-karma/helpers/test-hydrate.js b/packages/@lwc/integration-karma/helpers/test-hydrate.js
index c9e7bdd492..ab26c9257d 100644
--- a/packages/@lwc/integration-karma/helpers/test-hydrate.js
+++ b/packages/@lwc/integration-karma/helpers/test-hydrate.js
@@ -10,6 +10,8 @@ window.HydrateTest = (function (lwc, testUtils) {
sanitizeHtmlContent: (content) => content,
});
+ window.LwcSsrClientUtils.registerLwcStyleComponent();
+
function parseStringToDom(html) {
return Document.parseHTMLUnsafe(html).body.firstChild;
}
@@ -31,6 +33,7 @@ window.HydrateTest = (function (lwc, testUtils) {
}
function runTest(ssrRendered, Component, testConfig) {
+ window.__lwcClearStylesheetCache();
const container = appendTestTarget(ssrRendered);
const selector = container.firstChild.tagName.toLowerCase();
let target = container.querySelector(selector);
diff --git a/packages/@lwc/integration-karma/scripts/karma-configs/hydration/base.js b/packages/@lwc/integration-karma/scripts/karma-configs/hydration/base.js
index b4316eb0cc..2109126880 100644
--- a/packages/@lwc/integration-karma/scripts/karma-configs/hydration/base.js
+++ b/packages/@lwc/integration-karma/scripts/karma-configs/hydration/base.js
@@ -23,12 +23,13 @@ const COVERAGE_DIR = path.resolve(__dirname, '../../../coverage');
const SYNTHETIC_SHADOW = require.resolve('@lwc/synthetic-shadow/dist/index.js');
const LWC_ENGINE = require.resolve('@lwc/engine-dom/dist/index.js');
+const SSR_CLIENT_UTILS = require.resolve('@lwc/ssr-client-utils/dist/index.js');
const TEST_UTILS = require.resolve('../../../helpers/test-utils');
const TEST_SETUP = require.resolve('../../../helpers/test-setup');
const TEST_HYDRATE = require.resolve('../../../helpers/test-hydrate');
-const ALL_FRAMEWORK_FILES = [SYNTHETIC_SHADOW, LWC_ENGINE];
+const ALL_FRAMEWORK_FILES = [SYNTHETIC_SHADOW, LWC_ENGINE, SSR_CLIENT_UTILS];
// Fix Node warning about >10 event listeners ("Possible EventEmitter memory leak detected").
// This is due to the fact that we are running so many simultaneous rollup commands
@@ -40,6 +41,7 @@ function getFiles() {
const files = [
...(ENABLE_SYNTHETIC_SHADOW_IN_HYDRATION ? [createPattern(SYNTHETIC_SHADOW)] : []),
createPattern(LWC_ENGINE),
+ createPattern(SSR_CLIENT_UTILS),
createPattern(TEST_SETUP),
createPattern(TEST_UTILS),
createPattern(TEST_HYDRATE),
diff --git a/packages/@lwc/integration-karma/scripts/karma-plugins/hydration-tests.js b/packages/@lwc/integration-karma/scripts/karma-plugins/hydration-tests.js
index f46fbee3a2..7a5d1cad1a 100644
--- a/packages/@lwc/integration-karma/scripts/karma-plugins/hydration-tests.js
+++ b/packages/@lwc/integration-karma/scripts/karma-plugins/hydration-tests.js
@@ -77,7 +77,13 @@ async function getCompiledModule(dirName, compileForSSR) {
}),
],
- external: ['lwc', '@lwc/ssr-runtime', 'test-utils', '@test/loader'], // @todo: add ssr modules for test-utils and @test/loader
+ external: [
+ 'lwc',
+ '@lwc/ssr-runtime',
+ 'test-utils',
+ '@test/loader',
+ '@lwc/ssr-client-utils',
+ ], // @todo: add ssr modules for test-utils and @test/loader
onwarn(warning, warn) {
// Ignore warnings from our own Rollup plugin
@@ -96,6 +102,7 @@ async function getCompiledModule(dirName, compileForSSR) {
lwc: 'LWC',
'@lwc/ssr-runtime': 'LWC',
'test-utils': 'TestUtils',
+ '@lwc/ssr-client-utils': 'LwcSsrClientUtils',
},
});
@@ -156,7 +163,7 @@ async function getSsrCode(moduleCode, testConfig, filename, expectedSSRConsoleCa
'x-${COMPONENT_UNDER_TEST}-${guid++}',
Main,
config.props || {},
- false,
+ true,
'sync'
);
`,
diff --git a/packages/@lwc/integration-karma/scripts/karma-plugins/transform-framework.js b/packages/@lwc/integration-karma/scripts/karma-plugins/transform-framework.js
index 85b2f15ee9..ce3863cafd 100644
--- a/packages/@lwc/integration-karma/scripts/karma-plugins/transform-framework.js
+++ b/packages/@lwc/integration-karma/scripts/karma-plugins/transform-framework.js
@@ -26,6 +26,8 @@ function getIifeName(filename) {
} else if (filename.includes('aria-reflection')) {
// aria reflection global polyfill does not need an IIFE name
return undefined;
+ } else if (filename.includes('@lwc/ssr-client-utils')) {
+ return 'LwcSsrClientUtils';
}
throw new Error(`Unknown framework filename, not sure which IIFE name to use: ${filename}`);
}
diff --git a/packages/@lwc/integration-karma/test-hydration/light-dom/scoped-styles/deduped-scoped-styles/index.spec.js b/packages/@lwc/integration-karma/test-hydration/light-dom/scoped-styles/deduped-scoped-styles/index.spec.js
new file mode 100644
index 0000000000..84218066a9
--- /dev/null
+++ b/packages/@lwc/integration-karma/test-hydration/light-dom/scoped-styles/deduped-scoped-styles/index.spec.js
@@ -0,0 +1,9 @@
+export default {
+ test(target, snapshot, consoleCalls) {
+ // W-19087941: Expect no errors or warnings, hydration or otherwise
+ TestUtils.expectConsoleCalls(consoleCalls, {
+ error: [],
+ warn: [],
+ });
+ },
+};
diff --git a/packages/@lwc/integration-karma/test-hydration/light-dom/scoped-styles/deduped-scoped-styles/x/child/child.html b/packages/@lwc/integration-karma/test-hydration/light-dom/scoped-styles/deduped-scoped-styles/x/child/child.html
new file mode 100644
index 0000000000..6f06182f35
--- /dev/null
+++ b/packages/@lwc/integration-karma/test-hydration/light-dom/scoped-styles/deduped-scoped-styles/x/child/child.html
@@ -0,0 +1,3 @@
+
+ child content
+
diff --git a/packages/@lwc/integration-karma/test-hydration/light-dom/scoped-styles/deduped-scoped-styles/x/child/child.js b/packages/@lwc/integration-karma/test-hydration/light-dom/scoped-styles/deduped-scoped-styles/x/child/child.js
new file mode 100644
index 0000000000..0679d2bc10
--- /dev/null
+++ b/packages/@lwc/integration-karma/test-hydration/light-dom/scoped-styles/deduped-scoped-styles/x/child/child.js
@@ -0,0 +1,5 @@
+import { LightningElement } from 'lwc';
+
+export default class extends LightningElement {
+ static renderMode = 'light';
+}
diff --git a/packages/@lwc/integration-karma/test-hydration/light-dom/scoped-styles/deduped-scoped-styles/x/child/child.scoped.css b/packages/@lwc/integration-karma/test-hydration/light-dom/scoped-styles/deduped-scoped-styles/x/child/child.scoped.css
new file mode 100644
index 0000000000..72e32daf4d
--- /dev/null
+++ b/packages/@lwc/integration-karma/test-hydration/light-dom/scoped-styles/deduped-scoped-styles/x/child/child.scoped.css
@@ -0,0 +1,3 @@
+.blue {
+ background-color: blue;
+}
diff --git a/packages/@lwc/integration-karma/test-hydration/light-dom/scoped-styles/deduped-scoped-styles/x/main/main.css b/packages/@lwc/integration-karma/test-hydration/light-dom/scoped-styles/deduped-scoped-styles/x/main/main.css
new file mode 100644
index 0000000000..edb1d0fb9d
--- /dev/null
+++ b/packages/@lwc/integration-karma/test-hydration/light-dom/scoped-styles/deduped-scoped-styles/x/main/main.css
@@ -0,0 +1,3 @@
+.main {
+ color: red;
+}
diff --git a/packages/@lwc/integration-karma/test-hydration/light-dom/scoped-styles/deduped-scoped-styles/x/main/main.html b/packages/@lwc/integration-karma/test-hydration/light-dom/scoped-styles/deduped-scoped-styles/x/main/main.html
new file mode 100644
index 0000000000..9b2366dfc3
--- /dev/null
+++ b/packages/@lwc/integration-karma/test-hydration/light-dom/scoped-styles/deduped-scoped-styles/x/main/main.html
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/packages/@lwc/integration-karma/test-hydration/light-dom/scoped-styles/deduped-scoped-styles/x/main/main.js b/packages/@lwc/integration-karma/test-hydration/light-dom/scoped-styles/deduped-scoped-styles/x/main/main.js
new file mode 100644
index 0000000000..0679d2bc10
--- /dev/null
+++ b/packages/@lwc/integration-karma/test-hydration/light-dom/scoped-styles/deduped-scoped-styles/x/main/main.js
@@ -0,0 +1,5 @@
+import { LightningElement } from 'lwc';
+
+export default class extends LightningElement {
+ static renderMode = 'light';
+}
diff --git a/packages/@lwc/integration-karma/test-hydration/light-dom/scoped-styles/nested-scoped-styles/child-scoped-styles/x/main/main.html b/packages/@lwc/integration-karma/test-hydration/light-dom/scoped-styles/nested-scoped-styles/child-scoped-styles/x/main/main.html
index 586e14e39f..2d69fe28ac 100644
--- a/packages/@lwc/integration-karma/test-hydration/light-dom/scoped-styles/nested-scoped-styles/child-scoped-styles/x/main/main.html
+++ b/packages/@lwc/integration-karma/test-hydration/light-dom/scoped-styles/nested-scoped-styles/child-scoped-styles/x/main/main.html
@@ -1,3 +1,3 @@
-
+
diff --git a/packages/@lwc/ssr-client-utils/src/index.ts b/packages/@lwc/ssr-client-utils/src/index.ts
index ee39511dcf..558db09f60 100644
--- a/packages/@lwc/ssr-client-utils/src/index.ts
+++ b/packages/@lwc/ssr-client-utils/src/index.ts
@@ -24,6 +24,10 @@ class StyleDeduplicator extends HTMLElement {
root.adoptedStyleSheets.push(stylesheet);
const placeholder = document.createElement('style');
placeholder.setAttribute('type', 'text/css');
+
+ // TODO [#2869]: ``;
} else if (stylesheetToId.has(stylesheet)) {
const styleId = stylesheetToId.get(stylesheet);
- result += ``;
+ // TODO [#2869]: ``s should not have scope token classes, but required for hydration to function correctly (W-19087941).
+ result += ``;
} else {
const styleId = emit.cxt.nextId++;
stylesheetToId.set(stylesheet, styleId.toString());
diff --git a/scripts/test-utils/swap-lwc-style-for-style.ts b/scripts/test-utils/swap-lwc-style-for-style.ts
index 560bb04718..7e4b33e60a 100644
--- a/scripts/test-utils/swap-lwc-style-for-style.ts
+++ b/scripts/test-utils/swap-lwc-style-for-style.ts
@@ -50,7 +50,8 @@ export function swapLwcStyleForStyleTag(src: string): string {
});
}
- const lwcStyleCapture = /(\s*)[^<]*<\/lwc-style>/s;
+ const lwcStyleCapture =
+ /(\s*)[^<]*<\/lwc-style>/s;
const idToStyleTag = Object.fromEntries(
capturedStyleTags.map((styleTagInfo) => [styleTagInfo.styleId, styleTagInfo])
);