From 58c31e36992d2647e5247de4904246fb2d6112ed Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 17 Sep 2020 15:59:01 -0400 Subject: [PATCH 01/17] feat(runtime-core): support using inject() inside props default functions --- .../__tests__/componentProps.spec.ts | 30 ++++++++++++++++++- packages/runtime-core/src/componentProps.ts | 26 ++++++++++------ 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/packages/runtime-core/__tests__/componentProps.spec.ts b/packages/runtime-core/__tests__/componentProps.spec.ts index d0ddc5c1fdc..f75d3c2ebbd 100644 --- a/packages/runtime-core/__tests__/componentProps.spec.ts +++ b/packages/runtime-core/__tests__/componentProps.spec.ts @@ -8,7 +8,9 @@ import { defineComponent, ref, serializeInner, - createApp + createApp, + provide, + inject } from '@vue/runtime-test' import { render as domRender, nextTick } from 'vue' @@ -212,6 +214,32 @@ describe('component props', () => { expect(defaultFn).toHaveBeenCalledTimes(1) }) + test('using inject in default value factory', () => { + const Child = defineComponent({ + props: { + test: { + default: () => inject('test', 'default') + } + }, + setup(props) { + return () => { + return h('div', props.test) + } + } + }) + + const Comp = { + setup() { + provide('test', 'injected') + return () => h(Child) + } + } + + const root = nodeOps.createElement('div') + render(h(Comp), root) + expect(serializeInner(root)).toBe(`
injected
`) + }) + test('optimized props updates', async () => { const Child = defineComponent({ props: ['foo'], diff --git a/packages/runtime-core/src/componentProps.ts b/packages/runtime-core/src/componentProps.ts index 0fde127a28f..f977099d806 100644 --- a/packages/runtime-core/src/componentProps.ts +++ b/packages/runtime-core/src/componentProps.ts @@ -27,7 +27,8 @@ import { Data, ComponentInternalInstance, ComponentOptions, - ConcreteComponent + ConcreteComponent, + setCurrentInstance } from './component' import { isEmitListener } from './componentEmits' import { InternalObjectKey } from './vnode' @@ -179,7 +180,8 @@ export function updateProps( options, rawCurrentProps, camelizedKey, - value + value, + instance ) } } else { @@ -214,7 +216,8 @@ export function updateProps( options, rawProps || EMPTY_OBJ, key, - undefined + undefined, + instance ) } } else { @@ -277,7 +280,8 @@ function setFullProps( options!, rawCurrentProps, key, - rawCurrentProps[key] + rawCurrentProps[key], + instance ) } } @@ -287,7 +291,8 @@ function resolvePropValue( options: NormalizedProps, props: Data, key: string, - value: unknown + value: unknown, + instance: ComponentInternalInstance ) { const opt = options[key] if (opt != null) { @@ -295,10 +300,13 @@ function resolvePropValue( // default values if (hasDefault && value === undefined) { const defaultValue = opt.default - value = - opt.type !== Function && isFunction(defaultValue) - ? defaultValue(props) - : defaultValue + if (opt.type !== Function && isFunction(defaultValue)) { + setCurrentInstance(instance) + value = defaultValue(props) + setCurrentInstance(null) + } else { + value = defaultValue + } } // boolean casting if (opt[BooleanFlags.shouldCast]) { From 49bb44756fda0a7019c69f2fa6b880d9e41125aa Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 17 Sep 2020 23:17:21 -0400 Subject: [PATCH 02/17] refactor: watch APIs default to trigger pre-flush BREAKING CHANGE: watch APIs now default to use `flush: 'pre'` instead of `flush: 'post'`. - This change affects `watch`, `watchEffect`, the `watch` component option, and `this.$watch`. - As pointed out by @skirtles-code in [this comment](https://github.com/vuejs/vue-next/issues/1706#issuecomment-666258948), Vue 2's watch behavior is pre-flush, and the ecosystem has many uses of watch that assumes the pre-flush behavior. Defaulting to post-flush can result in unnecessary re-renders without the users being aware of it. - With this change, watchers need to specify `{ flush: 'post' }` via options to trigger callback after Vue render updates. Note that specifying `{ flush: 'post' }` will also defer `watchEffect`'s initial run to wait for the component's initial render. --- .../runtime-core/__tests__/apiWatch.spec.ts | 65 +++++++++---------- .../__tests__/components/Suspense.spec.ts | 52 +++++++++------ packages/runtime-core/src/apiWatch.ts | 11 ++-- .../runtime-core/src/components/KeepAlive.ts | 7 +- 4 files changed, 73 insertions(+), 62 deletions(-) diff --git a/packages/runtime-core/__tests__/apiWatch.spec.ts b/packages/runtime-core/__tests__/apiWatch.spec.ts index 7b64e50bd5f..31bca6bed3f 100644 --- a/packages/runtime-core/__tests__/apiWatch.spec.ts +++ b/packages/runtime-core/__tests__/apiWatch.spec.ts @@ -280,22 +280,29 @@ describe('api: watch', () => { expect(cleanup).toHaveBeenCalledTimes(2) }) - it('flush timing: post (default)', async () => { + it('flush timing: pre (default)', async () => { const count = ref(0) + const count2 = ref(0) + let callCount = 0 - let result - const assertion = jest.fn(count => { + let result1 + let result2 + const assertion = jest.fn((count, count2Value) => { callCount++ // on mount, the watcher callback should be called before DOM render - // on update, should be called after the count is updated - const expectedDOM = callCount === 1 ? `` : `${count}` - result = serializeInner(root) === expectedDOM + // on update, should be called before the count is updated + const expectedDOM = callCount === 1 ? `` : `${count - 1}` + result1 = serializeInner(root) === expectedDOM + + // in a pre-flush callback, all state should have been updated + const expectedState = callCount - 1 + result2 = count === expectedState && count2Value === expectedState }) const Comp = { setup() { watchEffect(() => { - assertion(count.value) + assertion(count.value, count2.value) }) return () => count.value } @@ -303,42 +310,32 @@ describe('api: watch', () => { const root = nodeOps.createElement('div') render(h(Comp), root) expect(assertion).toHaveBeenCalledTimes(1) - expect(result).toBe(true) + expect(result1).toBe(true) + expect(result2).toBe(true) count.value++ + count2.value++ await nextTick() + // two mutations should result in 1 callback execution expect(assertion).toHaveBeenCalledTimes(2) - expect(result).toBe(true) + expect(result1).toBe(true) + expect(result2).toBe(true) }) - it('flush timing: pre', async () => { + it('flush timing: post', async () => { const count = ref(0) - const count2 = ref(0) - - let callCount = 0 - let result1 - let result2 - const assertion = jest.fn((count, count2Value) => { - callCount++ - // on mount, the watcher callback should be called before DOM render - // on update, should be called before the count is updated - const expectedDOM = callCount === 1 ? `` : `${count - 1}` - result1 = serializeInner(root) === expectedDOM - - // in a pre-flush callback, all state should have been updated - const expectedState = callCount - 1 - result2 = count === expectedState && count2Value === expectedState + let result + const assertion = jest.fn(count => { + result = serializeInner(root) === `${count}` }) const Comp = { setup() { watchEffect( () => { - assertion(count.value, count2.value) + assertion(count.value) }, - { - flush: 'pre' - } + { flush: 'post' } ) return () => count.value } @@ -346,16 +343,12 @@ describe('api: watch', () => { const root = nodeOps.createElement('div') render(h(Comp), root) expect(assertion).toHaveBeenCalledTimes(1) - expect(result1).toBe(true) - expect(result2).toBe(true) + expect(result).toBe(true) count.value++ - count2.value++ await nextTick() - // two mutations should result in 1 callback execution expect(assertion).toHaveBeenCalledTimes(2) - expect(result1).toBe(true) - expect(result2).toBe(true) + expect(result).toBe(true) }) it('flush timing: sync', async () => { @@ -410,7 +403,7 @@ describe('api: watch', () => { const cb = jest.fn() const Comp = { setup() { - watch(toggle, cb) + watch(toggle, cb, { flush: 'post' }) }, render() {} } diff --git a/packages/runtime-core/__tests__/components/Suspense.spec.ts b/packages/runtime-core/__tests__/components/Suspense.spec.ts index e4a57804314..dd7d67bc909 100644 --- a/packages/runtime-core/__tests__/components/Suspense.spec.ts +++ b/packages/runtime-core/__tests__/components/Suspense.spec.ts @@ -154,7 +154,7 @@ describe('Suspense', () => { expect(onResolve).toHaveBeenCalled() }) - test('buffer mounted/updated hooks & watch callbacks', async () => { + test('buffer mounted/updated hooks & post flush watch callbacks', async () => { const deps: Promise[] = [] const calls: string[] = [] const toggle = ref(true) @@ -165,14 +165,21 @@ describe('Suspense', () => { // extra tick needed for Node 12+ deps.push(p.then(() => Promise.resolve())) - watchEffect(() => { - calls.push('immediate effect') - }) + watchEffect( + () => { + calls.push('watch effect') + }, + { flush: 'post' } + ) const count = ref(0) - watch(count, () => { - calls.push('watch callback') - }) + watch( + count, + () => { + calls.push('watch callback') + }, + { flush: 'post' } + ) count.value++ // trigger the watcher now onMounted(() => { @@ -201,12 +208,12 @@ describe('Suspense', () => { const root = nodeOps.createElement('div') render(h(Comp), root) expect(serializeInner(root)).toBe(`
fallback
`) - expect(calls).toEqual([`immediate effect`]) + expect(calls).toEqual([]) await Promise.all(deps) await nextTick() expect(serializeInner(root)).toBe(`
async
`) - expect(calls).toEqual([`immediate effect`, `watch callback`, `mounted`]) + expect(calls).toEqual([`watch effect`, `watch callback`, `mounted`]) // effects inside an already resolved suspense should happen at normal timing toggle.value = false @@ -214,7 +221,7 @@ describe('Suspense', () => { await nextTick() expect(serializeInner(root)).toBe(``) expect(calls).toEqual([ - `immediate effect`, + `watch effect`, `watch callback`, `mounted`, 'unmounted' @@ -319,14 +326,21 @@ describe('Suspense', () => { const p = new Promise(r => setTimeout(r, 1)) deps.push(p) - watchEffect(() => { - calls.push('immediate effect') - }) + watchEffect( + () => { + calls.push('watch effect') + }, + { flush: 'post' } + ) const count = ref(0) - watch(count, () => { - calls.push('watch callback') - }) + watch( + count, + () => { + calls.push('watch callback') + }, + { flush: 'post' } + ) count.value++ // trigger the watcher now onMounted(() => { @@ -355,7 +369,7 @@ describe('Suspense', () => { const root = nodeOps.createElement('div') render(h(Comp), root) expect(serializeInner(root)).toBe(`
fallback
`) - expect(calls).toEqual(['immediate effect']) + expect(calls).toEqual([]) // remove the async dep before it's resolved toggle.value = false @@ -366,8 +380,8 @@ describe('Suspense', () => { await Promise.all(deps) await nextTick() expect(serializeInner(root)).toBe(``) - // should discard effects (except for immediate ones) - expect(calls).toEqual(['immediate effect', 'unmounted']) + // should discard effects (except for unmount) + expect(calls).toEqual(['unmounted']) }) test('unmount suspense after resolve', async () => { diff --git a/packages/runtime-core/src/apiWatch.ts b/packages/runtime-core/src/apiWatch.ts index ac1b1d16d7f..14253a2a403 100644 --- a/packages/runtime-core/src/apiWatch.ts +++ b/packages/runtime-core/src/apiWatch.ts @@ -268,9 +268,10 @@ function doWatch( let scheduler: (job: () => any) => void if (flush === 'sync') { scheduler = job - } else if (flush === 'pre') { - // ensure it's queued before component updates (which have positive ids) - job.id = -1 + } else if (flush === 'post') { + scheduler = () => queuePostRenderEffect(job, instance && instance.suspense) + } else { + // default: 'pre' scheduler = () => { if (!instance || instance.isMounted) { queuePreFlushCb(job) @@ -280,8 +281,6 @@ function doWatch( job() } } - } else { - scheduler = () => queuePostRenderEffect(job, instance && instance.suspense) } const runner = effect(getter, { @@ -300,6 +299,8 @@ function doWatch( } else { oldValue = runner() } + } else if (flush === 'post') { + queuePostRenderEffect(runner, instance && instance.suspense) } else { runner() } diff --git a/packages/runtime-core/src/components/KeepAlive.ts b/packages/runtime-core/src/components/KeepAlive.ts index 3259ca685c6..ac6eec56f2e 100644 --- a/packages/runtime-core/src/components/KeepAlive.ts +++ b/packages/runtime-core/src/components/KeepAlive.ts @@ -171,15 +171,18 @@ const KeepAliveImpl = { keys.delete(key) } + // prune cache on include/exclude prop change watch( () => [props.include, props.exclude], ([include, exclude]) => { include && pruneCache(name => matches(include, name)) exclude && pruneCache(name => !matches(exclude, name)) - } + }, + // prune post-render after `current` has been updated + { flush: 'post' } ) - // cache sub tree in beforeMount/Update (i.e. right after the render) + // cache sub tree after render let pendingCacheKey: CacheKey | null = null const cacheSubtree = () => { // fix #1621, the pendingCacheKey could be 0 From 5bfcad155b444b2f7ffaac171c1f61bc23909287 Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 17 Sep 2020 23:49:06 -0400 Subject: [PATCH 03/17] fix(suspense): should discard unmount effects of invalidated pending branch --- packages/runtime-core/__tests__/components/Suspense.spec.ts | 4 ++-- packages/runtime-core/src/components/Suspense.ts | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/runtime-core/__tests__/components/Suspense.spec.ts b/packages/runtime-core/__tests__/components/Suspense.spec.ts index dd7d67bc909..c6ab0f3fa32 100644 --- a/packages/runtime-core/__tests__/components/Suspense.spec.ts +++ b/packages/runtime-core/__tests__/components/Suspense.spec.ts @@ -380,8 +380,8 @@ describe('Suspense', () => { await Promise.all(deps) await nextTick() expect(serializeInner(root)).toBe(``) - // should discard effects (except for unmount) - expect(calls).toEqual(['unmounted']) + // should discard effects + expect(calls).toEqual([]) }) test('unmount suspense after resolve', async () => { diff --git a/packages/runtime-core/src/components/Suspense.ts b/packages/runtime-core/src/components/Suspense.ts index 16204b6d0e0..288139609a9 100644 --- a/packages/runtime-core/src/components/Suspense.ts +++ b/packages/runtime-core/src/components/Suspense.ts @@ -201,11 +201,12 @@ function patchSuspense( suspense.isHydrating = false suspense.activeBranch = pendingBranch } else { - unmount(pendingBranch, parentComponent, null) + unmount(pendingBranch, parentComponent, suspense) } // increment pending ID. this is used to invalidate async callbacks // reset suspense state suspense.deps = 0 + // discard effects from pending branch suspense.effects.length = 0 // discard previous container suspense.hiddenContainer = createElement('div') From 1c9a0b3e195d144ac90d22d2cc2cef6a3fd8276d Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 18 Sep 2020 00:00:39 -0400 Subject: [PATCH 04/17] feat(watch): support dot-delimited path in watch option --- .../runtime-core/__tests__/apiOptions.spec.ts | 14 ++++++++++++-- packages/runtime-core/src/componentOptions.ts | 17 +++++++++++++++-- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/packages/runtime-core/__tests__/apiOptions.spec.ts b/packages/runtime-core/__tests__/apiOptions.spec.ts index 00ecb6e4c4c..6b6014c05cc 100644 --- a/packages/runtime-core/__tests__/apiOptions.spec.ts +++ b/packages/runtime-core/__tests__/apiOptions.spec.ts @@ -113,6 +113,7 @@ describe('api: options', () => { const spyB = jest.fn(returnThis) const spyC = jest.fn(returnThis) const spyD = jest.fn(returnThis) + const spyE = jest.fn(returnThis) let ctx: any const Comp = { @@ -123,7 +124,10 @@ describe('api: options', () => { baz: { qux: 3 }, - qux: 4 + qux: 4, + dot: { + path: 5 + } } }, watch: { @@ -137,7 +141,8 @@ describe('api: options', () => { }, qux: { handler: 'onQuxChange' - } + }, + 'dot.path': spyE }, methods: { onFooChange: spyA, @@ -175,6 +180,11 @@ describe('api: options', () => { await nextTick() expect(spyD).toHaveBeenCalledTimes(1) assertCall(spyD, 0, [5, 4]) + + ctx.dot.path++ + await nextTick() + expect(spyE).toHaveBeenCalledTimes(1) + assertCall(spyE, 0, [6, 5]) }) test('watch array', async () => { diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index ff499d36cdc..0ff710c36c6 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -816,7 +816,9 @@ function createWatcher( publicThis: ComponentPublicInstance, key: string ) { - const getter = () => (publicThis as any)[key] + const getter = key.includes('.') + ? createPathGetter(publicThis, key) + : () => (publicThis as any)[key] if (isString(raw)) { const handler = ctx[raw] if (isFunction(handler)) { @@ -840,7 +842,18 @@ function createWatcher( } } } else if (__DEV__) { - warn(`Invalid watch option: "${key}"`) + warn(`Invalid watch option: "${key}"`, raw) + } +} + +function createPathGetter(ctx: any, path: string) { + const segments = path.split('.') + return () => { + let cur = ctx + for (let i = 0; i < segments.length && cur; i++) { + cur = cur[segments[i]] + } + return cur } } From 57bdaa2220afefbde21118659c1ce2377d6b86d6 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Fri, 18 Sep 2020 12:13:47 +0800 Subject: [PATCH 05/17] fix(types): component instance inference without props (#2145) --- .../runtime-core/src/apiDefineComponent.ts | 4 ++-- packages/runtime-core/src/componentOptions.ts | 19 +++---------------- test-dts/component.test-d.ts | 12 ++++++++++++ 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/packages/runtime-core/src/apiDefineComponent.ts b/packages/runtime-core/src/apiDefineComponent.ts index ef08d3c6533..9b85638c2dd 100644 --- a/packages/runtime-core/src/apiDefineComponent.ts +++ b/packages/runtime-core/src/apiDefineComponent.ts @@ -94,8 +94,8 @@ export function defineComponent< Props = {}, RawBindings = {}, D = {}, - C extends ComputedOptions = ComputedOptions, - M extends MethodOptions = MethodOptions, + C extends ComputedOptions = {}, + M extends MethodOptions = {}, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, E extends EmitsOptions = EmitsOptions, diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index 0ff710c36c6..69f1f2afd1e 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -166,8 +166,7 @@ export type ComponentOptionsWithoutProps< Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, E extends EmitsOptions = EmitsOptions, - EE extends string = string, - Defaults = {} + EE extends string = string > = ComponentOptionsBase< Props, RawBindings, @@ -178,23 +177,11 @@ export type ComponentOptionsWithoutProps< Extends, E, EE, - Defaults + {} > & { props?: undefined } & ThisType< - CreateComponentPublicInstance< - {}, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - Readonly, - Defaults, - false - > + CreateComponentPublicInstance<{}, RawBindings, D, C, M, Mixin, Extends, E> > export type ComponentOptionsWithArrayProps< diff --git a/test-dts/component.test-d.ts b/test-dts/component.test-d.ts index 990e370518b..30b3b8e5f53 100644 --- a/test-dts/component.test-d.ts +++ b/test-dts/component.test-d.ts @@ -190,6 +190,12 @@ describe('object props', () => { expectType(setup.setupProps.ggg) expectType(setup.setupProps.ffff) expectType(setup.setupProps.validated) + + // instance + const instance = new MyComponent() + expectType(instance.setupA) + // @ts-expect-error + instance.notExist }) describe('options', () => { @@ -356,6 +362,12 @@ describe('no props', () => { expectType(rawBindings.setupA) expectType(setup.setupA) + + // instance + const instance = new MyComponent() + expectType(instance.setupA) + // @ts-expect-error + instance.notExist }) describe('options', () => { From 422f05e085036e23ea3632c2ce75d86181a087b8 Mon Sep 17 00:00:00 2001 From: Katashin Date: Fri, 18 Sep 2020 12:14:59 +0800 Subject: [PATCH 06/17] fix(hmr): make hmr working with class components (#2144) --- packages/runtime-core/__tests__/hmr.spec.ts | 43 +++++++++++++++++++++ packages/runtime-core/src/component.ts | 4 ++ packages/runtime-core/src/hmr.ts | 7 +++- packages/runtime-core/src/vnode.ts | 5 ++- 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/packages/runtime-core/__tests__/hmr.spec.ts b/packages/runtime-core/__tests__/hmr.spec.ts index a53c7a3e258..31c910d17d4 100644 --- a/packages/runtime-core/__tests__/hmr.spec.ts +++ b/packages/runtime-core/__tests__/hmr.spec.ts @@ -148,6 +148,49 @@ describe('hot module replacement', () => { expect(mountSpy).toHaveBeenCalledTimes(1) }) + test('reload class component', async () => { + const root = nodeOps.createElement('div') + const childId = 'test4-child' + const unmountSpy = jest.fn() + const mountSpy = jest.fn() + + class Child { + static __vccOpts: ComponentOptions = { + __hmrId: childId, + data() { + return { count: 0 } + }, + unmounted: unmountSpy, + render: compileToFunction(`
{{ count }}
`) + } + } + createRecord(childId) + + const Parent: ComponentOptions = { + render: () => h(Child) + } + + render(h(Parent), root) + expect(serializeInner(root)).toBe(`
0
`) + + class UpdatedChild { + static __vccOpts: ComponentOptions = { + __hmrId: childId, + data() { + return { count: 1 } + }, + mounted: mountSpy, + render: compileToFunction(`
{{ count }}
`) + } + } + + reload(childId, UpdatedChild) + await nextTick() + expect(serializeInner(root)).toBe(`
1
`) + expect(unmountSpy).toHaveBeenCalledTimes(1) + expect(mountSpy).toHaveBeenCalledTimes(1) + }) + // #1156 - static nodes should retain DOM element reference across updates // when HMR is active test('static el reference', async () => { diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index ac482d6707a..78abad60a8a 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -800,3 +800,7 @@ export function formatComponentName( return name ? classify(name) : isRoot ? `App` : `Anonymous` } + +export function isClassComponent(value: unknown): value is ClassComponent { + return isFunction(value) && '__vccOpts' in value +} diff --git a/packages/runtime-core/src/hmr.ts b/packages/runtime-core/src/hmr.ts index b831498baa4..df557313565 100644 --- a/packages/runtime-core/src/hmr.ts +++ b/packages/runtime-core/src/hmr.ts @@ -3,7 +3,9 @@ import { ConcreteComponent, ComponentInternalInstance, ComponentOptions, - InternalRenderFunction + InternalRenderFunction, + ClassComponent, + isClassComponent } from './component' import { queueJob, queuePostFlushCb } from './scheduler' import { extend } from '@vue/shared' @@ -83,7 +85,7 @@ function rerender(id: string, newRender?: Function) { }) } -function reload(id: string, newComp: ComponentOptions) { +function reload(id: string, newComp: ComponentOptions | ClassComponent) { const record = map.get(id) if (!record) return // Array.from creates a snapshot which avoids the set being mutated during @@ -92,6 +94,7 @@ function reload(id: string, newComp: ComponentOptions) { const comp = instance.type if (!hmrDirtyComponents.has(comp)) { // 1. Update existing comp definition to match new one + newComp = isClassComponent(newComp) ? newComp.__vccOpts : newComp extend(comp, newComp) for (const key in comp) { if (!(key in newComp)) { diff --git a/packages/runtime-core/src/vnode.ts b/packages/runtime-core/src/vnode.ts index 9a11090a37c..56ff85f5eea 100644 --- a/packages/runtime-core/src/vnode.ts +++ b/packages/runtime-core/src/vnode.ts @@ -17,7 +17,8 @@ import { Data, ConcreteComponent, ClassComponent, - Component + Component, + isClassComponent } from './component' import { RawSlots } from './componentSlots' import { isProxy, Ref, toRaw, ReactiveFlags } from '@vue/reactivity' @@ -340,7 +341,7 @@ function _createVNode( } // class component normalization. - if (isFunction(type) && '__vccOpts' in type) { + if (isClassComponent(type)) { type = type.__vccOpts } From f316a332b055d3f448dc735365551d89041f1098 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=B4=9C=C9=B4=D0=B2=CA=8F=D1=82=E1=B4=87?= Date: Fri, 18 Sep 2020 13:01:36 +0800 Subject: [PATCH 07/17] fix(reactivity): avoid length mutating array methods causing infinite updates (#2138) fix #2137 Co-authored-by: Evan You --- packages/reactivity/__tests__/effect.spec.ts | 23 +++++++++++++++++ packages/reactivity/src/baseHandlers.ts | 26 +++++++++++++++++--- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/packages/reactivity/__tests__/effect.spec.ts b/packages/reactivity/__tests__/effect.spec.ts index 63fea444202..6be4d8e25dd 100644 --- a/packages/reactivity/__tests__/effect.spec.ts +++ b/packages/reactivity/__tests__/effect.spec.ts @@ -358,6 +358,29 @@ describe('reactivity/effect', () => { expect(counterSpy).toHaveBeenCalledTimes(2) }) + it('should avoid infinite recursive loops when use Array.prototype.push/unshift/pop/shift', () => { + ;(['push', 'unshift'] as const).forEach(key => { + const arr = reactive([]) + const counterSpy1 = jest.fn(() => (arr[key] as any)(1)) + const counterSpy2 = jest.fn(() => (arr[key] as any)(2)) + effect(counterSpy1) + effect(counterSpy2) + expect(arr.length).toBe(2) + expect(counterSpy1).toHaveBeenCalledTimes(1) + expect(counterSpy2).toHaveBeenCalledTimes(1) + }) + ;(['pop', 'shift'] as const).forEach(key => { + const arr = reactive([1, 2, 3, 4]) + const counterSpy1 = jest.fn(() => (arr[key] as any)()) + const counterSpy2 = jest.fn(() => (arr[key] as any)()) + effect(counterSpy1) + effect(counterSpy2) + expect(arr.length).toBe(2) + expect(counterSpy1).toHaveBeenCalledTimes(1) + expect(counterSpy2).toHaveBeenCalledTimes(1) + }) + }) + it('should allow explicitly recursive raw function loops', () => { const counter = reactive({ num: 0 }) const numSpy = jest.fn(() => { diff --git a/packages/reactivity/src/baseHandlers.ts b/packages/reactivity/src/baseHandlers.ts index 2b7b29b03a8..f612043a339 100644 --- a/packages/reactivity/src/baseHandlers.ts +++ b/packages/reactivity/src/baseHandlers.ts @@ -8,7 +8,13 @@ import { reactiveMap } from './reactive' import { TrackOpTypes, TriggerOpTypes } from './operations' -import { track, trigger, ITERATE_KEY } from './effect' +import { + track, + trigger, + ITERATE_KEY, + pauseTracking, + enableTracking +} from './effect' import { isObject, hasOwn, @@ -32,22 +38,36 @@ const readonlyGet = /*#__PURE__*/ createGetter(true) const shallowReadonlyGet = /*#__PURE__*/ createGetter(true, true) const arrayInstrumentations: Record = {} +// instrument identity-sensitive Array methods to account for possible reactive +// values ;(['includes', 'indexOf', 'lastIndexOf'] as const).forEach(key => { + const method = Array.prototype[key] as any arrayInstrumentations[key] = function(this: unknown[], ...args: unknown[]) { const arr = toRaw(this) for (let i = 0, l = this.length; i < l; i++) { track(arr, TrackOpTypes.GET, i + '') } // we run the method using the original args first (which may be reactive) - const res = (arr[key] as any)(...args) + const res = method.apply(arr, args) if (res === -1 || res === false) { // if that didn't work, run it again using raw values. - return (arr[key] as any)(...args.map(toRaw)) + return method.apply(arr, args.map(toRaw)) } else { return res } } }) +// instrument length-altering mutation methods to avoid length being tracked +// which leads to infinite loops in some cases (#2137) +;(['push', 'pop', 'shift', 'unshift', 'splice'] as const).forEach(key => { + const method = Array.prototype[key] as any + arrayInstrumentations[key] = function(this: unknown[], ...args: unknown[]) { + pauseTracking() + const res = method.apply(this, args) + enableTracking() + return res + } +}) function createGetter(isReadonly = false, shallow = false) { return function get(target: Target, key: string | symbol, receiver: object) { From 39a1a6d05dbac74beb44b46c03b204507fc5b335 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 18 Sep 2020 05:04:29 +0000 Subject: [PATCH 08/17] build(deps-dev): bump sass from 1.26.10 to 1.26.11 (#2146) --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index cd2df31c9e7..5ee15944781 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6447,9 +6447,9 @@ sane@^4.0.3: walker "~1.0.5" sass@^1.26.9: - version "1.26.10" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.26.10.tgz#851d126021cdc93decbf201d1eca2a20ee434760" - integrity sha512-bzN0uvmzfsTvjz0qwccN1sPm2HxxpNI/Xa+7PlUEMS+nQvbyuEK7Y0qFqxlPHhiNHb1Ze8WQJtU31olMObkAMw== + version "1.26.11" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.26.11.tgz#0f22cc4ab2ba27dad1d4ca30837beb350b709847" + integrity sha512-W1l/+vjGjIamsJ6OnTe0K37U2DBO/dgsv2Z4c89XQ8ZOO6l/VwkqwLSqoYzJeJs6CLuGSTRWc91GbQFL3lvrvw== dependencies: chokidar ">=2.0.0 <4.0.0" From 3d03dd50d4fa8cbe639c8f1e218ed53837e3a204 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 18 Sep 2020 05:08:23 +0000 Subject: [PATCH 09/17] build(deps-dev): bump @types/jest from 26.0.13 to 26.0.14 (#2147) --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 5ee15944781..4eaf5263b50 100644 --- a/yarn.lock +++ b/yarn.lock @@ -864,9 +864,9 @@ "@types/istanbul-lib-report" "*" "@types/jest@26.x", "@types/jest@^26.0.0": - version "26.0.13" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.13.tgz#5a7b9d5312f5dd521a38329c38ee9d3802a0b85e" - integrity sha512-sCzjKow4z9LILc6DhBvn5AkIfmQzDZkgtVVKmGwVrs5tuid38ws281D4l+7x1kP487+FlKDh5kfMZ8WSPAdmdA== + version "26.0.14" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.14.tgz#078695f8f65cb55c5a98450d65083b2b73e5a3f3" + integrity sha512-Hz5q8Vu0D288x3iWXePSn53W7hAjP0H7EQ6QvDO9c7t46mR0lNOLlfuwQ+JkVxuhygHzlzPX+0jKdA3ZgSh+Vg== dependencies: jest-diff "^25.2.1" pretty-format "^25.2.1" From ecd49793c37ee4b34df6c18d87b7e36763aa4b9a Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 18 Sep 2020 05:15:23 +0000 Subject: [PATCH 10/17] build(deps-dev): bump rollup from 2.26.11 to 2.27.1 (#2149) --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 4eaf5263b50..236e291664f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6386,9 +6386,9 @@ rollup-pluginutils@^2.3.1: estree-walker "^0.6.1" rollup@^2.26.11: - version "2.26.11" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.26.11.tgz#4fc31de9c7b83d50916fc8395f8c3d24730cdaae" - integrity sha512-xyfxxhsE6hW57xhfL1I+ixH8l2bdoIMaAecdQiWF3N7IgJEMu99JG+daBiSZQjnBpzFxa0/xZm+3pbCdAQehHw== + version "2.27.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.27.1.tgz#372744e1d36eba0fd942d997600c2fc2ca266305" + integrity sha512-GiWHQvnmMgBktSpY/1+nrGpwPsTw4b9P28og2uedfeq4JZ16rzAmnQ5Pm/E0/BEmDNia1ZbY7+qu3nBgNa19Hg== optionalDependencies: fsevents "~2.1.2" From 76137e95a618c8b1ebd6a5de12f9348cd8a7bbc7 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 18 Sep 2020 05:17:40 +0000 Subject: [PATCH 11/17] build(deps-dev): bump lint-staged from 10.3.0 to 10.4.0 (#2150) --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 236e291664f..d898ecb5e4b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4624,9 +4624,9 @@ lines-and-columns@^1.1.6: integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= lint-staged@^10.2.10: - version "10.3.0" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.3.0.tgz#388c3d440590c45c339e7163f669ea69ae90b1e0" - integrity sha512-an3VgjHqmJk0TORB/sdQl0CTkRg4E5ybYCXTTCSJ5h9jFwZbcgKIx5oVma5e7wp/uKt17s1QYFmYqT9MGVosGw== + version "10.4.0" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.4.0.tgz#d18628f737328e0bbbf87d183f4020930e9a984e" + integrity sha512-uaiX4U5yERUSiIEQc329vhCTDDwUcSvKdRLsNomkYLRzijk3v8V9GWm2Nz0RMVB87VcuzLvtgy6OsjoH++QHIg== dependencies: chalk "^4.1.0" cli-truncate "^2.1.0" From 62cd7f2e90f8d21b1355cd80213f64ed8a8691f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?ChangJoo=20Park=28=EB=B0=95=EC=B0=BD=EC=A3=BC=29?= Date: Fri, 18 Sep 2020 14:22:45 +0900 Subject: [PATCH 12/17] chore: fix changelog typo (#2152) [ci skip] --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b289346e282..7d16dbe3aca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ### Bug Fixes -* **reactivity:** effect shoud only recursively self trigger with explicit options ([3810de7](https://github.com/vuejs/vue-next/commit/3810de7d6bd0044177f043285228c2e988093883)), closes [#2125](https://github.com/vuejs/vue-next/issues/2125) +* **reactivity:** effect should only recursively self trigger with explicit options ([3810de7](https://github.com/vuejs/vue-next/commit/3810de7d6bd0044177f043285228c2e988093883)), closes [#2125](https://github.com/vuejs/vue-next/issues/2125) * **runtime-core:** ensure root stable fragments inherit elements for moving ([bebd44f](https://github.com/vuejs/vue-next/commit/bebd44f793ccd13bfdf90c7e45eac320a340650c)), closes [#2134](https://github.com/vuejs/vue-next/issues/2134) * **runtime-core:** should still do full traverse of stable fragment children in dev + hmr ([dd40ad8](https://github.com/vuejs/vue-next/commit/dd40ad8fca47af0e1f0a963be2f48c23f7457952)) * **runtime-core/async-component:** fix error component when there are no error handlers ([c7b4a37](https://github.com/vuejs/vue-next/commit/c7b4a379cf8627c79a01d61039d3e3b283477dc1)), closes [#2129](https://github.com/vuejs/vue-next/issues/2129) From a6bfe6f5f9ac95d868ac03f0c57168eb4347ffca Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 18 Sep 2020 01:23:03 -0400 Subject: [PATCH 13/17] build(deps-dev): bump @types/node from 14.10.2 to 14.11.1 (#2151) Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 14.10.2 to 14.11.1. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index d898ecb5e4b..a649eeccbf1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -887,9 +887,9 @@ integrity sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY= "@types/node@*", "@types/node@^14.10.1": - version "14.10.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.10.2.tgz#9b47a2c8e4dabd4db73b57e750b24af689600514" - integrity sha512-IzMhbDYCpv26pC2wboJ4MMOa9GKtjplXfcAqrMeNJpUUwpM/2ATt2w1JPUXwS6spu856TvKZL2AOmeU2rAxskw== + version "14.11.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.11.1.tgz#56af902ad157e763f9ba63d671c39cda3193c835" + integrity sha512-oTQgnd0hblfLsJ6BvJzzSL+Inogp3lq9fGgqRkMB/ziKMgEUaFl801OncOzUmalfzt14N0oPHMK47ipl+wbTIw== "@types/node@10.17.13": version "10.17.13" From a8d27cc058274ce644986c8df524a0a1b68e8992 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 18 Sep 2020 01:23:17 -0400 Subject: [PATCH 14/17] build(deps): bump postcss from 7.0.32 to 7.0.34 (#2148) Bumps [postcss](https://github.com/postcss/postcss) from 7.0.32 to 7.0.34. - [Release notes](https://github.com/postcss/postcss/releases) - [Changelog](https://github.com/postcss/postcss/blob/master/CHANGELOG.md) - [Commits](https://github.com/postcss/postcss/compare/7.0.32...7.0.34) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index a649eeccbf1..063307a72a5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5708,9 +5708,9 @@ postcss-value-parser@^4.0.0: integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: - version "7.0.32" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d" - integrity sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw== + version "7.0.34" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.34.tgz#f2baf57c36010df7de4009940f21532c16d65c20" + integrity sha512-H/7V2VeNScX9KE83GDrDZNiGT1m2H+UTnlinIzhjlLX9hfMUn1mHNnGeX81a1c8JSBdBvqk7c2ZOG6ZPn5itGw== dependencies: chalk "^2.4.2" source-map "^0.6.1" From 44e1237d1f5492051d30c37ef87e449afbee7d44 Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 18 Sep 2020 01:25:53 -0400 Subject: [PATCH 15/17] chore: update readme [ci skip] --- README.md | 84 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 46 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index e2750cf8409..fbaf3cbc324 100644 --- a/README.md +++ b/README.md @@ -1,88 +1,96 @@ # vue-next [![beta](https://img.shields.io/npm/v/vue/next.svg)](https://www.npmjs.com/package/vue/v/next) [![CircleCI](https://circleci.com/gh/vuejs/vue-next.svg?style=svg&circle-token=fb883a2d0a73df46e80b2e79fd430959d8f2b488)](https://circleci.com/gh/vuejs/vue-next) -## Status: Release Candidate +This is the repository for Vue 3.0. -- All planned RFCs have been merged. +## Quickstart -- All [merged RFCs](https://github.com/vuejs/rfcs/pulls?q=is%3Apr+is%3Amerged+label%3A3.x) have been implemented. +- Via CDN: `` +- In-browser playground on [Codepen](https://codepen.io/yyx990803/pen/OJNoaZL) +- Scaffold via [Vite](https://github.com/vitejs/vite): -- Vue CLI now has experimental support via [vue-cli-plugin-vue-next](https://github.com/vuejs/vue-cli-plugin-vue-next). + ```bash + npm init vite-app hello-vue3 # OR yarn create vite-app hello-vue3 + ``` -- There is also a simple plain webpack-based setup with Single-File Component support available [here](https://github.com/vuejs/vue-next-webpack-preview). +- Scaffold via [vue-cli](https://cli.vuejs.org/): -Please note that there could still be undocumented behavior inconsistencies with 2.x. When you run into such a case, please make sure to first check if the behavior difference has already been proposed in an existing RFC. If the inconsistency is not part of an RFC, then it's likely unintended, and an issue should be opened (please make sure to use the [issue helper](https://new-issue.vuejs.org/?repo=vuejs/vue-next) when opening new issues). + ```bash + npm install -g @vue/cli # OR yarn global add @vue/cli + vue create hello-vue3 + # select vue 3 preset + ``` -In addition, the current implementation requires native ES2015+ in the runtime environment and does not support IE11 (yet). The IE11 compatible build will be worked on after we have reached RC stage. +## Changes from Vue 2 -The documentation of Vue 3 can be found at https://v3.vuejs.org/ +Please consult the [Migration Guide](https://v3.vuejs.org/guide/migration/introduction.html). -## Status of the rest of the framework +- Note: IE11 support is still pending. + +## Supporting Libraries + +All of our official libraries and tools now support Vue 3, but most of them are still in beta status and distributed under the `next` dist tag on NPM. **We are planning to stabilize and switch all projects to use the `latest` dist tag by end of 2020.** + +### Vue CLI + +As of v4.5.0, `vue-cli` now provides built-in option to choose Vue 3 preset when creating a new project. You can upgrade `vue-cli` and run `vue create` to create a Vue 3 project today. ### Vue Router +Vue Router 4.0 provides Vue 3 support and has a number of breaking changes of its own. Check out its [Migration Guide](https://next.router.vuejs.org/guide/migration/) for full details. + - [![beta](https://img.shields.io/npm/v/vue-router/next.svg)](https://www.npmjs.com/package/vue-router/v/next) - [Github](https://github.com/vuejs/vue-router-next) - [RFCs](https://github.com/vuejs/rfcs/pulls?q=is%3Apr+is%3Amerged+label%3Arouter) ### Vuex +Vuex 4.0 provides Vue 3 support with largely the same API as 3.x. The only breaking change is [how the plugin is installed](https://github.com/vuejs/vuex/tree/4.0#breaking-changes). + - [![beta](https://img.shields.io/npm/v/vuex/next.svg)](https://www.npmjs.com/package/vuex/v/next) - [Github](https://github.com/vuejs/vuex/tree/4.0) -The only difference between Vuex 4.0 and 3.x is that it's Vue 3 compatible! It is ready to enter RC together with Vue 3 core. - -### Vue CLI - -As of v4.5.0, `vue-cli` now provides built-in option to choose Vue 3 preset when creating a new project. +### Devtools Extension -### JSX Support +We are working on a new version of the Devtools with a new UI and refactored internals to support multiple Vue versions. The new version is currently in beta and only supports Vue 3 (for now). Vuex and Router integration is also work in progress. -There are currently two JSX transform implementations for Vue 3 with slightly differing syntax (for Vue specific features): +- For Chrome: [Install from Chrome web store](https://chrome.google.com/webstore/detail/vuejs-devtools/ljjemllljcmogpfapbkkighbhhppjdbg?hl=en) -- [vuejs/jsx-next](https://github.com/vuejs/jsx-next) -- [HcySunYang/vue-next-jsx](https://github.com/HcySunYang/vue-next-jsx) + - Note: the beta channel may conflict with the stable version of devtools so you may need to temporarily disable the stable version for the beta channel to work properly. -We are using [this thread](https://github.com/vuejs/jsx/issues/141) to unify the design and land on an official specification of how Vue features should be handled in JSX. If you use Vue with JSX, please provide your feedback in that thread. +- For Firefox: [Download the signed extension](https://github.com/vuejs/vue-devtools/releases/tag/v6.0.0-beta.2) (`.xpi` file under Assets) ### Other Projects -| Project | Status | -| ------------------- | ------ | -| vue-devtools | [![alpha][vd-badge]][vd-npm] [[Github][vd-code]] | -| eslint-plugin-vue | [![alpha][epv-badge]][epv-npm] [[Github][epv-code]] | -| @vue/test-utils | [![alpha][vtu-badge]][vtu-npm] [[Github][vtu-code]] | -| vue-class-component | [![alpha][vcc-badge]][vcc-npm] [[Github][vcc-code]] | -| vue-loader | [![alpha][vl-badge]][vl-npm] [[Github][vl-code]] | -| rollup-plugin-vue | [![alpha][rpv-badge]][rpv-npm] [[Github][rpv-code]] | - +| Project | NPM | Repo | +| --------------------- | ----------------------------- | -------------------- | +| @vue/babel-plugin-jsx | [![rc][jsx-badge]][jsx-npm] | [[Github][jsx-code]] | +| eslint-plugin-vue | [![beta][epv-badge]][epv-npm] | [[Github][epv-code]] | +| @vue/test-utils | [![beta][vtu-badge]][vtu-npm] | [[Github][vtu-code]] | +| vue-class-component | [![beta][vcc-badge]][vcc-npm] | [[Github][vcc-code]] | +| vue-loader | [![beta][vl-badge]][vl-npm] | [[Github][vl-code]] | +| rollup-plugin-vue | [![beta][rpv-badge]][rpv-npm] | [[Github][rpv-code]] | + +[jsx-badge]: https://img.shields.io/npm/v/@vue/babel-plugin-jsx.svg +[jsx-npm]: https://www.npmjs.com/package/@vue/babel-plugin-jsx +[jsx-code]: https://github.com/vuejs/jsx-next [vd-badge]: https://img.shields.io/npm/v/@vue/devtools/beta.svg [vd-npm]: https://www.npmjs.com/package/@vue/devtools/v/beta [vd-code]: https://github.com/vuejs/vue-devtools/tree/next - [epv-badge]: https://img.shields.io/npm/v/eslint-plugin-vue/next.svg [epv-npm]: https://www.npmjs.com/package/eslint-plugin-vue/v/next [epv-code]: https://github.com/vuejs/eslint-plugin-vue - [vtu-badge]: https://img.shields.io/npm/v/@vue/test-utils/next.svg [vtu-npm]: https://www.npmjs.com/package/@vue/test-utils/v/next [vtu-code]: https://github.com/vuejs/vue-test-utils-next - [jsx-badge]: https://img.shields.io/npm/v/@ant-design-vue/babel-plugin-jsx.svg [jsx-npm]: https://www.npmjs.com/package/@ant-design-vue/babel-plugin-jsx [jsx-code]: https://github.com/vueComponent/jsx - [vcc-badge]: https://img.shields.io/npm/v/vue-class-component/next.svg [vcc-npm]: https://www.npmjs.com/package/vue-class-component/v/next [vcc-code]: https://github.com/vuejs/vue-class-component/tree/next - [vl-badge]: https://img.shields.io/npm/v/vue-loader/next.svg [vl-npm]: https://www.npmjs.com/package/vue-loader/v/next [vl-code]: https://github.com/vuejs/vue-loader/tree/next - [rpv-badge]: https://img.shields.io/npm/v/rollup-plugin-vue/next.svg [rpv-npm]: https://www.npmjs.com/package/rollup-plugin-vue/v/next [rpv-code]: https://github.com/vuejs/rollup-plugin-vue/tree/next - -## Contribution - -See [Contributing Guide](https://github.com/vuejs/vue-next/blob/master/.github/contributing.md). From e90ec6e98ca061c88fa80e3b163804bb9cf25c27 Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 18 Sep 2020 01:29:34 -0400 Subject: [PATCH 16/17] chore: add note for vetur [ci skip] --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index fbaf3cbc324..bc287c38d25 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,10 @@ We are working on a new version of the Devtools with a new UI and refactored int - For Firefox: [Download the signed extension](https://github.com/vuejs/vue-devtools/releases/tag/v6.0.0-beta.2) (`.xpi` file under Assets) +### IDE Support + +It is recommended to use [VSCode](https://code.visualstudio.com/) with our official extension [Vetur](https://marketplace.visualstudio.com/items?itemName=octref.vetur), which provides comprehensive IDE support for Vue 3. + ### Other Projects | Project | NPM | Repo | From 876ecc86720d46c09261a9ca41443dd1e1c713ea Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 18 Sep 2020 01:39:30 -0400 Subject: [PATCH 17/17] release: v3.0.0-rc.13 --- CHANGELOG.md | 34 +++++++++++++++++++++++++ package.json | 2 +- packages/compiler-core/package.json | 4 +-- packages/compiler-dom/package.json | 6 ++--- packages/compiler-sfc/package.json | 12 ++++----- packages/compiler-ssr/package.json | 6 ++--- packages/reactivity/package.json | 4 +-- packages/runtime-core/package.json | 6 ++--- packages/runtime-dom/package.json | 6 ++--- packages/runtime-test/package.json | 6 ++--- packages/server-renderer/package.json | 8 +++--- packages/shared/package.json | 2 +- packages/size-check/package.json | 2 +- packages/template-explorer/package.json | 2 +- packages/vue/package.json | 8 +++--- 15 files changed, 71 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d16dbe3aca..0385eed3b7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,37 @@ +# [3.0.0-rc.13](https://github.com/vuejs/vue-next/compare/v3.0.0-rc.12...v3.0.0-rc.13) (2020-09-18) + + +### Bug Fixes + +* **hmr:** make hmr working with class components ([#2144](https://github.com/vuejs/vue-next/issues/2144)) ([422f05e](https://github.com/vuejs/vue-next/commit/422f05e085036e23ea3632c2ce75d86181a087b8)) +* **reactivity:** avoid length mutating array methods causing infinite updates ([#2138](https://github.com/vuejs/vue-next/issues/2138)) ([f316a33](https://github.com/vuejs/vue-next/commit/f316a332b055d3f448dc735365551d89041f1098)), closes [#2137](https://github.com/vuejs/vue-next/issues/2137) +* **suspense:** should discard unmount effects of invalidated pending branch ([5bfcad1](https://github.com/vuejs/vue-next/commit/5bfcad155b444b2f7ffaac171c1f61bc23909287)) +* **types:** component instance inference without props ([#2145](https://github.com/vuejs/vue-next/issues/2145)) ([57bdaa2](https://github.com/vuejs/vue-next/commit/57bdaa2220afefbde21118659c1ce2377d6b86d6)) + + +### Code Refactoring + +* watch APIs default to trigger pre-flush ([49bb447](https://github.com/vuejs/vue-next/commit/49bb44756fda0a7019c69f2fa6b880d9e41125aa)), closes [/github.com/vuejs/vue-next/issues/1706#issuecomment-666258948](https://github.com//github.com/vuejs/vue-next/issues/1706/issues/issuecomment-666258948) + + +### Features + +* **runtime-core:** support using inject() inside props default functions ([58c31e3](https://github.com/vuejs/vue-next/commit/58c31e36992d2647e5247de4904246fb2d6112ed)) +* **watch:** support dot-delimited path in watch option ([1c9a0b3](https://github.com/vuejs/vue-next/commit/1c9a0b3e195d144ac90d22d2cc2cef6a3fd8276d)) + + +### BREAKING CHANGES + +* watch APIs now default to use `flush: 'pre'` instead of +`flush: 'post'`. + + - This change affects `watch`, `watchEffect`, the `watch` component + option, and `this.$watch`. + + - As pointed out by @skirtles-code in + + + # [3.0.0-rc.12](https://github.com/vuejs/vue-next/compare/v3.0.0-rc.11...v3.0.0-rc.12) (2020-09-16) diff --git a/package.json b/package.json index d4c700cc635..7a8fcaf6619 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "private": true, - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "workspaces": [ "packages/*" ], diff --git a/packages/compiler-core/package.json b/packages/compiler-core/package.json index f0928920831..8ded40ecf56 100644 --- a/packages/compiler-core/package.json +++ b/packages/compiler-core/package.json @@ -1,6 +1,6 @@ { "name": "@vue/compiler-core", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "description": "@vue/compiler-core", "main": "index.js", "module": "dist/compiler-core.esm-bundler.js", @@ -31,7 +31,7 @@ }, "homepage": "https://github.com/vuejs/vue-next/tree/master/packages/compiler-core#readme", "dependencies": { - "@vue/shared": "3.0.0-rc.12", + "@vue/shared": "3.0.0-rc.13", "@babel/parser": "^7.11.5", "@babel/types": "^7.11.5", "estree-walker": "^2.0.1", diff --git a/packages/compiler-dom/package.json b/packages/compiler-dom/package.json index 3c98116f0a3..91afba2aac0 100644 --- a/packages/compiler-dom/package.json +++ b/packages/compiler-dom/package.json @@ -1,6 +1,6 @@ { "name": "@vue/compiler-dom", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "description": "@vue/compiler-dom", "main": "index.js", "module": "dist/compiler-dom.esm-bundler.js", @@ -36,7 +36,7 @@ }, "homepage": "https://github.com/vuejs/vue-next/tree/master/packages/compiler-dom#readme", "dependencies": { - "@vue/shared": "3.0.0-rc.12", - "@vue/compiler-core": "3.0.0-rc.12" + "@vue/shared": "3.0.0-rc.13", + "@vue/compiler-core": "3.0.0-rc.13" } } diff --git a/packages/compiler-sfc/package.json b/packages/compiler-sfc/package.json index 9815e4fa716..ed4f90a629b 100644 --- a/packages/compiler-sfc/package.json +++ b/packages/compiler-sfc/package.json @@ -1,6 +1,6 @@ { "name": "@vue/compiler-sfc", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "description": "@vue/compiler-sfc", "main": "dist/compiler-sfc.cjs.js", "types": "dist/compiler-sfc.d.ts", @@ -32,15 +32,15 @@ }, "homepage": "https://github.com/vuejs/vue-next/tree/master/packages/compiler-sfc#readme", "peerDependencies": { - "vue": "3.0.0-rc.12" + "vue": "3.0.0-rc.13" }, "dependencies": { "@babel/parser": "^7.11.5", "@babel/types": "^7.11.5", - "@vue/compiler-core": "3.0.0-rc.12", - "@vue/compiler-dom": "3.0.0-rc.12", - "@vue/compiler-ssr": "3.0.0-rc.12", - "@vue/shared": "3.0.0-rc.12", + "@vue/compiler-core": "3.0.0-rc.13", + "@vue/compiler-dom": "3.0.0-rc.13", + "@vue/compiler-ssr": "3.0.0-rc.13", + "@vue/shared": "3.0.0-rc.13", "consolidate": "^0.16.0", "estree-walker": "^2.0.1", "hash-sum": "^2.0.0", diff --git a/packages/compiler-ssr/package.json b/packages/compiler-ssr/package.json index 887859e6dbc..194fcf8ba17 100644 --- a/packages/compiler-ssr/package.json +++ b/packages/compiler-ssr/package.json @@ -1,6 +1,6 @@ { "name": "@vue/compiler-ssr", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "description": "@vue/compiler-ssr", "main": "dist/compiler-ssr.cjs.js", "types": "dist/compiler-ssr.d.ts", @@ -28,7 +28,7 @@ }, "homepage": "https://github.com/vuejs/vue-next/tree/master/packages/compiler-ssr#readme", "dependencies": { - "@vue/shared": "3.0.0-rc.12", - "@vue/compiler-dom": "3.0.0-rc.12" + "@vue/shared": "3.0.0-rc.13", + "@vue/compiler-dom": "3.0.0-rc.13" } } diff --git a/packages/reactivity/package.json b/packages/reactivity/package.json index cc8983720a0..eb675381105 100644 --- a/packages/reactivity/package.json +++ b/packages/reactivity/package.json @@ -1,6 +1,6 @@ { "name": "@vue/reactivity", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "description": "@vue/reactivity", "main": "index.js", "module": "dist/reactivity.esm-bundler.js", @@ -36,6 +36,6 @@ }, "homepage": "https://github.com/vuejs/vue-next/tree/master/packages/reactivity#readme", "dependencies": { - "@vue/shared": "3.0.0-rc.12" + "@vue/shared": "3.0.0-rc.13" } } diff --git a/packages/runtime-core/package.json b/packages/runtime-core/package.json index 78226ccd5fc..5ed9cc653ae 100644 --- a/packages/runtime-core/package.json +++ b/packages/runtime-core/package.json @@ -1,6 +1,6 @@ { "name": "@vue/runtime-core", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "description": "@vue/runtime-core", "main": "index.js", "module": "dist/runtime-core.esm-bundler.js", @@ -32,7 +32,7 @@ }, "homepage": "https://github.com/vuejs/vue-next/tree/master/packages/runtime-core#readme", "dependencies": { - "@vue/shared": "3.0.0-rc.12", - "@vue/reactivity": "3.0.0-rc.12" + "@vue/shared": "3.0.0-rc.13", + "@vue/reactivity": "3.0.0-rc.13" } } diff --git a/packages/runtime-dom/package.json b/packages/runtime-dom/package.json index c7ce948ac84..cae5257fcad 100644 --- a/packages/runtime-dom/package.json +++ b/packages/runtime-dom/package.json @@ -1,6 +1,6 @@ { "name": "@vue/runtime-dom", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "description": "@vue/runtime-dom", "main": "index.js", "module": "dist/runtime-dom.esm-bundler.js", @@ -35,8 +35,8 @@ }, "homepage": "https://github.com/vuejs/vue-next/tree/master/packages/runtime-dom#readme", "dependencies": { - "@vue/shared": "3.0.0-rc.12", - "@vue/runtime-core": "3.0.0-rc.12", + "@vue/shared": "3.0.0-rc.13", + "@vue/runtime-core": "3.0.0-rc.13", "csstype": "^2.6.8" } } diff --git a/packages/runtime-test/package.json b/packages/runtime-test/package.json index ab5f885d5bb..f0aad177ade 100644 --- a/packages/runtime-test/package.json +++ b/packages/runtime-test/package.json @@ -1,6 +1,6 @@ { "name": "@vue/runtime-test", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "description": "@vue/runtime-test", "private": true, "main": "index.js", @@ -25,7 +25,7 @@ }, "homepage": "https://github.com/vuejs/vue-next/tree/master/packages/runtime-test#readme", "dependencies": { - "@vue/shared": "3.0.0-rc.12", - "@vue/runtime-core": "3.0.0-rc.12" + "@vue/shared": "3.0.0-rc.13", + "@vue/runtime-core": "3.0.0-rc.13" } } diff --git a/packages/server-renderer/package.json b/packages/server-renderer/package.json index 98a2979f388..a480e9a12be 100644 --- a/packages/server-renderer/package.json +++ b/packages/server-renderer/package.json @@ -1,6 +1,6 @@ { "name": "@vue/server-renderer", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "description": "@vue/server-renderer", "main": "index.js", "types": "dist/server-renderer.d.ts", @@ -28,10 +28,10 @@ }, "homepage": "https://github.com/vuejs/vue-next/tree/master/packages/server-renderer#readme", "peerDependencies": { - "vue": "3.0.0-rc.12" + "vue": "3.0.0-rc.13" }, "dependencies": { - "@vue/shared": "3.0.0-rc.12", - "@vue/compiler-ssr": "3.0.0-rc.12" + "@vue/shared": "3.0.0-rc.13", + "@vue/compiler-ssr": "3.0.0-rc.13" } } diff --git a/packages/shared/package.json b/packages/shared/package.json index 275d8c32780..cb67f854670 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -1,6 +1,6 @@ { "name": "@vue/shared", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "description": "internal utils shared across @vue packages", "main": "index.js", "module": "dist/shared.esm-bundler.js", diff --git a/packages/size-check/package.json b/packages/size-check/package.json index f21de24e606..d2e8039d3c3 100644 --- a/packages/size-check/package.json +++ b/packages/size-check/package.json @@ -1,6 +1,6 @@ { "name": "@vue/size-check", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "private": true, "buildOptions": { "name": "Vue", diff --git a/packages/template-explorer/package.json b/packages/template-explorer/package.json index e6402f74141..e1afed4c27c 100644 --- a/packages/template-explorer/package.json +++ b/packages/template-explorer/package.json @@ -1,6 +1,6 @@ { "name": "@vue/template-explorer", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "private": true, "buildOptions": { "formats": [ diff --git a/packages/vue/package.json b/packages/vue/package.json index 805318f3642..a940a4a4756 100644 --- a/packages/vue/package.json +++ b/packages/vue/package.json @@ -1,6 +1,6 @@ { "name": "vue", - "version": "3.0.0-rc.12", + "version": "3.0.0-rc.13", "description": "vue", "main": "index.js", "module": "dist/vue.runtime.esm-bundler.js", @@ -37,9 +37,9 @@ }, "homepage": "https://github.com/vuejs/vue-next/tree/master/packages/vue#readme", "dependencies": { - "@vue/shared": "3.0.0-rc.12", - "@vue/compiler-dom": "3.0.0-rc.12", - "@vue/runtime-dom": "3.0.0-rc.12" + "@vue/shared": "3.0.0-rc.13", + "@vue/compiler-dom": "3.0.0-rc.13", + "@vue/runtime-dom": "3.0.0-rc.13" }, "devDependencies": { "lodash": "^4.17.15", pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy