UNPKG

puppeteer-core

Version:

A high-level API to control headless Chrome over the DevTools Protocol

109 lines 3.15 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Deferred = void 0; /** * @license * Copyright 2024 Google Inc. * SPDX-License-Identifier: Apache-2.0 */ const Errors_js_1 = require("../common/Errors.js"); /** * Creates and returns a deferred object along with the resolve/reject functions. * * If the deferred has not been resolved/rejected within the `timeout` period, * the deferred gets resolves with a timeout error. `timeout` has to be greater than 0 or * it is ignored. * * @internal */ class Deferred { static create(opts) { return new Deferred(opts); } static async race(awaitables) { const deferredWithTimeout = new Set(); try { const promises = awaitables.map(value => { if (value instanceof Deferred) { if (value.#timeoutId) { deferredWithTimeout.add(value); } return value.valueOrThrow(); } return value; }); // eslint-disable-next-line no-restricted-syntax return await Promise.race(promises); } finally { for (const deferred of deferredWithTimeout) { // We need to stop the timeout else // Node.JS will keep running the event loop till the // timer executes deferred.reject(new Error('Timeout cleared')); } } } #isResolved = false; #isRejected = false; #value; // SAFETY: This is ensured by #taskPromise. #resolve; // TODO: Switch to Promise.withResolvers with Node 22 #taskPromise = new Promise(resolve => { this.#resolve = resolve; }); #timeoutId; #timeoutError; constructor(opts) { if (opts && opts.timeout > 0) { this.#timeoutError = new Errors_js_1.TimeoutError(opts.message); this.#timeoutId = setTimeout(() => { this.reject(this.#timeoutError); }, opts.timeout); } } #finish(value) { clearTimeout(this.#timeoutId); this.#value = value; this.#resolve(); } resolve(value) { if (this.#isRejected || this.#isResolved) { return; } this.#isResolved = true; this.#finish(value); } reject(error) { if (this.#isRejected || this.#isResolved) { return; } this.#isRejected = true; this.#finish(error); } resolved() { return this.#isResolved; } finished() { return this.#isResolved || this.#isRejected; } value() { return this.#value; } #promise; valueOrThrow() { if (!this.#promise) { this.#promise = (async () => { await this.#taskPromise; if (this.#isRejected) { throw this.#value; } return this.#value; })(); } return this.#promise; } } exports.Deferred = Deferred; //# sourceMappingURL=Deferred.js.map