Skip to content

Commit

Permalink
fix(setup): setup hook should be called before beforeCreate
Browse files Browse the repository at this point in the history
fix #12802

Note this commit moves the initialization of injections and props to
before the invocation of beforeCreate. This should not cause breakage
because props and inject normalization has always been done before
beforeCreate, so code that attempts to modifiy props/inject options
inside beforeCreate should have never worked.
  • Loading branch information
yyx990803 committed Oct 11, 2022
1 parent 0d6d972 commit e1342df
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 10 deletions.
9 changes: 7 additions & 2 deletions src/core/instance/init.ts
@@ -1,6 +1,6 @@
import config from '../config'
import { initProxy } from './proxy'
import { initState } from './state'
import { initProps, initState } from './state'
import { initRender } from './render'
import { initEvents } from './events'
import { mark, measure } from '../util/perf'
Expand All @@ -10,6 +10,7 @@ import { extend, mergeOptions, formatComponentName } from '../util/index'
import type { Component } from 'types/component'
import type { InternalComponentOptions } from 'types/options'
import { EffectScope } from 'v3/reactivity/effectScope'
import { initSetup } from '../../v3/apiSetup'

let uid = 0

Expand Down Expand Up @@ -59,8 +60,12 @@ export function initMixin(Vue: typeof Component) {
initLifecycle(vm)
initEvents(vm)
initRender(vm)
callHook(vm, 'beforeCreate', undefined, false /* setContext */)

const opts = vm.$options
initInjections(vm) // resolve injections before data/props
initProps(vm, opts.props)
initSetup(vm)
callHook(vm, 'beforeCreate', undefined, false /* setContext */)
initState(vm)
initProvide(vm) // resolve provide after data/props
callHook(vm, 'created')
Expand Down
9 changes: 2 additions & 7 deletions src/core/instance/state.ts
Expand Up @@ -2,7 +2,6 @@ import config from '../config'
import Watcher from '../observer/watcher'
import Dep, { pushTarget, popTarget } from '../observer/dep'
import { isUpdatingChildComponent } from './lifecycle'
import { initSetup } from 'v3/apiSetup'

import {
set,
Expand Down Expand Up @@ -51,11 +50,6 @@ export function proxy(target: Object, sourceKey: string, key: string) {

export function initState(vm: Component) {
const opts = vm.$options
if (opts.props) initProps(vm, opts.props)

// Composition API
initSetup(vm)

if (opts.methods) initMethods(vm, opts.methods)
if (opts.data) {
initData(vm)
Expand All @@ -69,7 +63,8 @@ export function initState(vm: Component) {
}
}

function initProps(vm: Component, propsOptions: Object) {
export function initProps(vm: Component, propsOptions: Object | undefined) {
if (!propsOptions) return
const propsData = vm.$options.propsData || {}
const props = (vm._props = shallowReactive({}))
// cache prop keys so that future props updates can iterate using Array
Expand Down
28 changes: 27 additions & 1 deletion test/unit/features/v3/apiSetup.spec.ts
Expand Up @@ -263,7 +263,7 @@ describe('api: setup context', () => {
}).$mount()
expect(spy).toHaveBeenCalled()
})

// #12561
it('setup props should be reactive', () => {
const msg = ref('hi')
Expand Down Expand Up @@ -333,4 +333,30 @@ describe('api: setup context', () => {
await nextTick()
expect(_listeners.foo()).toBe(2)
})

// #12802
it('should be called before all lifecycle hooks', () => {
const calls: string[] = []

Vue.mixin({
beforeCreate() {
calls.push('global beforeCreate')
}
})

new Vue({
beforeCreate() {
calls.push('component beforeCreate')
},
setup() {
calls.push('setup')
}
})

expect(calls).toEqual([
'setup',
'global beforeCreate',
'component beforeCreate'
])
})
})

0 comments on commit e1342df

Please sign in to comment.