import { isArray } from '../shared' ; import { ReactiveEffect , KeyToDepMap , ReactiveEffectOptions } from '../shared/svu' ; /**
 * 三层数据结构组合
 * targetMap(weakMap)【多次的reciver】
 *    |
 * depsMap(Map)【reciver数据中不同的键】
 *    |
 * dep(Set)[用来发布订阅的执行 effect]
 */ let activeEffect ; const targetMap = new WeakMap < any , KeyToDepMap > ( ) ; export function track ( target , key ) { if ( activeEffect ) { let depsMap = targetMap . get ( target ) ; if ( ! depsMap ) { targetMap . set ( target , ( depsMap = new Map ( ) ) ) ; } let dep = depsMap . get ( key ) ; if ( ! dep ) { depsMap . set ( key , ( dep = new Set ( ) ) ) ; } if ( ! dep . has ( activeEffect ) ) { dep . add ( activeEffect ) ; } } } export function trigger ( target , key , newValue ? ) { const depsMap = targetMap . get ( target ) ; if ( ! depsMap ) { return ; } const effects = new Set < ReactiveEffect > ( ) ; const add = ( effectsToAdd ) => { if ( effectsToAdd ) { effectsToAdd . forEach ( effect => { if ( effect !== activeEffect ) { effects . add ( effect ) ; } } ) ; } } ; if ( key === 'length' && isArray ( target ) ) { depsMap . forEach ( ( dep , key ) => { if ( key === 'length' || key >= ( newValue as number ) ) { add ( dep ) ; } } ) ; } else if ( key !== void 0 ) { add ( depsMap . get ( key ) ) ; } const run = ( effect ) => { if ( effect . options . scheduler ) { effect . options . scheduler ( effect ) ; } else { effect ( ) ; } } ; effects . forEach ( run ) ; } let uid = 0 ; function creatReactiveEffect < T = any > ( fn , options ) { const effect = function reactiveEffect ( ) : unknown { try { activeEffect = effect ; return fn ( ) ; } finally { activeEffect = undefined ; } } as ReactiveEffect ; effect . id = uid ++ ; effect . _isEffect = true ; effect . active = true ; effect . raw = fn ; effect . options = options ; return effect ; } export const isEffect = ( fn ) : fn is ReactiveEffect => fn && fn . _isEffect ; export function effect < T = any > ( fn , options = { } ) { /**
     * 对应测试 should not double wrap if the passed function is a effect
     * const runner = effect(() => {
            console.log(111111, state.count)
        })
        const otherRunner = effect(runner)
        state.count = 11
     *
    */ if ( isEffect ( fn ) ) { fn = fn . raw ; } const effectFn = creatReactiveEffect ( fn , options ) ; ! options . lazy && effectFn ( ) ; return effectFn ; }