refactor: reduce bundle size
This commit is contained in:
parent
6cf2377cd4
commit
eae7c247af
@ -1,4 +1,4 @@
|
|||||||
import { ReactiveEffect, getTrackOpBit } from './effect'
|
import { ReactiveEffect, trackOpBit } from './effect'
|
||||||
|
|
||||||
export type Dep = Set<ReactiveEffect> & TrackedMarkers
|
export type Dep = Set<ReactiveEffect> & TrackedMarkers
|
||||||
|
|
||||||
@ -7,45 +7,51 @@ export type Dep = Set<ReactiveEffect> & TrackedMarkers
|
|||||||
* tracking recursion. One bit per level is used to define wheter the dependency
|
* tracking recursion. One bit per level is used to define wheter the dependency
|
||||||
* was/is tracked.
|
* was/is tracked.
|
||||||
*/
|
*/
|
||||||
type TrackedMarkers = { wasTracked: number; newTracked: number }
|
type TrackedMarkers = {
|
||||||
|
/**
|
||||||
|
* wasTracked
|
||||||
|
*/
|
||||||
|
w: number
|
||||||
|
/**
|
||||||
|
* newTracked
|
||||||
|
*/
|
||||||
|
n: number
|
||||||
|
}
|
||||||
|
|
||||||
export function createDep(effects?: ReactiveEffect[]): Dep {
|
export const createDep = (effects?: ReactiveEffect[]): Dep => {
|
||||||
const dep = new Set<ReactiveEffect>(effects) as Dep
|
const dep = new Set<ReactiveEffect>(effects) as Dep
|
||||||
dep.wasTracked = 0
|
dep.w = 0
|
||||||
dep.newTracked = 0
|
dep.n = 0
|
||||||
return dep
|
return dep
|
||||||
}
|
}
|
||||||
|
|
||||||
export function wasTracked(dep: Dep): boolean {
|
export const wasTracked = (dep: Dep): boolean => (dep.w & trackOpBit) > 0
|
||||||
return hasBit(dep.wasTracked, getTrackOpBit())
|
|
||||||
|
export const newTracked = (dep: Dep): boolean => (dep.n & trackOpBit) > 0
|
||||||
|
|
||||||
|
export const initDepMarkers = ({ deps }: ReactiveEffect) => {
|
||||||
|
if (deps.length) {
|
||||||
|
for (let i = 0; i < deps.length; i++) {
|
||||||
|
deps[i].w |= trackOpBit // set was tracked
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function newTracked(dep: Dep): boolean {
|
export const finalizeDepMarkers = (effect: ReactiveEffect) => {
|
||||||
return hasBit(dep.newTracked, getTrackOpBit())
|
const { deps } = effect
|
||||||
}
|
if (deps.length) {
|
||||||
|
let ptr = 0
|
||||||
export function setWasTracked(dep: Dep) {
|
for (let i = 0; i < deps.length; i++) {
|
||||||
dep.wasTracked = setBit(dep.wasTracked, getTrackOpBit())
|
const dep = deps[i]
|
||||||
}
|
if (wasTracked(dep) && !newTracked(dep)) {
|
||||||
|
dep.delete(effect)
|
||||||
export function setNewTracked(dep: Dep) {
|
} else {
|
||||||
dep.newTracked = setBit(dep.newTracked, getTrackOpBit())
|
deps[ptr++] = dep
|
||||||
}
|
}
|
||||||
|
// clear bits
|
||||||
export function resetTracked(dep: Dep) {
|
dep.w &= ~trackOpBit
|
||||||
const trackOpBit = getTrackOpBit()
|
dep.n &= ~trackOpBit
|
||||||
dep.wasTracked = clearBit(dep.wasTracked, trackOpBit)
|
}
|
||||||
dep.newTracked = clearBit(dep.newTracked, trackOpBit)
|
deps.length = ptr
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasBit(value: number, bit: number): boolean {
|
|
||||||
return (value & bit) > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
function setBit(value: number, bit: number): number {
|
|
||||||
return value | bit
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearBit(value: number, bit: number): number {
|
|
||||||
return value & ~bit
|
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,9 @@ import { EffectScope, recordEffectScope } from './effectScope'
|
|||||||
import {
|
import {
|
||||||
createDep,
|
createDep,
|
||||||
Dep,
|
Dep,
|
||||||
|
finalizeDepMarkers,
|
||||||
|
initDepMarkers,
|
||||||
newTracked,
|
newTracked,
|
||||||
resetTracked,
|
|
||||||
setNewTracked,
|
|
||||||
setWasTracked,
|
|
||||||
wasTracked
|
wasTracked
|
||||||
} from './Dep'
|
} from './Dep'
|
||||||
|
|
||||||
@ -18,6 +17,18 @@ import {
|
|||||||
type KeyToDepMap = Map<any, Dep>
|
type KeyToDepMap = Map<any, Dep>
|
||||||
const targetMap = new WeakMap<any, KeyToDepMap>()
|
const targetMap = new WeakMap<any, KeyToDepMap>()
|
||||||
|
|
||||||
|
// The number of effects currently being tracked recursively.
|
||||||
|
let effectTrackDepth = 0
|
||||||
|
|
||||||
|
export let trackOpBit = 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The bitwise track markers support at most 30 levels op recursion.
|
||||||
|
* This value is chosen to enable modern JS engines to use a SMI on all platforms.
|
||||||
|
* When recursion depth is greater, fall back to using a full cleanup.
|
||||||
|
*/
|
||||||
|
const maxMarkerBits = 30
|
||||||
|
|
||||||
export type EffectScheduler = () => void
|
export type EffectScheduler = () => void
|
||||||
|
|
||||||
export type DebuggerEvent = {
|
export type DebuggerEvent = {
|
||||||
@ -38,6 +49,7 @@ let activeEffect: ReactiveEffect | undefined
|
|||||||
|
|
||||||
export const ITERATE_KEY = Symbol(__DEV__ ? 'iterate' : '')
|
export const ITERATE_KEY = Symbol(__DEV__ ? 'iterate' : '')
|
||||||
export const MAP_KEY_ITERATE_KEY = Symbol(__DEV__ ? 'Map key iterate' : '')
|
export const MAP_KEY_ITERATE_KEY = Symbol(__DEV__ ? 'Map key iterate' : '')
|
||||||
|
|
||||||
export class ReactiveEffect<T = any> {
|
export class ReactiveEffect<T = any> {
|
||||||
active = true
|
active = true
|
||||||
deps: Dep[] = []
|
deps: Dep[] = []
|
||||||
@ -68,19 +80,21 @@ export class ReactiveEffect<T = any> {
|
|||||||
effectStack.push((activeEffect = this))
|
effectStack.push((activeEffect = this))
|
||||||
enableTracking()
|
enableTracking()
|
||||||
|
|
||||||
effectTrackDepth++
|
trackOpBit = 1 << ++effectTrackDepth
|
||||||
|
|
||||||
if (effectTrackDepth <= maxMarkerBits) {
|
if (effectTrackDepth <= maxMarkerBits) {
|
||||||
this.initDepMarkers()
|
initDepMarkers(this)
|
||||||
} else {
|
} else {
|
||||||
this.cleanup()
|
cleanupEffect(this)
|
||||||
}
|
}
|
||||||
return this.fn()
|
return this.fn()
|
||||||
} finally {
|
} finally {
|
||||||
if (effectTrackDepth <= maxMarkerBits) {
|
if (effectTrackDepth <= maxMarkerBits) {
|
||||||
this.finalizeDepMarkers()
|
finalizeDepMarkers(this)
|
||||||
}
|
}
|
||||||
effectTrackDepth--
|
|
||||||
|
trackOpBit = 1 << --effectTrackDepth
|
||||||
|
|
||||||
resetTracking()
|
resetTracking()
|
||||||
effectStack.pop()
|
effectStack.pop()
|
||||||
const n = effectStack.length
|
const n = effectStack.length
|
||||||
@ -89,45 +103,9 @@ export class ReactiveEffect<T = any> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
initDepMarkers() {
|
|
||||||
const { deps } = this
|
|
||||||
if (deps.length) {
|
|
||||||
for (let i = 0; i < deps.length; i++) {
|
|
||||||
setWasTracked(deps[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
finalizeDepMarkers() {
|
|
||||||
const { deps } = this
|
|
||||||
if (deps.length) {
|
|
||||||
let ptr = 0
|
|
||||||
for (let i = 0; i < deps.length; i++) {
|
|
||||||
const dep = deps[i]
|
|
||||||
if (wasTracked(dep) && !newTracked(dep)) {
|
|
||||||
dep.delete(this)
|
|
||||||
} else {
|
|
||||||
deps[ptr++] = dep
|
|
||||||
}
|
|
||||||
resetTracked(dep)
|
|
||||||
}
|
|
||||||
deps.length = ptr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup() {
|
|
||||||
const { deps } = this
|
|
||||||
if (deps.length) {
|
|
||||||
for (let i = 0; i < deps.length; i++) {
|
|
||||||
deps[i].delete(this)
|
|
||||||
}
|
|
||||||
deps.length = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stop() {
|
stop() {
|
||||||
if (this.active) {
|
if (this.active) {
|
||||||
this.cleanup()
|
cleanupEffect(this)
|
||||||
if (this.onStop) {
|
if (this.onStop) {
|
||||||
this.onStop()
|
this.onStop()
|
||||||
}
|
}
|
||||||
@ -136,18 +114,14 @@ export class ReactiveEffect<T = any> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The number of effects currently being tracked recursively.
|
function cleanupEffect(effect: ReactiveEffect) {
|
||||||
let effectTrackDepth = 0
|
const { deps } = effect
|
||||||
|
if (deps.length) {
|
||||||
/**
|
for (let i = 0; i < deps.length; i++) {
|
||||||
* The bitwise track markers support at most 30 levels op recursion.
|
deps[i].delete(effect)
|
||||||
* This value is chosen to enable modern JS engines to use a SMI on all platforms.
|
}
|
||||||
* When recursion depth is greater, fall back to using a full cleanup.
|
deps.length = 0
|
||||||
*/
|
}
|
||||||
const maxMarkerBits = 30
|
|
||||||
|
|
||||||
export function getTrackOpBit(): number {
|
|
||||||
return 1 << effectTrackDepth
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ReactiveEffectOptions {
|
export interface ReactiveEffectOptions {
|
||||||
@ -218,8 +192,7 @@ export function track(target: object, type: TrackOpTypes, key: unknown) {
|
|||||||
}
|
}
|
||||||
let dep = depsMap.get(key)
|
let dep = depsMap.get(key)
|
||||||
if (!dep) {
|
if (!dep) {
|
||||||
dep = createDep()
|
depsMap.set(key, (dep = createDep()))
|
||||||
depsMap.set(key, dep)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const eventInfo = __DEV__
|
const eventInfo = __DEV__
|
||||||
@ -240,7 +213,7 @@ export function trackEffects(
|
|||||||
let shouldTrack = false
|
let shouldTrack = false
|
||||||
if (effectTrackDepth <= maxMarkerBits) {
|
if (effectTrackDepth <= maxMarkerBits) {
|
||||||
if (!newTracked(dep)) {
|
if (!newTracked(dep)) {
|
||||||
setNewTracked(dep)
|
dep.n |= trackOpBit // set newly tracked
|
||||||
shouldTrack = !wasTracked(dep)
|
shouldTrack = !wasTracked(dep)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1395,33 +1395,28 @@ function baseCreateRenderer(
|
|||||||
isSVG,
|
isSVG,
|
||||||
optimized
|
optimized
|
||||||
) => {
|
) => {
|
||||||
const componentUpdateFn = function(this: ReactiveEffect) {
|
const componentUpdateFn = () => {
|
||||||
if (!instance.isMounted) {
|
if (!instance.isMounted) {
|
||||||
let vnodeHook: VNodeHook | null | undefined
|
let vnodeHook: VNodeHook | null | undefined
|
||||||
const { el, props } = initialVNode
|
const { el, props } = initialVNode
|
||||||
const { bm, m, parent } = instance
|
const { bm, m, parent } = instance
|
||||||
|
|
||||||
try {
|
effect.allowRecurse = false
|
||||||
// Disallow component effect recursion during pre-lifecycle hooks.
|
// beforeMount hook
|
||||||
this.allowRecurse = false
|
if (bm) {
|
||||||
|
invokeArrayFns(bm)
|
||||||
// beforeMount hook
|
|
||||||
if (bm) {
|
|
||||||
invokeArrayFns(bm)
|
|
||||||
}
|
|
||||||
// onVnodeBeforeMount
|
|
||||||
if ((vnodeHook = props && props.onVnodeBeforeMount)) {
|
|
||||||
invokeVNodeHook(vnodeHook, parent, initialVNode)
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
__COMPAT__ &&
|
|
||||||
isCompatEnabled(DeprecationTypes.INSTANCE_EVENT_HOOKS, instance)
|
|
||||||
) {
|
|
||||||
instance.emit('hook:beforeMount')
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
this.allowRecurse = true
|
|
||||||
}
|
}
|
||||||
|
// onVnodeBeforeMount
|
||||||
|
if ((vnodeHook = props && props.onVnodeBeforeMount)) {
|
||||||
|
invokeVNodeHook(vnodeHook, parent, initialVNode)
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
__COMPAT__ &&
|
||||||
|
isCompatEnabled(DeprecationTypes.INSTANCE_EVENT_HOOKS, instance)
|
||||||
|
) {
|
||||||
|
instance.emit('hook:beforeMount')
|
||||||
|
}
|
||||||
|
effect.allowRecurse = true
|
||||||
|
|
||||||
if (el && hydrateNode) {
|
if (el && hydrateNode) {
|
||||||
// vnode has adopted host node - perform hydration instead of mount.
|
// vnode has adopted host node - perform hydration instead of mount.
|
||||||
@ -1547,27 +1542,23 @@ function baseCreateRenderer(
|
|||||||
next = vnode
|
next = vnode
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
// Disallow component effect recursion during pre-lifecycle hooks.
|
||||||
// Disallow component effect recursion during pre-lifecycle hooks.
|
effect.allowRecurse = false
|
||||||
this.allowRecurse = false
|
// beforeUpdate hook
|
||||||
|
if (bu) {
|
||||||
// beforeUpdate hook
|
invokeArrayFns(bu)
|
||||||
if (bu) {
|
|
||||||
invokeArrayFns(bu)
|
|
||||||
}
|
|
||||||
// onVnodeBeforeUpdate
|
|
||||||
if ((vnodeHook = next.props && next.props.onVnodeBeforeUpdate)) {
|
|
||||||
invokeVNodeHook(vnodeHook, parent, next, vnode)
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
__COMPAT__ &&
|
|
||||||
isCompatEnabled(DeprecationTypes.INSTANCE_EVENT_HOOKS, instance)
|
|
||||||
) {
|
|
||||||
instance.emit('hook:beforeUpdate')
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
this.allowRecurse = true
|
|
||||||
}
|
}
|
||||||
|
// onVnodeBeforeUpdate
|
||||||
|
if ((vnodeHook = next.props && next.props.onVnodeBeforeUpdate)) {
|
||||||
|
invokeVNodeHook(vnodeHook, parent, next, vnode)
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
__COMPAT__ &&
|
||||||
|
isCompatEnabled(DeprecationTypes.INSTANCE_EVENT_HOOKS, instance)
|
||||||
|
) {
|
||||||
|
instance.emit('hook:beforeUpdate')
|
||||||
|
}
|
||||||
|
effect.allowRecurse = true
|
||||||
|
|
||||||
// render
|
// render
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user