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
|
||||
|
||||
@ -7,45 +7,51 @@ export type Dep = Set<ReactiveEffect> & TrackedMarkers
|
||||
* tracking recursion. One bit per level is used to define wheter the dependency
|
||||
* 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
|
||||
dep.wasTracked = 0
|
||||
dep.newTracked = 0
|
||||
dep.w = 0
|
||||
dep.n = 0
|
||||
return dep
|
||||
}
|
||||
|
||||
export function wasTracked(dep: Dep): boolean {
|
||||
return hasBit(dep.wasTracked, getTrackOpBit())
|
||||
export const wasTracked = (dep: Dep): boolean => (dep.w & trackOpBit) > 0
|
||||
|
||||
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 {
|
||||
return hasBit(dep.newTracked, getTrackOpBit())
|
||||
}
|
||||
|
||||
export function setWasTracked(dep: Dep) {
|
||||
dep.wasTracked = setBit(dep.wasTracked, getTrackOpBit())
|
||||
}
|
||||
|
||||
export function setNewTracked(dep: Dep) {
|
||||
dep.newTracked = setBit(dep.newTracked, getTrackOpBit())
|
||||
}
|
||||
|
||||
export function resetTracked(dep: Dep) {
|
||||
const trackOpBit = getTrackOpBit()
|
||||
dep.wasTracked = clearBit(dep.wasTracked, trackOpBit)
|
||||
dep.newTracked = clearBit(dep.newTracked, trackOpBit)
|
||||
}
|
||||
|
||||
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
|
||||
export const finalizeDepMarkers = (effect: ReactiveEffect) => {
|
||||
const { deps } = effect
|
||||
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(effect)
|
||||
} else {
|
||||
deps[ptr++] = dep
|
||||
}
|
||||
// clear bits
|
||||
dep.w &= ~trackOpBit
|
||||
dep.n &= ~trackOpBit
|
||||
}
|
||||
deps.length = ptr
|
||||
}
|
||||
}
|
||||
|
@ -4,10 +4,9 @@ import { EffectScope, recordEffectScope } from './effectScope'
|
||||
import {
|
||||
createDep,
|
||||
Dep,
|
||||
finalizeDepMarkers,
|
||||
initDepMarkers,
|
||||
newTracked,
|
||||
resetTracked,
|
||||
setNewTracked,
|
||||
setWasTracked,
|
||||
wasTracked
|
||||
} from './Dep'
|
||||
|
||||
@ -18,6 +17,18 @@ import {
|
||||
type KeyToDepMap = Map<any, Dep>
|
||||
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 DebuggerEvent = {
|
||||
@ -38,6 +49,7 @@ let activeEffect: ReactiveEffect | undefined
|
||||
|
||||
export const ITERATE_KEY = Symbol(__DEV__ ? 'iterate' : '')
|
||||
export const MAP_KEY_ITERATE_KEY = Symbol(__DEV__ ? 'Map key iterate' : '')
|
||||
|
||||
export class ReactiveEffect<T = any> {
|
||||
active = true
|
||||
deps: Dep[] = []
|
||||
@ -68,19 +80,21 @@ export class ReactiveEffect<T = any> {
|
||||
effectStack.push((activeEffect = this))
|
||||
enableTracking()
|
||||
|
||||
effectTrackDepth++
|
||||
trackOpBit = 1 << ++effectTrackDepth
|
||||
|
||||
if (effectTrackDepth <= maxMarkerBits) {
|
||||
this.initDepMarkers()
|
||||
initDepMarkers(this)
|
||||
} else {
|
||||
this.cleanup()
|
||||
cleanupEffect(this)
|
||||
}
|
||||
return this.fn()
|
||||
} finally {
|
||||
if (effectTrackDepth <= maxMarkerBits) {
|
||||
this.finalizeDepMarkers()
|
||||
finalizeDepMarkers(this)
|
||||
}
|
||||
effectTrackDepth--
|
||||
|
||||
trackOpBit = 1 << --effectTrackDepth
|
||||
|
||||
resetTracking()
|
||||
effectStack.pop()
|
||||
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() {
|
||||
if (this.active) {
|
||||
this.cleanup()
|
||||
cleanupEffect(this)
|
||||
if (this.onStop) {
|
||||
this.onStop()
|
||||
}
|
||||
@ -136,18 +114,14 @@ export class ReactiveEffect<T = any> {
|
||||
}
|
||||
}
|
||||
|
||||
// The number of effects currently being tracked recursively.
|
||||
let effectTrackDepth = 0
|
||||
|
||||
/**
|
||||
* 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 function getTrackOpBit(): number {
|
||||
return 1 << effectTrackDepth
|
||||
function cleanupEffect(effect: ReactiveEffect) {
|
||||
const { deps } = effect
|
||||
if (deps.length) {
|
||||
for (let i = 0; i < deps.length; i++) {
|
||||
deps[i].delete(effect)
|
||||
}
|
||||
deps.length = 0
|
||||
}
|
||||
}
|
||||
|
||||
export interface ReactiveEffectOptions {
|
||||
@ -218,8 +192,7 @@ export function track(target: object, type: TrackOpTypes, key: unknown) {
|
||||
}
|
||||
let dep = depsMap.get(key)
|
||||
if (!dep) {
|
||||
dep = createDep()
|
||||
depsMap.set(key, dep)
|
||||
depsMap.set(key, (dep = createDep()))
|
||||
}
|
||||
|
||||
const eventInfo = __DEV__
|
||||
@ -240,7 +213,7 @@ export function trackEffects(
|
||||
let shouldTrack = false
|
||||
if (effectTrackDepth <= maxMarkerBits) {
|
||||
if (!newTracked(dep)) {
|
||||
setNewTracked(dep)
|
||||
dep.n |= trackOpBit // set newly tracked
|
||||
shouldTrack = !wasTracked(dep)
|
||||
}
|
||||
} else {
|
||||
|
@ -1395,33 +1395,28 @@ function baseCreateRenderer(
|
||||
isSVG,
|
||||
optimized
|
||||
) => {
|
||||
const componentUpdateFn = function(this: ReactiveEffect) {
|
||||
const componentUpdateFn = () => {
|
||||
if (!instance.isMounted) {
|
||||
let vnodeHook: VNodeHook | null | undefined
|
||||
const { el, props } = initialVNode
|
||||
const { bm, m, parent } = instance
|
||||
|
||||
try {
|
||||
// Disallow component effect recursion during pre-lifecycle hooks.
|
||||
this.allowRecurse = false
|
||||
|
||||
// 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
|
||||
effect.allowRecurse = false
|
||||
// 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')
|
||||
}
|
||||
effect.allowRecurse = true
|
||||
|
||||
if (el && hydrateNode) {
|
||||
// vnode has adopted host node - perform hydration instead of mount.
|
||||
@ -1547,27 +1542,23 @@ function baseCreateRenderer(
|
||||
next = vnode
|
||||
}
|
||||
|
||||
try {
|
||||
// Disallow component effect recursion during pre-lifecycle hooks.
|
||||
this.allowRecurse = false
|
||||
|
||||
// beforeUpdate hook
|
||||
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
|
||||
// Disallow component effect recursion during pre-lifecycle hooks.
|
||||
effect.allowRecurse = false
|
||||
// beforeUpdate hook
|
||||
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')
|
||||
}
|
||||
effect.allowRecurse = true
|
||||
|
||||
// render
|
||||
if (__DEV__) {
|
||||
|
Loading…
Reference in New Issue
Block a user