From b9ca202f477be595477e182972ee9bae3f2b9f74 Mon Sep 17 00:00:00 2001 From: huangcheng Date: Thu, 30 May 2024 17:24:37 +0800 Subject: [PATCH 01/74] fix(compiler-core): v-for expression missing source with spaces should emit error (#5821) close #5819 --- .../__tests__/transforms/vFor.spec.ts | 24 +++++++++++++++++++ packages/compiler-core/src/utils.ts | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/packages/compiler-core/__tests__/transforms/vFor.spec.ts b/packages/compiler-core/__tests__/transforms/vFor.spec.ts index 7fabcbb57..e434b8888 100644 --- a/packages/compiler-core/__tests__/transforms/vFor.spec.ts +++ b/packages/compiler-core/__tests__/transforms/vFor.spec.ts @@ -202,6 +202,18 @@ describe('compiler: v-for', () => { expect(forNode.valueAlias).toBeUndefined() expect((forNode.source as SimpleExpressionNode).content).toBe('items') }) + + test('source containing string expression with spaces', () => { + const { node: forNode } = parseWithForTransform( + ``, + ) + expect(forNode.keyAlias).toBeUndefined() + expect(forNode.objectIndexAlias).toBeUndefined() + expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('item') + expect((forNode.source as SimpleExpressionNode).content).toBe( + "state ['my items']", + ) + }) }) describe('errors', () => { @@ -253,6 +265,18 @@ describe('compiler: v-for', () => { ) }) + test('missing source and have multiple spaces with', () => { + const onError = vi.fn() + parseWithForTransform('', { onError }) + + expect(onError).toHaveBeenCalledTimes(1) + expect(onError).toHaveBeenCalledWith( + expect.objectContaining({ + code: ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION, + }), + ) + }) + test('missing value', () => { const onError = vi.fn() parseWithForTransform('', { onError }) diff --git a/packages/compiler-core/src/utils.ts b/packages/compiler-core/src/utils.ts index 99a2c5b61..aa5960284 100644 --- a/packages/compiler-core/src/utils.ts +++ b/packages/compiler-core/src/utils.ts @@ -499,4 +499,4 @@ export function getMemoedVNodeCall(node: BlockCodegenNode | MemoExpression) { } } -export const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/ +export const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+(\S[\s\S]*)/ From 4c74302aae64c118752db7fc2a2c229a11ebaead Mon Sep 17 00:00:00 2001 From: mmis1000 <2993977+mmis1000@users.noreply.github.com> Date: Thu, 30 May 2024 17:43:34 +0800 Subject: [PATCH 02/74] fix(ssr): fix the bug that multi slot scope id does not work on component (#6100) close #6093 --- .../__tests__/ssrScopeId.spec.ts | 90 +++++++++++++++++++ packages/server-renderer/src/render.ts | 5 +- 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/packages/server-renderer/__tests__/ssrScopeId.spec.ts b/packages/server-renderer/__tests__/ssrScopeId.spec.ts index f9d356065..4ceb865fb 100644 --- a/packages/server-renderer/__tests__/ssrScopeId.spec.ts +++ b/packages/server-renderer/__tests__/ssrScopeId.spec.ts @@ -179,4 +179,94 @@ describe('ssr: scopedId runtime behavior', () => { const result = await renderToString(createApp(Comp)) // output: `
` expect(result).toBe(`
`) }) + + // #6093 + test(':slotted on forwarded slots on component', async () => { + const Wrapper = { + __scopeId: 'wrapper', + ssrRender: (ctx: any, push: any, parent: any, attrs: any) => { + //
+ push( + ``, + ) + ssrRenderSlot( + ctx.$slots, + 'default', + {}, + null, + push, + parent, + 'wrapper-s', + ) + push(``) + }, + } + + const Slotted = { + __scopeId: 'slotted', + ssrRender: (ctx: any, push: any, parent: any, attrs: any) => { + // + push( + ssrRenderComponent( + Wrapper, + attrs, + { + default: withCtx( + (_: any, push: any, parent: any, scopeId: string) => { + ssrRenderSlot( + ctx.$slots, + 'default', + {}, + null, + push, + parent, + 'slotted-s' + scopeId, + ) + }, + ), + _: 1, + } as any, + parent, + ), + ) + }, + } + + const Child = { + ssrRender: (ctx: any, push: any, parent: any, attrs: any) => { + push(``) + }, + } + + const Root = { + __scopeId: 'root', + // + ssrRender: (_: any, push: any, parent: any, attrs: any) => { + push( + ssrRenderComponent( + Slotted, + attrs, + { + default: withCtx( + (_: any, push: any, parent: any, scopeId: string) => { + push(ssrRenderComponent(Child, null, null, parent, scopeId)) + }, + ), + _: 1, + } as any, + parent, + ), + ) + }, + } + + const result = await renderToString(createApp(Root)) + expect(result).toBe( + `
` + + `
` + + `
`, + ) + }) }) diff --git a/packages/server-renderer/src/render.ts b/packages/server-renderer/src/render.ts index 28a78c668..7e274c3b9 100644 --- a/packages/server-renderer/src/render.ts +++ b/packages/server-renderer/src/render.ts @@ -181,7 +181,10 @@ function renderComponentSubTree( if (slotScopeId) { if (!hasCloned) attrs = { ...attrs } - attrs![slotScopeId.trim()] = '' + const slotScopeIdList = slotScopeId.trim().split(' ') + for (let i = 0; i < slotScopeIdList.length; i++) { + attrs![slotScopeIdList[i]] = '' + } } // set current rendering instance for asset resolution From 3ea964473d3ac0ba3e7b0b2c22d71f23d0f69123 Mon Sep 17 00:00:00 2001 From: Travis Date: Thu, 30 May 2024 17:45:11 +0800 Subject: [PATCH 03/74] fix(compiler-core): allow unicode to appear in simple identifiers (#6765) close #6367 --- .../compiler-core/__tests__/transforms/vOn.spec.ts | 14 +++++++++++++- packages/compiler-core/src/utils.ts | 2 +- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/compiler-core/__tests__/transforms/vOn.spec.ts b/packages/compiler-core/__tests__/transforms/vOn.spec.ts index b1c37e3f7..27d502753 100644 --- a/packages/compiler-core/__tests__/transforms/vOn.spec.ts +++ b/packages/compiler-core/__tests__/transforms/vOn.spec.ts @@ -10,6 +10,7 @@ import { baseParse as parse, transform, } from '../../src' +import { transformFor } from '../../src/transforms/vFor' import { transformOn } from '../../src/transforms/vOn' import { transformElement } from '../../src/transforms/transformElement' import { transformExpression } from '../../src/transforms/transformExpression' @@ -17,7 +18,7 @@ import { transformExpression } from '../../src/transforms/transformExpression' function parseWithVOn(template: string, options: CompilerOptions = {}) { const ast = parse(template, options) transform(ast, { - nodeTransforms: [transformExpression, transformElement], + nodeTransforms: [transformExpression, transformElement, transformFor], directiveTransforms: { on: transformOn, }, @@ -602,6 +603,17 @@ describe('compiler: transform v-on', () => { expect(root.cached).toBe(1) }) + test('unicode identifier should not be cached (v-for)', () => { + const { root } = parseWithVOn( + `
`, + { + prefixIdentifiers: true, + cacheHandlers: true, + }, + ) + expect(root.cached).toBe(0) + }) + test('inline function expression handler', () => { const { root, node } = parseWithVOn(`
`, { prefixIdentifiers: true, diff --git a/packages/compiler-core/src/utils.ts b/packages/compiler-core/src/utils.ts index aa5960284..561c63578 100644 --- a/packages/compiler-core/src/utils.ts +++ b/packages/compiler-core/src/utils.ts @@ -62,7 +62,7 @@ export function isCoreComponent(tag: string): symbol | void { } } -const nonIdentifierRE = /^\d|[^\$\w]/ +const nonIdentifierRE = /^\d|[^\$\w\xA0-\uFFFF]/ export const isSimpleIdentifier = (name: string): boolean => !nonIdentifierRE.test(name) From 5d258502a0faffc8a451b8701f13a31b2566d068 Mon Sep 17 00:00:00 2001 From: Wouter Date: Thu, 30 May 2024 12:19:04 +0200 Subject: [PATCH 04/74] fix(compiler-core): emit TS-compatible function declaration when requested (#9363) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Haoqun Jiang --- .../__snapshots__/scopeId.spec.ts.snap | 16 ++++++++++++ .../compiler-core/__tests__/scopeId.spec.ts | 25 +++++++++++++++++++ packages/compiler-core/src/codegen.ts | 3 ++- 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/packages/compiler-core/__tests__/__snapshots__/scopeId.spec.ts.snap b/packages/compiler-core/__tests__/__snapshots__/scopeId.spec.ts.snap index 445d3fd13..7267ba6b0 100644 --- a/packages/compiler-core/__tests__/__snapshots__/scopeId.spec.ts.snap +++ b/packages/compiler-core/__tests__/__snapshots__/scopeId.spec.ts.snap @@ -16,6 +16,22 @@ export function render(_ctx, _cache) { }" `; +exports[`scopeId compiler support > should push typescript-compatible scopeId for hoisted nodes 1`] = ` +"import { createElementVNode as _createElementVNode, toDisplayString as _toDisplayString, createTextVNode as _createTextVNode, openBlock as _openBlock, createElementBlock as _createElementBlock, pushScopeId as _pushScopeId, popScopeId as _popScopeId } from "vue" + +const _withScopeId = (n: any) => (_pushScopeId("test"),n=n(),_popScopeId(),n) +const _hoisted_1 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "hello", -1 /* HOISTED */)) +const _hoisted_2 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "world", -1 /* HOISTED */)) + +export function render(_ctx: any,_cache: any) { + return (_openBlock(), _createElementBlock("div", null, [ + _hoisted_1, + _createTextVNode(_toDisplayString(_ctx.foo), 1 /* TEXT */), + _hoisted_2 + ])) +}" +`; + exports[`scopeId compiler support > should wrap default slot 1`] = ` "import { createElementVNode as _createElementVNode, resolveComponent as _resolveComponent, withCtx as _withCtx, openBlock as _openBlock, createBlock as _createBlock } from "vue" diff --git a/packages/compiler-core/__tests__/scopeId.spec.ts b/packages/compiler-core/__tests__/scopeId.spec.ts index c7a21df7a..21e7327f2 100644 --- a/packages/compiler-core/__tests__/scopeId.spec.ts +++ b/packages/compiler-core/__tests__/scopeId.spec.ts @@ -81,4 +81,29 @@ describe('scopeId compiler support', () => { ].forEach(c => expect(code).toMatch(c)) expect(code).toMatchSnapshot() }) + + test('should push typescript-compatible scopeId for hoisted nodes', () => { + const { ast, code } = baseCompile( + `
hello
{{ foo }}
world
`, + { + mode: 'module', + scopeId: 'test', + hoistStatic: true, + isTS: true, + }, + ) + expect(ast.helpers).toContain(PUSH_SCOPE_ID) + expect(ast.helpers).toContain(POP_SCOPE_ID) + expect(ast.hoists.length).toBe(2) + ;[ + `const _withScopeId = (n: any) => (_pushScopeId("test"),n=n(),_popScopeId(),n)`, + `const _hoisted_1 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "hello", ${genFlagText( + PatchFlags.HOISTED, + )}))`, + `const _hoisted_2 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "world", ${genFlagText( + PatchFlags.HOISTED, + )}))`, + ].forEach(c => expect(code).toMatch(c)) + expect(code).toMatchSnapshot() + }) }) diff --git a/packages/compiler-core/src/codegen.ts b/packages/compiler-core/src/codegen.ts index 987293d51..39170bac5 100644 --- a/packages/compiler-core/src/codegen.ts +++ b/packages/compiler-core/src/codegen.ts @@ -572,8 +572,9 @@ function genHoists(hoists: (JSChildNode | null)[], context: CodegenContext) { // generate inlined withScopeId helper if (genScopeId) { + const param = context.isTS ? '(n: any)' : 'n' push( - `const _withScopeId = n => (${helper( + `const _withScopeId = ${param} => (${helper( PUSH_SCOPE_ID, )}("${scopeId}"),n=n(),${helper(POP_SCOPE_ID)}(),n)`, ) From 3a0b463a2c2e288dfe6850b9cb235f12419f32a6 Mon Sep 17 00:00:00 2001 From: Haoqun Jiang Date: Thu, 30 May 2024 18:22:11 +0800 Subject: [PATCH 05/74] chore: fix typo (DistrubuteRef -> DistributeRef) (#11040) --- packages/reactivity/src/ref.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/reactivity/src/ref.ts b/packages/reactivity/src/ref.ts index 5f40fbb7c..bd121e47d 100644 --- a/packages/reactivity/src/ref.ts +++ b/packages/reactivity/src/ref.ts @@ -496,10 +496,10 @@ type BaseTypes = string | number | boolean export interface RefUnwrapBailTypes {} export type ShallowUnwrapRef = { - [K in keyof T]: DistrubuteRef + [K in keyof T]: DistributeRef } -type DistrubuteRef = T extends Ref ? V : T +type DistributeRef = T extends Ref ? V : T export type UnwrapRef = T extends ShallowRef From 70f2f283eee1f34330d38687e5e6d69e2f1d371b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BF=9C=E6=96=B9os?= Date: Thu, 30 May 2024 18:27:38 +0800 Subject: [PATCH 06/74] refactor(types/compat): improve the types for $set and $delete (#8719) --- packages/runtime-core/src/compat/instance.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/runtime-core/src/compat/instance.ts b/packages/runtime-core/src/compat/instance.ts index 18e745ca4..7b89c5ad6 100644 --- a/packages/runtime-core/src/compat/instance.ts +++ b/packages/runtime-core/src/compat/instance.ts @@ -43,8 +43,15 @@ export type LegacyPublicInstance = ComponentPublicInstance & LegacyPublicProperties export interface LegacyPublicProperties { - $set(target: object, key: string, value: any): void - $delete(target: object, key: string): void + $set, K extends keyof T>( + target: T, + key: K, + value: T[K] + ): void + $delete, K extends keyof T>( + target: T, + key: K + ): void $mount(el?: string | Element): this $destroy(): void $scopedSlots: Slots From f8994da00f523d5d792997671f4f55eca43d6598 Mon Sep 17 00:00:00 2001 From: Alex Liu Date: Thu, 30 May 2024 19:41:38 +0800 Subject: [PATCH 07/74] types: improve readability of built-in type (#9129) --- packages/reactivity/src/reactive.ts | 2 +- packages/reactivity/src/ref.ts | 10 ++-------- packages/runtime-core/src/compat/instance.ts | 4 ++-- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/packages/reactivity/src/reactive.ts b/packages/reactivity/src/reactive.ts index a3e7ecc7b..6e28be404 100644 --- a/packages/reactivity/src/reactive.ts +++ b/packages/reactivity/src/reactive.ts @@ -135,7 +135,7 @@ export function shallowReactive( } type Primitive = string | number | boolean | bigint | symbol | undefined | null -type Builtin = Primitive | Function | Date | Error | RegExp +export type Builtin = Primitive | Function | Date | Error | RegExp export type DeepReadonly = T extends Builtin ? T : T extends Map diff --git a/packages/reactivity/src/ref.ts b/packages/reactivity/src/ref.ts index bd121e47d..99170d154 100644 --- a/packages/reactivity/src/ref.ts +++ b/packages/reactivity/src/ref.ts @@ -21,7 +21,7 @@ import { toRaw, toReactive, } from './reactive' -import type { ShallowReactiveMarker } from './reactive' +import type { Builtin, ShallowReactiveMarker } from './reactive' import { type Dep, createDep } from './dep' import { ComputedRefImpl } from './computed' import { getDepFromReactive } from './reactiveEffect' @@ -475,11 +475,6 @@ function propertyToRef( : (new ObjectRefImpl(source, key, defaultValue) as any) } -// corner case when use narrows type -// Ex. type RelativePath = string & { __brand: unknown } -// RelativePath extends object -> true -type BaseTypes = string | number | boolean - /** * This is a special exported interface for other packages to declare * additional types that should bail out for ref unwrapping. For example @@ -509,8 +504,7 @@ export type UnwrapRef = : UnwrapRefSimple export type UnwrapRefSimple = T extends - | Function - | BaseTypes + | Builtin | Ref | RefUnwrapBailTypes[keyof RefUnwrapBailTypes] | { [RawSymbol]?: true } diff --git a/packages/runtime-core/src/compat/instance.ts b/packages/runtime-core/src/compat/instance.ts index 7b89c5ad6..3fa7b454c 100644 --- a/packages/runtime-core/src/compat/instance.ts +++ b/packages/runtime-core/src/compat/instance.ts @@ -46,11 +46,11 @@ export interface LegacyPublicProperties { $set, K extends keyof T>( target: T, key: K, - value: T[K] + value: T[K], ): void $delete, K extends keyof T>( target: T, - key: K + key: K, ): void $mount(el?: string | Element): this $destroy(): void From 34a97edd2c8273c213599c44770accdb0846da8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20Deng=20=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90?= Date: Fri, 31 May 2024 17:08:54 +0800 Subject: [PATCH 08/74] fix(compiler-sfc): throw error when import macro as alias (#11041) --- packages/compiler-sfc/src/compileScript.ts | 48 ++++++++++++++-------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/packages/compiler-sfc/src/compileScript.ts b/packages/compiler-sfc/src/compileScript.ts index 31bee3af7..8a0aaeaf7 100644 --- a/packages/compiler-sfc/src/compileScript.ts +++ b/packages/compiler-sfc/src/compileScript.ts @@ -49,7 +49,7 @@ import { } from './script/defineEmits' import { DEFINE_EXPOSE, processDefineExpose } from './script/defineExpose' import { DEFINE_OPTIONS, processDefineOptions } from './script/defineOptions' -import { processDefineSlots } from './script/defineSlots' +import { DEFINE_SLOTS, processDefineSlots } from './script/defineSlots' import { DEFINE_MODEL, processDefineModel } from './script/defineModel' import { getImportedName, isCallOf, isLiteralNode } from './script/utils' import { analyzeScriptBindings } from './script/analyzeScriptBindings' @@ -135,6 +135,16 @@ export interface ImportBinding { isUsedInTemplate: boolean } +const MACROS = [ + DEFINE_PROPS, + DEFINE_EMITS, + DEFINE_EXPOSE, + DEFINE_OPTIONS, + DEFINE_SLOTS, + DEFINE_MODEL, + WITH_DEFAULTS, +] + /** * Compile `