{"version":3,"file":"scheduler.browser.mjs","names":[],"sources":["../../src/scheduler.browser.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport type { FrameBudget } from './scheduler.ts';\n\nexport { yieldOrContinue } from '@dxos/async';\nexport { scheduleTask } from 'main-thread-scheduling';\n\n/** Room left in a 60 Hz frame for layout, paint and the render the flushed updates trigger. */\nconst FRAME_BUDGET_MS = 5;\n\n/** Resets on each animation frame; a hidden tab has none, so its updates go to the scheduler. */\nclass BrowserFrameBudget implements FrameBudget {\n  #spent = 0;\n  #resetRequested = false;\n  #urgent = false;\n\n  hasTime(): boolean {\n    return this.#urgent || this.#spent < FRAME_BUDGET_MS;\n  }\n\n  spend(ms: number): void {\n    this.#spent += ms;\n    if (!this.#resetRequested) {\n      this.#resetRequested = true;\n      requestAnimationFrame(() => {\n        this.#spent = 0;\n        this.#resetRequested = false;\n      });\n    }\n  }\n\n  /** The result of a user action reaches the screen in the frame after it rather than one frame later. */\n  flushBeforePaint(): void {\n    if (this.#urgent) {\n      return;\n    }\n    this.#urgent = true;\n    const channel = new MessageChannel();\n    channel.port1.onmessage = () => {\n      this.#urgent = false;\n      channel.port1.close();\n    };\n    channel.port2.postMessage(null);\n  }\n}\n\nexport const makeFrameBudget = (): FrameBudget => new BrowserFrameBudget();\n"],"mappings":";;;;AAUA,IAAM,kBAAkB;;AAGxB,IAAM,qBAAN,MAAgD;CAC9C,SAAS;CACT,kBAAkB;CAClB,UAAU;CAEV,UAAmB;EACjB,OAAO,KAAK,WAAW,KAAK,SAAS;CACvC;CAEA,MAAM,IAAkB;EACtB,KAAK,UAAU;EACf,IAAI,CAAC,KAAK,iBAAiB;GACzB,KAAK,kBAAkB;GACvB,4BAA4B;IAC1B,KAAK,SAAS;IACd,KAAK,kBAAkB;GACzB,CAAC;EACH;CACF;;CAGA,mBAAyB;EACvB,IAAI,KAAK,SACP;EAEF,KAAK,UAAU;EACf,MAAM,UAAU,IAAI,eAAe;EACnC,QAAQ,MAAM,kBAAkB;GAC9B,KAAK,UAAU;GACf,QAAQ,MAAM,MAAM;EACtB;EACA,QAAQ,MAAM,YAAY,IAAI;CAChC;AACF;AAEA,IAAa,wBAAqC,IAAI,mBAAmB"}