Skip to content

Commit 4d13710

Browse files
authored
fix(hydration): only ignore mutated host attributes (#4385)
1 parent ae5e7be commit 4d13710

File tree

25 files changed

+188
-15
lines changed

25 files changed

+188
-15
lines changed

packages/@lwc/engine-core/src/framework/hydration.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
APIFeature,
2121
isAPIFeatureEnabled,
2222
isFalse,
23+
StringSplit,
2324
} from '@lwc/shared';
2425

2526
import { logError, logWarn } from '../shared/logger';
@@ -165,9 +166,11 @@ function getValidationPredicate(
165166
optOutStaticProp: string[] | true | undefined
166167
): AttrValidationPredicate {
167168
// `data-lwc-host-mutated` is a special attribute added by the SSR engine itself,
168-
// which does the same thing as an explicit `static validationOptOut = true`.
169-
if (renderer.getAttribute(elm, 'data-lwc-host-mutated') === '') {
170-
return (_attrName: string) => false;
169+
// which does the same thing as an explicit `static validationOptOut = ['attr1', 'attr2']`.
170+
const hostMutatedValue = renderer.getAttribute(elm, 'data-lwc-host-mutated');
171+
if (isString(hostMutatedValue)) {
172+
const mutatedAttrValues = new Set(StringSplit.call(hostMutatedValue, / /));
173+
return (attrName: string) => !mutatedAttrValues.has(attrName);
171174
}
172175

173176
if (isUndefined(optOutStaticProp)) {
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<x-cmp aria-label="haha" class="yolo woot" data-foo="bar" data-lwc-host-mutated="aria-label class data-foo">
2+
<template shadowrootmode="open">
3+
</template>
4+
</x-cmp>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const tagName = 'x-cmp';
2+
export { default } from 'x/cmp';
3+
export * from 'x/cmp';
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<template>
2+
</template>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { LightningElement } from 'lwc';
2+
3+
export default class extends LightningElement {
4+
connectedCallback() {
5+
// Modify this component's class and attributes at runtime
6+
// We expect a data-lwc-host-mutated attr to be added with the mutated attribute names in unique sorted order
7+
this.setAttribute('data-foo', 'bar')
8+
this.classList.add('yolo')
9+
this.classList.add('woot')
10+
this.setAttribute('aria-label', 'haha')
11+
}
12+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<x-cmp aria-activedescendant="foo" aria-busy="true" data-lwc-host-mutated>
1+
<x-cmp aria-activedescendant="foo" aria-busy="true" data-lwc-host-mutated="aria-activedescendant aria-busy">
22
<template shadowrootmode="open">
33
</template>
44
</x-cmp>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<x-cmp ARIA-LABEL="haha" DATA-FOO="bar" data-lwc-host-mutated="aria-label data-bar data-foo">
2+
<template shadowrootmode="open">
3+
</template>
4+
</x-cmp>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const tagName = 'x-cmp';
2+
export { default } from 'x/cmp';
3+
export * from 'x/cmp';
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<template>
2+
</template>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { LightningElement } from 'lwc';
2+
3+
export default class extends LightningElement {
4+
connectedCallback() {
5+
// Modify this component's attributes at runtime, using uppercase
6+
// We expect a data-lwc-host-mutated attr to be added with the mutated attribute names in unique sorted order,
7+
// all lowercase
8+
this.setAttribute('DATA-FOO', 'bar')
9+
this.setAttribute('ARIA-LABEL', 'haha')
10+
this.removeAttribute('dAtA-BaR')
11+
}
12+
}

0 commit comments

Comments
 (0)