Skip to content

Commit 7ad67ce

Browse files
authoredJun 22, 2024··
fix(hydration): fix css vars hydration mismatch false positive on attr-fallthrough (#11190)
close #11188
1 parent 80ba50d commit 7ad67ce

File tree

2 files changed

+48
-16
lines changed

2 files changed

+48
-16
lines changed
 

‎packages/runtime-core/__tests__/hydration.spec.ts

+21
Original file line numberDiff line numberDiff line change
@@ -1674,5 +1674,26 @@ describe('SSR hydration', () => {
16741674
app.mount(container)
16751675
expect(`Hydration style mismatch`).not.toHaveBeenWarned()
16761676
})
1677+
1678+
// #11188
1679+
test('css vars support fallthrough', () => {
1680+
const container = document.createElement('div')
1681+
container.innerHTML = `<div style="padding: 4px;--foo:red;"></div>`
1682+
const app = createSSRApp({
1683+
setup() {
1684+
useCssVars(() => ({
1685+
foo: 'red',
1686+
}))
1687+
return () => h(Child)
1688+
},
1689+
})
1690+
const Child = {
1691+
setup() {
1692+
return () => h('div', { style: 'padding: 4px' })
1693+
},
1694+
}
1695+
app.mount(container)
1696+
expect(`Hydration style mismatch`).not.toHaveBeenWarned()
1697+
})
16771698
})
16781699
})

‎packages/runtime-core/src/hydration.ts

+27-16
Original file line numberDiff line numberDiff line change
@@ -766,18 +766,8 @@ function propHasMismatch(
766766
}
767767
}
768768

769-
// eslint-disable-next-line no-restricted-syntax
770-
const root = instance?.subTree
771-
if (
772-
vnode === root ||
773-
// eslint-disable-next-line no-restricted-syntax
774-
(root?.type === Fragment && (root.children as VNode[]).includes(vnode))
775-
) {
776-
// eslint-disable-next-line no-restricted-syntax
777-
const cssVars = instance?.getCssVars?.()
778-
for (const key in cssVars) {
779-
expectedMap.set(`--${key}`, String(cssVars[key]))
780-
}
769+
if (instance) {
770+
resolveCssVars(instance, vnode, expectedMap)
781771
}
782772

783773
if (!isMapEqual(actualMap, expectedMap)) {
@@ -854,10 +844,8 @@ function toStyleMap(str: string): Map<string, string> {
854844
const styleMap: Map<string, string> = new Map()
855845
for (const item of str.split(';')) {
856846
let [key, value] = item.split(':')
857-
// eslint-disable-next-line no-restricted-syntax
858-
key = key?.trim()
859-
// eslint-disable-next-line no-restricted-syntax
860-
value = value?.trim()
847+
key = key.trim()
848+
value = value && value.trim()
861849
if (key && value) {
862850
styleMap.set(key, value)
863851
}
@@ -876,3 +864,26 @@ function isMapEqual(a: Map<string, string>, b: Map<string, string>): boolean {
876864
}
877865
return true
878866
}
867+
868+
function resolveCssVars(
869+
instance: ComponentInternalInstance,
870+
vnode: VNode,
871+
expectedMap: Map<string, string>,
872+
) {
873+
const root = instance.subTree
874+
if (
875+
instance.getCssVars &&
876+
(vnode === root ||
877+
(root &&
878+
root.type === Fragment &&
879+
(root.children as VNode[]).includes(vnode)))
880+
) {
881+
const cssVars = instance.getCssVars()
882+
for (const key in cssVars) {
883+
expectedMap.set(`--${key}`, String(cssVars[key]))
884+
}
885+
}
886+
if (vnode === root && instance.parent) {
887+
resolveCssVars(instance.parent, instance.vnode, expectedMap)
888+
}
889+
}

0 commit comments

Comments
 (0)
Please sign in to comment.