From 818c10e86d9c44b7e99197a0983ba143754474be Mon Sep 17 00:00:00 2001 From: Raz Luvaton <16746759+rluvaton@users.noreply.github.com> Date: Sun, 7 Apr 2024 22:32:02 +0300 Subject: [PATCH] lib: improve perf of `AbortSignal` creation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/52408 Reviewed-By: Yagiz Nizipli Reviewed-By: Vinícius Lourenço Claro Cardoso Reviewed-By: Matteo Collina Reviewed-By: Michaël Zasso Reviewed-By: Moshe Atlow Reviewed-By: Minwoo Jung Reviewed-By: Matthew Aitken --- lib/internal/abort_controller.js | 75 ++++++++++++++++---------------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/lib/internal/abort_controller.js b/lib/internal/abort_controller.js index b10fb35a1a6e4f..2d9aabb2c35d3e 100644 --- a/lib/internal/abort_controller.js +++ b/lib/internal/abort_controller.js @@ -6,7 +6,6 @@ const { ObjectAssign, ObjectDefineProperties, - ObjectSetPrototypeOf, ObjectDefineProperty, PromiseResolve, SafeFinalizationRegistry, @@ -69,6 +68,8 @@ const { let _MessageChannel; let markTransferMode; +const kDontThrowSymbol = Symbol('kDontThrowSymbol'); + // Loading the MessageChannel and markTransferable have to be done lazily // because otherwise we'll end up with a require cycle that ends up with // an incomplete initialization of abort_controller. @@ -137,8 +138,35 @@ function setWeakAbortSignalTimeout(weakRef, delay) { } class AbortSignal extends EventTarget { - constructor() { - throw new ERR_ILLEGAL_CONSTRUCTOR(); + + /** + * @param {symbol | undefined} dontThrowSymbol + * @param {{ + * aborted? : boolean, + * reason? : any, + * transferable? : boolean, + * composite? : boolean, + * }} [init] + * @private + */ + constructor(dontThrowSymbol = undefined, init = kEmptyObject) { + if (dontThrowSymbol !== kDontThrowSymbol) { + throw new ERR_ILLEGAL_CONSTRUCTOR(); + } + super(); + + const { + aborted = false, + reason = undefined, + transferable = false, + composite = false, + } = init; + this[kAborted] = aborted; + this[kReason] = reason; + this[kComposite] = composite; + if (transferable) { + lazyMarkTransferMode(this, false, true); + } } /** @@ -176,7 +204,7 @@ class AbortSignal extends EventTarget { */ static abort( reason = new DOMException('This operation was aborted', 'AbortError')) { - return createAbortSignal({ aborted: true, reason }); + return new AbortSignal(kDontThrowSymbol, { aborted: true, reason }); } /** @@ -185,7 +213,7 @@ class AbortSignal extends EventTarget { */ static timeout(delay) { validateUint32(delay, 'delay', false); - const signal = createAbortSignal(); + const signal = new AbortSignal(kDontThrowSymbol); signal[kTimeout] = true; clearTimeoutRegistry.register( signal, @@ -199,7 +227,7 @@ class AbortSignal extends EventTarget { */ static any(signals) { validateAbortSignalArray(signals, 'signals'); - const resultSignal = createAbortSignal({ composite: true }); + const resultSignal = new AbortSignal(kDontThrowSymbol, { composite: true }); if (!signals.length) { return resultSignal; } @@ -319,7 +347,7 @@ class AbortSignal extends EventTarget { } function ClonedAbortSignal() { - return createAbortSignal({ transferable: true }); + return new AbortSignal(kDontThrowSymbol, { transferable: true }); } ClonedAbortSignal.prototype[kDeserialize] = () => {}; @@ -337,33 +365,6 @@ ObjectDefineProperty(AbortSignal.prototype, SymbolToStringTag, { defineEventHandler(AbortSignal.prototype, 'abort'); -/** - * @param {{ - * aborted? : boolean, - * reason? : any, - * transferable? : boolean, - * composite? : boolean, - * }} [init] - * @returns {AbortSignal} - */ -function createAbortSignal(init = kEmptyObject) { - const { - aborted = false, - reason = undefined, - transferable = false, - composite = false, - } = init; - const signal = new EventTarget(); - ObjectSetPrototypeOf(signal, AbortSignal.prototype); - signal[kAborted] = aborted; - signal[kReason] = reason; - signal[kComposite] = composite; - if (transferable) { - lazyMarkTransferMode(signal, false, true); - } - return signal; -} - function abortSignal(signal, reason) { if (signal[kAborted]) return; signal[kAborted] = true; @@ -385,7 +386,7 @@ class AbortController { * @type {AbortSignal} */ get signal() { - this.#signal ??= createAbortSignal(); + this.#signal ??= new AbortSignal(kDontThrowSymbol); return this.#signal; } @@ -393,7 +394,7 @@ class AbortController { * @param {any} [reason] */ abort(reason = new DOMException('This operation was aborted', 'AbortError')) { - abortSignal(this.#signal ??= createAbortSignal(), reason); + abortSignal(this.#signal ??= new AbortSignal(kDontThrowSymbol), reason); } [customInspectSymbol](depth, options) { @@ -404,7 +405,7 @@ class AbortController { static [kMakeTransferable]() { const controller = new AbortController(); - controller.#signal = createAbortSignal({ transferable: true }); + controller.#signal = new AbortSignal(kDontThrowSymbol, { transferable: true }); return controller; } }