/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @format */ import {CancelledPromiseError} from './errors'; import {sleep} from './promiseTimeout'; import {Idler} from 'flipper-plugin'; export class IdlerImpl implements Idler { private lastIdle = performance.now(); private kill = false; constructor(private interval = 16) {} shouldIdle(): boolean { return this.kill || performance.now() - this.lastIdle > this.interval; } async idle(): Promise { if (this.kill) { throw new CancelledPromiseError('Idler got killed'); } const now = performance.now(); if (now - this.lastIdle > this.interval) { this.lastIdle = now; return new Promise((resolve) => { if (typeof requestIdleCallback !== 'undefined') { requestIdleCallback(() => { resolve(); }); } else { setTimeout(resolve, 0); } }); } return undefined; } cancel() { this.kill = true; } isCancelled() { return this.kill; } } // This smills like we should be using generators :) export class TestIdler implements Idler { private resolver?: () => void; private kill = false; private autoRun = false; private hasProgressed = false; constructor(autorun = false) { this.autoRun = autorun; } shouldIdle() { if (this.kill) { return true; } if (this.autoRun) { return false; } // In turns we signal that idling is needed and that it isn't if (!this.hasProgressed) { this.hasProgressed = true; return false; } return true; } async idle() { if (this.kill) { throw new CancelledPromiseError('Idler got killed'); } if (this.autoRun) { return undefined; } if (this.resolver) { throw new Error('Already idling'); } return new Promise((resolve) => { this.resolver = () => { this.resolver = undefined; this.hasProgressed = false; resolve(); }; }); } cancel() { this.kill = true; this.run(); } async next() { if (!this.resolver) { throw new Error('Not yet idled'); } this.resolver(); // make sure waiting promise runs first await sleep(10); } /** * Automatically progresses through all idle calls */ run() { this.resolver?.(); this.autoRun = true; } isCancelled() { return this.kill; } }