Skip to content

Commit a5f3c2e

Browse files
committedSep 13, 2024··
fix(hydration): fix mismatch of leading newline in <textarea> and <pre>
close #11873 close #11874
1 parent 3c4bf76 commit a5f3c2e

File tree

2 files changed

+27
-2
lines changed

2 files changed

+27
-2
lines changed
 

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

+15
Original file line numberDiff line numberDiff line change
@@ -1908,6 +1908,21 @@ describe('SSR hydration', () => {
19081908
expect(`Hydration attribute mismatch`).toHaveBeenWarned()
19091909
})
19101910

1911+
// #11873
1912+
test('<textarea> with newlines at the beginning', async () => {
1913+
const render = () => h('textarea', null, '\nhello')
1914+
const html = await renderToString(createSSRApp({ render }))
1915+
mountWithHydration(html, render)
1916+
expect(`Hydration text content mismatch`).not.toHaveBeenWarned()
1917+
})
1918+
1919+
test('<pre> with newlines at the beginning', async () => {
1920+
const render = () => h('pre', null, '\n')
1921+
const html = await renderToString(createSSRApp({ render }))
1922+
mountWithHydration(html, render)
1923+
expect(`Hydration text content mismatch`).not.toHaveBeenWarned()
1924+
})
1925+
19111926
test('boolean attr handling', () => {
19121927
mountWithHydration(`<input />`, () => h('input', { readonly: false }))
19131928
expect(`Hydration attribute mismatch`).not.toHaveBeenWarned()

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

+12-2
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,17 @@ export function createHydrationFunctions(
440440
remove(cur)
441441
}
442442
} else if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {
443-
if (el.textContent !== vnode.children) {
443+
// #11873 the HTML parser will "eat" the first newline when parsing
444+
// <pre> and <textarea>, so if the client value starts with a newline,
445+
// we need to remove it before comparing
446+
let clientText = vnode.children as string
447+
if (
448+
clientText[0] === '\n' &&
449+
(el.tagName === 'PRE' || el.tagName === 'TEXTAREA')
450+
) {
451+
clientText = clientText.slice(1)
452+
}
453+
if (el.textContent !== clientText) {
444454
if (!isMismatchAllowed(el, MismatchTypes.TEXT)) {
445455
;(__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) &&
446456
warn(
@@ -753,7 +763,7 @@ export function createHydrationFunctions(
753763
const isTemplateNode = (node: Node): node is HTMLTemplateElement => {
754764
return (
755765
node.nodeType === DOMNodeTypes.ELEMENT &&
756-
(node as Element).tagName.toLowerCase() === 'template'
766+
(node as Element).tagName === 'TEMPLATE'
757767
)
758768
}
759769

0 commit comments

Comments
 (0)
Please sign in to comment.