From 6958ec1b37fb4a9244ae222a35fcac032d26ad8a Mon Sep 17 00:00:00 2001 From: Travis Date: Tue, 27 Sep 2022 17:30:10 +0800 Subject: [PATCH 01/39] fix(compiler-sfc): fix expression check for v-on with object literal value (#6652) fix #6650 fix #6674 --- packages/compiler-sfc/src/compileScript.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/compiler-sfc/src/compileScript.ts b/packages/compiler-sfc/src/compileScript.ts index 5a77e8a9463..a21f94cba71 100644 --- a/packages/compiler-sfc/src/compileScript.ts +++ b/packages/compiler-sfc/src/compileScript.ts @@ -2135,7 +2135,7 @@ function processExp(exp: string, dir?: string): string { if (dir === 'slot') { exp = `(${exp})=>{}` } else if (dir === 'on') { - exp = `()=>{${exp}}` + exp = `()=>{return ${exp}}` } else if (dir === 'for') { const inMatch = exp.match(forAliasRE) if (inMatch) { From 121eb32fb0a21cf9988d788cfad1b4249b15997b Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 27 Sep 2022 17:40:22 +0800 Subject: [PATCH 02/39] fix(ssr): respect case when rendering dynamic attrs on svg fix #6755 --- .../server-renderer/__tests__/ssrRenderAttrs.spec.ts | 11 +++++++++++ .../server-renderer/src/helpers/ssrRenderAttrs.ts | 6 +++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/packages/server-renderer/__tests__/ssrRenderAttrs.spec.ts b/packages/server-renderer/__tests__/ssrRenderAttrs.spec.ts index 62ccdb59974..e9dfb0dbd59 100644 --- a/packages/server-renderer/__tests__/ssrRenderAttrs.spec.ts +++ b/packages/server-renderer/__tests__/ssrRenderAttrs.spec.ts @@ -98,6 +98,17 @@ describe('ssr: renderAttrs', () => { ) ).toBe(` fooBar="ok"`) }) + + test('preserve name on svg elements', () => { + expect( + ssrRenderAttrs( + { + viewBox: 'foo' + }, + 'svg' + ) + ).toBe(` viewBox="foo"`) + }) }) describe('ssr: renderAttr', () => { diff --git a/packages/server-renderer/src/helpers/ssrRenderAttrs.ts b/packages/server-renderer/src/helpers/ssrRenderAttrs.ts index 746ffa10729..6bbf83a1eaa 100644 --- a/packages/server-renderer/src/helpers/ssrRenderAttrs.ts +++ b/packages/server-renderer/src/helpers/ssrRenderAttrs.ts @@ -1,4 +1,4 @@ -import { escapeHtml, stringifyStyle } from '@vue/shared' +import { escapeHtml, isSVGTag, stringifyStyle } from '@vue/shared' import { normalizeClass, normalizeStyle, @@ -51,8 +51,8 @@ export function ssrRenderDynamicAttr( return `` } const attrKey = - tag && tag.indexOf('-') > 0 - ? key // preserve raw name on custom elements + tag && (tag.indexOf('-') > 0 || isSVGTag(tag)) + ? key // preserve raw name on custom elements and svg : propsToAttrMap[key] || key.toLowerCase() if (isBooleanAttr(attrKey)) { return includeBooleanAttr(value) ? ` ${attrKey}` : `` From 03820193a8f768293d665ca2753439fe73aed0fd Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 28 Sep 2022 08:45:32 +0800 Subject: [PATCH 03/39] fix(ssr): fix pre tag windows newline hydration mismatch fix #6410 --- packages/compiler-core/src/parse.ts | 61 ++++++++++++++++------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/packages/compiler-core/src/parse.ts b/packages/compiler-core/src/parse.ts index 5cdd9ae3eda..2f904098e60 100644 --- a/packages/compiler-core/src/parse.ts +++ b/packages/compiler-core/src/parse.ts @@ -257,34 +257,41 @@ function parseChildren( const shouldCondense = context.options.whitespace !== 'preserve' for (let i = 0; i < nodes.length; i++) { const node = nodes[i] - if (!context.inPre && node.type === NodeTypes.TEXT) { - if (!/[^\t\r\n\f ]/.test(node.content)) { - const prev = nodes[i - 1] - const next = nodes[i + 1] - // Remove if: - // - the whitespace is the first or last node, or: - // - (condense mode) the whitespace is adjacent to a comment, or: - // - (condense mode) the whitespace is between two elements AND contains newline - if ( - !prev || - !next || - (shouldCondense && - (prev.type === NodeTypes.COMMENT || - next.type === NodeTypes.COMMENT || - (prev.type === NodeTypes.ELEMENT && - next.type === NodeTypes.ELEMENT && - /[\r\n]/.test(node.content)))) - ) { - removedWhitespace = true - nodes[i] = null as any - } else { - // Otherwise, the whitespace is condensed into a single space - node.content = ' ' + if (node.type === NodeTypes.TEXT) { + if (!context.inPre) { + if (!/[^\t\r\n\f ]/.test(node.content)) { + const prev = nodes[i - 1] + const next = nodes[i + 1] + // Remove if: + // - the whitespace is the first or last node, or: + // - (condense mode) the whitespace is adjacent to a comment, or: + // - (condense mode) the whitespace is between two elements AND contains newline + if ( + !prev || + !next || + (shouldCondense && + (prev.type === NodeTypes.COMMENT || + next.type === NodeTypes.COMMENT || + (prev.type === NodeTypes.ELEMENT && + next.type === NodeTypes.ELEMENT && + /[\r\n]/.test(node.content)))) + ) { + removedWhitespace = true + nodes[i] = null as any + } else { + // Otherwise, the whitespace is condensed into a single space + node.content = ' ' + } + } else if (shouldCondense) { + // in condense mode, consecutive whitespaces in text are condensed + // down to a single space. + node.content = node.content.replace(/[\t\r\n\f ]+/g, ' ') } - } else if (shouldCondense) { - // in condense mode, consecutive whitespaces in text are condensed - // down to a single space. - node.content = node.content.replace(/[\t\r\n\f ]+/g, ' ') + } else { + // #6410 normalize windows newlines in
:
+          // in SSR, browsers normalize server-rendered \r\n into a single \n
+          // in the DOM
+          node.content = node.content.replace(/\r\n/g, '\n')
         }
       }
       // Remove comment nodes if desired by configuration.

