From 42c40ed406a9a91291baf88895947de93a24e657 Mon Sep 17 00:00:00 2001 From: RafaelGSS Date: Tue, 3 Jan 2023 19:35:09 -0300 Subject: [PATCH] lib: reuse invalid state errors on webstreams Signed-off-by: RafaelGSS --- lib/internal/webstreams/readablestream.js | 39 +++++++++++++++++++---- lib/internal/webstreams/writablestream.js | 23 ++++++++++--- 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/lib/internal/webstreams/readablestream.js b/lib/internal/webstreams/readablestream.js index 5344785b90cd3e..bb5f1f1321cb99 100644 --- a/lib/internal/webstreams/readablestream.js +++ b/lib/internal/webstreams/readablestream.js @@ -54,6 +54,7 @@ const { isArrayBufferDetached, kEmptyObject, kEnumerableProperty, + SideEffectFreeRegExpPrototypeSymbolReplace, } = require('internal/util'); const { @@ -140,6 +141,33 @@ const kError = Symbol('kError'); const kPull = Symbol('kPull'); const kRelease = Symbol('kRelease'); +let releasedError; +let releasingError; + +function lazyReadableReleasedError() { + if (releasedError) { + return releasedError; + } + releasedError = new ERR_INVALID_STATE.TypeError('Reader released'); + // Avoid V8 leak and remove userland stackstrace + releasedError.stack = SideEffectFreeRegExpPrototypeSymbolReplace( + /^.*\((?!node:|internal)[^()]*\).*$/gm, + releasedError.stack, ''); + return releasedError; +} + +function lazyReadableReleasingError() { + if (releasingError) { + return releasingError; + } + releasingError = new ERR_INVALID_STATE.TypeError('Releasing reader'); + // Avoid V8 leak and remove userland stackstrace + releasingError.stack = SideEffectFreeRegExpPrototypeSymbolReplace( + /^.*\((?!node:|internal)[^()]*\).*$/gm, + releasingError.stack, ''); + return releasingError; +} + const getNonWritablePropertyDescriptor = (value) => { return { __proto__: null, @@ -2029,7 +2057,7 @@ function readableStreamDefaultReaderRelease(reader) { readableStreamReaderGenericRelease(reader); readableStreamDefaultReaderErrorReadRequests( reader, - new ERR_INVALID_STATE.TypeError('Releasing reader') + lazyReadableReleasingError(), ); } @@ -2044,7 +2072,7 @@ function readableStreamBYOBReaderRelease(reader) { readableStreamReaderGenericRelease(reader); readableStreamBYOBReaderErrorReadIntoRequests( reader, - new ERR_INVALID_STATE.TypeError('Releasing reader') + lazyReadableReleasingError(), ); } @@ -2062,13 +2090,12 @@ function readableStreamReaderGenericRelease(reader) { assert(stream !== undefined); assert(stream[kState].reader === reader); + const releasedStateError = lazyReadableReleasedError(); if (stream[kState].state === 'readable') { - reader[kState].close.reject?.( - new ERR_INVALID_STATE.TypeError('Reader released')); + reader[kState].close.reject?.(releasedStateError); } else { reader[kState].close = { - promise: PromiseReject( - new ERR_INVALID_STATE.TypeError('Reader released')), + promise: PromiseReject(releasedStateError), resolve: undefined, reject: undefined, }; diff --git a/lib/internal/webstreams/writablestream.js b/lib/internal/webstreams/writablestream.js index ba66cea7a4850d..74af986f6d6564 100644 --- a/lib/internal/webstreams/writablestream.js +++ b/lib/internal/webstreams/writablestream.js @@ -24,6 +24,7 @@ const { ERR_INVALID_STATE, ERR_INVALID_THIS, }, + hideStackFrames, } = require('internal/errors'); const { @@ -34,6 +35,7 @@ const { createDeferredPromise, customInspectSymbol: kInspect, kEnumerableProperty, + SideEffectFreeRegExpPrototypeSymbolReplace, } = require('internal/util'); const { @@ -77,6 +79,20 @@ const kAbort = Symbol('kAbort'); const kCloseSentinel = Symbol('kCloseSentinel'); const kError = Symbol('kError'); +let releasedError; + +function lazyWritableReleasedError() { + if (releasedError) { + return releasedError; + } + releasedError = new ERR_INVALID_STATE.TypeError('Writer has been released'); + // Avoid V8 leak and remove userland stackstrace + releasedError.stack = SideEffectFreeRegExpPrototypeSymbolReplace( + /^.*\((?!node:|internal)[^()]*\).*$/gm, + releasedError.stack, ''); + return releasedError; +}; + const getNonWritablePropertyDescriptor = (value) => { return { __proto__: null, @@ -970,10 +986,9 @@ function writableStreamDefaultWriterRelease(writer) { } = writer[kState]; assert(stream !== undefined); assert(stream[kState].writer === writer); - const releasedError = - new ERR_INVALID_STATE.TypeError('Writer has been released'); - writableStreamDefaultWriterEnsureReadyPromiseRejected(writer, releasedError); - writableStreamDefaultWriterEnsureClosedPromiseRejected(writer, releasedError); + const releasedStateError = lazyWritableReleasedError(); + writableStreamDefaultWriterEnsureReadyPromiseRejected(writer, releasedStateError); + writableStreamDefaultWriterEnsureClosedPromiseRejected(writer, releasedStateError); stream[kState].writer = undefined; writer[kState].stream = undefined; }