lib: reuse invalid state errors on webstreams

Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
PR-URL: https://github.com/nodejs/node/pull/46086
Reviewed-By: Robert Nagy <ronagy@icloud.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
This commit is contained in:
Rafael Gonzaga 2023-01-13 03:33:29 +00:00 committed by GitHub
parent 31ea7be98d
commit 5d50b8435c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 50 additions and 10 deletions

View File

@ -54,6 +54,7 @@ const {
isArrayBufferDetached, isArrayBufferDetached,
kEmptyObject, kEmptyObject,
kEnumerableProperty, kEnumerableProperty,
SideEffectFreeRegExpPrototypeSymbolReplace,
} = require('internal/util'); } = require('internal/util');
const { const {
@ -140,6 +141,32 @@ const kError = Symbol('kError');
const kPull = Symbol('kPull'); const kPull = Symbol('kPull');
const kRelease = Symbol('kRelease'); const kRelease = Symbol('kRelease');
let releasedError;
let releasingError;
const userModuleRegExp = /^ {4}at (?:[^/\\(]+ \()(?!node:(.+):\d+:\d+\)$).*/gm;
function lazyReadableReleasedError() {
if (releasedError) {
return releasedError;
}
releasedError = new ERR_INVALID_STATE.TypeError('Reader released');
// Avoid V8 leak and remove userland stackstrace
releasedError.stack = SideEffectFreeRegExpPrototypeSymbolReplace(userModuleRegExp, 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(userModuleRegExp, releasingError.stack, '');
return releasingError;
}
const getNonWritablePropertyDescriptor = (value) => { const getNonWritablePropertyDescriptor = (value) => {
return { return {
__proto__: null, __proto__: null,
@ -2029,7 +2056,7 @@ function readableStreamDefaultReaderRelease(reader) {
readableStreamReaderGenericRelease(reader); readableStreamReaderGenericRelease(reader);
readableStreamDefaultReaderErrorReadRequests( readableStreamDefaultReaderErrorReadRequests(
reader, reader,
new ERR_INVALID_STATE.TypeError('Releasing reader') lazyReadableReleasingError(),
); );
} }
@ -2044,7 +2071,7 @@ function readableStreamBYOBReaderRelease(reader) {
readableStreamReaderGenericRelease(reader); readableStreamReaderGenericRelease(reader);
readableStreamBYOBReaderErrorReadIntoRequests( readableStreamBYOBReaderErrorReadIntoRequests(
reader, reader,
new ERR_INVALID_STATE.TypeError('Releasing reader') lazyReadableReleasingError(),
); );
} }
@ -2062,13 +2089,12 @@ function readableStreamReaderGenericRelease(reader) {
assert(stream !== undefined); assert(stream !== undefined);
assert(stream[kState].reader === reader); assert(stream[kState].reader === reader);
const releasedStateError = lazyReadableReleasedError();
if (stream[kState].state === 'readable') { if (stream[kState].state === 'readable') {
reader[kState].close.reject?.( reader[kState].close.reject?.(releasedStateError);
new ERR_INVALID_STATE.TypeError('Reader released'));
} else { } else {
reader[kState].close = { reader[kState].close = {
promise: PromiseReject( promise: PromiseReject(releasedStateError),
new ERR_INVALID_STATE.TypeError('Reader released')),
resolve: undefined, resolve: undefined,
reject: undefined, reject: undefined,
}; };

View File

@ -34,6 +34,7 @@ const {
createDeferredPromise, createDeferredPromise,
customInspectSymbol: kInspect, customInspectSymbol: kInspect,
kEnumerableProperty, kEnumerableProperty,
SideEffectFreeRegExpPrototypeSymbolReplace,
} = require('internal/util'); } = require('internal/util');
const { const {
@ -77,6 +78,20 @@ const kAbort = Symbol('kAbort');
const kCloseSentinel = Symbol('kCloseSentinel'); const kCloseSentinel = Symbol('kCloseSentinel');
const kError = Symbol('kError'); const kError = Symbol('kError');
let releasedError;
function lazyWritableReleasedError() {
if (releasedError) {
return releasedError;
}
const userModuleRegExp = /^ {4}at (?:[^/\\(]+ \()(?!node:(.+):\d+:\d+\)$).*/gm;
releasedError = new ERR_INVALID_STATE.TypeError('Writer has been released');
// Avoid V8 leak and remove userland stackstrace
releasedError.stack = SideEffectFreeRegExpPrototypeSymbolReplace(userModuleRegExp, releasedError.stack, '');
return releasedError;
}
const getNonWritablePropertyDescriptor = (value) => { const getNonWritablePropertyDescriptor = (value) => {
return { return {
__proto__: null, __proto__: null,
@ -970,10 +985,9 @@ function writableStreamDefaultWriterRelease(writer) {
} = writer[kState]; } = writer[kState];
assert(stream !== undefined); assert(stream !== undefined);
assert(stream[kState].writer === writer); assert(stream[kState].writer === writer);
const releasedError = const releasedStateError = lazyWritableReleasedError();
new ERR_INVALID_STATE.TypeError('Writer has been released'); writableStreamDefaultWriterEnsureReadyPromiseRejected(writer, releasedStateError);
writableStreamDefaultWriterEnsureReadyPromiseRejected(writer, releasedError); writableStreamDefaultWriterEnsureClosedPromiseRejected(writer, releasedStateError);
writableStreamDefaultWriterEnsureClosedPromiseRejected(writer, releasedError);
stream[kState].writer = undefined; stream[kState].writer = undefined;
writer[kState].stream = undefined; writer[kState].stream = undefined;
} }