From 201c46df07a38f3c2b73f384e8e6846dc62f224e Mon Sep 17 00:00:00 2001 From: edison Date: Tue, 11 Jul 2023 17:13:18 +0800 Subject: [PATCH 01/17] fix(ssr): render correct initial selected state for select with v-model (#7432) close #7392 --- .../compiler-ssr/__tests__/ssrVModel.spec.ts | 38 +++++++++++++++++++ .../compiler-ssr/src/transforms/ssrVModel.ts | 33 ++++++++++++++-- .../__tests__/ssrDirectives.spec.ts | 24 ++++++++++++ 3 files changed, 92 insertions(+), 3 deletions(-) diff --git a/packages/compiler-ssr/__tests__/ssrVModel.spec.ts b/packages/compiler-ssr/__tests__/ssrVModel.spec.ts index 3411aa291c9..5bccbcb788c 100644 --- a/packages/compiler-ssr/__tests__/ssrVModel.spec.ts +++ b/packages/compiler-ssr/__tests__/ssrVModel.spec.ts @@ -33,6 +33,44 @@ describe('ssr: v-model', () => { `) }) + test('` + ).code + ).toMatchInlineSnapshot(` + "const { ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"vue/server-renderer\\") + + return function ssrRender(_ctx, _push, _parent, _attrs) { + _push(\`\`) + }" + `) + + expect( + compileWithWrapper( + `` + ).code + ).toMatchInlineSnapshot(` + "const { ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"vue/server-renderer\\") + + return function ssrRender(_ctx, _push, _parent, _attrs) { + _push(\`\`) + }" + `) + }) + test('', () => { expect( compileWithWrapper(``).code diff --git a/packages/compiler-ssr/src/transforms/ssrVModel.ts b/packages/compiler-ssr/src/transforms/ssrVModel.ts index 589ef6a8650..bd587edcb9c 100644 --- a/packages/compiler-ssr/src/transforms/ssrVModel.ts +++ b/packages/compiler-ssr/src/transforms/ssrVModel.ts @@ -18,7 +18,8 @@ import { import { SSR_LOOSE_EQUAL, SSR_LOOSE_CONTAIN, - SSR_RENDER_DYNAMIC_MODEL + SSR_RENDER_DYNAMIC_MODEL, + SSR_INCLUDE_BOOLEAN_ATTR } from '../runtimeHelpers' import { DirectiveTransformResult } from 'packages/compiler-core/src/transform' @@ -129,8 +130,34 @@ export const ssrTransformModel: DirectiveTransform = (dir, node, context) => { checkDuplicatedValue() node.children = [createInterpolation(model, model.loc)] } else if (node.tag === 'select') { - // NOOP - // select relies on client-side directive to set initial selected state. + node.children.forEach(option => { + if (option.type === NodeTypes.ELEMENT) { + const plainNode = option as PlainElementNode + if (plainNode.props.findIndex(p => p.name === 'selected') === -1) { + const value = findValueBinding(plainNode) + plainNode.ssrCodegenNode!.elements.push( + createConditionalExpression( + createCallExpression(context.helper(SSR_INCLUDE_BOOLEAN_ATTR), [ + createConditionalExpression( + createCallExpression(`Array.isArray`, [model]), + createCallExpression(context.helper(SSR_LOOSE_CONTAIN), [ + model, + value + ]), + createCallExpression(context.helper(SSR_LOOSE_EQUAL), [ + model, + value + ]) + ) + ]), + createSimpleExpression(' selected', true), + createSimpleExpression('', true), + false /* no newline */ + ) + ) + } + } + }) } else { context.onError( createDOMCompilerError( diff --git a/packages/server-renderer/__tests__/ssrDirectives.spec.ts b/packages/server-renderer/__tests__/ssrDirectives.spec.ts index 102e95d5b27..e52ef2db69f 100644 --- a/packages/server-renderer/__tests__/ssrDirectives.spec.ts +++ b/packages/server-renderer/__tests__/ssrDirectives.spec.ts @@ -107,6 +107,30 @@ describe('ssr: directives', () => { ).toBe(``) }) + test('select', async () => { + expect( + await renderToString( + createApp({ + data: () => ({ model: 1 }), + template: `` + }) + ) + ).toBe( + `` + ) + + expect( + await renderToString( + createApp({ + data: () => ({ model: [0, 1] }), + template: `` + }) + ) + ).toBe( + `` + ) + }) + test('checkbox', async () => { expect( await renderToString( From 776ebf25b2e7570e78ac1c148fc45c823c21a542 Mon Sep 17 00:00:00 2001 From: vaakian X Date: Tue, 11 Jul 2023 17:26:31 +0800 Subject: [PATCH 02/17] fix(compiler-sfc): fix using imported ref as template ref during dev (#7593) close #7567 --- .../__snapshots__/compileScript.spec.ts.snap | 15 +++++++++++++++ .../__tests__/compileScript.spec.ts | 17 +++++++++++++++++ .../compiler-sfc/src/script/importUsageCheck.ts | 3 +++ 3 files changed, 35 insertions(+) diff --git a/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap b/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap index 18b5d90eaf6..de19ec5aaf2 100644 --- a/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap +++ b/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap @@ -775,6 +775,21 @@ return { get FooBaz() { return FooBaz }, get Last() { return Last } } })" `; +exports[`SFC compile + + `) + expect(content).toMatch( + 'return { get foo() { return foo }, get bar() { return bar }, get Baz() { return Baz } }' + ) + assertCode(content) + }) }) describe('inlineTemplate mode', () => { diff --git a/packages/compiler-sfc/src/script/importUsageCheck.ts b/packages/compiler-sfc/src/script/importUsageCheck.ts index b42397d573b..28456a45bba 100644 --- a/packages/compiler-sfc/src/script/importUsageCheck.ts +++ b/packages/compiler-sfc/src/script/importUsageCheck.ts @@ -57,6 +57,9 @@ function resolveTemplateUsageCheckString(sfc: SFCDescriptor) { )}` } } + if (prop.type === NodeTypes.ATTRIBUTE && prop.name === 'ref' && prop.value?.content) { + code += `,${prop.value.content}` + } } } else if (node.type === NodeTypes.INTERPOLATION) { code += `,${processExp( From ceb0732e0b1bb4c8c505d80e97ff6fc89035fa90 Mon Sep 17 00:00:00 2001 From: Kid <44045911+kidonng@users.noreply.github.com> Date: Tue, 11 Jul 2023 17:30:01 +0800 Subject: [PATCH 03/17] fix(types/jsx): add `inert` attribute and missing `hidden` values (#8090) --- packages/runtime-dom/src/jsx.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/runtime-dom/src/jsx.ts b/packages/runtime-dom/src/jsx.ts index f76c8d7fb17..d3c0332c7c3 100644 --- a/packages/runtime-dom/src/jsx.ts +++ b/packages/runtime-dom/src/jsx.ts @@ -248,8 +248,9 @@ export interface HTMLAttributes extends AriaAttributes, EventHandlers { contextmenu?: string dir?: string draggable?: Booleanish - hidden?: Booleanish + hidden?: Booleanish | '' | 'hidden' | 'until-found' id?: string + inert?: Booleanish lang?: string placeholder?: string spellcheck?: Booleanish From 140a89b833bceed60838182b875d2953c70af114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E9=9B=BE=E4=B8=89=E8=AF=AD?= <32354856+baiwusanyu-c@users.noreply.github.com> Date: Tue, 11 Jul 2023 17:36:26 +0800 Subject: [PATCH 04/17] fix(teleport): handle target change while disabled (#7837) close #7835 --- .../__tests__/components/Teleport.spec.ts | 53 +++++++++++++++++++ .../runtime-core/src/components/Teleport.ts | 7 +++ 2 files changed, 60 insertions(+) diff --git a/packages/runtime-core/__tests__/components/Teleport.spec.ts b/packages/runtime-core/__tests__/components/Teleport.spec.ts index 57180ea139d..7371f53f7b6 100644 --- a/packages/runtime-core/__tests__/components/Teleport.spec.ts +++ b/packages/runtime-core/__tests__/components/Teleport.spec.ts @@ -475,4 +475,57 @@ describe('renderer: teleport', () => { expect(dir.mounted).toHaveBeenCalledTimes(1) expect(dir.unmounted).toHaveBeenCalledTimes(1) }) + + // #7835 + test(`ensure that target changes when disabled are updated correctly when enabled`, async () => { + const root = nodeOps.createElement('div') + const target1 = nodeOps.createElement('div') + const target2 = nodeOps.createElement('div') + const target3 = nodeOps.createElement('div') + const target = ref(target1) + const disabled = ref(true) + + const App = { + setup() { + return () => + h(Fragment, [ + h( + Teleport, + { to: target.value, disabled: disabled.value }, + h('div', 'teleported') + ) + ]) + } + } + render(h(App), root) + disabled.value = false + await nextTick() + expect(serializeInner(target1)).toMatchInlineSnapshot( + `"
teleported
"` + ) + expect(serializeInner(target2)).toMatchInlineSnapshot(`""`) + expect(serializeInner(target3)).toMatchInlineSnapshot(`""`) + + disabled.value = true + await nextTick() + target.value = target2 + await nextTick() + expect(serializeInner(target1)).toMatchInlineSnapshot(`""`) + expect(serializeInner(target2)).toMatchInlineSnapshot(`""`) + expect(serializeInner(target3)).toMatchInlineSnapshot(`""`) + + target.value = target3 + await nextTick() + expect(serializeInner(target1)).toMatchInlineSnapshot(`""`) + expect(serializeInner(target2)).toMatchInlineSnapshot(`""`) + expect(serializeInner(target3)).toMatchInlineSnapshot(`""`) + + disabled.value = false + await nextTick() + expect(serializeInner(target1)).toMatchInlineSnapshot(`""`) + expect(serializeInner(target2)).toMatchInlineSnapshot(`""`) + expect(serializeInner(target3)).toMatchInlineSnapshot( + `"
teleported
"` + ) + }) }) diff --git a/packages/runtime-core/src/components/Teleport.ts b/packages/runtime-core/src/components/Teleport.ts index 6e66d0444f9..4f7d16bc7d1 100644 --- a/packages/runtime-core/src/components/Teleport.ts +++ b/packages/runtime-core/src/components/Teleport.ts @@ -186,6 +186,13 @@ export const TeleportImpl = { internals, TeleportMoveTypes.TOGGLE ) + } else { + // #7835 + // When `teleport` is disabled, `to` may change, making it always old, + // to ensure the correct `to` when enabled + if (n2.props && n1.props && n2.props.to !== n1.props.to) { + n2.props.to = n1.props.to + } } } else { // target changed From 701fa735fc412eb9c0007f1877e5e31ef8ee84a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E9=9B=BE=E4=B8=89=E8=AF=AD?= <32354856+baiwusanyu-c@users.noreply.github.com> Date: Tue, 11 Jul 2023 17:36:54 +0800 Subject: [PATCH 05/17] dx(compiler-sfc): enhance `:deep` warnings (#8328) close #8313 --- packages/compiler-sfc/src/style/pluginScoped.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/compiler-sfc/src/style/pluginScoped.ts b/packages/compiler-sfc/src/style/pluginScoped.ts index 1dcc248ad71..f6e9be2fde7 100644 --- a/packages/compiler-sfc/src/style/pluginScoped.ts +++ b/packages/compiler-sfc/src/style/pluginScoped.ts @@ -130,9 +130,10 @@ function rewriteSelector( // DEPRECATED usage // .foo ::v-deep .bar -> .foo[xxxxxxx] .bar warn( - `::v-deep usage as a combinator has ` + - `been deprecated. Use :deep() instead.` + `${value} usage as a combinator has been deprecated. ` + + `Use :deep() instead of ${value} .` ) + const prev = selector.at(selector.index(n) - 1) if (prev && isSpaceCombinator(prev)) { selector.removeChild(prev) From 7c2e44ff5f10e2d381b503979f6193f6c20fa4c1 Mon Sep 17 00:00:00 2001 From: zqran <215244947@qq.com> Date: Tue, 11 Jul 2023 17:37:56 +0800 Subject: [PATCH 06/17] test(reactivity): use vitest fn instead of counting manually (#8476) --- packages/reactivity/__tests__/ref.spec.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/reactivity/__tests__/ref.spec.ts b/packages/reactivity/__tests__/ref.spec.ts index b0ba9d9cb1c..0ee32866da8 100644 --- a/packages/reactivity/__tests__/ref.spec.ts +++ b/packages/reactivity/__tests__/ref.spec.ts @@ -28,19 +28,18 @@ describe('reactivity/ref', () => { it('should be reactive', () => { const a = ref(1) let dummy - let calls = 0 - effect(() => { - calls++ + const fn = vi.fn(() => { dummy = a.value }) - expect(calls).toBe(1) + effect(fn) + expect(fn).toHaveBeenCalledTimes(1) expect(dummy).toBe(1) a.value = 2 - expect(calls).toBe(2) + expect(fn).toHaveBeenCalledTimes(2) expect(dummy).toBe(2) // same value should not trigger a.value = 2 - expect(calls).toBe(2) + expect(fn).toHaveBeenCalledTimes(2) }) it('should make nested properties reactive', () => { From 736cf154cc27f422c58b10cd9e1fe20ceab0eb10 Mon Sep 17 00:00:00 2001 From: zqran <215244947@qq.com> Date: Tue, 11 Jul 2023 17:38:32 +0800 Subject: [PATCH 07/17] chore(test): replace deprecated `initEvent` (#8490) --- packages/runtime-dom/__tests__/directives/vOn.spec.ts | 6 ++++-- packages/vue-compat/__tests__/utils.ts | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/runtime-dom/__tests__/directives/vOn.spec.ts b/packages/runtime-dom/__tests__/directives/vOn.spec.ts index 8a608343d43..2a4b02478f5 100644 --- a/packages/runtime-dom/__tests__/directives/vOn.spec.ts +++ b/packages/runtime-dom/__tests__/directives/vOn.spec.ts @@ -6,8 +6,10 @@ function triggerEvent( event: string, process?: (e: any) => any ) { - const e = document.createEvent('HTMLEvents') - e.initEvent(event, true, true) + const e = new Event(event, { + bubbles: true, + cancelable: true + }) if (event === 'click') { ;(e as any).button = 0 } diff --git a/packages/vue-compat/__tests__/utils.ts b/packages/vue-compat/__tests__/utils.ts index bcf72b296de..a7242122bcb 100644 --- a/packages/vue-compat/__tests__/utils.ts +++ b/packages/vue-compat/__tests__/utils.ts @@ -3,8 +3,10 @@ export function triggerEvent( event: string, process?: (e: any) => any ) { - const e = document.createEvent('HTMLEvents') - e.initEvent(event, true, true) + const e = new Event(event, { + bubbles: true, + cancelable: true + }) if (process) process(e) target.dispatchEvent(e) return e From 97b6fae6b477d5b1a95e94963667e171e16d5410 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=B6=E8=BF=9C=E6=96=B9?= Date: Tue, 11 Jul 2023 17:41:09 +0800 Subject: [PATCH 08/17] chore(shared): improve isPromise check in accordance with Promise A+ specification (#8506) --- packages/shared/src/general.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/shared/src/general.ts b/packages/shared/src/general.ts index 4138b2730e6..59a1e911b6c 100644 --- a/packages/shared/src/general.ts +++ b/packages/shared/src/general.ts @@ -50,7 +50,11 @@ export const isObject = (val: unknown): val is Record => val !== null && typeof val === 'object' export const isPromise = (val: unknown): val is Promise => { - return isObject(val) && isFunction(val.then) && isFunction(val.catch) + return ( + (isObject(val) || isFunction(val)) && + isFunction(val.then) && + isFunction(val.catch) + ) } export const objectToString = Object.prototype.toString From 438027cf9ecb63260f59d3027e0b188717694795 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Tue, 11 Jul 2023 11:52:43 +0200 Subject: [PATCH 09/17] perf: mark `defineComponent` as side-effects-free (#8512) --- package.json | 2 +- .../runtime-core/src/apiAsyncComponent.ts | 1 + .../runtime-core/src/apiDefineComponent.ts | 1 + packages/runtime-dom/src/apiCustomElement.ts | 2 + pnpm-lock.yaml | 90 +++++++++---------- 5 files changed, 46 insertions(+), 50 deletions(-) diff --git a/package.json b/package.json index 4310ae6368b..07caa03dbb5 100644 --- a/package.json +++ b/package.json @@ -87,7 +87,7 @@ "prettier": "^2.7.1", "pug": "^3.0.1", "puppeteer": "~19.6.0", - "rollup": "^3.20.2", + "rollup": "^3.26.0", "rollup-plugin-dts": "^5.3.0", "rollup-plugin-esbuild": "^5.0.0", "rollup-plugin-polyfill-node": "^0.12.0", diff --git a/packages/runtime-core/src/apiAsyncComponent.ts b/packages/runtime-core/src/apiAsyncComponent.ts index bd878a49442..342339042ef 100644 --- a/packages/runtime-core/src/apiAsyncComponent.ts +++ b/packages/runtime-core/src/apiAsyncComponent.ts @@ -40,6 +40,7 @@ export interface AsyncComponentOptions { export const isAsyncWrapper = (i: ComponentInternalInstance | VNode): boolean => !!(i.type as ComponentOptions).__asyncLoader +/*! #__NO_SIDE_EFFECTS__ */ export function defineAsyncComponent< T extends Component = { new (): ComponentPublicInstance } >(source: AsyncComponentLoader | AsyncComponentOptions): T { diff --git a/packages/runtime-core/src/apiDefineComponent.ts b/packages/runtime-core/src/apiDefineComponent.ts index 76e9567fe2f..272bb548751 100644 --- a/packages/runtime-core/src/apiDefineComponent.ts +++ b/packages/runtime-core/src/apiDefineComponent.ts @@ -274,6 +274,7 @@ export function defineComponent< > // implementation, close to no-op +/*! #__NO_SIDE_EFFECTS__ */ export function defineComponent( options: unknown, extraOptions?: ComponentOptions diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts index 1e551cc05da..2add422586d 100644 --- a/packages/runtime-dom/src/apiCustomElement.ts +++ b/packages/runtime-dom/src/apiCustomElement.ts @@ -140,6 +140,7 @@ export function defineCustomElement(options: { new (...args: any[]): ComponentPublicInstance }): VueElementConstructor +/*! #__NO_SIDE_EFFECTS__ */ export function defineCustomElement( options: any, hydrate?: RootHydrateFunction @@ -155,6 +156,7 @@ export function defineCustomElement( return VueCustomElement } +/*! #__NO_SIDE_EFFECTS__ */ export const defineSSRCustomElement = ((options: any) => { // @ts-ignore return defineCustomElement(options, hydrate) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 17029035c31..77ac98cc527 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,22 +16,22 @@ importers: version: 7.21.3 '@rollup/plugin-alias': specifier: ^4.0.3 - version: 4.0.4(rollup@3.20.2) + version: 4.0.4(rollup@3.26.2) '@rollup/plugin-commonjs': specifier: ^24.0.1 - version: 24.1.0(rollup@3.20.2) + version: 24.1.0(rollup@3.26.2) '@rollup/plugin-json': specifier: ^6.0.0 - version: 6.0.0(rollup@3.20.2) + version: 6.0.0(rollup@3.26.2) '@rollup/plugin-node-resolve': specifier: ^15.0.1 - version: 15.1.0(rollup@3.20.2) + version: 15.1.0(rollup@3.26.2) '@rollup/plugin-replace': specifier: ^5.0.2 - version: 5.0.2(rollup@3.20.2) + version: 5.0.2(rollup@3.26.2) '@rollup/plugin-terser': specifier: ^0.4.0 - version: 0.4.0(rollup@3.20.2) + version: 0.4.0(rollup@3.26.2) '@types/hash-sum': specifier: ^1.0.0 version: 1.0.0 @@ -105,17 +105,17 @@ importers: specifier: ~19.6.0 version: 19.6.3 rollup: - specifier: ^3.20.2 - version: 3.20.2 + specifier: ^3.26.0 + version: 3.26.2 rollup-plugin-dts: specifier: ^5.3.0 - version: 5.3.0(rollup@3.20.2)(typescript@5.0.2) + version: 5.3.0(rollup@3.26.2)(typescript@5.0.2) rollup-plugin-esbuild: specifier: ^5.0.0 - version: 5.0.0(esbuild@0.17.19)(rollup@3.20.2) + version: 5.0.0(esbuild@0.17.19)(rollup@3.26.2) rollup-plugin-polyfill-node: specifier: ^0.12.0 - version: 0.12.0(rollup@3.20.2) + version: 0.12.0(rollup@3.26.2) semver: specifier: ^7.3.2 version: 7.5.3 @@ -1130,7 +1130,7 @@ packages: fastq: 1.15.0 dev: true - /@rollup/plugin-alias@4.0.4(rollup@3.20.2): + /@rollup/plugin-alias@4.0.4(rollup@3.26.2): resolution: {integrity: sha512-0CaAY238SMtYAWEXXptWSR8iz8NYZnH7zNBKuJ14xFJSGwLtPgjvXYsoApAHfzYXXH1ejxpVw7WlHss3zhh9SQ==} engines: {node: '>=14.0.0'} peerDependencies: @@ -1139,11 +1139,11 @@ packages: rollup: optional: true dependencies: - rollup: 3.20.2 + rollup: 3.26.2 slash: 4.0.0 dev: true - /@rollup/plugin-commonjs@24.1.0(rollup@3.20.2): + /@rollup/plugin-commonjs@24.1.0(rollup@3.26.2): resolution: {integrity: sha512-eSL45hjhCWI0jCCXcNtLVqM5N1JlBGvlFfY0m6oOYnLCJ6N0qEXoZql4sY2MOUArzhH4SA/qBpTxvvZp2Sc+DQ==} engines: {node: '>=14.0.0'} peerDependencies: @@ -1152,16 +1152,16 @@ packages: rollup: optional: true dependencies: - '@rollup/pluginutils': 5.0.2(rollup@3.20.2) + '@rollup/pluginutils': 5.0.2(rollup@3.26.2) commondir: 1.0.1 estree-walker: 2.0.2 glob: 8.1.0 is-reference: 1.2.1 magic-string: 0.27.0 - rollup: 3.20.2 + rollup: 3.26.2 dev: true - /@rollup/plugin-inject@5.0.3(rollup@3.20.2): + /@rollup/plugin-inject@5.0.3(rollup@3.26.2): resolution: {integrity: sha512-411QlbL+z2yXpRWFXSmw/teQRMkXcAAC8aYTemc15gwJRpvEVDQwoe+N/HTFD8RFG8+88Bme9DK2V9CVm7hJdA==} engines: {node: '>=14.0.0'} peerDependencies: @@ -1170,13 +1170,13 @@ packages: rollup: optional: true dependencies: - '@rollup/pluginutils': 5.0.2(rollup@3.20.2) + '@rollup/pluginutils': 5.0.2(rollup@3.26.2) estree-walker: 2.0.2 magic-string: 0.27.0 - rollup: 3.20.2 + rollup: 3.26.2 dev: true - /@rollup/plugin-json@6.0.0(rollup@3.20.2): + /@rollup/plugin-json@6.0.0(rollup@3.26.2): resolution: {integrity: sha512-i/4C5Jrdr1XUarRhVu27EEwjt4GObltD7c+MkCIpO2QIbojw8MUs+CCTqOphQi3Qtg1FLmYt+l+6YeoIf51J7w==} engines: {node: '>=14.0.0'} peerDependencies: @@ -1185,11 +1185,11 @@ packages: rollup: optional: true dependencies: - '@rollup/pluginutils': 5.0.2(rollup@3.20.2) - rollup: 3.20.2 + '@rollup/pluginutils': 5.0.2(rollup@3.26.2) + rollup: 3.26.2 dev: true - /@rollup/plugin-node-resolve@15.1.0(rollup@3.20.2): + /@rollup/plugin-node-resolve@15.1.0(rollup@3.26.2): resolution: {integrity: sha512-xeZHCgsiZ9pzYVgAo9580eCGqwh/XCEUM9q6iQfGNocjgkufHAqC3exA+45URvhiYV8sBF9RlBai650eNs7AsA==} engines: {node: '>=14.0.0'} peerDependencies: @@ -1198,16 +1198,16 @@ packages: rollup: optional: true dependencies: - '@rollup/pluginutils': 5.0.2(rollup@3.20.2) + '@rollup/pluginutils': 5.0.2(rollup@3.26.2) '@types/resolve': 1.20.2 deepmerge: 4.3.0 is-builtin-module: 3.2.1 is-module: 1.0.0 resolve: 1.22.1 - rollup: 3.20.2 + rollup: 3.26.2 dev: true - /@rollup/plugin-replace@5.0.2(rollup@3.20.2): + /@rollup/plugin-replace@5.0.2(rollup@3.26.2): resolution: {integrity: sha512-M9YXNekv/C/iHHK+cvORzfRYfPbq0RDD8r0G+bMiTXjNGKulPnCT9O3Ss46WfhI6ZOCgApOP7xAdmCQJ+U2LAA==} engines: {node: '>=14.0.0'} peerDependencies: @@ -1216,12 +1216,12 @@ packages: rollup: optional: true dependencies: - '@rollup/pluginutils': 5.0.2(rollup@3.20.2) + '@rollup/pluginutils': 5.0.2(rollup@3.26.2) magic-string: 0.27.0 - rollup: 3.20.2 + rollup: 3.26.2 dev: true - /@rollup/plugin-terser@0.4.0(rollup@3.20.2): + /@rollup/plugin-terser@0.4.0(rollup@3.26.2): resolution: {integrity: sha512-Ipcf3LPNerey1q9ZMjiaWHlNPEHNU/B5/uh9zXLltfEQ1lVSLLeZSgAtTPWGyw8Ip1guOeq+mDtdOlEj/wNxQw==} engines: {node: '>=14.0.0'} peerDependencies: @@ -1230,13 +1230,13 @@ packages: rollup: optional: true dependencies: - rollup: 3.20.2 + rollup: 3.26.2 serialize-javascript: 6.0.1 smob: 0.0.6 terser: 5.18.2 dev: true - /@rollup/pluginutils@5.0.2(rollup@3.20.2): + /@rollup/pluginutils@5.0.2(rollup@3.26.2): resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} engines: {node: '>=14.0.0'} peerDependencies: @@ -1248,7 +1248,7 @@ packages: '@types/estree': 1.0.0 estree-walker: 2.0.2 picomatch: 2.3.1 - rollup: 3.20.2 + rollup: 3.26.2 dev: true /@tootallnate/once@2.0.0: @@ -4996,7 +4996,7 @@ packages: glob: 7.2.3 dev: true - /rollup-plugin-dts@5.3.0(rollup@3.20.2)(typescript@5.0.2): + /rollup-plugin-dts@5.3.0(rollup@3.26.2)(typescript@5.0.2): resolution: {integrity: sha512-8FXp0ZkyZj1iU5klkIJYLjIq/YZSwBoERu33QBDxm/1yw5UU4txrEtcmMkrq+ZiKu3Q4qvPCNqc3ovX6rjqzbQ==} engines: {node: '>=v14'} peerDependencies: @@ -5004,45 +5004,37 @@ packages: typescript: ^4.1 || ^5.0 dependencies: magic-string: 0.30.0 - rollup: 3.20.2 + rollup: 3.26.2 typescript: 5.0.2 optionalDependencies: '@babel/code-frame': 7.22.5 dev: true - /rollup-plugin-esbuild@5.0.0(esbuild@0.17.19)(rollup@3.20.2): + /rollup-plugin-esbuild@5.0.0(esbuild@0.17.19)(rollup@3.26.2): resolution: {integrity: sha512-1cRIOHAPh8WQgdQQyyvFdeOdxuiyk+zB5zJ5+YOwrZP4cJ0MT3Fs48pQxrZeyZHcn+klFherytILVfE4aYrneg==} engines: {node: '>=14.18.0', npm: '>=8.0.0'} peerDependencies: esbuild: '>=0.10.1' rollup: ^1.20.0 || ^2.0.0 || ^3.0.0 dependencies: - '@rollup/pluginutils': 5.0.2(rollup@3.20.2) + '@rollup/pluginutils': 5.0.2(rollup@3.26.2) debug: 4.3.4 es-module-lexer: 1.1.0 esbuild: 0.17.19 joycon: 3.1.1 jsonc-parser: 3.2.0 - rollup: 3.20.2 + rollup: 3.26.2 transitivePeerDependencies: - supports-color dev: true - /rollup-plugin-polyfill-node@0.12.0(rollup@3.20.2): + /rollup-plugin-polyfill-node@0.12.0(rollup@3.26.2): resolution: {integrity: sha512-PWEVfDxLEKt8JX1nZ0NkUAgXpkZMTb85rO/Ru9AQ69wYW8VUCfDgP4CGRXXWYni5wDF0vIeR1UoF3Jmw/Lt3Ug==} peerDependencies: rollup: ^1.20.0 || ^2.0.0 || ^3.0.0 dependencies: - '@rollup/plugin-inject': 5.0.3(rollup@3.20.2) - rollup: 3.20.2 - dev: true - - /rollup@3.20.2: - resolution: {integrity: sha512-3zwkBQl7Ai7MFYQE0y1MeQ15+9jsi7XxfrqwTb/9EK8D9C9+//EBR4M+CuA1KODRaNbFez/lWxA5vhEGZp4MUg==} - engines: {node: '>=14.18.0', npm: '>=8.0.0'} - hasBin: true - optionalDependencies: - fsevents: 2.3.2 + '@rollup/plugin-inject': 5.0.3(rollup@3.26.2) + rollup: 3.26.2 dev: true /rollup@3.26.2: @@ -5808,7 +5800,7 @@ packages: '@types/node': 16.18.38 esbuild: 0.17.19 postcss: 8.4.21 - rollup: 3.20.2 + rollup: 3.26.2 terser: 5.18.2 optionalDependencies: fsevents: 2.3.2 From 6a22b1f6c287b60eda385df8a514335af8e040ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=B6=E8=BF=9C=E6=96=B9?= Date: Tue, 11 Jul 2023 17:56:02 +0800 Subject: [PATCH 10/17] fix(types): ensure nextTick return type reflect correct Promise value (#8406) --- packages/runtime-core/__tests__/scheduler.spec.ts | 12 ++++++++++++ packages/runtime-core/src/scheduler.ts | 8 ++++---- packages/shared/src/typeUtils.ts | 9 +++++++++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/packages/runtime-core/__tests__/scheduler.spec.ts b/packages/runtime-core/__tests__/scheduler.spec.ts index c06b9afb3e3..6246a87e8f7 100644 --- a/packages/runtime-core/__tests__/scheduler.spec.ts +++ b/packages/runtime-core/__tests__/scheduler.spec.ts @@ -546,4 +546,16 @@ describe('scheduler', () => { await nextTick() expect(spy).toHaveBeenCalledTimes(1) }) + + it('nextTick should return promise', async () => { + const fn = vi.fn(() => { + return 1 + }) + + const p = nextTick(fn) + + expect(p).toBeInstanceOf(Promise) + expect(await p).toBe(1) + expect(fn).toHaveBeenCalledTimes(1) + }) }) diff --git a/packages/runtime-core/src/scheduler.ts b/packages/runtime-core/src/scheduler.ts index 923f3ec8251..64c70ab59ca 100644 --- a/packages/runtime-core/src/scheduler.ts +++ b/packages/runtime-core/src/scheduler.ts @@ -1,5 +1,5 @@ import { ErrorCodes, callWithErrorHandling } from './errorHandling' -import { isArray, NOOP } from '@vue/shared' +import { Awaited, isArray, NOOP } from '@vue/shared' import { ComponentInternalInstance, getComponentName } from './component' import { warn } from './warning' @@ -50,10 +50,10 @@ let currentFlushPromise: Promise | null = null const RECURSION_LIMIT = 100 type CountMap = Map -export function nextTick( +export function nextTick( this: T, - fn?: (this: T) => void -): Promise { + fn?: (this: T) => R +): Promise> { const p = currentFlushPromise || resolvedPromise return fn ? p.then(this ? fn.bind(this) : fn) : p } diff --git a/packages/shared/src/typeUtils.ts b/packages/shared/src/typeUtils.ts index 67fb47c23b3..1deb4729125 100644 --- a/packages/shared/src/typeUtils.ts +++ b/packages/shared/src/typeUtils.ts @@ -12,3 +12,12 @@ export type LooseRequired = { [P in keyof (T & Required)]: T[P] } // If the type T accepts type "any", output type Y, otherwise output type N. // https://stackoverflow.com/questions/49927523/disallow-call-with-any/49928360#49928360 export type IfAny = 0 extends 1 & T ? Y : N + +// To prevent users with TypeScript versions lower than 4.5 from encountering unsupported Awaited type, a copy has been made here. +export type Awaited = T extends null | undefined + ? T // special case for `null | undefined` when not in `--strictNullChecks` mode + : T extends object & { then(onfulfilled: infer F, ...args: infer _): any } // `await` only unwraps object types with a callable `then`. Non-object types are not unwrapped + ? F extends (value: infer V, ...args: infer _) => any // if the argument to `then` is callable, extracts the first argument + ? Awaited // recursively unwrap the value + : never // the argument to `then` was not callable + : T // non-object or non-thenable From f07cb18fedf9a446545aadf76bcdfb957c7ebcbd Mon Sep 17 00:00:00 2001 From: zqran <215244947@qq.com> Date: Tue, 11 Jul 2023 18:35:22 +0800 Subject: [PATCH 11/17] fix(types): correct withDefaults return type for boolean prop with undefined default value (#8602) --- packages/dts-test/setupHelpers.test-d.ts | 20 ++++++++++++++++++++ packages/runtime-core/src/apiSetupHelpers.ts | 8 +++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/packages/dts-test/setupHelpers.test-d.ts b/packages/dts-test/setupHelpers.test-d.ts index 77342590dc6..934e6056d2d 100644 --- a/packages/dts-test/setupHelpers.test-d.ts +++ b/packages/dts-test/setupHelpers.test-d.ts @@ -134,6 +134,26 @@ describe('defineProps w/ generic type declaration + withDefaults', (res.bool) }) +describe('withDefaults w/ boolean type', () => { + const res1 = withDefaults( + defineProps<{ + bool?: boolean + }>(), + { bool: false } + ) + expectType(res1.bool) + + const res2 = withDefaults( + defineProps<{ + bool?: boolean + }>(), + { + bool: undefined + } + ) + expectType(res2.bool) +}) + describe('defineProps w/ runtime declaration', () => { // runtime declaration const props = defineProps({ diff --git a/packages/runtime-core/src/apiSetupHelpers.ts b/packages/runtime-core/src/apiSetupHelpers.ts index c00937981d9..93200667081 100644 --- a/packages/runtime-core/src/apiSetupHelpers.ts +++ b/packages/runtime-core/src/apiSetupHelpers.ts @@ -303,7 +303,13 @@ type PropsWithDefaults< ? T[K] : NotUndefined : never -} & { readonly [K in BKeys]-?: boolean } +} & { + readonly [K in BKeys]-?: K extends keyof Defaults + ? Defaults[K] extends undefined + ? boolean | undefined + : boolean + : boolean +} /** * Vue ` + + `) + expect(content).toMatch( + `return { get FooBar() { return FooBar }, get foo() { return foo }, ` + + `get bar() { return bar } }` + ) + assertCode(content) + }) + // https://github.com/vuejs/core/issues/4599 test('attribute expressions', () => { const { content } = compile(` diff --git a/packages/compiler-sfc/src/script/importUsageCheck.ts b/packages/compiler-sfc/src/script/importUsageCheck.ts index 28456a45bba..7019dcf2312 100644 --- a/packages/compiler-sfc/src/script/importUsageCheck.ts +++ b/packages/compiler-sfc/src/script/importUsageCheck.ts @@ -50,6 +50,12 @@ function resolveTemplateUsageCheckString(sfc: SFCDescriptor) { if (!isBuiltInDirective(prop.name)) { code += `,v${capitalize(camelize(prop.name))}` } + if (prop.arg && !(prop.arg as SimpleExpressionNode).isStatic) { + code += `,${processExp( + (prop.arg as SimpleExpressionNode).content, + prop.name + )}` + } if (prop.exp) { code += `,${processExp( (prop.exp as SimpleExpressionNode).content, From 2a2810c716e7882a2dbd5ce2007973d5c14e81f5 Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 11 Jul 2023 18:44:00 +0800 Subject: [PATCH 13/17] chore: upgrade to typescript 5.1 --- package.json | 2 +- packages/dts-test/defineComponent.test-d.tsx | 2 +- packages/shared/src/general.ts | 4 +- pnpm-lock.yaml | 51 +++++++++++--------- 4 files changed, 33 insertions(+), 26 deletions(-) diff --git a/package.json b/package.json index 07caa03dbb5..f14db16ddae 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "terser": "^5.15.1", "todomvc-app-css": "^2.3.0", "tslib": "^2.5.0", - "typescript": "^5.0.0", + "typescript": "^5.1.6", "vite": "^4.3.0", "vitest": "^0.30.1" } diff --git a/packages/dts-test/defineComponent.test-d.tsx b/packages/dts-test/defineComponent.test-d.tsx index edd8d17eb06..7466249e10f 100644 --- a/packages/dts-test/defineComponent.test-d.tsx +++ b/packages/dts-test/defineComponent.test-d.tsx @@ -1363,13 +1363,13 @@ describe('function syntax w/ runtime props', () => { } ) - // @ts-expect-error prop type mismatch defineComponent( (_props: { msg: string }) => { return () => {} }, { props: { + // @ts-expect-error prop type mismatch msg: Number } } diff --git a/packages/shared/src/general.ts b/packages/shared/src/general.ts index 59a1e911b6c..0117e67000d 100644 --- a/packages/shared/src/general.ts +++ b/packages/shared/src/general.ts @@ -52,8 +52,8 @@ export const isObject = (val: unknown): val is Record => export const isPromise = (val: unknown): val is Promise => { return ( (isObject(val) || isFunction(val)) && - isFunction(val.then) && - isFunction(val.catch) + isFunction((val as any).then) && + isFunction((val as any).catch) ) } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 77ac98cc527..62d5e18f419 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,7 +40,7 @@ importers: version: 16.18.38 '@typescript-eslint/parser': specifier: ^5.56.0 - version: 5.56.0(eslint@8.33.0)(typescript@5.0.2) + version: 5.56.0(eslint@8.33.0)(typescript@5.1.6) '@vitest/coverage-istanbul': specifier: ^0.29.7 version: 0.29.7(vitest@0.30.1) @@ -67,7 +67,7 @@ importers: version: 8.33.0 eslint-plugin-jest: specifier: ^27.2.1 - version: 27.2.2(eslint@8.33.0)(typescript@5.0.2) + version: 27.2.2(eslint@8.33.0)(typescript@5.1.6) estree-walker: specifier: ^2.0.2 version: 2.0.2 @@ -109,7 +109,7 @@ importers: version: 3.26.2 rollup-plugin-dts: specifier: ^5.3.0 - version: 5.3.0(rollup@3.26.2)(typescript@5.0.2) + version: 5.3.0(rollup@3.26.2)(typescript@5.1.6) rollup-plugin-esbuild: specifier: ^5.0.0 version: 5.0.0(esbuild@0.17.19)(rollup@3.26.2) @@ -135,8 +135,8 @@ importers: specifier: ^2.5.0 version: 2.6.0 typescript: - specifier: ^5.0.0 - version: 5.0.2 + specifier: ^5.1.6 + version: 5.1.6 vite: specifier: ^4.3.0 version: 4.3.1(@types/node@16.18.38)(terser@5.18.2) @@ -1318,7 +1318,7 @@ packages: dev: true optional: true - /@typescript-eslint/parser@5.56.0(eslint@8.33.0)(typescript@5.0.2): + /@typescript-eslint/parser@5.56.0(eslint@8.33.0)(typescript@5.1.6): resolution: {integrity: sha512-sn1OZmBxUsgxMmR8a8U5QM/Wl+tyqlH//jTqCg8daTAmhAk26L2PFhcqPLlYBhYUJMZJK276qLXlHN3a83o2cg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -1330,10 +1330,10 @@ packages: dependencies: '@typescript-eslint/scope-manager': 5.56.0 '@typescript-eslint/types': 5.56.0 - '@typescript-eslint/typescript-estree': 5.56.0(typescript@5.0.2) + '@typescript-eslint/typescript-estree': 5.56.0(typescript@5.1.6) debug: 4.3.4 eslint: 8.33.0 - typescript: 5.0.2 + typescript: 5.1.6 transitivePeerDependencies: - supports-color dev: true @@ -1364,7 +1364,7 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@typescript-eslint/typescript-estree@5.50.0(typescript@5.0.2): + /@typescript-eslint/typescript-estree@5.50.0(typescript@5.1.6): resolution: {integrity: sha512-Gq4zapso+OtIZlv8YNAStFtT6d05zyVCK7Fx3h5inlLBx2hWuc/0465C2mg/EQDDU2LKe52+/jN4f0g9bd+kow==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -1379,13 +1379,13 @@ packages: globby: 11.1.0 is-glob: 4.0.3 semver: 7.5.3 - tsutils: 3.21.0(typescript@5.0.2) - typescript: 5.0.2 + tsutils: 3.21.0(typescript@5.1.6) + typescript: 5.1.6 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/typescript-estree@5.56.0(typescript@5.0.2): + /@typescript-eslint/typescript-estree@5.56.0(typescript@5.1.6): resolution: {integrity: sha512-41CH/GncsLXOJi0jb74SnC7jVPWeVJ0pxQj8bOjH1h2O26jXN3YHKDT1ejkVz5YeTEQPeLCCRY0U2r68tfNOcg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -1400,13 +1400,13 @@ packages: globby: 11.1.0 is-glob: 4.0.3 semver: 7.5.3 - tsutils: 3.21.0(typescript@5.0.2) - typescript: 5.0.2 + tsutils: 3.21.0(typescript@5.1.6) + typescript: 5.1.6 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/utils@5.50.0(eslint@8.33.0)(typescript@5.0.2): + /@typescript-eslint/utils@5.50.0(eslint@8.33.0)(typescript@5.1.6): resolution: {integrity: sha512-v/AnUFImmh8G4PH0NDkf6wA8hujNNcrwtecqW4vtQ1UOSNBaZl49zP1SHoZ/06e+UiwzHpgb5zP5+hwlYYWYAw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -1416,7 +1416,7 @@ packages: '@types/semver': 7.3.13 '@typescript-eslint/scope-manager': 5.50.0 '@typescript-eslint/types': 5.50.0 - '@typescript-eslint/typescript-estree': 5.50.0(typescript@5.0.2) + '@typescript-eslint/typescript-estree': 5.50.0(typescript@5.1.6) eslint: 8.33.0 eslint-scope: 5.1.1 eslint-utils: 3.0.0(eslint@8.33.0) @@ -2643,7 +2643,7 @@ packages: source-map: 0.6.1 dev: true - /eslint-plugin-jest@27.2.2(eslint@8.33.0)(typescript@5.0.2): + /eslint-plugin-jest@27.2.2(eslint@8.33.0)(typescript@5.1.6): resolution: {integrity: sha512-euzbp06F934Z7UDl5ZUaRPLAc9MKjh0rMPERrHT7UhlCEwgb25kBj37TvMgWeHZVkR5I9CayswrpoaqZU1RImw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: @@ -2656,7 +2656,7 @@ packages: jest: optional: true dependencies: - '@typescript-eslint/utils': 5.50.0(eslint@8.33.0)(typescript@5.0.2) + '@typescript-eslint/utils': 5.50.0(eslint@8.33.0)(typescript@5.1.6) eslint: 8.33.0 transitivePeerDependencies: - supports-color @@ -4996,7 +4996,7 @@ packages: glob: 7.2.3 dev: true - /rollup-plugin-dts@5.3.0(rollup@3.26.2)(typescript@5.0.2): + /rollup-plugin-dts@5.3.0(rollup@3.26.2)(typescript@5.1.6): resolution: {integrity: sha512-8FXp0ZkyZj1iU5klkIJYLjIq/YZSwBoERu33QBDxm/1yw5UU4txrEtcmMkrq+ZiKu3Q4qvPCNqc3ovX6rjqzbQ==} engines: {node: '>=v14'} peerDependencies: @@ -5005,7 +5005,7 @@ packages: dependencies: magic-string: 0.30.0 rollup: 3.26.2 - typescript: 5.0.2 + typescript: 5.1.6 optionalDependencies: '@babel/code-frame': 7.22.5 dev: true @@ -5599,14 +5599,14 @@ packages: resolution: {integrity: sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==} dev: true - /tsutils@3.21.0(typescript@5.0.2): + /tsutils@3.21.0(typescript@5.1.6): resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} engines: {node: '>= 6'} peerDependencies: typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' dependencies: tslib: 1.14.1 - typescript: 5.0.2 + typescript: 5.1.6 dev: true /type-check@0.3.2: @@ -5665,6 +5665,13 @@ packages: resolution: {integrity: sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==} engines: {node: '>=12.20'} hasBin: true + dev: false + + /typescript@5.1.6: + resolution: {integrity: sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==} + engines: {node: '>=14.17'} + hasBin: true + dev: true /ufo@1.1.1: resolution: {integrity: sha512-MvlCc4GHrmZdAllBc0iUDowff36Q9Ndw/UzqmEKyrfSzokTd9ZCy1i+IIk5hrYKkjoYVQyNbrw7/F8XJ2rEwTg==} From 24db9516d8b4857182ec1a3af86cb7346691679b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90=20Kevin=20Deng?= Date: Wed, 12 Jul 2023 11:03:14 +0800 Subject: [PATCH 14/17] fix(compiler-sfc): don't hoist props and emit (#8535) fix #7805 close #7812 --- .../__snapshots__/compileScript.spec.ts.snap | 87 ++++--------------- .../__tests__/compileScript.spec.ts | 76 ++++------------ .../__snapshots__/defineEmits.spec.ts.snap | 64 +++++++------- .../__snapshots__/defineProps.spec.ts.snap | 48 +++------- .../definePropsDestructure.spec.ts.snap | 59 ++++++++++++- .../compileScript/defineEmits.spec.ts | 6 +- .../definePropsDestructure.spec.ts | 52 +++++++++++ packages/compiler-sfc/src/compileScript.ts | 55 +++++++----- packages/compiler-sfc/src/script/context.ts | 7 +- .../compiler-sfc/src/script/defineEmits.ts | 5 +- .../compiler-sfc/src/script/defineProps.ts | 55 ++++++------ .../src/script/definePropsDestructure.ts | 1 - 12 files changed, 260 insertions(+), 255 deletions(-) diff --git a/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap b/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap index b7925ada895..949c9946d9f 100644 --- a/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap +++ b/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap @@ -62,6 +62,24 @@ return { fn } })" `; +exports[`SFC compile - `) - assertCode(content) - expect(content).toMatch(`const a = 1;`) // test correct removal - expect(content).toMatch(`props: ['item'],`) - expect(content).toMatch(`emits: ['a'],`) - }) - - // #6757 - test('defineProps/defineEmits in multi-variable declaration fix #6757 ', () => { - const { content } = compile(` - - `) - assertCode(content) - expect(content).toMatch(`const a = 1;`) // test correct removal - expect(content).toMatch(`props: ['item'],`) - expect(content).toMatch(`emits: ['a'],`) - }) - - // #7422 - test('defineProps/defineEmits in multi-variable declaration fix #7422', () => { - const { content } = compile(` - - `) - assertCode(content) - expect(content).toMatch(`props: ['item'],`) - expect(content).toMatch(`emits: ['foo'],`) - expect(content).toMatch(`const a = 0,`) - expect(content).toMatch(`b = 0;`) - }) - - test('defineProps/defineEmits in multi-variable declaration (full removal)', () => { - const { content } = compile(` - - `) - assertCode(content) - expect(content).toMatch(`props: ['item'],`) - expect(content).toMatch(`emits: ['a'],`) - }) - describe(' + `) + assertCode(content) + + expect(content).toMatch(`console.log('test')`) + expect(content).toMatch(`const props = __props;`) + expect(content).toMatch(`const emit = __emit;`) + expect(content).toMatch(`(function () {})()`) + }) + test('script setup first, named default export', () => { const { content } = compile(` + `) + assertCode(content) + expect(content).toMatch(`const a = 1;`) + expect(content).toMatch(`props: ['item'],`) + }) + + // #6757 + test('multi-variable declaration fix #6757 ', () => { + const { content } = compile(` + + `) + assertCode(content) + expect(content).toMatch(`const a = 1;`) + expect(content).toMatch(`props: ['item'],`) + }) + + // #7422 + test('multi-variable declaration fix #7422', () => { + const { content } = compile(` + + `) + assertCode(content) + expect(content).toMatch(`const a = 0,`) + expect(content).toMatch(`b = 0;`) + expect(content).toMatch(`props: ['item'],`) + }) + + test('defineProps/defineEmits in multi-variable declaration (full removal)', () => { + const { content } = compile(` + + `) + assertCode(content) + expect(content).toMatch(`props: ['item'],`) + expect(content).toMatch(`emits: ['a'],`) + }) + describe('errors', () => { test('should error on deep destructure', () => { expect(() => diff --git a/packages/compiler-sfc/src/compileScript.ts b/packages/compiler-sfc/src/compileScript.ts index 046797cfbe5..cfcc607c72d 100644 --- a/packages/compiler-sfc/src/compileScript.ts +++ b/packages/compiler-sfc/src/compileScript.ts @@ -552,7 +552,11 @@ export function compileScript( (processDefineSlots(ctx, init, decl.id) || processDefineModel(ctx, init, decl.id)) - if (isDefineProps || isDefineEmits) { + if ( + isDefineProps && + !ctx.propsDestructureRestId && + ctx.propsDestructureDecl + ) { if (left === 1) { ctx.s.remove(node.start! + startOffset, node.end! + startOffset) } else { @@ -570,6 +574,12 @@ export function compileScript( ctx.s.remove(start, end) left-- } + } else if (isDefineEmits) { + ctx.s.overwrite( + startOffset + init.start!, + startOffset + init.end!, + '__emit' + ) } else { lastNonRemoved = i } @@ -781,22 +791,29 @@ export function compileScript( // inject user assignment of props // we use a default __props so that template expressions referencing props // can use it directly - if (ctx.propsIdentifier) { - ctx.s.prependLeft( - startOffset, - `\nconst ${ctx.propsIdentifier} = __props;\n` - ) - } - if (ctx.propsDestructureRestId) { - ctx.s.prependLeft( - startOffset, - `\nconst ${ctx.propsDestructureRestId} = ${ctx.helper( - `createPropsRestProxy` - )}(__props, ${JSON.stringify( - Object.keys(ctx.propsDestructuredBindings) - )});\n` - ) + if (ctx.propsDecl) { + if (ctx.propsDestructureRestId) { + ctx.s.overwrite( + startOffset + ctx.propsCall!.start!, + startOffset + ctx.propsCall!.end!, + `${ctx.helper(`createPropsRestProxy`)}(__props, ${JSON.stringify( + Object.keys(ctx.propsDestructuredBindings) + )})` + ) + ctx.s.overwrite( + startOffset + ctx.propsDestructureDecl!.start!, + startOffset + ctx.propsDestructureDecl!.end!, + ctx.propsDestructureRestId + ) + } else if (!ctx.propsDestructureDecl) { + ctx.s.overwrite( + startOffset + ctx.propsCall!.start!, + startOffset + ctx.propsCall!.end!, + '__props' + ) + } } + // inject temp variables for async context preservation if (hasAwait) { const any = ctx.isTS ? `: any` : `` @@ -807,10 +824,8 @@ export function compileScript( ctx.hasDefineExposeCall || !options.inlineTemplate ? [`expose: __expose`] : [] - if (ctx.emitIdentifier) { - destructureElements.push( - ctx.emitIdentifier === `emit` ? `emit` : `emit: ${ctx.emitIdentifier}` - ) + if (ctx.emitDecl) { + destructureElements.push(`emit: __emit`) } if (destructureElements.length) { args += `, { ${destructureElements.join(', ')} }` diff --git a/packages/compiler-sfc/src/script/context.ts b/packages/compiler-sfc/src/script/context.ts index af2dee16568..5fe09d28a42 100644 --- a/packages/compiler-sfc/src/script/context.ts +++ b/packages/compiler-sfc/src/script/context.ts @@ -1,4 +1,4 @@ -import { Node, ObjectPattern, Program } from '@babel/types' +import { CallExpression, Node, ObjectPattern, Program } from '@babel/types' import { SFCDescriptor } from '../parse' import { generateCodeFrame } from '@vue/shared' import { parse as babelParse, ParserPlugin } from '@babel/parser' @@ -38,7 +38,8 @@ export class ScriptCompileContext { hasDefineModelCall = false // defineProps - propsIdentifier: string | undefined + propsCall: CallExpression | undefined + propsDecl: Node | undefined propsRuntimeDecl: Node | undefined propsTypeDecl: Node | undefined propsDestructureDecl: ObjectPattern | undefined @@ -49,7 +50,7 @@ export class ScriptCompileContext { // defineEmits emitsRuntimeDecl: Node | undefined emitsTypeDecl: Node | undefined - emitIdentifier: string | undefined + emitDecl: Node | undefined // defineModel modelDecls: Record = {} diff --git a/packages/compiler-sfc/src/script/defineEmits.ts b/packages/compiler-sfc/src/script/defineEmits.ts index a50cf91fc4a..02014d1b276 100644 --- a/packages/compiler-sfc/src/script/defineEmits.ts +++ b/packages/compiler-sfc/src/script/defineEmits.ts @@ -29,10 +29,7 @@ export function processDefineEmits( ctx.emitsTypeDecl = node.typeParameters.params[0] } - if (declId) { - ctx.emitIdentifier = - declId.type === 'Identifier' ? declId.name : ctx.getString(declId) - } + ctx.emitDecl = declId return true } diff --git a/packages/compiler-sfc/src/script/defineProps.ts b/packages/compiler-sfc/src/script/defineProps.ts index 1ae5a16e3d6..5004e314da1 100644 --- a/packages/compiler-sfc/src/script/defineProps.ts +++ b/packages/compiler-sfc/src/script/defineProps.ts @@ -77,15 +77,14 @@ export function processDefineProps( ctx.propsTypeDecl = node.typeParameters.params[0] } - if (declId) { - // handle props destructure - if (declId.type === 'ObjectPattern') { - processPropsDestructure(ctx, declId) - } else { - ctx.propsIdentifier = ctx.getString(declId) - } + // handle props destructure + if (declId && declId.type === 'ObjectPattern') { + processPropsDestructure(ctx, declId) } + ctx.propsCall = node + ctx.propsDecl = declId + return true } @@ -97,31 +96,33 @@ function processWithDefaults( if (!isCallOf(node, WITH_DEFAULTS)) { return false } - if (processDefineProps(ctx, node.arguments[0], declId)) { - if (ctx.propsRuntimeDecl) { - ctx.error( - `${WITH_DEFAULTS} can only be used with type-based ` + - `${DEFINE_PROPS} declaration.`, - node - ) - } - if (ctx.propsDestructureDecl) { - ctx.error( - `${WITH_DEFAULTS}() is unnecessary when using destructure with ${DEFINE_PROPS}().\n` + - `Prefer using destructure default values, e.g. const { foo = 1 } = defineProps(...).`, - node.callee - ) - } - ctx.propsRuntimeDefaults = node.arguments[1] - if (!ctx.propsRuntimeDefaults) { - ctx.error(`The 2nd argument of ${WITH_DEFAULTS} is required.`, node) - } - } else { + if (!processDefineProps(ctx, node.arguments[0], declId)) { ctx.error( `${WITH_DEFAULTS}' first argument must be a ${DEFINE_PROPS} call.`, node.arguments[0] || node ) } + + if (ctx.propsRuntimeDecl) { + ctx.error( + `${WITH_DEFAULTS} can only be used with type-based ` + + `${DEFINE_PROPS} declaration.`, + node + ) + } + if (ctx.propsDestructureDecl) { + ctx.error( + `${WITH_DEFAULTS}() is unnecessary when using destructure with ${DEFINE_PROPS}().\n` + + `Prefer using destructure default values, e.g. const { foo = 1 } = defineProps(...).`, + node.callee + ) + } + ctx.propsRuntimeDefaults = node.arguments[1] + if (!ctx.propsRuntimeDefaults) { + ctx.error(`The 2nd argument of ${WITH_DEFAULTS} is required.`, node) + } + ctx.propsCall = node + return true } diff --git a/packages/compiler-sfc/src/script/definePropsDestructure.ts b/packages/compiler-sfc/src/script/definePropsDestructure.ts index 5965262f3c3..5aa895bc7fe 100644 --- a/packages/compiler-sfc/src/script/definePropsDestructure.ts +++ b/packages/compiler-sfc/src/script/definePropsDestructure.ts @@ -28,7 +28,6 @@ export function processPropsDestructure( declId: ObjectPattern ) { if (!ctx.options.propsDestructure && !ctx.options.reactivityTransform) { - ctx.propsIdentifier = ctx.getString(declId) return } From 70c3ac746d584d20956628bec185d24e0e90cef4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90=20Kevin=20Deng?= Date: Wed, 12 Jul 2023 11:05:43 +0800 Subject: [PATCH 15/17] dx(compiler-sfc): warn when disabled defineModel (#8534) --- packages/compiler-sfc/src/script/defineModel.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/compiler-sfc/src/script/defineModel.ts b/packages/compiler-sfc/src/script/defineModel.ts index 987e67fc147..432b8676fbd 100644 --- a/packages/compiler-sfc/src/script/defineModel.ts +++ b/packages/compiler-sfc/src/script/defineModel.ts @@ -24,7 +24,15 @@ export function processDefineModel( node: Node, declId?: LVal ): boolean { - if (!ctx.options.defineModel || !isCallOf(node, DEFINE_MODEL)) { + if (!isCallOf(node, DEFINE_MODEL)) { + return false + } + + if (!ctx.options.defineModel) { + warnOnce( + `defineModel() is an experimental feature and disabled by default.\n` + + `To enable it, follow the RFC at https://github.com/vuejs/rfcs/discussions/503.` + ) return false } From 24d98f03276de5b0fbced5a4c9d61b24e7d9d084 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=B6=E8=BF=9C=E6=96=B9?= Date: Wed, 12 Jul 2023 11:13:20 +0800 Subject: [PATCH 16/17] perf(custom-element): cancel `MutationObserver` listener when disconnected (#8666) --- packages/runtime-dom/src/apiCustomElement.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts index 2add422586d..5662b0b535b 100644 --- a/packages/runtime-dom/src/apiCustomElement.ts +++ b/packages/runtime-dom/src/apiCustomElement.ts @@ -178,7 +178,7 @@ export class VueElement extends BaseClass { private _resolved = false private _numberProps: Record | null = null private _styles?: HTMLStyleElement[] - + private _ob?: MutationObserver | null = null constructor( private _def: InnerComponentDef, private _props: Record = {}, @@ -215,6 +215,10 @@ export class VueElement extends BaseClass { disconnectedCallback() { this._connected = false + if (this._ob) { + this._ob.disconnect() + this._ob = null + } nextTick(() => { if (!this._connected) { render(null, this.shadowRoot!) @@ -235,11 +239,13 @@ export class VueElement extends BaseClass { } // watch future attr changes - new MutationObserver(mutations => { + this._ob = new MutationObserver(mutations => { for (const m of mutations) { this._setAttr(m.attributeName!) } - }).observe(this, { attributes: true }) + }) + + this._ob.observe(this, { attributes: true }) const resolve = (def: InnerComponentDef, isAsync = false) => { const { props, styles } = def From 37a14a5dae9999bbe684c6de400afc63658ffe90 Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 12 Jul 2023 11:38:59 +0800 Subject: [PATCH 17/17] Revert "fix(types): propagate type parameter constraints for TypeScript 4.8 (#6351)" This reverts commit 516fabb725cdf29e948b8b83dd6db9b80fbd706d. --- packages/runtime-core/src/apiCreateApp.ts | 4 ++-- packages/runtime-core/src/directives.ts | 16 ++++------------ packages/runtime-core/src/renderer.ts | 8 ++++---- packages/runtime-core/src/vnode.ts | 4 ++-- 4 files changed, 12 insertions(+), 20 deletions(-) diff --git a/packages/runtime-core/src/apiCreateApp.ts b/packages/runtime-core/src/apiCreateApp.ts index 971b406cf01..c5ac9d68a52 100644 --- a/packages/runtime-core/src/apiCreateApp.ts +++ b/packages/runtime-core/src/apiCreateApp.ts @@ -16,7 +16,7 @@ import { ComponentPublicInstance } from './componentPublicInstance' import { Directive, validateDirectiveName } from './directives' -import { RendererElement, RootRenderFunction } from './renderer' +import { RootRenderFunction } from './renderer' import { InjectionKey } from './apiInject' import { warn } from './warning' import { createVNode, cloneVNode, VNode } from './vnode' @@ -196,7 +196,7 @@ export type CreateAppFunction = ( let uid = 0 -export function createAppAPI( +export function createAppAPI( render: RootRenderFunction, hydrate?: RootHydrateFunction ): CreateAppFunction { diff --git a/packages/runtime-core/src/directives.ts b/packages/runtime-core/src/directives.ts index eb80cd495f6..18c3352b002 100644 --- a/packages/runtime-core/src/directives.ts +++ b/packages/runtime-core/src/directives.ts @@ -21,7 +21,6 @@ import { ComponentPublicInstance } from './componentPublicInstance' import { mapCompatDirectiveHook } from './compat/customDirective' import { pauseTracking, resetTracking } from '@vue/reactivity' import { traverse } from './apiWatch' -import { RendererElement } from './renderer' export interface DirectiveBinding { instance: ComponentPublicInstance | null @@ -32,11 +31,7 @@ export interface DirectiveBinding { dir: ObjectDirective } -export type DirectiveHook< - T extends RendererElement = any, - Prev = VNode | null, - V = any -> = ( +export type DirectiveHook | null, V = any> = ( el: T, binding: DirectiveBinding, vnode: VNode, @@ -48,7 +43,7 @@ export type SSRDirectiveHook = ( vnode: VNode ) => Data | undefined -export interface ObjectDirective { +export interface ObjectDirective { created?: DirectiveHook beforeMount?: DirectiveHook mounted?: DirectiveHook @@ -60,12 +55,9 @@ export interface ObjectDirective { deep?: boolean } -export type FunctionDirective< - T extends RendererElement = any, - V = any -> = DirectiveHook +export type FunctionDirective = DirectiveHook -export type Directive = +export type Directive = | ObjectDirective | FunctionDirective diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index 3ab81cbf3ba..383e17fb0f5 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -90,7 +90,7 @@ export type RootRenderFunction = ( export interface RendererOptions< HostNode = RendererNode, - HostElement extends RendererElement = RendererElement + HostElement = RendererElement > { patchProp( el: HostElement, @@ -145,7 +145,7 @@ export interface RendererElement extends RendererNode {} // to optimize bundle size. export interface RendererInternals< HostNode = RendererNode, - HostElement extends RendererElement = RendererElement + HostElement = RendererElement > { p: PatchFn um: UnmountFn @@ -295,7 +295,7 @@ export const queuePostRenderEffect = __FEATURE_SUSPENSE__ */ export function createRenderer< HostNode = RendererNode, - HostElement extends RendererElement = RendererElement + HostElement = RendererElement >(options: RendererOptions) { return baseCreateRenderer(options) } @@ -312,7 +312,7 @@ export function createHydrationRenderer( // overload 1: no hydration function baseCreateRenderer< HostNode = RendererNode, - HostElement extends RendererElement = RendererElement + HostElement = RendererElement >(options: RendererOptions): Renderer // overload 2: with hydration diff --git a/packages/runtime-core/src/vnode.ts b/packages/runtime-core/src/vnode.ts index 89242b94247..f8cf6652d31 100644 --- a/packages/runtime-core/src/vnode.ts +++ b/packages/runtime-core/src/vnode.ts @@ -133,7 +133,7 @@ export type VNodeNormalizedChildren = export interface VNode< HostNode = RendererNode, - HostElement extends RendererElement = RendererElement, + HostElement = RendererElement, ExtraProps = { [key: string]: any } > { /** @@ -613,7 +613,7 @@ export function guardReactiveProps(props: (Data & VNodeProps) | null) { : props } -export function cloneVNode( +export function cloneVNode( vnode: VNode, extraProps?: (Data & VNodeProps) | null, mergeRef = false