From 7ad67ced26e5f53a47cb42f4834496e4958cb53b Mon Sep 17 00:00:00 2001 From: yangxiuxiu <79584569+yangxiuxiu1115@users.noreply.github.com> Date: Sat, 22 Jun 2024 17:49:25 +0800 Subject: [PATCH] fix(hydration): fix css vars hydration mismatch false positive on attr-fallthrough (#11190) close #11188 --- .../runtime-core/__tests__/hydration.spec.ts | 21 +++++++++ packages/runtime-core/src/hydration.ts | 43 ++++++++++++------- 2 files changed, 48 insertions(+), 16 deletions(-) diff --git a/packages/runtime-core/__tests__/hydration.spec.ts b/packages/runtime-core/__tests__/hydration.spec.ts index 933542ab98d..f68d2f240d4 100644 --- a/packages/runtime-core/__tests__/hydration.spec.ts +++ b/packages/runtime-core/__tests__/hydration.spec.ts @@ -1674,5 +1674,26 @@ describe('SSR hydration', () => { app.mount(container) expect(`Hydration style mismatch`).not.toHaveBeenWarned() }) + + // #11188 + test('css vars support fallthrough', () => { + const container = document.createElement('div') + container.innerHTML = `
` + const app = createSSRApp({ + setup() { + useCssVars(() => ({ + foo: 'red', + })) + return () => h(Child) + }, + }) + const Child = { + setup() { + return () => h('div', { style: 'padding: 4px' }) + }, + } + app.mount(container) + expect(`Hydration style mismatch`).not.toHaveBeenWarned() + }) }) }) diff --git a/packages/runtime-core/src/hydration.ts b/packages/runtime-core/src/hydration.ts index 6fcf4dd4c2e..ec829a6e3ba 100644 --- a/packages/runtime-core/src/hydration.ts +++ b/packages/runtime-core/src/hydration.ts @@ -766,18 +766,8 @@ function propHasMismatch( } } - // eslint-disable-next-line no-restricted-syntax - const root = instance?.subTree - if ( - vnode === root || - // eslint-disable-next-line no-restricted-syntax - (root?.type === Fragment && (root.children as VNode[]).includes(vnode)) - ) { - // eslint-disable-next-line no-restricted-syntax - const cssVars = instance?.getCssVars?.() - for (const key in cssVars) { - expectedMap.set(`--${key}`, String(cssVars[key])) - } + if (instance) { + resolveCssVars(instance, vnode, expectedMap) } if (!isMapEqual(actualMap, expectedMap)) { @@ -854,10 +844,8 @@ function toStyleMap(str: string): Map { const styleMap: Map = new Map() for (const item of str.split(';')) { let [key, value] = item.split(':') - // eslint-disable-next-line no-restricted-syntax - key = key?.trim() - // eslint-disable-next-line no-restricted-syntax - value = value?.trim() + key = key.trim() + value = value && value.trim() if (key && value) { styleMap.set(key, value) } @@ -876,3 +864,26 @@ function isMapEqual(a: Map, b: Map): boolean { } return true } + +function resolveCssVars( + instance: ComponentInternalInstance, + vnode: VNode, + expectedMap: Map, +) { + const root = instance.subTree + if ( + instance.getCssVars && + (vnode === root || + (root && + root.type === Fragment && + (root.children as VNode[]).includes(vnode))) + ) { + const cssVars = instance.getCssVars() + for (const key in cssVars) { + expectedMap.set(`--${key}`, String(cssVars[key])) + } + } + if (vnode === root && instance.parent) { + resolveCssVars(instance.parent, instance.vnode, expectedMap) + } +}