From 9698dd3cf1dfdb95d4dc4b4f7bd24ff94b4b5d84 Mon Sep 17 00:00:00 2001
From: Evan You 
Date: Wed, 28 Sep 2022 09:33:17 +0800
Subject: [PATCH 04/39] fix(ssr): fix hydration mismatch when entire multi-root
 template is stringified

fix #6637
---
 packages/runtime-core/__tests__/hydration.spec.ts |  8 ++++++++
 packages/runtime-core/src/hydration.ts            | 15 ++++++++++-----
 2 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/packages/runtime-core/__tests__/hydration.spec.ts b/packages/runtime-core/__tests__/hydration.spec.ts
index 17ffbb40092..493405b8ab8 100644
--- a/packages/runtime-core/__tests__/hydration.spec.ts
+++ b/packages/runtime-core/__tests__/hydration.spec.ts
@@ -982,6 +982,14 @@ describe('SSR hydration', () => {
     expect((container as any)._vnode).toBe(null)
   })
 
+  // #6637
+  test('stringified root fragment', () => {
+    mountWithHydration(`
`, () => + createStaticVNode(`
`, 1) + ) + expect(`mismatch`).not.toHaveBeenWarned() + }) + describe('mismatch handling', () => { test('text node', () => { const { container } = mountWithHydration(`foo`, () => 'bar') diff --git a/packages/runtime-core/src/hydration.ts b/packages/runtime-core/src/hydration.ts index 8ada97b166b..2170a9192cf 100644 --- a/packages/runtime-core/src/hydration.ts +++ b/packages/runtime-core/src/hydration.ts @@ -108,7 +108,7 @@ export function createHydrationFunctions( ) const { type, ref, shapeFlag, patchFlag } = vnode - const domType = node.nodeType + let domType = node.nodeType vnode.el = node if (patchFlag === PatchFlags.BAIL) { @@ -150,9 +150,12 @@ export function createHydrationFunctions( } break case Static: - if (domType !== DOMNodeTypes.ELEMENT && domType !== DOMNodeTypes.TEXT) { - nextNode = onMismatch() - } else { + if (isFragmentStart) { + // entire template is static but SSRed as a fragment + node = nextSibling(node)! + domType = node.nodeType + } + if (domType === DOMNodeTypes.ELEMENT || domType === DOMNodeTypes.TEXT) { // determine anchor, adopt content nextNode = node // if the static vnode has its content stripped during build, @@ -169,7 +172,9 @@ export function createHydrationFunctions( } nextNode = nextSibling(nextNode)! } - return nextNode + return isFragmentStart ? nextSibling(nextNode) : nextNode + } else { + onMismatch() } break case Fragment: From 8963c5508cde3a0c990b2748787ffb582b16f23f Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 28 Sep 2022 10:24:57 +0800 Subject: [PATCH 05/39] fix(ssr): fix dynamic slot regression in ssr fix #6651 --- packages/runtime-core/src/helpers/createSlots.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/runtime-core/src/helpers/createSlots.ts b/packages/runtime-core/src/helpers/createSlots.ts index 89ea7ac77c8..b44d1f1090b 100644 --- a/packages/runtime-core/src/helpers/createSlots.ts +++ b/packages/runtime-core/src/helpers/createSlots.ts @@ -33,7 +33,8 @@ export function createSlots( const res = slot.fn(...args) // attach branch key so each conditional branch is considered a // different fragment - ;(res as any).key = slot.key + // #6651 res can be undefined in SSR in string push mode + if (res) (res as any).key = slot.key return res } : slot.fn From 3cc8e024e60c85860baf5de13996506c7e4de7fb Mon Sep 17 00:00:00 2001 From: Shigma Date: Wed, 28 Sep 2022 10:36:11 +0800 Subject: [PATCH 06/39] test(slots): ensure createSlots helper work with ssr slots (#6660) --- .../runtime-core/__tests__/helpers/createSlots.spec.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/runtime-core/__tests__/helpers/createSlots.spec.ts b/packages/runtime-core/__tests__/helpers/createSlots.spec.ts index 891789d048a..2af24380cca 100644 --- a/packages/runtime-core/__tests__/helpers/createSlots.spec.ts +++ b/packages/runtime-core/__tests__/helpers/createSlots.spec.ts @@ -26,6 +26,14 @@ describe('createSlot', () => { expect(ret.key).toBe('1') }) + it('should check nullability', () => { + const slot = (() => {}) as Slot + const dynamicSlot = [{ name: 'descriptor', fn: slot, key: '1' }] + + const actual = createSlots(record, dynamicSlot) + expect(actual).toHaveProperty('descriptor') + }) + it('should add all slots to the record', () => { const dynamicSlot = [ { name: 'descriptor', fn: slot }, From 05c7b0d180024c5cd2e7bdda40de637de32a0523 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 28 Sep 2022 05:36:47 +0300 Subject: [PATCH 07/39] ci: GitHub workflows security hardening (#6743) --- .github/workflows/ci.yml | 4 ++++ .github/workflows/release-tag.yml | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eadcd94f6d8..3128dd2cb4f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,10 @@ on: pull_request: branches: - main + +permissions: + contents: read # to fetch code (actions/checkout) + jobs: unit-test: runs-on: ubuntu-latest diff --git a/.github/workflows/release-tag.yml b/.github/workflows/release-tag.yml index d9ea7a07f72..16c6c9c5c10 100644 --- a/.github/workflows/release-tag.yml +++ b/.github/workflows/release-tag.yml @@ -5,8 +5,12 @@ on: name: Create Release +permissions: {} jobs: build: + permissions: + contents: write # to create release (yyx990803/release-tag) + name: Create Release runs-on: ubuntu-latest steps: From cae1aa82cc5f16abc2b63feaedfe8158aa0c4a16 Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 28 Sep 2022 10:38:19 +0800 Subject: [PATCH 08/39] chore: use stricter slots type in createSlots --- packages/runtime-core/src/helpers/createSlots.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/runtime-core/src/helpers/createSlots.ts b/packages/runtime-core/src/helpers/createSlots.ts index b44d1f1090b..f370f5ca803 100644 --- a/packages/runtime-core/src/helpers/createSlots.ts +++ b/packages/runtime-core/src/helpers/createSlots.ts @@ -1,9 +1,12 @@ -import { Slot } from '../componentSlots' import { isArray } from '@vue/shared' +import { VNode } from '../vnode' + +// #6651 res can be undefined in SSR in string push mode +type SSRSlot = (...args: any[]) => VNode[] | undefined interface CompiledSlotDescriptor { name: string - fn: Slot + fn: SSRSlot key?: string } @@ -12,13 +15,13 @@ interface CompiledSlotDescriptor { * @private */ export function createSlots( - slots: Record, + slots: Record, dynamicSlots: ( | CompiledSlotDescriptor | CompiledSlotDescriptor[] | undefined )[] -): Record { +): Record { for (let i = 0; i < dynamicSlots.length; i++) { const slot = dynamicSlots[i] // array of dynamic slot generated by