Skip to content

Commit 9fb4f7d

Browse files
committed
wip: effectScope
1 parent b4c511d commit 9fb4f7d

24 files changed

+522
-113
lines changed

src/core/instance/events.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export function updateComponentListeners(
5656
target = undefined
5757
}
5858

59-
export function eventsMixin(Vue: Component) {
59+
export function eventsMixin(Vue: typeof Component) {
6060
const hookRE = /^hook:/
6161
Vue.prototype.$on = function (
6262
event: string | Array<string>,

src/core/instance/init.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ import { initProvide, initInjections } from './inject'
99
import { extend, mergeOptions, formatComponentName } from '../util/index'
1010
import type { Component } from 'typescript/component'
1111
import type { InternalComponentOptions } from 'typescript/options'
12+
import { EffectScope } from 'v3'
1213

1314
let uid = 0
1415

15-
export function initMixin(Vue: Component) {
16+
export function initMixin(Vue: typeof Component) {
1617
Vue.prototype._init = function (options?: Record<string, any>) {
1718
const vm: Component = this
1819
// a uid
@@ -31,6 +32,8 @@ export function initMixin(Vue: Component) {
3132
vm._isVue = true
3233
// avoid instances from being observed
3334
vm.__v_skip = true
35+
// effect scope
36+
vm._scope = new EffectScope(true /* detached */)
3437
// merge options
3538
if (options && options._isComponent) {
3639
// optimize internal component instantiation
@@ -96,7 +99,7 @@ export function initInternalComponent(
9699
}
97100
}
98101

99-
export function resolveConstructorOptions(Ctor: Component) {
102+
export function resolveConstructorOptions(Ctor: typeof Component) {
100103
let options = Ctor.options
101104
if (Ctor.super) {
102105
const superOptions = resolveConstructorOptions(Ctor.super)
@@ -120,7 +123,9 @@ export function resolveConstructorOptions(Ctor: Component) {
120123
return options
121124
}
122125

123-
function resolveModifiedOptions(Ctor: Component): Record<string, any> | null {
126+
function resolveModifiedOptions(
127+
Ctor: typeof Component
128+
): Record<string, any> | null {
124129
let modified
125130
const latest = Ctor.options
126131
const sealed = Ctor.sealedOptions

src/core/instance/lifecycle.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export function initLifecycle(vm: Component) {
5757
vm._isBeingDestroyed = false
5858
}
5959

60-
export function lifecycleMixin(Vue: Component) {
60+
export function lifecycleMixin(Vue: typeof Component) {
6161
Vue.prototype._update = function (vnode: VNode, hydrating?: boolean) {
6262
const vm: Component = this
6363
const prevEl = vm.$el
@@ -108,14 +108,9 @@ export function lifecycleMixin(Vue: Component) {
108108
if (parent && !parent._isBeingDestroyed && !vm.$options.abstract) {
109109
remove(parent.$children, vm)
110110
}
111-
// teardown watchers
112-
if (vm._watcher) {
113-
vm._watcher.teardown()
114-
}
115-
let i = vm._watchers.length
116-
while (i--) {
117-
vm._watchers[i].teardown()
118-
}
111+
// teardown scope. this includes both the render watcher and other
112+
// watchers created
113+
vm._scope.stop()
119114
// remove reference from data ob
120115
// frozen object may not have observer.
121116
if (vm._data.__ob__) {

src/core/instance/render.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,11 @@ export function setCurrentRenderingInstance(vm: Component) {
8686
currentRenderingInstance = vm
8787
}
8888

89-
export function renderMixin(Vue: Component) {
89+
export function renderMixin(Vue: typeof Component) {
9090
// install runtime convenience helpers
9191
installRenderHelpers(Vue.prototype)
9292

93-
Vue.prototype.$nextTick = function (fn: Function) {
93+
Vue.prototype.$nextTick = function (fn: (...args: any[]) => any) {
9494
return nextTick(fn, this)
9595
}
9696

src/core/instance/state.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import {
2929
invokeWithErrorHandling,
3030
isFunction
3131
} from '../util/index'
32-
import type { Component } from '../../../typescript/component'
32+
import type { Component } from 'typescript/component'
3333

3434
const sharedPropertyDefinition = {
3535
enumerable: true,
@@ -49,7 +49,6 @@ export function proxy(target: Object, sourceKey: string, key: string) {
4949
}
5050

5151
export function initState(vm: Component) {
52-
vm._watchers = []
5352
const opts = vm.$options
5453
if (opts.props) initProps(vm, opts.props)
5554

@@ -310,7 +309,7 @@ function initWatch(vm: Component, watch: Object) {
310309

311310
function createWatcher(
312311
vm: Component,
313-
expOrFn: string | Function,
312+
expOrFn: string | (() => any),
314313
handler: any,
315314
options?: Object
316315
) {
@@ -324,7 +323,7 @@ function createWatcher(
324323
return vm.$watch(expOrFn, handler, options)
325324
}
326325

327-
export function stateMixin(Vue: Component) {
326+
export function stateMixin(Vue: typeof Component) {
328327
// flow somehow has problems with directly declared definition object
329328
// when using Object.defineProperty, so we have to procedurally build up
330329
// the object here.

src/core/observer/watcher.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ import Dep, { pushTarget, popTarget, DepTarget } from './dep'
1616

1717
import type { SimpleSet } from '../util/index'
1818
import type { Component } from 'typescript/component'
19+
import {
20+
activeEffectScope,
21+
recordEffectScope
22+
} from '../../v3/reactivity/effectScope'
1923

2024
let uid = 0
2125

@@ -59,11 +63,11 @@ export default class Watcher implements DepTarget {
5963
} | null,
6064
isRenderWatcher?: boolean
6165
) {
66+
recordEffectScope(this, activeEffectScope || (vm ? vm._scope : undefined))
6267
if ((this.vm = vm)) {
6368
if (isRenderWatcher) {
6469
vm._watcher = this
6570
}
66-
vm._watchers.push(this)
6771
}
6872
// options
6973
if (options) {
@@ -237,13 +241,10 @@ export default class Watcher implements DepTarget {
237241
* Remove self from all dependencies' subscriber list.
238242
*/
239243
teardown() {
244+
if (this.vm && !this.vm._isBeingDestroyed) {
245+
remove(this.vm._scope.effects, this)
246+
}
240247
if (this.active) {
241-
// remove self from vm's watcher list
242-
// this is a somewhat expensive operation so we skip it
243-
// if the vm is being destroyed.
244-
if (this.vm && !this.vm._isBeingDestroyed) {
245-
remove(this.vm._watchers, this)
246-
}
247248
let i = this.deps.length
248249
while (i--) {
249250
this.deps[i].removeSub(this)

src/core/util/next-tick.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ if (typeof Promise !== 'undefined' && isNative(Promise)) {
8585
}
8686
}
8787

88-
export function nextTick(cb?: Function, ctx?: Object) {
88+
export function nextTick(): Promise<void>
89+
export function nextTick(cb: (...args: any[]) => any, ctx?: object): void
90+
export function nextTick(cb?: (...args: any[]) => any, ctx?: object) {
8991
let _resolve
9092
callbacks.push(() => {
9193
if (cb) {

src/core/vdom/create-component.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ import type {
2626
VNodeWithData
2727
} from 'typescript/vnode'
2828
import type { Component } from 'typescript/component'
29-
import type { InternalComponentOptions } from 'typescript/options'
29+
import type {
30+
ComponentOptions,
31+
InternalComponentOptions
32+
} from 'typescript/options'
3033

3134
// inline hooks to be invoked on component VNodes during patch
3235
const componentVNodeHooks = {
@@ -95,7 +98,7 @@ const componentVNodeHooks = {
9598
const hooksToMerge = Object.keys(componentVNodeHooks)
9699

97100
export function createComponent(
98-
Ctor: Component | Function | Object | void,
101+
Ctor: typeof Component | Function | ComponentOptions | void,
99102
data: VNodeData | undefined,
100103
context: Component,
101104
children?: Array<VNode>,
@@ -109,7 +112,7 @@ export function createComponent(
109112

110113
// plain options object: turn it into a constructor
111114
if (isObject(Ctor)) {
112-
Ctor = baseCtor.extend(Ctor)
115+
Ctor = baseCtor.extend(Ctor as typeof Component)
113116
}
114117

115118
// if at this stage it's not a constructor or an async component factory,
@@ -139,7 +142,7 @@ export function createComponent(
139142

140143
// resolve constructor options in case global mixins are applied after
141144
// component constructor creation
142-
resolveConstructorOptions(Ctor as Component)
145+
resolveConstructorOptions(Ctor as typeof Component)
143146

144147
// transform component v-model data into props & events
145148
if (isDef(data.model)) {
@@ -155,7 +158,7 @@ export function createComponent(
155158
// @ts-expect-error
156159
if (isTrue(Ctor.options.functional)) {
157160
return createFunctionalComponent(
158-
Ctor as Component,
161+
Ctor as typeof Component,
159162
propsData,
160163
data,
161164
context,

src/core/vdom/create-element.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ export function _createElement(
126126
}
127127
} else {
128128
// direct component options / constructor
129-
vnode = createComponent(tag, data, context, children)
129+
vnode = createComponent(tag as any, data, context, children)
130130
}
131131
if (isArray(vnode)) {
132132
return vnode

src/core/vdom/create-functional-component.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,22 +23,21 @@ export function FunctionalRenderContext(
2323
props: Object,
2424
children: Array<VNode> | undefined,
2525
parent: Component,
26-
Ctor: Component
26+
Ctor: typeof Component
2727
) {
2828
const options = Ctor.options
2929
// ensure the createElement function in functional components
3030
// gets a unique context - this is necessary for correct named slot check
3131
let contextVm
3232
if (hasOwn(parent, '_uid')) {
3333
contextVm = Object.create(parent)
34-
// $flow-disable-line
3534
contextVm._original = parent
3635
} else {
3736
// the context vm passed in is a functional context as well.
3837
// in this case we want to make sure we are able to get a hold to the
3938
// real context instance.
4039
contextVm = parent
41-
// $flow-disable-line
40+
// @ts-ignore
4241
parent = parent._original
4342
}
4443
const isCompiled = isTrue(options._compiled)
@@ -94,7 +93,7 @@ export function FunctionalRenderContext(
9493
installRenderHelpers(FunctionalRenderContext.prototype)
9594

9695
export function createFunctionalComponent(
97-
Ctor: Component,
96+
Ctor: typeof Component,
9897
propsData: Object | undefined,
9998
data: VNodeData,
10099
contextVm: Component,

0 commit comments

Comments
 (0)