From 00458cd38d209410d3c675729230a42a0a34a4b9 Mon Sep 17 00:00:00 2001 From: jf-paradis <89814003+jf-paradis@users.noreply.github.com> Date: Mon, 8 Aug 2022 17:50:53 -0700 Subject: [PATCH 01/20] fix(types): Make SetupBindings optional on ExtendedVue and CombinedVueInstance (#12727) fix #12726 fix #12717 --- types/vue.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/types/vue.d.ts b/types/vue.d.ts index 74bce2c8a45..8c91bc88a2f 100644 --- a/types/vue.d.ts +++ b/types/vue.d.ts @@ -100,7 +100,7 @@ export type CombinedVueInstance< Methods, Computed, Props, - SetupBindings + SetupBindings = {} > = Data & Methods & Computed & @@ -114,7 +114,7 @@ export type ExtendedVue< Methods, Computed, Props, - SetupBindings + SetupBindings = {} > = VueConstructor< CombinedVueInstance & Vue From 5c742eb2e0d8dad268fb29ed4f92d286b5e0f4b5 Mon Sep 17 00:00:00 2001 From: Jonas <30421456+jonaskuske@users.noreply.github.com> Date: Mon, 15 Aug 2022 03:37:08 +0200 Subject: [PATCH 02/20] fix(compiler-sfc): allow full hostnames in asset url base (#12732) fix #12731 --- .../compiler-sfc/src/templateCompilerModules/utils.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/compiler-sfc/src/templateCompilerModules/utils.ts b/packages/compiler-sfc/src/templateCompilerModules/utils.ts index 3e635b00207..8a2d19c6ce7 100644 --- a/packages/compiler-sfc/src/templateCompilerModules/utils.ts +++ b/packages/compiler-sfc/src/templateCompilerModules/utils.ts @@ -24,10 +24,15 @@ export function urlToRequire( // does not apply to absolute urls or urls that start with `@` // since they are aliases if (firstChar === '.' || firstChar === '~') { + // Allow for full hostnames provided in options.base + const base = parseUriParts(transformAssetUrlsOption.base) + const protocol = base.protocol || '' + const host = base.host ? protocol + '//' + base.host : '' + const basePath = base.path || '/' // when packaged in the browser, path will be using the posix- // only version provided by rollup-plugin-node-builtins. - return `"${(path.posix || path).join( - transformAssetUrlsOption.base, + return `"${host}${(path.posix || path).join( + basePath, uriParts.path + (uriParts.hash || '') )}"` } @@ -64,7 +69,7 @@ function parseUriParts(urlString: string): UrlWithStringQuery { // @see https://nodejs.org/api/url.html#url_url_parse_urlstring_parsequerystring_slashesdenotehost if ('string' === typeof urlString) { // check is an uri - return uriParse(urlString) // take apart the uri + return uriParse(urlString, false, true) // take apart the uri } } return returnValue From 4b37b568c7c3fd238aa61fcc956f882223f8e87f Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 15 Aug 2022 09:53:12 +0800 Subject: [PATCH 03/20] fix(types): fix options suggestions when using defineComponent functional component overloads should be moved last fix #12736 --- types/v3-define-component.d.ts | 56 +++++++++++++++++----------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/types/v3-define-component.d.ts b/types/v3-define-component.d.ts index 30f7046e403..a2c47322b49 100644 --- a/types/v3-define-component.d.ts +++ b/types/v3-define-component.d.ts @@ -67,30 +67,6 @@ type DefineComponent< props: PropsOrPropOptions } -/** - * overload 0.0: functional component with array props - */ -export function defineComponent< - PropNames extends string, - Props = Readonly<{ [key in PropNames]?: any }> ->(options: { - functional: true - props?: PropNames[] - render?: (h: CreateElement, context: RenderContext) => any -}): DefineComponent - -/** - * overload 0.1: functional component with object props - */ -export function defineComponent< - PropsOptions extends ComponentPropsOptions = ComponentPropsOptions, - Props = ExtractPropTypes ->(options: { - functional: true - props?: PropsOptions - render?: (h: CreateElement, context: RenderContext) => any -}): DefineComponent - /** * overload 1: object format with no props */ @@ -104,7 +80,7 @@ export function defineComponent< Emits extends EmitsOptions = {}, EmitsNames extends string = string >( - options: ComponentOptionsWithoutProps< + options: { functional?: never } & ComponentOptionsWithoutProps< {}, RawBindings, D, @@ -135,7 +111,7 @@ export function defineComponent< EmitsNames extends string = string, PropsOptions extends ComponentPropsOptions = ComponentPropsOptions >( - options: ComponentOptionsWithArrayProps< + options: { functional?: never } & ComponentOptionsWithArrayProps< PropNames, RawBindings, D, @@ -175,7 +151,7 @@ export function defineComponent< PropsOptions extends ComponentPropsOptions = ComponentPropsOptions >( options: HasDefined extends true - ? ComponentOptionsWithProps< + ? { functional?: never } & ComponentOptionsWithProps< PropsOptions, RawBindings, D, @@ -187,7 +163,7 @@ export function defineComponent< EmitsNames, Props > - : ComponentOptionsWithProps< + : { functional?: never } & ComponentOptionsWithProps< PropsOptions, RawBindings, D, @@ -199,3 +175,27 @@ export function defineComponent< EmitsNames > ): DefineComponent + +/** + * overload 4.1: functional component with array props + */ +export function defineComponent< + PropNames extends string, + Props = Readonly<{ [key in PropNames]?: any }> +>(options: { + functional: true + props?: PropNames[] + render?: (h: CreateElement, context: RenderContext) => any +}): DefineComponent + +/** + * overload 4.2: functional component with object props + */ +export function defineComponent< + PropsOptions extends ComponentPropsOptions = ComponentPropsOptions, + Props = ExtractPropTypes +>(options: { + functional: true + props?: PropsOptions + render?: (h: CreateElement, context: RenderContext) => any +}): DefineComponent From bd89ce53a9de417a9372630bb5d433a40acc1a53 Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 15 Aug 2022 15:37:13 +0800 Subject: [PATCH 04/20] fix: ensure render watcher of manually created instance is correctly tracked in owner scope fix #12701 --- src/core/instance/lifecycle.ts | 2 ++ src/core/observer/watcher.ts | 6 ++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/instance/lifecycle.ts b/src/core/instance/lifecycle.ts index df70b7113fd..fec330ad5fc 100644 --- a/src/core/instance/lifecycle.ts +++ b/src/core/instance/lifecycle.ts @@ -209,6 +209,7 @@ export function mountComponent( // we set this to vm._watcher inside the watcher's constructor // since the watcher's initial patch may call $forceUpdate (e.g. inside child // component's mounted hook), which relies on vm._watcher being already defined + vm._scope.on() new Watcher( vm, updateComponent, @@ -216,6 +217,7 @@ export function mountComponent( watcherOptions, true /* isRenderWatcher */ ) + vm._scope.off() hydrating = false // flush buffer for flush: "pre" watchers queued in setup() diff --git a/src/core/observer/watcher.ts b/src/core/observer/watcher.ts index b1f491acb33..00bf19b9123 100644 --- a/src/core/observer/watcher.ts +++ b/src/core/observer/watcher.ts @@ -72,10 +72,8 @@ export default class Watcher implements DepTarget { isRenderWatcher?: boolean ) { recordEffectScope(this, activeEffectScope || (vm ? vm._scope : undefined)) - if ((this.vm = vm)) { - if (isRenderWatcher) { - vm._watcher = this - } + if ((this.vm = vm) && isRenderWatcher) { + vm._watcher = this } // options if (options) { From f0057b101e6451d5095cdb7fd6308fd31ac0450c Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 15 Aug 2022 19:06:38 +0800 Subject: [PATCH 05/20] fix(watch): avoid pre watcher firing on unmount fix #12703 --- src/v3/apiWatch.ts | 5 +---- test/unit/features/v3/apiWatch.spec.ts | 4 ++-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/v3/apiWatch.ts b/src/v3/apiWatch.ts index 7fe5eeb9dcc..141a58eb686 100644 --- a/src/v3/apiWatch.ts +++ b/src/v3/apiWatch.ts @@ -274,10 +274,7 @@ function doWatch( let oldValue = isMultiSource ? [] : INITIAL_WATCHER_VALUE // overwrite default run watcher.run = () => { - if ( - !watcher.active && - !(flush === 'pre' && instance && instance._isBeingDestroyed) - ) { + if (!watcher.active) { return } if (cb) { diff --git a/test/unit/features/v3/apiWatch.spec.ts b/test/unit/features/v3/apiWatch.spec.ts index 0206e8df3bf..c92bc150ae7 100644 --- a/test/unit/features/v3/apiWatch.spec.ts +++ b/test/unit/features/v3/apiWatch.spec.ts @@ -542,7 +542,7 @@ describe('api: watch', () => { expect(cb).not.toHaveBeenCalled() }) - it('should fire on component unmount w/ flush: pre', async () => { + it('should not fire on component unmount w/ flush: pre', async () => { const toggle = ref(true) const cb = vi.fn() const Comp = { @@ -560,7 +560,7 @@ describe('api: watch', () => { expect(cb).not.toHaveBeenCalled() toggle.value = false await nextTick() - expect(cb).toHaveBeenCalledTimes(1) + expect(cb).not.toHaveBeenCalled() }) // vuejs/core#1763 From 80d1baf92050da411fb1bfe714401c498001dd36 Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 18 Aug 2022 15:23:47 +0800 Subject: [PATCH 06/20] feat(types): export DefineComponent close #12748 --- types/index.d.ts | 2 +- types/v3-define-component.d.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/types/index.d.ts b/types/index.d.ts index 2b5d3a89da2..19fce98726f 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -41,7 +41,7 @@ export * from './v3-setup-helpers' export { Data } from './common' export { SetupContext } from './v3-setup-context' -export { defineComponent } from './v3-define-component' +export { defineComponent, DefineComponent } from './v3-define-component' export { defineAsyncComponent } from './v3-define-async-component' export { SetupFunction, diff --git a/types/v3-define-component.d.ts b/types/v3-define-component.d.ts index a2c47322b49..69f65a2ec35 100644 --- a/types/v3-define-component.d.ts +++ b/types/v3-define-component.d.ts @@ -20,7 +20,7 @@ import { Data, HasDefined } from './common' import { EmitsOptions } from './v3-setup-context' import { CreateElement, RenderContext } from './umd' -type DefineComponent< +export type DefineComponent< PropsOrPropOptions = {}, RawBindings = {}, D = {}, From b4bf4c52ad31e02307cfd4d643dc5610c893e3ba Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 18 Aug 2022 15:32:12 +0800 Subject: [PATCH 07/20] fix(types): allow attaching unknown options to defined component fix #12742 --- types/test/v3/define-component-test.tsx | 4 ++++ types/v3-component-options.d.ts | 3 +++ 2 files changed, 7 insertions(+) diff --git a/types/test/v3/define-component-test.tsx b/types/test/v3/define-component-test.tsx index 42d0f32eb0d..481a2d11ac7 100644 --- a/types/test/v3/define-component-test.tsx +++ b/types/test/v3/define-component-test.tsx @@ -1165,3 +1165,7 @@ defineComponent({ return h('div', {}, [...this.$slots.default!]) } }) + +// #12742 allow attaching custom properties (consistent with v3) +const Foo = defineComponent({}) +Foo.foobar = 123 diff --git a/types/v3-component-options.d.ts b/types/v3-component-options.d.ts index d8c64ab13ab..e2da34e753f 100644 --- a/types/v3-component-options.d.ts +++ b/types/v3-component-options.d.ts @@ -88,6 +88,9 @@ export interface ComponentOptionsBase< 'data' | 'computed' | 'methods' | 'setup' | 'props' | 'mixins' | 'extends' >, ComponentCustomOptions { + // allow any options + [key: string]: any + // rewrite options api types data?: ( this: CreateComponentPublicInstance, From 89a6b5e8658a6e3ae2cf649829901784ac9deb3c Mon Sep 17 00:00:00 2001 From: gu <11851303+gulewei@users.noreply.github.com> Date: Thu, 18 Aug 2022 15:56:37 +0800 Subject: [PATCH 08/20] feat(types): support mixins inference for new Vue() (#12737) close #12730 --- types/options.d.ts | 33 +++++-- types/test/vue-test.ts | 39 +++++++- types/v3-component-public-instance.d.ts | 4 +- types/vue.d.ts | 124 +++++++++++++++++++----- 4 files changed, 166 insertions(+), 34 deletions(-) diff --git a/types/options.d.ts b/types/options.d.ts index e11020f4948..c82c6c5f8ae 100644 --- a/types/options.d.ts +++ b/types/options.d.ts @@ -3,6 +3,7 @@ import { VNode, VNodeData, VNodeDirective, NormalizedScopedSlot } from './vnode' import { SetupContext } from './v3-setup-context' import { DebuggerEvent } from './v3-generated' import { DefineComponent } from './v3-define-component' +import { ComponentOptionsMixin } from './v3-component-options' type Constructor = { new (...args: any[]): any @@ -93,7 +94,9 @@ export type ThisTypedComponentOptionsWithArrayProps< Methods, Computed, PropNames extends string, - SetupBindings + SetupBindings, + Mixin, + Extends > = object & ComponentOptions< V, @@ -102,7 +105,9 @@ export type ThisTypedComponentOptionsWithArrayProps< Computed, PropNames[], Record, - SetupBindings + SetupBindings, + Mixin, + Extends > & ThisType< CombinedVueInstance< @@ -111,7 +116,9 @@ export type ThisTypedComponentOptionsWithArrayProps< Methods, Computed, Readonly>, - SetupBindings + SetupBindings, + Mixin, + Extends > > @@ -124,7 +131,9 @@ export type ThisTypedComponentOptionsWithRecordProps< Methods, Computed, Props, - SetupBindings + SetupBindings, + Mixin, + Extends > = object & ComponentOptions< V, @@ -133,7 +142,9 @@ export type ThisTypedComponentOptionsWithRecordProps< Computed, RecordPropsDefinition, Props, - SetupBindings + SetupBindings, + Mixin, + Extends > & ThisType< CombinedVueInstance< @@ -142,7 +153,9 @@ export type ThisTypedComponentOptionsWithRecordProps< Methods, Computed, Readonly, - SetupBindings + SetupBindings, + Mixin, + Extends > > @@ -158,7 +171,9 @@ export interface ComponentOptions< Computed = DefaultComputed, PropsDef = PropsDefinition, Props = DefaultProps, - RawBindings = {} + RawBindings = {}, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin > { data?: Data props?: PropsDef @@ -217,12 +232,12 @@ export interface ComponentOptions< } parent?: Vue - mixins?: (ComponentOptions | typeof Vue)[] + mixins?: (Mixin | ComponentOptions | typeof Vue)[] name?: string // for SFC auto name inference w/ ts-loader check __name?: string // TODO: support properly inferred 'extends' - extends?: ComponentOptions | typeof Vue + extends?: Extends | ComponentOptions | typeof Vue delimiters?: [string, string] comments?: boolean inheritAttrs?: boolean diff --git a/types/test/vue-test.ts b/types/test/vue-test.ts index 8489f3ae8ed..b792cec583d 100644 --- a/types/test/vue-test.ts +++ b/types/test/vue-test.ts @@ -1,4 +1,4 @@ -import Vue, { VNode } from '../index' +import Vue, { VNode, defineComponent } from '../index' import { ComponentOptions } from '../options' class Test extends Vue { @@ -246,3 +246,40 @@ const ComponentWithStyleInVNodeData = Vue.extend({ ]) } }) + +// infer mixin type with new Vue() #12730 +new Vue({ + mixins: [ + defineComponent({ + props: { + p1: String, + p2: { + type: Number, + default: 0 + } + }, + data() { + return { + foo: 123 + } + }, + computed: { + bar() { + return 123 + } + } + }), + { + methods: { + hello(n: number) {} + } + } + ], + created() { + this.hello(this.foo) + this.hello(this.bar) + // @ts-expect-error + this.hello(this.p1) + this.hello(this.p2) + } +}) diff --git a/types/v3-component-public-instance.d.ts b/types/v3-component-public-instance.d.ts index 3586f4031e8..1c55908ac73 100644 --- a/types/v3-component-public-instance.d.ts +++ b/types/v3-component-public-instance.d.ts @@ -79,11 +79,11 @@ type ExtractMixin = { Mixin: MixinToOptionTypes }[T extends ComponentOptionsMixin ? 'Mixin' : never] -type IntersectionMixin = IsDefaultMixinComponent extends true +export type IntersectionMixin = IsDefaultMixinComponent extends true ? OptionTypesType<{}, {}, {}, {}, {}, {}> : UnionToIntersection> -type UnwrapMixinsType< +export type UnwrapMixinsType< T, Type extends OptionTypesKeys > = T extends OptionTypesType ? T[Type] : never diff --git a/types/vue.d.ts b/types/vue.d.ts index 8c91bc88a2f..5a2027a0179 100644 --- a/types/vue.d.ts +++ b/types/vue.d.ts @@ -13,7 +13,15 @@ import { import { VNode, VNodeData, VNodeChildren, NormalizedScopedSlot } from './vnode' import { PluginFunction, PluginObject } from './plugin' import { DefineComponent } from './v3-define-component' -import { nextTick } from './v3-generated' +import { nextTick, UnwrapNestedRefs, ShallowUnwrapRef } from './v3-generated' +import { + UnwrapMixinsType, + IntersectionMixin +} from './v3-component-public-instance' +import { + ExtractComputedReturns, + ComponentOptionsMixin +} from './v3-component-options' export interface CreateElement { ( @@ -100,12 +108,20 @@ export type CombinedVueInstance< Methods, Computed, Props, - SetupBindings = {} -> = Data & + SetupBindings = {}, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin, + PublicMixin = IntersectionMixin & IntersectionMixin +> = UnwrapNestedRefs> & + Data & + UnwrapMixinsType & Methods & + ExtractComputedReturns> & Computed & + UnwrapMixinsType & Props & Instance & + ShallowUnwrapRef> & (SetupBindings extends void ? {} : SetupBindings) export type ExtendedVue< @@ -114,9 +130,20 @@ export type ExtendedVue< Methods, Computed, Props, - SetupBindings = {} + SetupBindings = {}, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin > = VueConstructor< - CombinedVueInstance & + CombinedVueInstance< + Instance, + Data, + Methods, + Computed, + Props, + SetupBindings, + Mixin, + Extends + > & Vue > @@ -142,7 +169,9 @@ export interface VueConstructor { Methods = object, Computed = object, PropNames extends string = never, - SetupBindings = {} + SetupBindings = {}, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin >( options?: ThisTypedComponentOptionsWithArrayProps< V, @@ -150,7 +179,9 @@ export interface VueConstructor { Methods, Computed, PropNames, - SetupBindings + SetupBindings, + Mixin, + Extends > ): CombinedVueInstance< V, @@ -158,7 +189,9 @@ export interface VueConstructor { Methods, Computed, Record, - SetupBindings + SetupBindings, + Mixin, + Extends > /** @@ -172,7 +205,9 @@ export interface VueConstructor { Methods = object, Computed = object, Props = object, - SetupBindings = {} + SetupBindings = {}, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin >( options?: ThisTypedComponentOptionsWithRecordProps< V, @@ -180,7 +215,9 @@ export interface VueConstructor { Methods, Computed, Props, - SetupBindings + SetupBindings, + Mixin, + Extends > ): CombinedVueInstance< V, @@ -188,7 +225,9 @@ export interface VueConstructor { Methods, Computed, Record, - SetupBindings + SetupBindings, + Mixin, + Extends > /** @@ -211,7 +250,9 @@ export interface VueConstructor { Methods, Computed, PropNames extends string = never, - SetupBindings = {} + SetupBindings = {}, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin >( options?: ThisTypedComponentOptionsWithArrayProps< V, @@ -219,7 +260,9 @@ export interface VueConstructor { Methods, Computed, PropNames, - SetupBindings + SetupBindings, + Mixin, + Extends > ): ExtendedVue< V, @@ -227,22 +270,43 @@ export interface VueConstructor { Methods, Computed, Record, - SetupBindings + SetupBindings, + Mixin, + Extends > /** * extend with object props */ - extend( + extend< + Data, + Methods, + Computed, + Props, + SetupBindings = {}, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin + >( options?: ThisTypedComponentOptionsWithRecordProps< V, Data, Methods, Computed, Props, - SetupBindings + SetupBindings, + Mixin, + Extends > - ): ExtendedVue + ): ExtendedVue< + V, + Data, + Methods, + Computed, + Props, + SetupBindings, + Mixin, + Extends + > /** * extend with functional + array props @@ -287,7 +351,9 @@ export interface VueConstructor { Methods, Computed, PropNames extends string = never, - SetupBindings = {} + SetupBindings = {}, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin >( id: string, definition?: ThisTypedComponentOptionsWithArrayProps< @@ -296,7 +362,9 @@ export interface VueConstructor { Methods, Computed, PropNames, - SetupBindings + SetupBindings, + Mixin, + Extends > ): ExtendedVue< V, @@ -304,9 +372,19 @@ export interface VueConstructor { Methods, Computed, Record, - SetupBindings + SetupBindings, + Mixin, + Extends > - component( + component< + Data, + Methods, + Computed, + Props, + SetupBindings, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin + >( id: string, definition?: ThisTypedComponentOptionsWithRecordProps< V, @@ -314,7 +392,9 @@ export interface VueConstructor { Methods, Computed, Props, - SetupBindings + SetupBindings, + Mixin, + Extends > ): ExtendedVue component( From 5221d4d3b6049c87d196d99dbb64bcd3f3b07279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E7=83=81=E5=A3=95?= <1138674510@qq.com> Date: Thu, 18 Aug 2022 16:01:00 +0800 Subject: [PATCH 09/20] fix(compiler-sfc): rewriteDefault for class with decorators (#12747) --- packages/compiler-sfc/src/rewriteDefault.ts | 7 +- .../compiler-sfc/test/rewriteDefault.spec.ts | 245 ++++++++++++++++++ 2 files changed, 251 insertions(+), 1 deletion(-) create mode 100644 packages/compiler-sfc/test/rewriteDefault.spec.ts diff --git a/packages/compiler-sfc/src/rewriteDefault.ts b/packages/compiler-sfc/src/rewriteDefault.ts index ced9f56d8a9..e61cf691bba 100644 --- a/packages/compiler-sfc/src/rewriteDefault.ts +++ b/packages/compiler-sfc/src/rewriteDefault.ts @@ -42,7 +42,12 @@ export function rewriteDefault( }).program.body ast.forEach(node => { if (node.type === 'ExportDefaultDeclaration') { - s.overwrite(node.start!, node.declaration.start!, `const ${as} = `) + if (node.declaration.type === 'ClassDeclaration') { + s.overwrite(node.start!, node.declaration.id.start!, `class `) + s.append(`\nconst ${as} = ${node.declaration.id.name}`) + } else { + s.overwrite(node.start!, node.declaration.start!, `const ${as} = `) + } } if (node.type === 'ExportNamedDeclaration') { for (const specifier of node.specifiers) { diff --git a/packages/compiler-sfc/test/rewriteDefault.spec.ts b/packages/compiler-sfc/test/rewriteDefault.spec.ts new file mode 100644 index 00000000000..9fb4c64bbb3 --- /dev/null +++ b/packages/compiler-sfc/test/rewriteDefault.spec.ts @@ -0,0 +1,245 @@ +import { rewriteDefault } from '../src' + +describe('compiler sfc: rewriteDefault', () => { + test('without export default', () => { + expect(rewriteDefault(`export a = {}`, 'script')).toMatchInlineSnapshot(` + "export a = {} + const script = {}" + `) + }) + + test('rewrite export default', () => { + expect( + rewriteDefault(`export default {}`, 'script') + ).toMatchInlineSnapshot(`"const script = {}"`) + }) + + test('rewrite export named default', () => { + expect( + rewriteDefault( + `const a = 1 \n export { a as b, a as default, a as c}`, + 'script' + ) + ).toMatchInlineSnapshot(` + "const a = 1 + export { a as b, a as c} + const script = a" + `) + + expect( + rewriteDefault( + `const a = 1 \n export { a as b, a as default , a as c}`, + 'script' + ) + ).toMatchInlineSnapshot(` + "const a = 1 + export { a as b, a as c} + const script = a" + `) + }) + + test('w/ comments', async () => { + expect(rewriteDefault(`// export default\nexport default {}`, 'script')) + .toMatchInlineSnapshot(` + "// export default + const script = {}" + `) + }) + + test('export named default multiline', () => { + expect( + rewriteDefault(`let App = {}\n export {\nApp as default\n}`, '_sfc_main') + ).toMatchInlineSnapshot(` + "let App = {} + export { + + } + const _sfc_main = App" + `) + }) + + test('export named default multiline /w comments', () => { + expect( + rewriteDefault( + `const a = 1 \n export {\n a as b,\n a as default,\n a as c}\n` + + `// export { myFunction as default }`, + 'script' + ) + ).toMatchInlineSnapshot(` + "const a = 1 + export { + a as b, + + a as c} + // export { myFunction as default } + const script = a" + `) + + expect( + rewriteDefault( + `const a = 1 \n export {\n a as b,\n a as default ,\n a as c}\n` + + `// export { myFunction as default }`, + 'script' + ) + ).toMatchInlineSnapshot(` + "const a = 1 + export { + a as b, + + a as c} + // export { myFunction as default } + const script = a" + `) + }) + + test(`export { default } from '...'`, async () => { + expect( + rewriteDefault(`export { default, foo } from './index.js'`, 'script') + ).toMatchInlineSnapshot(` + "import { default as __VUE_DEFAULT__ } from './index.js' + export { foo } from './index.js' + const script = __VUE_DEFAULT__" + `) + + expect( + rewriteDefault(`export { default , foo } from './index.js'`, 'script') + ).toMatchInlineSnapshot(` + "import { default as __VUE_DEFAULT__ } from './index.js' + export { foo } from './index.js' + const script = __VUE_DEFAULT__" + `) + + expect( + rewriteDefault(`export { foo, default } from './index.js'`, 'script') + ).toMatchInlineSnapshot(` + "import { default as __VUE_DEFAULT__ } from './index.js' + export { foo, } from './index.js' + const script = __VUE_DEFAULT__" + `) + + expect( + rewriteDefault( + `export { foo as default, bar } from './index.js'`, + 'script' + ) + ).toMatchInlineSnapshot(` + "import { foo } from './index.js' + export { bar } from './index.js' + const script = foo" + `) + + expect( + rewriteDefault( + `export { foo as default , bar } from './index.js'`, + 'script' + ) + ).toMatchInlineSnapshot(` + "import { foo } from './index.js' + export { bar } from './index.js' + const script = foo" + `) + + expect( + rewriteDefault( + `export { bar, foo as default } from './index.js'`, + 'script' + ) + ).toMatchInlineSnapshot(` + "import { foo } from './index.js' + export { bar, } from './index.js' + const script = foo" + `) + }) + + test('export default class', async () => { + expect(rewriteDefault(`export default class Foo {}`, 'script')) + .toMatchInlineSnapshot(` + "class Foo {} + const script = Foo" + `) + }) + + test('export default class w/ comments', async () => { + expect( + rewriteDefault(`// export default\nexport default class Foo {}`, 'script') + ).toMatchInlineSnapshot(` + "// export default + class Foo {} + const script = Foo" + `) + }) + + test('export default class w/ comments 2', async () => { + expect( + rewriteDefault( + `export default {}\n` + `// export default class Foo {}`, + 'script' + ) + ).toMatchInlineSnapshot(` + "const script = {} + // export default class Foo {}" + `) + }) + + test('export default class w/ comments 3', async () => { + expect( + rewriteDefault( + `/*\nexport default class Foo {}*/\n` + `export default class Bar {}`, + 'script' + ) + ).toMatchInlineSnapshot(` + "/* + export default class Foo {}*/ + class Bar {} + const script = Bar" + `) + }) + + test('@Component\nexport default class', async () => { + expect(rewriteDefault(`@Component\nexport default class Foo {}`, 'script')) + .toMatchInlineSnapshot(` + "@Component + class Foo {} + const script = Foo" + `) + }) + + test('@Component\nexport default class w/ comments', async () => { + expect( + rewriteDefault(`// export default\n@Component\nexport default class Foo {}`, 'script') + ).toMatchInlineSnapshot(` + "// export default + @Component + class Foo {} + const script = Foo" + `) + }) + + test('@Component\nexport default class w/ comments 2', async () => { + expect( + rewriteDefault( + `export default {}\n` + `// @Component\n// export default class Foo {}`, + 'script' + ) + ).toMatchInlineSnapshot(` + "const script = {} + // @Component + // export default class Foo {}" + `) + }) + + test('@Component\nexport default class w/ comments 3', async () => { + expect( + rewriteDefault( + `/*\n@Component\nexport default class Foo {}*/\n` + `export default class Bar {}`, + 'script' + ) + ).toMatchInlineSnapshot(` + "/* + @Component + export default class Foo {}*/ + class Bar {} + const script = Bar" + `) + }) +}) From 2263948c249e7486403bc5880712e6d9fd15c17f Mon Sep 17 00:00:00 2001 From: JuniorTour Date: Thu, 18 Aug 2022 16:11:47 +0800 Subject: [PATCH 10/20] fix: directives shorthand normalize error (#12744) fix #12743 --- src/core/vdom/modules/directives.ts | 10 +++++++++- test/unit/features/v3/apiSetup.spec.ts | 13 +++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/core/vdom/modules/directives.ts b/src/core/vdom/modules/directives.ts index 9e4a87f7f6e..853b20021e7 100644 --- a/src/core/vdom/modules/directives.ts +++ b/src/core/vdom/modules/directives.ts @@ -103,7 +103,15 @@ function normalizeDirectives( } res[getRawDirName(dir)] = dir if (vm._setupState && vm._setupState.__sfc) { - dir.def = dir.def || resolveAsset(vm, '_setupState', 'v-' + dir.name) + const setupDef = dir.def || resolveAsset(vm, '_setupState', 'v-' + dir.name) + if (typeof setupDef === 'function') { + dir.def = { + bind: setupDef, + update: setupDef, + } + } else { + dir.def = setupDef + } } dir.def = dir.def || resolveAsset(vm.$options, 'directives', dir.name, true) } diff --git a/test/unit/features/v3/apiSetup.spec.ts b/test/unit/features/v3/apiSetup.spec.ts index 7c69d06d1c4..11757878e9c 100644 --- a/test/unit/features/v3/apiSetup.spec.ts +++ b/test/unit/features/v3/apiSetup.spec.ts @@ -251,6 +251,19 @@ describe('api: setup context', () => { expect(spy).toHaveBeenCalled() }) + // #12743 + it('directive resolution for shorthand', () => { + const spy = vi.fn() + new Vue({ + setup: () => ({ + __sfc: true, + vDir: spy + }), + template: `
` + }).$mount() + expect(spy).toHaveBeenCalled() + }) + // #12561 it('setup props should be reactive', () => { const msg = ref('hi') From 9eb8ea5b63eec2b09f268738e9d0e311d9eafb19 Mon Sep 17 00:00:00 2001 From: GU Yiling Date: Thu, 18 Aug 2022 16:12:20 +0800 Subject: [PATCH 11/20] chore: fix some legacy doc urls in warnings and readme (#12725) [ci skip] --- README.md | 2 +- src/core/instance/proxy.ts | 4 ++-- src/core/instance/state.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5a3f576d716..5eef53d3fa0 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ Vue.js supports all browsers that are [ES5-compliant](https://kangax.github.io/c ## Documentation -To check out [live examples](https://vuejs.org/v2/examples/) and docs, visit [vuejs.org](https://vuejs.org). +To check out [live examples](https://v2.vuejs.org/v2/examples/) and docs, visit [vuejs.org](https://v2.vuejs.org). ## Questions diff --git a/src/core/instance/proxy.ts b/src/core/instance/proxy.ts index 3543d74954a..685d9651fcc 100644 --- a/src/core/instance/proxy.ts +++ b/src/core/instance/proxy.ts @@ -19,7 +19,7 @@ if (__DEV__) { 'referenced during render. Make sure that this property is reactive, ' + 'either in the data option, or for class-based components, by ' + 'initializing the property. ' + - 'See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.', + 'See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.', target ) } @@ -29,7 +29,7 @@ if (__DEV__) { `Property "${key}" must be accessed with "$data.${key}" because ` + 'properties starting with "$" or "_" are not proxied in the Vue instance to ' + 'prevent conflicts with Vue internals. ' + - 'See: https://vuejs.org/v2/api/#data', + 'See: https://v2.vuejs.org/v2/api/#data', target ) } diff --git a/src/core/instance/state.ts b/src/core/instance/state.ts index e22ec6705fb..aedb72555c9 100644 --- a/src/core/instance/state.ts +++ b/src/core/instance/state.ts @@ -127,7 +127,7 @@ function initData(vm: Component) { __DEV__ && warn( 'data functions should return an object:\n' + - 'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function', + 'https://v2.vuejs.org/v2/guide/components.html#data-Must-Be-a-Function', vm ) } From bba6b3d6b4e3e26d28abbf20e74ec2f3e64f1a92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=8D=E8=A7=81=E6=9C=88?= <61452855+nooooooom@users.noreply.github.com> Date: Thu, 18 Aug 2022 16:20:27 +0800 Subject: [PATCH 12/20] feat(types): enhance type for onErrorCaptured (#12735) --- src/v3/apiLifecycle.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/v3/apiLifecycle.ts b/src/v3/apiLifecycle.ts index dc47bc4652b..31e0542920c 100644 --- a/src/v3/apiLifecycle.ts +++ b/src/v3/apiLifecycle.ts @@ -42,7 +42,6 @@ export const onBeforeUpdate = createLifeCycle('beforeUpdate') export const onUpdated = createLifeCycle('updated') export const onBeforeUnmount = createLifeCycle('beforeDestroy') export const onUnmounted = createLifeCycle('destroyed') -export const onErrorCaptured = createLifeCycle('errorCaptured') export const onActivated = createLifeCycle('activated') export const onDeactivated = createLifeCycle('deactivated') export const onServerPrefetch = createLifeCycle('serverPrefetch') @@ -51,3 +50,19 @@ export const onRenderTracked = createLifeCycle<(e: DebuggerEvent) => any>('renderTracked') export const onRenderTriggered = createLifeCycle<(e: DebuggerEvent) => any>('renderTriggered') + +export type ErrorCapturedHook = ( + err: TError, + instance: any, + info: string +) => boolean | void + +const injectErrorCapturedHook = + createLifeCycle>('errorCaptured') + +export function onErrorCaptured( + hook: ErrorCapturedHook, + target: any = currentInstance +) { + injectErrorCapturedHook(hook, target) +} From 165a14a6c6c406176037465d2961259c5c980399 Mon Sep 17 00:00:00 2001 From: Alexander Lichter Date: Thu, 18 Aug 2022 10:22:55 +0200 Subject: [PATCH 13/20] fix(ssr): fix on-component directives rendering (#12661) fix #10733 --- packages/server-renderer/src/render.ts | 10 +- .../server-renderer/test/ssr-string.spec.ts | 94 ++++++++++++++++++- src/core/vdom/vnode.ts | 1 + 3 files changed, 103 insertions(+), 2 deletions(-) diff --git a/packages/server-renderer/src/render.ts b/packages/server-renderer/src/render.ts index 907b795d797..b1116840ed5 100644 --- a/packages/server-renderer/src/render.ts +++ b/packages/server-renderer/src/render.ts @@ -206,6 +206,11 @@ function renderComponentInner(node, isRoot, context) { type: 'Component', prevActive }) + if (isDef(node.data) && isDef(node.data.directives)) { + childNode.data = childNode.data || {} + childNode.data.directives = node.data.directives + childNode.isComponentRootElement = true + } renderNode(childNode, isRoot, context) } @@ -372,7 +377,10 @@ function renderStartingTag(node: VNode, context) { if (dirRenderer) { // directives mutate the node's data // which then gets rendered by modules - dirRenderer(node, dirs[i]) + dirRenderer( + node.isComponentRootElement ? node.parent : node, + dirs[i] + ) } } } diff --git a/packages/server-renderer/test/ssr-string.spec.ts b/packages/server-renderer/test/ssr-string.spec.ts index 35810c8ed58..391671c1e52 100644 --- a/packages/server-renderer/test/ssr-string.spec.ts +++ b/packages/server-renderer/test/ssr-string.spec.ts @@ -1086,7 +1086,7 @@ describe('SSR: renderToString', () => { ) }) - it('custom directives', done => { + it('custom directives on raw element', done => { const renderer = createRenderer({ directives: { 'class-prefixer': (node, dir) => { @@ -1129,6 +1129,98 @@ describe('SSR: renderToString', () => { ) }) + it('custom directives on component', done => { + const Test = { + template: 'hello world' + } + const renderer = createRenderer({ + directives: { + 'class-prefixer': (node, dir) => { + if (node.data.class) { + node.data.class = `${dir.value}-${node.data.class}` + } + if (node.data.staticClass) { + node.data.staticClass = `${dir.value}-${node.data.staticClass}` + } + } + } + }) + renderer.renderToString( + new Vue({ + template: + '

', + components: { Test } + }), + (err, result) => { + expect(err).toBeNull() + expect(result).toContain( + '

hello world

' + ) + done() + } + ) + }) + + it('custom directives on element root of a component', done => { + const Test = { + template: + 'hello world' + } + const renderer = createRenderer({ + directives: { + 'class-prefixer': (node, dir) => { + if (node.data.class) { + node.data.class = `${dir.value}-${node.data.class}` + } + if (node.data.staticClass) { + node.data.staticClass = `${dir.value}-${node.data.staticClass}` + } + } + } + }) + renderer.renderToString( + new Vue({ + template: '

', + components: { Test } + }), + (err, result) => { + expect(err).toBeNull() + expect(result).toContain( + '

hello world

' + ) + done() + } + ) + }) + + it('custom directives on element with parent element', done => { + const renderer = createRenderer({ + directives: { + 'class-prefixer': (node, dir) => { + if (node.data.class) { + node.data.class = `${dir.value}-${node.data.class}` + } + if (node.data.staticClass) { + node.data.staticClass = `${dir.value}-${node.data.staticClass}` + } + } + } + }) + renderer.renderToString( + new Vue({ + template: + '

hello world

' + }), + (err, result) => { + expect(err).toBeNull() + expect(result).toContain( + '

hello world

' + ) + done() + } + ) + }) + it('should not warn for custom directives that do not have server-side implementation', done => { renderToString( new Vue({ diff --git a/src/core/vdom/vnode.ts b/src/core/vdom/vnode.ts index 80f784167ba..3b57f9aca0c 100644 --- a/src/core/vdom/vnode.ts +++ b/src/core/vdom/vnode.ts @@ -33,6 +33,7 @@ export default class VNode { fnOptions?: ComponentOptions | null // for SSR caching devtoolsMeta?: Object | null // used to store functional render context for devtools fnScopeId?: string | null // functional scope id support + isComponentRootElement?: boolean | null // for SSR directives constructor( tag?: string, From 7161176cd0dff10d65ab58e266018aff2660610f Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 18 Aug 2022 18:14:50 +0800 Subject: [PATCH 14/20] fix: fix effect scope tracking for manually created instances fix #12705 --- src/core/instance/init.ts | 1 + src/core/instance/lifecycle.ts | 2 -- src/core/observer/watcher.ts | 11 ++++++++++- src/v3/reactivity/effectScope.ts | 6 +++++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/core/instance/init.ts b/src/core/instance/init.ts index 876c9ddbf96..91456c21920 100644 --- a/src/core/instance/init.ts +++ b/src/core/instance/init.ts @@ -34,6 +34,7 @@ export function initMixin(Vue: typeof Component) { vm.__v_skip = true // effect scope vm._scope = new EffectScope(true /* detached */) + vm._scope._vm = true // merge options if (options && options._isComponent) { // optimize internal component instantiation diff --git a/src/core/instance/lifecycle.ts b/src/core/instance/lifecycle.ts index fec330ad5fc..df70b7113fd 100644 --- a/src/core/instance/lifecycle.ts +++ b/src/core/instance/lifecycle.ts @@ -209,7 +209,6 @@ export function mountComponent( // we set this to vm._watcher inside the watcher's constructor // since the watcher's initial patch may call $forceUpdate (e.g. inside child // component's mounted hook), which relies on vm._watcher being already defined - vm._scope.on() new Watcher( vm, updateComponent, @@ -217,7 +216,6 @@ export function mountComponent( watcherOptions, true /* isRenderWatcher */ ) - vm._scope.off() hydrating = false // flush buffer for flush: "pre" watchers queued in setup() diff --git a/src/core/observer/watcher.ts b/src/core/observer/watcher.ts index 00bf19b9123..b2989b53772 100644 --- a/src/core/observer/watcher.ts +++ b/src/core/observer/watcher.ts @@ -71,7 +71,16 @@ export default class Watcher implements DepTarget { options?: WatcherOptions | null, isRenderWatcher?: boolean ) { - recordEffectScope(this, activeEffectScope || (vm ? vm._scope : undefined)) + recordEffectScope( + this, + // if the active effect scope is manually created (not a component scope), + // prioritize it + activeEffectScope && !activeEffectScope._vm + ? activeEffectScope + : vm + ? vm._scope + : undefined + ) if ((this.vm = vm) && isRenderWatcher) { vm._watcher = this } diff --git a/src/v3/reactivity/effectScope.ts b/src/v3/reactivity/effectScope.ts index bc15380eb4a..2ba50cd9ca8 100644 --- a/src/v3/reactivity/effectScope.ts +++ b/src/v3/reactivity/effectScope.ts @@ -27,10 +27,14 @@ export class EffectScope { * @internal */ scopes: EffectScope[] | undefined + /** + * indicates this being a component root scope + * @internal + */ + _vm?: boolean /** * track a child scope's index in its parent's scopes array for optimized * removal - * @internal */ private index: number | undefined From 8521f9d3f63d26bde99b747f0cb14d0ac5ba5971 Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 19 Aug 2022 12:22:51 +0800 Subject: [PATCH 15/20] fix(types): fix missing error for accessing undefined instance properties fix #12718 --- types/test/v3/define-component-test.tsx | 62 +++++++++++++++++++++++-- types/v3-define-component.d.ts | 10 ++-- 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/types/test/v3/define-component-test.tsx b/types/test/v3/define-component-test.tsx index 481a2d11ac7..7e6d1968ca3 100644 --- a/types/test/v3/define-component-test.tsx +++ b/types/test/v3/define-component-test.tsx @@ -1166,6 +1166,62 @@ defineComponent({ } }) -// #12742 allow attaching custom properties (consistent with v3) -const Foo = defineComponent({}) -Foo.foobar = 123 +describe('constructor attach custom properties', () => { + // #12742 allow attaching custom properties (consistent with v3) + const Foo = defineComponent({}) + Foo.foobar = 123 +}) + +describe('constructor instance type', () => { + const Comp = defineComponent({ + data() { + return { + a: 1 + } + }, + + computed: { + ac() { + return 1 + } + }, + + methods: { + callA(b: number) { + return b + } + }, + + setup() { + return { + sa: '1' + } + } + }) + + const comp = new Comp() + + expectType(comp.a) + expectType(comp.ac) + expectType(comp.sa) + expectType<(b: number) => number>(comp.callA) +}) + +describe('should report non-existent properties in instance', () => { + const Foo = defineComponent({}) + const instance = new Foo() + // @ts-expect-error + instance.foo + + const Foo2 = defineComponent({ + data() { + return {} + }, + methods: { + example() {} + } + }) + const instance2 = new Foo2() + // @ts-expect-error + instance2.foo +}) diff --git a/types/v3-define-component.d.ts b/types/v3-define-component.d.ts index 69f65a2ec35..03ef52d1856 100644 --- a/types/v3-define-component.d.ts +++ b/types/v3-define-component.d.ts @@ -72,7 +72,7 @@ export type DefineComponent< */ export function defineComponent< RawBindings, - D = Data, + D = {}, C extends ComputedOptions = {}, M extends MethodOptions = {}, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, @@ -101,8 +101,8 @@ export function defineComponent< */ export function defineComponent< PropNames extends string, - RawBindings = Data, - D = Data, + RawBindings = {}, + D = {}, C extends ComputedOptions = {}, M extends MethodOptions = {}, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, @@ -140,8 +140,8 @@ export function defineComponent< */ export function defineComponent< Props, - RawBindings = Data, - D = Data, + RawBindings = {}, + D = {}, C extends ComputedOptions = {}, M extends MethodOptions = {}, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, From 15618888cb6aae2b6f0151b32c261b1fc19db1b8 Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 19 Aug 2022 12:27:12 +0800 Subject: [PATCH 16/20] release: v2.7.9 --- CHANGELOG.md | 26 +++++++++++++++++++++++++ package.json | 2 +- packages/compiler-sfc/package.json | 2 +- packages/server-renderer/package.json | 2 +- packages/template-compiler/package.json | 2 +- 5 files changed, 30 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc98f138f33..b5d38472209 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,29 @@ +## [2.7.9](https://github.com/vuejs/vue/compare/v2.7.8...v2.7.9) (2022-08-19) + + +### Bug Fixes + +* **compiler-sfc:** allow full hostnames in asset url base ([#12732](https://github.com/vuejs/vue/issues/12732)) ([5c742eb](https://github.com/vuejs/vue/commit/5c742eb2e0d8dad268fb29ed4f92d286b5e0f4b5)), closes [#12731](https://github.com/vuejs/vue/issues/12731) +* **compiler-sfc:** rewriteDefault for class with decorators ([#12747](https://github.com/vuejs/vue/issues/12747)) ([5221d4d](https://github.com/vuejs/vue/commit/5221d4d3b6049c87d196d99dbb64bcd3f3b07279)) +* directives shorthand normalize error ([#12744](https://github.com/vuejs/vue/issues/12744)) ([2263948](https://github.com/vuejs/vue/commit/2263948c249e7486403bc5880712e6d9fd15c17f)), closes [#12743](https://github.com/vuejs/vue/issues/12743) +* ensure render watcher of manually created instance is correctly tracked in owner scope ([bd89ce5](https://github.com/vuejs/vue/commit/bd89ce53a9de417a9372630bb5d433a40acc1a53)), closes [#12701](https://github.com/vuejs/vue/issues/12701) +* fix effect scope tracking for manually created instances ([7161176](https://github.com/vuejs/vue/commit/7161176cd0dff10d65ab58e266018aff2660610f)), closes [#12705](https://github.com/vuejs/vue/issues/12705) +* **ssr:** fix on-component directives rendering ([#12661](https://github.com/vuejs/vue/issues/12661)) ([165a14a](https://github.com/vuejs/vue/commit/165a14a6c6c406176037465d2961259c5c980399)), closes [#10733](https://github.com/vuejs/vue/issues/10733) +* **types:** allow attaching unknown options to defined component ([b4bf4c5](https://github.com/vuejs/vue/commit/b4bf4c52ad31e02307cfd4d643dc5610c893e3ba)), closes [#12742](https://github.com/vuejs/vue/issues/12742) +* **types:** fix missing error for accessing undefined instance properties ([8521f9d](https://github.com/vuejs/vue/commit/8521f9d3f63d26bde99b747f0cb14d0ac5ba5971)), closes [#12718](https://github.com/vuejs/vue/issues/12718) +* **types:** fix options suggestions when using defineComponent ([4b37b56](https://github.com/vuejs/vue/commit/4b37b568c7c3fd238aa61fcc956f882223f8e87f)), closes [#12736](https://github.com/vuejs/vue/issues/12736) +* **types:** Make SetupBindings optional on ExtendedVue and CombinedVueInstance ([#12727](https://github.com/vuejs/vue/issues/12727)) ([00458cd](https://github.com/vuejs/vue/commit/00458cd38d209410d3c675729230a42a0a34a4b9)), closes [#12726](https://github.com/vuejs/vue/issues/12726) [#12717](https://github.com/vuejs/vue/issues/12717) +* **watch:** avoid pre watcher firing on unmount ([f0057b1](https://github.com/vuejs/vue/commit/f0057b101e6451d5095cdb7fd6308fd31ac0450c)), closes [#12703](https://github.com/vuejs/vue/issues/12703) + + +### Features + +* **types:** enhance type for onErrorCaptured ([#12735](https://github.com/vuejs/vue/issues/12735)) ([bba6b3d](https://github.com/vuejs/vue/commit/bba6b3d6b4e3e26d28abbf20e74ec2f3e64f1a92)) +* **types:** export DefineComponent ([80d1baf](https://github.com/vuejs/vue/commit/80d1baf92050da411fb1bfe714401c498001dd36)), closes [#12748](https://github.com/vuejs/vue/issues/12748) +* **types:** support mixins inference for new Vue() ([#12737](https://github.com/vuejs/vue/issues/12737)) ([89a6b5e](https://github.com/vuejs/vue/commit/89a6b5e8658a6e3ae2cf649829901784ac9deb3c)), closes [#12730](https://github.com/vuejs/vue/issues/12730) + + + ## [2.7.8](https://github.com/vuejs/vue/compare/v2.7.7...v2.7.8) (2022-07-22) diff --git a/package.json b/package.json index 039c8882375..0bbc17d6b0b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue", - "version": "2.7.8", + "version": "2.7.9", "packageManager": "pnpm@7.1.0", "description": "Reactive, component-oriented view layer for modern web interfaces.", "main": "dist/vue.runtime.common.js", diff --git a/packages/compiler-sfc/package.json b/packages/compiler-sfc/package.json index 6a6037a3111..3e88b96778c 100644 --- a/packages/compiler-sfc/package.json +++ b/packages/compiler-sfc/package.json @@ -1,6 +1,6 @@ { "name": "@vue/compiler-sfc", - "version": "2.7.8", + "version": "2.7.9", "description": "compiler-sfc for Vue 2", "main": "dist/compiler-sfc.js", "types": "dist/compiler-sfc.d.ts", diff --git a/packages/server-renderer/package.json b/packages/server-renderer/package.json index 5e8adfd83f6..784b7838cbe 100644 --- a/packages/server-renderer/package.json +++ b/packages/server-renderer/package.json @@ -1,6 +1,6 @@ { "name": "vue-server-renderer", - "version": "2.7.8", + "version": "2.7.9", "description": "server renderer for Vue 2.0", "main": "index.js", "types": "types/index.d.ts", diff --git a/packages/template-compiler/package.json b/packages/template-compiler/package.json index d1be678cdfb..26bf6586f94 100644 --- a/packages/template-compiler/package.json +++ b/packages/template-compiler/package.json @@ -1,6 +1,6 @@ { "name": "vue-template-compiler", - "version": "2.7.8", + "version": "2.7.9", "description": "template compiler for Vue 2.0", "main": "index.js", "unpkg": "browser.js", From 810f6d12edea47cde7f39eaf7ec3ae1b7300d40c Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Sun, 21 Aug 2022 19:28:39 -0700 Subject: [PATCH 17/20] fix(types): Add missing type parameter constraints (#12754) --- types/options.d.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/types/options.d.ts b/types/options.d.ts index c82c6c5f8ae..9fcdaca624f 100644 --- a/types/options.d.ts +++ b/types/options.d.ts @@ -95,8 +95,8 @@ export type ThisTypedComponentOptionsWithArrayProps< Computed, PropNames extends string, SetupBindings, - Mixin, - Extends + Mixin extends ComponentOptionsMixin, + Extends extends ComponentOptionsMixin > = object & ComponentOptions< V, @@ -132,8 +132,8 @@ export type ThisTypedComponentOptionsWithRecordProps< Computed, Props, SetupBindings, - Mixin, - Extends + Mixin extends ComponentOptionsMixin, + Extends extends ComponentOptionsMixin > = object & ComponentOptions< V, From 46ca7bcddc06c50796ccff82d8c45693f1f14f47 Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 23 Aug 2022 09:18:36 +0800 Subject: [PATCH 18/20] fix(compiler-sfc): avoid deindent when lang is jsx/tsx fix #12755 --- packages/compiler-sfc/src/parseComponent.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/compiler-sfc/src/parseComponent.ts b/packages/compiler-sfc/src/parseComponent.ts index 65b858c9fc0..05489280e63 100644 --- a/packages/compiler-sfc/src/parseComponent.ts +++ b/packages/compiler-sfc/src/parseComponent.ts @@ -179,11 +179,11 @@ export function parseComponent( let text = source.slice(currentBlock.start, currentBlock.end) if ( options.deindent === true || - // by default, deindent unless it's script with default lang or ts + // by default, deindent unless it's script with default lang or (j/t)sx? (options.deindent !== false && !( currentBlock.type === 'script' && - (!currentBlock.lang || currentBlock.lang === 'ts') + (!currentBlock.lang || /^(j|t)sx?$/.test(currentBlock.lang)) )) ) { text = deindent(text) From e0b26c483a1ba407a818b1fcba1a439df24e84a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=8D=E8=A7=81=E6=9C=88?= <61452855+nooooooom@users.noreply.github.com> Date: Tue, 23 Aug 2022 09:22:45 +0800 Subject: [PATCH 19/20] fix: fix parent of multi-nested HOC $el not updating (#12757) fix #12589 --- src/core/instance/lifecycle.ts | 11 +++++++++-- test/unit/modules/vdom/patch/edge-cases.spec.ts | 4 ++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/core/instance/lifecycle.ts b/src/core/instance/lifecycle.ts index df70b7113fd..94f42e27eb5 100644 --- a/src/core/instance/lifecycle.ts +++ b/src/core/instance/lifecycle.ts @@ -83,8 +83,15 @@ export function lifecycleMixin(Vue: typeof Component) { vm.$el.__vue__ = vm } // if parent is an HOC, update its $el as well - if (vm.$vnode && vm.$parent && vm.$vnode === vm.$parent._vnode) { - vm.$parent.$el = vm.$el + let wrapper: Component | undefined = vm + while ( + wrapper && + wrapper.$vnode && + wrapper.$parent && + wrapper.$vnode === wrapper.$parent._vnode + ) { + wrapper.$parent.$el = wrapper.$el + wrapper = wrapper.$parent } // updated hook is called by the scheduler to ensure that children are // updated in a parent's updated hook. diff --git a/test/unit/modules/vdom/patch/edge-cases.spec.ts b/test/unit/modules/vdom/patch/edge-cases.spec.ts index 10b8ad8179d..f9295533b1e 100644 --- a/test/unit/modules/vdom/patch/edge-cases.spec.ts +++ b/test/unit/modules/vdom/patch/edge-cases.spec.ts @@ -257,11 +257,15 @@ describe('vdom patch: edge cases', () => { expect(vm.$refs.foo.$refs.bar.$el.tagName).toBe('DIV') expect(vm.$refs.foo.$refs.bar.$el.className).toBe(`hello`) + expect(vm.$el.tagName).toBe('DIV') + expect(vm.$el.className).toBe(`hello`) vm.$refs.foo.$refs.bar.ok = false waitForUpdate(() => { expect(vm.$refs.foo.$refs.bar.$el.tagName).toBe('SPAN') expect(vm.$refs.foo.$refs.bar.$el.className).toBe(`hello`) + expect(vm.$el.tagName).toBe('SPAN') + expect(vm.$el.className).toBe(`hello`) }).then(done) }) From ee57d9fd1d51abe245c6c37e6f8f2d45977b929e Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 23 Aug 2022 09:29:42 +0800 Subject: [PATCH 20/20] release: v2.7.10 --- CHANGELOG.md | 11 +++++++++++ package.json | 2 +- packages/compiler-sfc/package.json | 2 +- packages/server-renderer/package.json | 2 +- packages/template-compiler/package.json | 2 +- 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5d38472209..3ccae2540a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +## [2.7.10](https://github.com/vuejs/vue/compare/v2.7.9...v2.7.10) (2022-08-23) + + +### Bug Fixes + +* **compiler-sfc:** avoid deindent when lang is jsx/tsx ([46ca7bc](https://github.com/vuejs/vue/commit/46ca7bcddc06c50796ccff82d8c45693f1f14f47)), closes [#12755](https://github.com/vuejs/vue/issues/12755) +* fix parent of multi-nested HOC $el not updating ([#12757](https://github.com/vuejs/vue/issues/12757)) ([e0b26c4](https://github.com/vuejs/vue/commit/e0b26c483a1ba407a818b1fcba1a439df24e84a8)), closes [#12589](https://github.com/vuejs/vue/issues/12589) +* **types:** Add missing type parameter constraints ([#12754](https://github.com/vuejs/vue/issues/12754)) ([810f6d1](https://github.com/vuejs/vue/commit/810f6d12edea47cde7f39eaf7ec3ae1b7300d40c)) + + + ## [2.7.9](https://github.com/vuejs/vue/compare/v2.7.8...v2.7.9) (2022-08-19) diff --git a/package.json b/package.json index 0bbc17d6b0b..e8750ff7385 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue", - "version": "2.7.9", + "version": "2.7.10", "packageManager": "pnpm@7.1.0", "description": "Reactive, component-oriented view layer for modern web interfaces.", "main": "dist/vue.runtime.common.js", diff --git a/packages/compiler-sfc/package.json b/packages/compiler-sfc/package.json index 3e88b96778c..115ae6e775b 100644 --- a/packages/compiler-sfc/package.json +++ b/packages/compiler-sfc/package.json @@ -1,6 +1,6 @@ { "name": "@vue/compiler-sfc", - "version": "2.7.9", + "version": "2.7.10", "description": "compiler-sfc for Vue 2", "main": "dist/compiler-sfc.js", "types": "dist/compiler-sfc.d.ts", diff --git a/packages/server-renderer/package.json b/packages/server-renderer/package.json index 784b7838cbe..5470ebfaca3 100644 --- a/packages/server-renderer/package.json +++ b/packages/server-renderer/package.json @@ -1,6 +1,6 @@ { "name": "vue-server-renderer", - "version": "2.7.9", + "version": "2.7.10", "description": "server renderer for Vue 2.0", "main": "index.js", "types": "types/index.d.ts", diff --git a/packages/template-compiler/package.json b/packages/template-compiler/package.json index 26bf6586f94..75285bc0e85 100644 --- a/packages/template-compiler/package.json +++ b/packages/template-compiler/package.json @@ -1,6 +1,6 @@ { "name": "vue-template-compiler", - "version": "2.7.9", + "version": "2.7.10", "description": "template compiler for Vue 2.0", "main": "index.js", "unpkg": "browser.js",