From 8d2a7dca19f80e1ec6fb60020ce0e38ead0da4f5 Mon Sep 17 00:00:00 2001 From: Yagiz Nizipli Date: Sat, 7 Sep 2024 13:16:42 -0400 Subject: [PATCH 1/2] lib: refactor project to use `Promise.withResolvers` # Conflicts: # lib/internal/blob.js # lib/internal/test_runner/harness.js # lib/internal/test_runner/runner.js # test/parallel/test-runner-run-watch.mjs # test/parallel/test-runner-watch-mode-complex.mjs # test/parallel/test-runner-watch-mode.mjs --- lib/child_process.js | 4 +-- lib/internal/abort_controller.js | 4 +-- lib/internal/blob.js | 6 ++--- lib/internal/fs/watchers.js | 6 ++--- lib/internal/per_context/primordials.js | 13 ++++++++++ lib/internal/streams/duplexify.js | 6 ++--- lib/internal/test_runner/harness.js | 4 +-- lib/internal/test_runner/runner.js | 4 +-- lib/internal/test_runner/test.js | 6 ++--- lib/internal/test_runner/utils.js | 4 +-- lib/internal/util.js | 12 --------- lib/internal/webstreams/adapters.js | 12 ++++----- lib/internal/webstreams/readablestream.js | 26 +++++++++---------- lib/internal/webstreams/transfer.js | 9 +++---- lib/internal/webstreams/transformstream.js | 12 ++++----- lib/internal/webstreams/writablestream.js | 22 ++++++++-------- test/parallel/test-runner-run-watch.mjs | 6 ++--- .../test-runner-watch-mode-complex.mjs | 6 ++--- test/parallel/test-runner-watch-mode.mjs | 6 ++--- typings/primordials.d.ts | 1 + 20 files changed, 81 insertions(+), 88 deletions(-) diff --git a/lib/child_process.js b/lib/child_process.js index 2b2b6f083f1469..3fb21f755be3d7 100644 --- a/lib/child_process.js +++ b/lib/child_process.js @@ -37,6 +37,7 @@ const { ObjectAssign, ObjectDefineProperty, ObjectPrototypeHasOwnProperty, + PromiseWithResolvers, RegExpPrototypeExec, SafeSet, StringPrototypeIncludes, @@ -47,7 +48,6 @@ const { const { convertToValidSignal, - createDeferredPromise, getSystemErrorName, kEmptyObject, promisify, @@ -237,7 +237,7 @@ function exec(command, options, callback) { const customPromiseExecFunction = (orig) => { return (...args) => { - const { promise, resolve, reject } = createDeferredPromise(); + const { promise, resolve, reject } = PromiseWithResolvers(); promise.child = orig(...args, (err, stdout, stderr) => { if (err !== null) { diff --git a/lib/internal/abort_controller.js b/lib/internal/abort_controller.js index 25293a7c2e56f7..b812f588c23e99 100644 --- a/lib/internal/abort_controller.js +++ b/lib/internal/abort_controller.js @@ -10,6 +10,7 @@ const { ObjectDefineProperty, ObjectSetPrototypeOf, PromiseResolve, + PromiseWithResolvers, SafeFinalizationRegistry, SafeSet, SafeWeakRef, @@ -28,7 +29,6 @@ const { kWeakHandler, } = require('internal/event_target'); const { - createDeferredPromise, customInspectSymbol, kEmptyObject, kEnumerableProperty, @@ -486,7 +486,7 @@ async function aborted(signal, resource) { validateObject(resource, 'resource', kValidateObjectAllowObjects); if (signal.aborted) return PromiseResolve(); - const abortPromise = createDeferredPromise(); + const abortPromise = PromiseWithResolvers(); const opts = { __proto__: null, [kWeakHandler]: resource, once: true, [kResistStopPropagation]: true }; signal.addEventListener('abort', abortPromise.resolve, opts); return abortPromise.promise; diff --git a/lib/internal/blob.js b/lib/internal/blob.js index 1ec619f2bdbfcc..43a7ae5ac34d9c 100644 --- a/lib/internal/blob.js +++ b/lib/internal/blob.js @@ -9,6 +9,7 @@ const { ObjectSetPrototypeOf, PromisePrototypeThen, PromiseReject, + PromiseWithResolvers, RegExpPrototypeExec, RegExpPrototypeSymbolReplace, StringPrototypeSplit, @@ -47,7 +48,6 @@ const { } = require('internal/util/types'); const { - createDeferredPromise, customInspectSymbol: kInspect, kEmptyObject, kEnumerableProperty, @@ -325,7 +325,7 @@ class Blob { this.pendingPulls = []; }, pull(c) { - const { promise, resolve, reject } = createDeferredPromise(); + const { promise, resolve, reject } = PromiseWithResolvers(); this.pendingPulls.push({ resolve, reject }); const readNext = () => { reader.pull((status, buffer) => { @@ -478,7 +478,7 @@ function createBlobFromFilePath(path, options) { } function arrayBuffer(blob) { - const { promise, resolve, reject } = createDeferredPromise(); + const { promise, resolve, reject } = PromiseWithResolvers(); const reader = blob[kHandle].getReader(); const buffers = []; const readNext = () => { diff --git a/lib/internal/fs/watchers.js b/lib/internal/fs/watchers.js index f5ecc15159f457..efa8dd85c64bfb 100644 --- a/lib/internal/fs/watchers.js +++ b/lib/internal/fs/watchers.js @@ -4,6 +4,7 @@ const { FunctionPrototypeCall, ObjectDefineProperty, ObjectSetPrototypeOf, + PromiseWithResolvers, Symbol, } = primordials; @@ -15,7 +16,6 @@ const { }, } = require('internal/errors'); const { - createDeferredPromise, kEmptyObject, } = require('internal/util'); @@ -325,7 +325,7 @@ async function* watch(filename, options = kEmptyObject) { throw new AbortError(undefined, { cause: signal?.reason }); const handle = new FSEvent(); - let { promise, resolve, reject } = createDeferredPromise(); + let { promise, resolve, reject } = PromiseWithResolvers(); const oncancel = () => { handle.close(); reject(new AbortError(undefined, { cause: signal?.reason })); @@ -368,7 +368,7 @@ async function* watch(filename, options = kEmptyObject) { while (!signal?.aborted) { yield await promise; - ({ promise, resolve, reject } = createDeferredPromise()); + ({ promise, resolve, reject } = PromiseWithResolvers()); } throw new AbortError(undefined, { cause: signal?.reason }); } finally { diff --git a/lib/internal/per_context/primordials.js b/lib/internal/per_context/primordials.js index 9851f3f64f6e56..d5f336a444e80b 100644 --- a/lib/internal/per_context/primordials.js +++ b/lib/internal/per_context/primordials.js @@ -739,5 +739,18 @@ primordials.SafeStringPrototypeSearch = (str, regexp) => { return match ? match.index : -1; }; +// TODO(@anonrig): Remove this when V8 removes the flag to disable Promise.withResolvers() +// eslint-disable-next-line node-core/prefer-primordials +primordials.PromiseWithResolvers = Promise.withResolvers || (() => { + let resolve; + let reject; + const promise = new Promise((res, rej) => { + resolve = res; + reject = rej; + }); + + return { promise, resolve, reject }; +}); + ObjectSetPrototypeOf(primordials, null); ObjectFreeze(primordials); diff --git a/lib/internal/streams/duplexify.js b/lib/internal/streams/duplexify.js index 4498f0f3905be2..3e026352f20432 100644 --- a/lib/internal/streams/duplexify.js +++ b/lib/internal/streams/duplexify.js @@ -2,6 +2,7 @@ const { FunctionPrototypeCall, + PromiseWithResolvers, } = primordials; const { @@ -27,7 +28,6 @@ const { destroyer } = require('internal/streams/destroy'); const Duplex = require('internal/streams/duplex'); const Readable = require('internal/streams/readable'); const Writable = require('internal/streams/writable'); -const { createDeferredPromise } = require('internal/util'); const from = require('internal/streams/from'); const { @@ -209,7 +209,7 @@ module.exports = function duplexify(body, name) { }; function fromAsyncGen(fn) { - let { promise, resolve } = createDeferredPromise(); + let { promise, resolve } = PromiseWithResolvers(); const ac = new AbortController(); const signal = ac.signal; const value = fn(async function*() { @@ -221,7 +221,7 @@ function fromAsyncGen(fn) { if (done) return; if (signal.aborted) throw new AbortError(undefined, { cause: signal.reason }); - ({ promise, resolve } = createDeferredPromise()); + ({ promise, resolve } = PromiseWithResolvers()); yield chunk; } }(), { signal }); diff --git a/lib/internal/test_runner/harness.js b/lib/internal/test_runner/harness.js index 9109495fef03f3..e9356cbc0100bb 100644 --- a/lib/internal/test_runner/harness.js +++ b/lib/internal/test_runner/harness.js @@ -4,6 +4,7 @@ const { ArrayPrototypePush, FunctionPrototypeBind, PromiseResolve, + PromiseWithResolvers, SafeMap, SafePromiseAllReturnVoid, } = primordials; @@ -26,7 +27,6 @@ const { shouldColorizeTestFiles, } = require('internal/test_runner/utils'); const { queueMicrotask } = require('internal/process/task_queues'); -const { createDeferredPromise } = require('internal/util'); const { bigint: hrtime } = process.hrtime; const resolvedPromise = PromiseResolve(); const testResources = new SafeMap(); @@ -35,7 +35,7 @@ let globalRoot; testResources.set(reporterScope.asyncId(), reporterScope); function createTestTree(rootTestOptions, globalOptions) { - const buildPhaseDeferred = createDeferredPromise(); + const buildPhaseDeferred = PromiseWithResolvers(); const isFilteringByName = globalOptions.testNamePatterns || globalOptions.testSkipPatterns; const isFilteringByOnly = (globalOptions.isolation === 'process' || process.env.NODE_TEST_CONTEXT) ? diff --git a/lib/internal/test_runner/runner.js b/lib/internal/test_runner/runner.js index 18940ffdbe8b58..0ba40d7ba7f71f 100644 --- a/lib/internal/test_runner/runner.js +++ b/lib/internal/test_runner/runner.js @@ -18,6 +18,7 @@ const { ObjectAssign, PromisePrototypeThen, PromiseResolve, + PromiseWithResolvers, SafeMap, SafePromiseAll, SafePromiseAllReturnVoid, @@ -63,7 +64,6 @@ const { getInspectPort, isUsingInspector, isInspectorMessage } = require('intern const { isRegExp } = require('internal/util/types'); const { pathToFileURL } = require('internal/url'); const { - createDeferredPromise, kEmptyObject, } = require('internal/util'); const { kEmitMessage } = require('internal/test_runner/tests_stream'); @@ -744,7 +744,7 @@ function run(options = kEmptyObject) { }; } else { runFiles = async () => { - const { promise, resolve: finishBootstrap } = createDeferredPromise(); + const { promise, resolve: finishBootstrap } = PromiseWithResolvers(); await root.runInAsyncScope(async () => { const parentURL = pathToFileURL(cwd + sep).href; diff --git a/lib/internal/test_runner/test.js b/lib/internal/test_runner/test.js index 80d301cca00ae8..b679410c5561e5 100644 --- a/lib/internal/test_runner/test.js +++ b/lib/internal/test_runner/test.js @@ -18,6 +18,7 @@ const { Promise, PromisePrototypeThen, PromiseResolve, + PromiseWithResolvers, ReflectApply, RegExpPrototypeExec, SafeMap, @@ -53,7 +54,6 @@ const { reporterScope, } = require('internal/test_runner/utils'); const { - createDeferredPromise, kEmptyObject, once: runOnce, } = require('internal/util'); @@ -137,7 +137,7 @@ function lazyAssertObject(harness) { } function stopTest(timeout, signal) { - const deferred = createDeferredPromise(); + const deferred = PromiseWithResolvers(); const abortListener = addAbortListener(signal, deferred.resolve); let timer; let disposeFunction; @@ -822,7 +822,7 @@ class Test extends AsyncResource { // pending for later execution. this.reporter.enqueue(this.nesting, this.loc, this.name); if (this.root.harness.buildPromise || !this.parent.hasConcurrency()) { - const deferred = createDeferredPromise(); + const deferred = PromiseWithResolvers(); deferred.test = this; this.parent.addPendingSubtest(deferred); diff --git a/lib/internal/test_runner/utils.js b/lib/internal/test_runner/utils.js index f61e0450c2a7b1..243b648795a7ef 100644 --- a/lib/internal/test_runner/utils.js +++ b/lib/internal/test_runner/utils.js @@ -14,6 +14,7 @@ const { NumberParseInt, NumberPrototypeToFixed, ObjectGetOwnPropertyDescriptor, + PromiseWithResolvers, RegExp, RegExpPrototypeExec, SafeMap, @@ -29,7 +30,6 @@ const { AsyncResource } = require('async_hooks'); const { relative, sep } = require('path'); const { createWriteStream } = require('fs'); const { pathToFileURL } = require('internal/url'); -const { createDeferredPromise } = require('internal/util'); const { getOptionValue } = require('internal/options'); const { green, yellow, red, white, shouldColorize } = require('internal/util/colors'); @@ -62,7 +62,7 @@ const kDefaultPattern = `**/{${ArrayPrototypeJoin(kPatterns, ',')}}.{${ArrayProt function createDeferredCallback() { let calledCount = 0; - const { promise, resolve, reject } = createDeferredPromise(); + const { promise, resolve, reject } = PromiseWithResolvers(); const cb = (err) => { calledCount++; diff --git a/lib/internal/util.js b/lib/internal/util.js index fb09e5331222f4..8a009850aeb0fc 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -543,17 +543,6 @@ function sleep(msec) { _sleep(msec); } -function createDeferredPromise() { - let resolve; - let reject; - const promise = new Promise((res, rej) => { - resolve = res; - reject = rej; - }); - - return { promise, resolve, reject }; -} - // https://heycam.github.io/webidl/#define-the-operations function defineOperation(target, name, method) { ObjectDefineProperty(target, name, { @@ -872,7 +861,6 @@ module.exports = { cachedResult, convertToValidSignal, createClassWrapper, - createDeferredPromise, decorateErrorStack, defineOperation, defineLazyProperties, diff --git a/lib/internal/webstreams/adapters.js b/lib/internal/webstreams/adapters.js index 14f0f65b275b60..4e99d56aa4be7e 100644 --- a/lib/internal/webstreams/adapters.js +++ b/lib/internal/webstreams/adapters.js @@ -7,6 +7,7 @@ const { ObjectEntries, PromisePrototypeThen, PromiseResolve, + PromiseWithResolvers, SafePromiseAll, SafePromisePrototypeFinally, SafeSet, @@ -64,7 +65,6 @@ const { } = require('internal/errors'); const { - createDeferredPromise, kEmptyObject, normalizeEncoding, } = require('internal/util'); @@ -213,7 +213,7 @@ function newWritableStreamFromStreamWritable(streamWritable) { write(chunk) { if (streamWritable.writableNeedDrain || !streamWritable.write(chunk)) { - backpressurePromise = createDeferredPromise(); + backpressurePromise = PromiseWithResolvers(); return SafePromisePrototypeFinally( backpressurePromise.promise, () => { backpressurePromise = undefined; @@ -227,7 +227,7 @@ function newWritableStreamFromStreamWritable(streamWritable) { close() { if (closed === undefined && !isWritableEnded(streamWritable)) { - closed = createDeferredPromise(); + closed = PromiseWithResolvers(); streamWritable.end(); return closed.promise; } @@ -900,7 +900,7 @@ function newWritableStreamFromStreamBase(streamBase, strategy) { } function doWrite(chunk, controller) { - const promise = createDeferredPromise(); + const promise = PromiseWithResolvers(); let ret; let req; try { @@ -933,7 +933,7 @@ function newWritableStreamFromStreamBase(streamBase, strategy) { }, close() { - const promise = createDeferredPromise(); + const promise = PromiseWithResolvers(); const req = new ShutdownWrap(); req.oncomplete = () => promise.resolve(); const err = streamBase.shutdown(req); @@ -1000,7 +1000,7 @@ function newReadableStreamFromStreamBase(streamBase, strategy, options = kEmptyO }, cancel() { - const promise = createDeferredPromise(); + const promise = PromiseWithResolvers(); try { ondone(); } catch (error) { diff --git a/lib/internal/webstreams/readablestream.js b/lib/internal/webstreams/readablestream.js index 5d9379287e9605..2369175733c115 100644 --- a/lib/internal/webstreams/readablestream.js +++ b/lib/internal/webstreams/readablestream.js @@ -19,6 +19,7 @@ const { PromisePrototypeThen, PromiseReject, PromiseResolve, + PromiseWithResolvers, SafePromiseAll, Symbol, SymbolAsyncIterator, @@ -50,7 +51,6 @@ const { } = require('internal/util/types'); const { - createDeferredPromise, customInspectSymbol: kInspect, kEmptyObject, kEnumerableProperty, @@ -252,7 +252,7 @@ class ReadableStream { validateObject(strategy, 'strategy', kValidateObjectAllowObjectsAndNull); this[kState] = createReadableStreamState(); - this[kIsClosedPromise] = createDeferredPromise(); + this[kIsClosedPromise] = PromiseWithResolvers(); this[kControllerErrorFunction] = () => {}; // The spec requires handling of the strategy first @@ -486,7 +486,7 @@ class ReadableStream { new ERR_INVALID_STATE.TypeError( 'The reader is not bound to a ReadableStream')); } - const promise = createDeferredPromise(); + const promise = PromiseWithResolvers(); // eslint-disable-next-line no-use-before-define readableStreamDefaultReaderRead(reader, new ReadableStreamAsyncIteratorReadRequest(reader, state, promise)); @@ -643,7 +643,7 @@ function InternalTransferredReadableStream() { this[kType] = 'ReadableStream'; this[kState] = createReadableStreamState(); - this[kIsClosedPromise] = createDeferredPromise(); + this[kIsClosedPromise] = PromiseWithResolvers(); } ObjectSetPrototypeOf(InternalTransferredReadableStream.prototype, ReadableStream.prototype); @@ -786,7 +786,7 @@ class ReadableStreamAsyncIteratorReadRequest { class DefaultReadRequest { constructor() { - this[kState] = createDeferredPromise(); + this[kState] = PromiseWithResolvers(); } [kChunk](value) { @@ -806,7 +806,7 @@ class DefaultReadRequest { class ReadIntoRequest { constructor() { - this[kState] = createDeferredPromise(); + this[kState] = PromiseWithResolvers(); } [kChunk](value) { @@ -1230,7 +1230,7 @@ function InternalReadableStream(start, pull, cancel, highWaterMark, size) { markTransferMode(this, false, true); this[kType] = 'ReadableStream'; this[kState] = createReadableStreamState(); - this[kIsClosedPromise] = createDeferredPromise(); + this[kIsClosedPromise] = PromiseWithResolvers(); const controller = new ReadableStreamDefaultController(kSkipThrow); setupReadableStreamDefaultController( this, @@ -1258,7 +1258,7 @@ function InternalReadableByteStream(start, pull, cancel) { markTransferMode(this, false, true); this[kType] = 'ReadableStream'; this[kState] = createReadableStreamState(); - this[kIsClosedPromise] = createDeferredPromise(); + this[kIsClosedPromise] = PromiseWithResolvers(); const controller = new ReadableByteStreamController(kSkipThrow); setupReadableByteStreamController( this, @@ -1392,7 +1392,7 @@ function readableStreamPipeTo( } } - const promise = createDeferredPromise(); + const promise = PromiseWithResolvers(); const state = { currentWrite: PromiseResolve(), @@ -1509,7 +1509,7 @@ function readableStreamPipeTo( await writer[kState].ready.promise; - const promise = createDeferredPromise(); + const promise = PromiseWithResolvers(); // eslint-disable-next-line no-use-before-define readableStreamDefaultReaderRead(reader, new PipeToReadableStreamReadRequest(writer, state, promise)); @@ -1613,7 +1613,7 @@ function readableStreamDefaultTee(stream, cloneForBranch2) { let reason2; let branch1; let branch2; - const cancelPromise = createDeferredPromise(); + const cancelPromise = PromiseWithResolvers(); async function pullAlgorithm() { if (reading) return; @@ -1712,7 +1712,7 @@ function readableByteStreamTee(stream) { let reason2; let branch1; let branch2; - const cancelDeferred = createDeferredPromise(); + const cancelDeferred = PromiseWithResolvers(); function forwardReaderError(thisReader) { PromisePrototypeThen( @@ -2159,7 +2159,7 @@ function readableStreamReaderGenericInitialize(reader, stream) { stream[kState].reader = reader; switch (stream[kState].state) { case 'readable': - reader[kState].close = createDeferredPromise(); + reader[kState].close = PromiseWithResolvers(); break; case 'closed': reader[kState].close = { diff --git a/lib/internal/webstreams/transfer.js b/lib/internal/webstreams/transfer.js index 9835e6ab272c98..9ce3f249ffd2bd 100644 --- a/lib/internal/webstreams/transfer.js +++ b/lib/internal/webstreams/transfer.js @@ -3,6 +3,7 @@ const { ObjectDefineProperties, PromiseResolve, + PromiseWithResolvers, ReflectConstruct, } = primordials; @@ -28,10 +29,6 @@ const { writableStreamDefaultControllerErrorIfNeeded, } = require('internal/webstreams/writablestream'); -const { - createDeferredPromise, -} = require('internal/util'); - const assert = require('internal/assert'); const { @@ -181,7 +178,7 @@ class CrossRealmTransformWritableSink { this[kState] = { port, controller: undefined, - backpressurePromise: createDeferredPromise(), + backpressurePromise: PromiseWithResolvers(), unref, }; @@ -239,7 +236,7 @@ class CrossRealmTransformWritableSink { }; } await this[kState].backpressurePromise.promise; - this[kState].backpressurePromise = createDeferredPromise(); + this[kState].backpressurePromise = PromiseWithResolvers(); try { this[kState].port.postMessage({ type: 'chunk', value: chunk }); } catch (error) { diff --git a/lib/internal/webstreams/transformstream.js b/lib/internal/webstreams/transformstream.js index 9e26387b3b6110..cd3c96d68a59b8 100644 --- a/lib/internal/webstreams/transformstream.js +++ b/lib/internal/webstreams/transformstream.js @@ -5,6 +5,7 @@ const { ObjectDefineProperties, ObjectSetPrototypeOf, PromisePrototypeThen, + PromiseWithResolvers, Symbol, SymbolToStringTag, } = primordials; @@ -23,7 +24,6 @@ const { } = internalBinding('messaging'); const { - createDeferredPromise, customInspectSymbol: kInspect, kEmptyObject, kEnumerableProperty, @@ -161,7 +161,7 @@ class TransformStream { extractHighWaterMark(writableHighWaterMark, 1); const actualWritableSize = extractSizeAlgorithm(writableSize); - const startPromise = createDeferredPromise(); + const startPromise = PromiseWithResolvers(); initializeTransformStream( this, @@ -439,7 +439,7 @@ function transformStreamSetBackpressure(stream, backpressure) { assert(stream[kState].backpressure !== backpressure); if (stream[kState].backpressureChange.promise !== undefined) stream[kState].backpressureChange.resolve?.(); - stream[kState].backpressureChange = createDeferredPromise(); + stream[kState].backpressureChange = PromiseWithResolvers(); stream[kState].backpressure = backpressure; } @@ -583,7 +583,7 @@ async function transformStreamDefaultSinkAbortAlgorithm(stream, reason) { return controller[kState].finishPromise; } - const { promise, resolve, reject } = createDeferredPromise(); + const { promise, resolve, reject } = PromiseWithResolvers(); controller[kState].finishPromise = promise; const cancelPromise = controller[kState].cancelAlgorithm(reason); transformStreamDefaultControllerClearAlgorithms(controller); @@ -616,7 +616,7 @@ function transformStreamDefaultSinkCloseAlgorithm(stream) { if (controller[kState].finishPromise !== undefined) { return controller[kState].finishPromise; } - const { promise, resolve, reject } = createDeferredPromise(); + const { promise, resolve, reject } = PromiseWithResolvers(); controller[kState].finishPromise = promise; const flushPromise = controller[kState].flushAlgorithm(controller); transformStreamDefaultControllerClearAlgorithms(controller); @@ -654,7 +654,7 @@ function transformStreamDefaultSourceCancelAlgorithm(stream, reason) { return controller[kState].finishPromise; } - const { promise, resolve, reject } = createDeferredPromise(); + const { promise, resolve, reject } = PromiseWithResolvers(); controller[kState].finishPromise = promise; const cancelPromise = controller[kState].cancelAlgorithm(reason); transformStreamDefaultControllerClearAlgorithms(controller); diff --git a/lib/internal/webstreams/writablestream.js b/lib/internal/webstreams/writablestream.js index ba1461fc70e95f..5baaf20c30ba26 100644 --- a/lib/internal/webstreams/writablestream.js +++ b/lib/internal/webstreams/writablestream.js @@ -11,6 +11,7 @@ const { PromisePrototypeThen, PromiseReject, PromiseResolve, + PromiseWithResolvers, Symbol, SymbolToStringTag, } = primordials; @@ -30,7 +31,6 @@ const { } = internalBinding('messaging'); const { - createDeferredPromise, customInspectSymbol: kInspect, kEmptyObject, kEnumerableProperty, @@ -170,7 +170,7 @@ class WritableStream { this[kState] = createWritableStreamState(); - this[kIsClosedPromise] = createDeferredPromise(); + this[kIsClosedPromise] = PromiseWithResolvers(); this[kControllerErrorFunction] = () => {}; const size = extractSizeAlgorithm(strategy?.size); @@ -305,7 +305,7 @@ function InternalTransferredWritableStream() { this[kType] = 'WritableStream'; this[kState] = createWritableStreamState(); - this[kIsClosedPromise] = createDeferredPromise(); + this[kIsClosedPromise] = PromiseWithResolvers(); } ObjectSetPrototypeOf(InternalTransferredWritableStream.prototype, WritableStream.prototype); @@ -521,7 +521,7 @@ function InternalWritableStream(start, write, close, abort, highWaterMark, size) markTransferMode(this, false, true); this[kType] = 'WritableStream'; this[kState] = createWritableStreamState(); - this[kIsClosedPromise] = createDeferredPromise(); + this[kIsClosedPromise] = PromiseWithResolvers(); const controller = new WritableStreamDefaultController(kSkipThrow); setupWritableStreamDefaultController( @@ -557,7 +557,7 @@ const isWritableStreamDefaultController = function createWritableStreamState() { return { __proto__: null, - close: createDeferredPromise(), + close: PromiseWithResolvers(), closeRequest: { __proto__: null, promise: undefined, @@ -616,7 +616,7 @@ function setupWritableStreamDefaultWriter(writer, stream) { case 'writable': if (!writableStreamCloseQueuedOrInFlight(stream) && stream[kState].backpressure) { - writer[kState].ready = createDeferredPromise(); + writer[kState].ready = PromiseWithResolvers(); } else { writer[kState].ready = { promise: PromiseResolve(), @@ -663,7 +663,7 @@ function setupWritableStreamDefaultWriter(writer, stream) { } function setClosedPromiseToNewPromise() { - writer[kState].close = createDeferredPromise(); + writer[kState].close = PromiseWithResolvers(); } } @@ -688,7 +688,7 @@ function writableStreamAbort(stream, reason) { reason = undefined; } - const abort = createDeferredPromise(); + const abort = PromiseWithResolvers(); stream[kState].pendingAbortRequest = { abort, @@ -715,7 +715,7 @@ function writableStreamClose(stream) { } assert(state === 'writable' || state === 'erroring'); assert(!writableStreamCloseQueuedOrInFlight(stream)); - stream[kState].closeRequest = createDeferredPromise(); + stream[kState].closeRequest = PromiseWithResolvers(); const { promise } = stream[kState].closeRequest; if (writer !== undefined && backpressure && state === 'writable') writer[kState].ready.resolve?.(); @@ -731,7 +731,7 @@ function writableStreamUpdateBackpressure(stream, backpressure) { } = stream[kState]; if (writer !== undefined && stream[kState].backpressure !== backpressure) { if (backpressure) { - writer[kState].ready = createDeferredPromise(); + writer[kState].ready = PromiseWithResolvers(); } else { writer[kState].ready.resolve?.(); } @@ -961,7 +961,7 @@ function writableStreamAddWriteRequest(stream) { promise, resolve, reject, - } = createDeferredPromise(); + } = PromiseWithResolvers(); ArrayPrototypePush( stream[kState].writeRequests, { diff --git a/test/parallel/test-runner-run-watch.mjs b/test/parallel/test-runner-run-watch.mjs index fca8b492bc3ad0..83e8524f44a338 100644 --- a/test/parallel/test-runner-run-watch.mjs +++ b/test/parallel/test-runner-run-watch.mjs @@ -1,11 +1,9 @@ -// Flags: --expose-internals import * as common from '../common/index.mjs'; import { describe, it, beforeEach, run } from 'node:test'; import assert from 'node:assert'; import { spawn } from 'node:child_process'; import { once } from 'node:events'; import { writeFileSync, renameSync, unlinkSync, existsSync } from 'node:fs'; -import util from 'internal/util'; import tmpdir from '../common/tmpdir.js'; import { join } from 'node:path'; @@ -52,8 +50,8 @@ async function testWatch( isolation } ) { - const ran1 = util.createDeferredPromise(); - const ran2 = util.createDeferredPromise(); + const ran1 = Promise.withResolvers(); + const ran2 = Promise.withResolvers(); const args = [runner]; if (file) args.push('--file', file); if (runnerCwd) args.push('--cwd', runnerCwd); diff --git a/test/parallel/test-runner-watch-mode-complex.mjs b/test/parallel/test-runner-watch-mode-complex.mjs index bd33be61c7d058..daa37e04d67903 100644 --- a/test/parallel/test-runner-watch-mode-complex.mjs +++ b/test/parallel/test-runner-watch-mode-complex.mjs @@ -1,11 +1,9 @@ -// Flags: --expose-internals import * as common from '../common/index.mjs'; import { describe, it } from 'node:test'; import assert from 'node:assert'; import { spawn } from 'node:child_process'; import { writeFile, unlink } from 'node:fs/promises'; import { setTimeout } from 'node:timers/promises'; -import util from 'internal/util'; import tmpdir from '../common/tmpdir.js'; if (common.isIBMi) @@ -56,8 +54,8 @@ await setupFixtures(); describe('test runner watch mode with more complex setup', () => { it('should run tests when a dependency changed after a watched test file being deleted', async () => { - const ran1 = util.createDeferredPromise(); - const ran2 = util.createDeferredPromise(); + const ran1 = Promise.withResolvers(); + const ran2 = Promise.withResolvers(); const child = spawn(process.execPath, ['--watch', '--test'], { encoding: 'utf8', stdio: 'pipe', cwd: tmpdir.path }); diff --git a/test/parallel/test-runner-watch-mode.mjs b/test/parallel/test-runner-watch-mode.mjs index 0c56e4c20e5b37..697e5435a8491e 100644 --- a/test/parallel/test-runner-watch-mode.mjs +++ b/test/parallel/test-runner-watch-mode.mjs @@ -1,4 +1,3 @@ -// Flags: --expose-internals import * as common from '../common/index.mjs'; import { describe, it, beforeEach } from 'node:test'; import { once } from 'node:events'; @@ -6,7 +5,6 @@ import assert from 'node:assert'; import { spawn } from 'node:child_process'; import { writeFileSync, renameSync, unlinkSync } from 'node:fs'; import { setTimeout } from 'node:timers/promises'; -import util from 'internal/util'; import tmpdir from '../common/tmpdir.js'; if (common.isIBMi) @@ -45,8 +43,8 @@ async function testWatch({ fileToCreate, isolation, }) { - const ran1 = util.createDeferredPromise(); - const ran2 = util.createDeferredPromise(); + const ran1 = Promise.withResolvers(); + const ran2 = Promise.withResolvers(); const child = spawn(process.execPath, ['--watch', '--test', '--test-reporter=spec', isolation ? `--experimental-test-isolation=${isolation}` : '', diff --git a/typings/primordials.d.ts b/typings/primordials.d.ts index da00d43f515286..387a53025fde9d 100644 --- a/typings/primordials.d.ts +++ b/typings/primordials.d.ts @@ -531,6 +531,7 @@ declare namespace primordials { export const PromisePrototypeThen: UncurryThis export const PromisePrototypeCatch: UncurryThis export const PromisePrototypeFinally: UncurryThis + export const PromiseWithResolvers: typeof Promise.withResolvers export import Proxy = globalThis.Proxy import _globalThis = globalThis export { _globalThis as globalThis } From df1b7e5507564907d63e06c435f27abae149142f Mon Sep 17 00:00:00 2001 From: Yagiz Nizipli Date: Tue, 8 Oct 2024 09:44:52 -0400 Subject: [PATCH 2/2] Update primordials.js Co-authored-by: Antoine du Hamel --- lib/internal/per_context/primordials.js | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/lib/internal/per_context/primordials.js b/lib/internal/per_context/primordials.js index d5f336a444e80b..9851f3f64f6e56 100644 --- a/lib/internal/per_context/primordials.js +++ b/lib/internal/per_context/primordials.js @@ -739,18 +739,5 @@ primordials.SafeStringPrototypeSearch = (str, regexp) => { return match ? match.index : -1; }; -// TODO(@anonrig): Remove this when V8 removes the flag to disable Promise.withResolvers() -// eslint-disable-next-line node-core/prefer-primordials -primordials.PromiseWithResolvers = Promise.withResolvers || (() => { - let resolve; - let reject; - const promise = new Promise((res, rej) => { - resolve = res; - reject = rej; - }); - - return { promise, resolve, reject }; -}); - ObjectSetPrototypeOf(primordials, null); ObjectFreeze(primordials);