File size: 8,485 Bytes
645859a
1
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type {\n  FrameFn,\n  FrameUpdateFn,\n  NativeRaf,\n  Rafz,\n  Timeout,\n  Throttled,\n} from './types'\n\nexport type { FrameFn, FrameUpdateFn, Timeout, Throttled, Rafz }\n\nlet updateQueue = makeQueue<FrameUpdateFn>()\n\n/**\n * Schedule an update for next frame.\n * Your function can return `true` to repeat next frame.\n */\nexport const raf: Rafz = fn => schedule(fn, updateQueue)\n\nlet writeQueue = makeQueue<FrameFn>()\nraf.write = fn => schedule(fn, writeQueue)\n\nlet onStartQueue = makeQueue<FrameFn>()\nraf.onStart = fn => schedule(fn, onStartQueue)\n\nlet onFrameQueue = makeQueue<FrameFn>()\nraf.onFrame = fn => schedule(fn, onFrameQueue)\n\nlet onFinishQueue = makeQueue<FrameFn>()\nraf.onFinish = fn => schedule(fn, onFinishQueue)\n\nlet timeouts: Timeout[] = []\nraf.setTimeout = (handler, ms) => {\n  const time = raf.now() + ms\n  const cancel = () => {\n    const i = timeouts.findIndex(t => t.cancel == cancel)\n    if (~i) timeouts.splice(i, 1)\n    pendingCount -= ~i ? 1 : 0\n  }\n\n  const timeout: Timeout = { time, handler, cancel }\n  timeouts.splice(findTimeout(time), 0, timeout)\n  pendingCount += 1\n\n  start()\n  return timeout\n}\n\n/** Find the index where the given time is not greater. */\nconst findTimeout = (time: number) =>\n  ~(~timeouts.findIndex(t => t.time > time) || ~timeouts.length)\n\nraf.cancel = fn => {\n  onStartQueue.delete(fn)\n  onFrameQueue.delete(fn)\n  onFinishQueue.delete(fn)\n  updateQueue.delete(fn)\n  writeQueue.delete(fn)\n}\n\nraf.sync = fn => {\n  sync = true\n  raf.batchedUpdates(fn)\n  sync = false\n}\n\nraf.throttle = fn => {\n  let lastArgs: any\n  function queuedFn() {\n    try {\n      fn(...lastArgs)\n    } finally {\n      lastArgs = null\n    }\n  }\n  function throttled(...args: any) {\n    lastArgs = args\n    raf.onStart(queuedFn)\n  }\n  throttled.handler = fn\n  throttled.cancel = () => {\n    onStartQueue.delete(queuedFn)\n    lastArgs = null\n  }\n  return throttled as any\n}\n\nlet nativeRaf =\n  typeof window != 'undefined'\n    ? (window.requestAnimationFrame as NativeRaf)\n    : // eslint-disable-next-line @typescript-eslint/no-empty-function\n      () => {}\n\nraf.use = impl => (nativeRaf = impl)\nraf.now = typeof performance != 'undefined' ? () => performance.now() : Date.now\nraf.batchedUpdates = fn => fn()\nraf.catch = console.error\n\nraf.frameLoop = 'always'\n\nraf.advance = () => {\n  if (raf.frameLoop !== 'demand') {\n    console.warn(\n      'Cannot call the manual advancement of rafz whilst frameLoop is not set as demand'\n    )\n  } else {\n    update()\n  }\n}\n\n/** The most recent timestamp. */\nlet ts = -1\n\n/** The number of pending tasks  */\nlet pendingCount = 0\n\n/** When true, scheduling is disabled. */\nlet sync = false\n\nfunction schedule<T extends Function>(fn: T, queue: Queue<T>) {\n  if (sync) {\n    queue.delete(fn)\n    fn(0)\n  } else {\n    queue.add(fn)\n    start()\n  }\n}\n\nfunction start() {\n  if (ts < 0) {\n    ts = 0\n    if (raf.frameLoop !== 'demand') {\n      nativeRaf(loop)\n    }\n  }\n}\n\nfunction stop() {\n  ts = -1\n}\n\nfunction loop() {\n  if (~ts) {\n    nativeRaf(loop)\n    raf.batchedUpdates(update)\n  }\n}\n\nfunction update() {\n  const prevTs = ts\n  ts = raf.now()\n\n  // Flush timeouts whose time is up.\n  const count = findTimeout(ts)\n  if (count) {\n    eachSafely(timeouts.splice(0, count), t => t.handler())\n    pendingCount -= count\n  }\n\n  if (!pendingCount) {\n    stop()\n\n    return\n  }\n\n  onStartQueue.flush()\n  updateQueue.flush(prevTs ? Math.min(64, ts - prevTs) : 16.667)\n  onFrameQueue.flush()\n  writeQueue.flush()\n  onFinishQueue.flush()\n}\n\ninterface Queue<T extends Function = any> {\n  add: (fn: T) => void\n  delete: (fn: T) => boolean\n  flush: (arg?: any) => void\n}\n\nfunction makeQueue<T extends Function>(): Queue<T> {\n  let next = new Set<T>()\n  let current = next\n  return {\n    add(fn) {\n      pendingCount += current == next && !next.has(fn) ? 1 : 0\n      next.add(fn)\n    },\n    delete(fn) {\n      pendingCount -= current == next && next.has(fn) ? 1 : 0\n      return next.delete(fn)\n    },\n    flush(arg) {\n      if (current.size) {\n        next = new Set()\n        pendingCount -= current.size\n        eachSafely(current, fn => fn(arg) && next.add(fn))\n        pendingCount += next.size\n        current = next\n      }\n    },\n  }\n}\n\ninterface Eachable<T> {\n  forEach(cb: (value: T) => void): void\n}\n\nfunction eachSafely<T>(values: Eachable<T>, each: (value: T) => void) {\n  values.forEach(value => {\n    try {\n      each(value)\n    } catch (e) {\n      raf.catch(e as Error)\n    }\n  })\n}\n\n/** Tree-shakable state for testing purposes */\nexport const __raf = {\n  /** The number of pending tasks */\n  count(): number {\n    return pendingCount\n  },\n  /** Whether there's a raf update loop running */\n  isRunning(): boolean {\n    return ts >= 0\n  },\n  /** Clear internal state. Never call from update loop! */\n  clear() {\n    ts = -1\n    timeouts = []\n    onStartQueue = makeQueue()\n    updateQueue = makeQueue()\n    onFrameQueue = makeQueue()\n    writeQueue = makeQueue()\n    onFinishQueue = makeQueue()\n    pendingCount = 0\n  },\n}\n"],"mappings":"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","names":[]}