All files remodel-1.js

100% Statements 114/114
100% Branches 1/1
100% Functions 0/0
100% Lines 114/114

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 1141x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x
/* global requestAnimationFrame */
const _proxySet = new Set()
const _keyMaps = new Map()
const _triggerable = new Set()
const _triggered = new Set()
const _stack = []
const _afterTriggered = []
const _OWN_KEYS = Symbol('ownKeys as attribute')
let _handlingTriggered = false
 
function _reportKeyMutation (target, key) {
  if (_keyMaps.has(key)) {
    const keyMap = _keyMaps.get(key)
    if (keyMap.has(target)) {
      if (!_handlingTriggered) {
        _handlingTriggered = true
        requestAnimationFrame(() => {
          _handlingTriggered = false
          for (const callback of _triggered) {
            callback()
          }
          _triggered.clear()
          while (_afterTriggered.length) {
            _afterTriggered.shift()()
          }
        })
      }
      for (const callback of keyMap.get(target)) {
        _triggered.add(callback)
      }
      keyMap.delete(target)
      if (!keyMap.size) {
        _keyMaps.delete(key)
      }
    }
  }
}
 
function _reportKeyAccess (target, key) {
  if (_stack.length) {
    if (!_keyMaps.has(key)) {
      _keyMaps.set(key, new Map())
    }
    const keyMap = _keyMaps.get(key)
    if (!keyMap.has(target)) {
      keyMap.set(target, new Set())
    }
    keyMap.get(target).add(_stack[0])
  }
}
 
export function proxy (target = {}) {
  if (target instanceof Object && !_proxySet.has(target)) {
    const _self = new Proxy(Array.isArray(target) ? new Array(target.length) : {}, {
      has (target, key) {
        _reportKeyAccess(target, key)
        return key in target
      },
      get (target, key) {
        _reportKeyAccess(target, key)
        return target[key]
      },
      set (target, key, value) {
        value = proxy(value)
        if (target[key] !== value || key === 'length') { // array length is magical
          if (!(key in target)) {
            _reportKeyMutation(target, _OWN_KEYS)
          }
          _reportKeyMutation(target, key)
        }
        target[key] = value
        return true
      },
      deleteProperty (target, key) {
        if (key in target) {
          _reportKeyMutation(target, _OWN_KEYS)
          _reportKeyMutation(target, key)
        }
        return Reflect.deleteProperty(target, key)
      },
      ownKeys (target) {
        _reportKeyAccess(target, _OWN_KEYS)
        return Reflect.ownKeys(target)
      }
    })
    Object.assign(_self, target)
    _proxySet.add(_self)
    target = _self
  }
  return target
}
 
export function watchFunction (f) {
  function wrapped () {
    if (_triggerable.has(f)) {
      _stack.unshift(wrapped)
      f()
      _stack.shift()
    }
  }
  if (!_triggerable.has(f)) {
    _triggerable.add(f)
    wrapped()
  }
}
 
export function unwatchFunction (f) {
  _triggerable.delete(f)
}
 
export function after (f) {
  _afterTriggered.push(f)
}