dep.ts 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. import { ReactiveEffect, trackOpBit } from './effect'
  2. export type Dep = Set<ReactiveEffect> & TrackedMarkers
  3. /**
  4. * wasTracked and newTracked maintain the status for several levels of effect
  5. * tracking recursion. One bit per level is used to define whether the dependency
  6. * was/is tracked.
  7. */
  8. type TrackedMarkers = {
  9. /**
  10. * wasTracked
  11. */
  12. w: number
  13. /**
  14. * newTracked
  15. */
  16. n: number
  17. }
  18. export const createDep = (effects?: ReactiveEffect[]): Dep => {
  19. const dep = new Set<ReactiveEffect>(effects) as Dep
  20. dep.w = 0
  21. dep.n = 0
  22. return dep
  23. }
  24. export const wasTracked = (dep: Dep): boolean => (dep.w & trackOpBit) > 0
  25. export const newTracked = (dep: Dep): boolean => (dep.n & trackOpBit) > 0
  26. export const initDepMarkers = ({ deps }: ReactiveEffect) => {
  27. if (deps.length) {
  28. for (let i = 0; i < deps.length; i++) {
  29. deps[i].w |= trackOpBit // set was tracked
  30. }
  31. }
  32. }
  33. export const finalizeDepMarkers = (effect: ReactiveEffect) => {
  34. const { deps } = effect
  35. if (deps.length) {
  36. let ptr = 0
  37. for (let i = 0; i < deps.length; i++) {
  38. const dep = deps[i]
  39. if (wasTracked(dep) && !newTracked(dep)) {
  40. dep.delete(effect)
  41. } else {
  42. deps[ptr++] = dep
  43. }
  44. // clear bits
  45. dep.w &= ~trackOpBit
  46. dep.n &= ~trackOpBit
  47. }
  48. deps.length = ptr
  49. }
  50. }