.
\ No newline at end of file
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-div/error.txt b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-div/error.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-div/expected-ssr.html b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-div/expected-ssr.html
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-div/expected.html b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-div/expected.html
new file mode 100644
index 0000000000..dd36f951cc
--- /dev/null
+++ b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-div/expected.html
@@ -0,0 +1,19 @@
+
+
+
+ original
+
+
+ original
+
+
+ original
+
+
+ lwc:inner-html
+
+
+ injected
+
+
+
\ No newline at end of file
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-div/modules/x/outer/outer.html b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-div/modules/x/outer/outer.html
new file mode 100644
index 0000000000..0ac3a752d7
--- /dev/null
+++ b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-div/modules/x/outer/outer.html
@@ -0,0 +1,8 @@
+
+ original
+ original
+ original
+
+
+
+
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-div/modules/x/outer/outer.js b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-div/modules/x/outer/outer.js
new file mode 100644
index 0000000000..dc4b54ded2
--- /dev/null
+++ b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-div/modules/x/outer/outer.js
@@ -0,0 +1,6 @@
+import { LightningElement } from 'lwc';
+
+export default class extends LightningElement {
+ computed = 'injected';
+ spread = { innerHTML: 'wheeeeeeeeeeeeeeeeeeeeeeeeeee' };
+}
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-external/config.json b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-external/config.json
new file mode 100644
index 0000000000..52bc34cf9a
--- /dev/null
+++ b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-external/config.json
@@ -0,0 +1,7 @@
+{
+ "entry": "x/outer",
+ "ssrFiles": {
+ "error": "error-ssr.txt",
+ "expected": "expected-ssr.html"
+ }
+}
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-external/error-ssr.txt b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-external/error-ssr.txt
new file mode 100644
index 0000000000..8d3ab5d52f
--- /dev/null
+++ b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-external/error-ssr.txt
@@ -0,0 +1 @@
+Cannot set attribute "outer-h-t-m-l" on
.
\ No newline at end of file
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-external/error.txt b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-external/error.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-external/expected-ssr.html b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-external/expected-ssr.html
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-external/expected.html b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-external/expected.html
new file mode 100644
index 0000000000..9922597d77
--- /dev/null
+++ b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-external/expected.html
@@ -0,0 +1,13 @@
+
+
+
+ original
+
+
+ original
+
+
+ original
+
+
+
\ No newline at end of file
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-external/modules/x/outer/outer.html b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-external/modules/x/outer/outer.html
new file mode 100644
index 0000000000..7e3fc361d1
--- /dev/null
+++ b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-external/modules/x/outer/outer.html
@@ -0,0 +1,5 @@
+
+ original
+ original
+ original
+
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-external/modules/x/outer/outer.js b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-external/modules/x/outer/outer.js
new file mode 100644
index 0000000000..dc4b54ded2
--- /dev/null
+++ b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-external/modules/x/outer/outer.js
@@ -0,0 +1,6 @@
+import { LightningElement } from 'lwc';
+
+export default class extends LightningElement {
+ computed = 'injected';
+ spread = { innerHTML: 'wheeeeeeeeeeeeeeeeeeeeeeeeeee' };
+}
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-lwc/config.json b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-lwc/config.json
new file mode 100644
index 0000000000..e053573a97
--- /dev/null
+++ b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-lwc/config.json
@@ -0,0 +1,3 @@
+{
+ "entry": "x/outer"
+}
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-lwc/error.txt b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-lwc/error.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-lwc/expected.html b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-lwc/expected.html
new file mode 100644
index 0000000000..6786cd8a4a
--- /dev/null
+++ b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-lwc/expected.html
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+ original
+
+
+
+
+
+
+ original
+
+
+
+
+
+
+ original
+
+
+
\ No newline at end of file
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-lwc/modules/x/component/component.html b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-lwc/modules/x/component/component.html
new file mode 100644
index 0000000000..6806310398
--- /dev/null
+++ b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-lwc/modules/x/component/component.html
@@ -0,0 +1,3 @@
+
+
+
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-lwc/modules/x/component/component.js b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-lwc/modules/x/component/component.js
new file mode 100644
index 0000000000..ca8dce94e0
--- /dev/null
+++ b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-lwc/modules/x/component/component.js
@@ -0,0 +1,3 @@
+import { LightningElement } from 'lwc';
+
+export default class extends LightningElement {}
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-lwc/modules/x/outer/outer.html b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-lwc/modules/x/outer/outer.html
new file mode 100644
index 0000000000..42cc18e7dd
--- /dev/null
+++ b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-lwc/modules/x/outer/outer.html
@@ -0,0 +1,5 @@
+
+ original
+ original
+ original
+
diff --git a/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-lwc/modules/x/outer/outer.js b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-lwc/modules/x/outer/outer.js
new file mode 100644
index 0000000000..dc4b54ded2
--- /dev/null
+++ b/packages/@lwc/engine-server/src/__tests__/fixtures/inner-outer-html/outer-lwc/modules/x/outer/outer.js
@@ -0,0 +1,6 @@
+import { LightningElement } from 'lwc';
+
+export default class extends LightningElement {
+ computed = 'injected';
+ spread = { innerHTML: 'wheeeeeeeeeeeeeeeeeeeeeeeeeee' };
+}
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 561993edc1..8dce6af03c 100644
--- a/packages/@lwc/integration-karma/scripts/karma-plugins/hydration-tests.js
+++ b/packages/@lwc/integration-karma/scripts/karma-plugins/hydration-tests.js
@@ -15,18 +15,6 @@ const ssr = ENGINE_SERVER ? require('@lwc/engine-server') : require('@lwc/ssr-ru
const { DISABLE_STATIC_CONTENT_OPTIMIZATION } = require('../shared/options');
const Watcher = require('./Watcher');
-/*
- * These are hydration tests that currently fail in ssr-compiler (V2)
- * They need to be removed from this list and then fixed. There are only 4
- * so kept here for now.
- */
-const EXPECTED_V2_FAILURES = [
- 'mismatches/host-mutation-in-connected-callback/class-mutated-attr-mismatch',
- 'mismatches/host-mutation-in-connected-callback/class',
- 'directives/lwc-dynamic',
- 'inner-outer-html',
-];
-
const context = {
LWC: ssr,
moduleOutput: null,
@@ -84,6 +72,7 @@ async function getCompiledModule(dirName, compileForSSR) {
},
enableDynamicComponents: true,
enableStaticContentOptimization: !DISABLE_STATIC_CONTENT_OPTIMIZATION,
+ experimentalDynamicDirective: true,
}),
],
@@ -219,17 +208,14 @@ function createHCONFIG2JSPreprocessor(config, logger, emitter) {
// You can add an `.only` file alongside an `index.spec.js` file to make it `fdescribe()`
const onlyFileExists = await existsUp(suiteDir, '.only');
- // If V2 failure is expected, skip it.
- const v2FailureExpected =
- !ENGINE_SERVER && EXPECTED_V2_FAILURES.some((dir) => suiteDir.includes(dir));
- let describe = onlyFileExists ? 'fdescribe' : 'describe';
+ const describe = onlyFileExists ? 'fdescribe' : 'describe';
const { code: componentDefCSR, watchFiles: componentWatchFilesCSR } =
await getCompiledModule(suiteDir, false);
let ssrOutput;
- /* eslint-disable vitest/no-conditional-tests */
+
if (ENGINE_SERVER) {
// engine-server uses the same def as the client
watcher.watchSuite(filePath, testWatchFiles.concat(componentWatchFilesCSR));
@@ -238,7 +224,7 @@ function createHCONFIG2JSPreprocessor(config, logger, emitter) {
testCode,
path.join(suiteDir, 'ssr.js')
);
- } else if (!v2FailureExpected) {
+ } else {
// ssr-compiler has it's own def
const { code: componentDefSSR, watchFiles: componentWatchFilesSSR } =
await getCompiledModule(suiteDir, true);
@@ -251,11 +237,7 @@ function createHCONFIG2JSPreprocessor(config, logger, emitter) {
testCode,
path.join(suiteDir, 'ssr.js')
);
- } else {
- console.log(`Expected failure for ${suiteDir}, skipping`);
- describe = 'xdescribe';
}
- /* eslint-enable vitest/no-conditional-tests */
const newContent = format(
TEMPLATE,
diff --git a/packages/@lwc/integration-karma/test-hydration/directives/lwc-dynamic/index.spec.js b/packages/@lwc/integration-karma/test-hydration/directives/lwc-dynamic/index.spec.js
index 9ecce85f91..b6a49ef4ed 100644
--- a/packages/@lwc/integration-karma/test-hydration/directives/lwc-dynamic/index.spec.js
+++ b/packages/@lwc/integration-karma/test-hydration/directives/lwc-dynamic/index.spec.js
@@ -3,7 +3,7 @@ export default {
label: 'dynamic',
},
snapshot(target) {
- const cmp = target.shadowRoot.querySelector('x-dynamic-cmp');
+ const cmp = target.shadowRoot.querySelector('x-child');
const p = cmp.shadowRoot.querySelector('p');
return {
@@ -12,7 +12,7 @@ export default {
};
},
test(target, snapshots) {
- const cmp = target.shadowRoot.querySelector('x-dynamic-cmp');
+ const cmp = target.shadowRoot.querySelector('x-child');
const p = cmp.shadowRoot.querySelector('p');
expect(cmp).toBe(snapshots.cmp);
diff --git a/packages/@lwc/integration-karma/test-hydration/directives/lwc-dynamic/x/main/main.html b/packages/@lwc/integration-karma/test-hydration/directives/lwc-dynamic/x/main/main.html
index 100385d78d..575bfc8555 100644
--- a/packages/@lwc/integration-karma/test-hydration/directives/lwc-dynamic/x/main/main.html
+++ b/packages/@lwc/integration-karma/test-hydration/directives/lwc-dynamic/x/main/main.html
@@ -1,3 +1,3 @@
-
+
diff --git a/packages/@lwc/integration-karma/test-hydration/inner-outer-html/x/main/main.html b/packages/@lwc/integration-karma/test-hydration/inner-outer-html/x/main/main.html
index b0c85440a4..3e9615e892 100644
--- a/packages/@lwc/integration-karma/test-hydration/inner-outer-html/x/main/main.html
+++ b/packages/@lwc/integration-karma/test-hydration/inner-outer-html/x/main/main.html
@@ -1,26 +1,18 @@
- original
- original
original
original
original
original
- original
- original
original
- original
- original
original
original
original
original
- original
- original
original
diff --git a/packages/@lwc/integration-karma/test-hydration/light-dom/directives/lwc-dynamic/index.spec.js b/packages/@lwc/integration-karma/test-hydration/light-dom/directives/lwc-dynamic/index.spec.js
index 1618f6f9e0..77b5c3d75c 100644
--- a/packages/@lwc/integration-karma/test-hydration/light-dom/directives/lwc-dynamic/index.spec.js
+++ b/packages/@lwc/integration-karma/test-hydration/light-dom/directives/lwc-dynamic/index.spec.js
@@ -3,7 +3,7 @@ export default {
label: 'dynamic',
},
snapshot(target) {
- const cmp = target.querySelector('x-dynamic-cmp');
+ const cmp = target.querySelector('x-child');
const p = cmp.querySelector('p');
return {
@@ -12,7 +12,7 @@ export default {
};
},
test(target, snapshots) {
- const cmp = target.querySelector('x-dynamic-cmp');
+ const cmp = target.querySelector('x-child');
const p = cmp.querySelector('p');
expect(cmp).toBe(snapshots.cmp);
diff --git a/packages/@lwc/integration-karma/test-hydration/light-dom/directives/lwc-dynamic/x/main/main.html b/packages/@lwc/integration-karma/test-hydration/light-dom/directives/lwc-dynamic/x/main/main.html
index dca2fe3c69..ce8c44c26e 100644
--- a/packages/@lwc/integration-karma/test-hydration/light-dom/directives/lwc-dynamic/x/main/main.html
+++ b/packages/@lwc/integration-karma/test-hydration/light-dom/directives/lwc-dynamic/x/main/main.html
@@ -1,3 +1,3 @@
-
+
diff --git a/packages/@lwc/ssr-runtime/src/lightning-element.ts b/packages/@lwc/ssr-runtime/src/lightning-element.ts
index 207f920288..e81d87d8c0 100644
--- a/packages/@lwc/ssr-runtime/src/lightning-element.ts
+++ b/packages/@lwc/ssr-runtime/src/lightning-element.ts
@@ -84,6 +84,11 @@ export class LightningElement implements PropsAvailableAtConstruction {
this.#props = props;
this.#attrs = attrs;
+ // Class should be set explicitly to avoid it being overridden by connectedCallback classList mutation.
+ if (attrs.class) {
+ this.className = attrs.class;
+ }
+
// Avoid setting the following types of properties that should not be set:
// - Properties that are not public.
// - Properties that are not global.