Skip to content

Commit bc17f37

Browse files
RafaelGSSjuanarbol
authored andcommitted
lib: reuse invalid state errors on webstreams
Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com> PR-URL: #46086 Reviewed-By: Robert Nagy <ronagy@icloud.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent ed1ac82 commit bc17f37

File tree

2 files changed

+50
-10
lines changed

2 files changed

+50
-10
lines changed

lib/internal/webstreams/readablestream.js

+32-6
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ const {
5454
isArrayBufferDetached,
5555
kEmptyObject,
5656
kEnumerableProperty,
57+
SideEffectFreeRegExpPrototypeSymbolReplace,
5758
} = require('internal/util');
5859

5960
const {
@@ -140,6 +141,32 @@ const kError = Symbol('kError');
140141
const kPull = Symbol('kPull');
141142
const kRelease = Symbol('kRelease');
142143

144+
let releasedError;
145+
let releasingError;
146+
147+
const userModuleRegExp = /^ {4}at (?:[^/\\(]+ \()(?!node:(.+):\d+:\d+\)$).*/gm;
148+
149+
function lazyReadableReleasedError() {
150+
if (releasedError) {
151+
return releasedError;
152+
}
153+
154+
releasedError = new ERR_INVALID_STATE.TypeError('Reader released');
155+
// Avoid V8 leak and remove userland stackstrace
156+
releasedError.stack = SideEffectFreeRegExpPrototypeSymbolReplace(userModuleRegExp, releasedError.stack, '');
157+
return releasedError;
158+
}
159+
160+
function lazyReadableReleasingError() {
161+
if (releasingError) {
162+
return releasingError;
163+
}
164+
releasingError = new ERR_INVALID_STATE.TypeError('Releasing reader');
165+
// Avoid V8 leak and remove userland stackstrace
166+
releasingError.stack = SideEffectFreeRegExpPrototypeSymbolReplace(userModuleRegExp, releasingError.stack, '');
167+
return releasingError;
168+
}
169+
143170
const getNonWritablePropertyDescriptor = (value) => {
144171
return {
145172
__proto__: null,
@@ -2029,7 +2056,7 @@ function readableStreamDefaultReaderRelease(reader) {
20292056
readableStreamReaderGenericRelease(reader);
20302057
readableStreamDefaultReaderErrorReadRequests(
20312058
reader,
2032-
new ERR_INVALID_STATE.TypeError('Releasing reader')
2059+
lazyReadableReleasingError(),
20332060
);
20342061
}
20352062

@@ -2044,7 +2071,7 @@ function readableStreamBYOBReaderRelease(reader) {
20442071
readableStreamReaderGenericRelease(reader);
20452072
readableStreamBYOBReaderErrorReadIntoRequests(
20462073
reader,
2047-
new ERR_INVALID_STATE.TypeError('Releasing reader')
2074+
lazyReadableReleasingError(),
20482075
);
20492076
}
20502077

@@ -2062,13 +2089,12 @@ function readableStreamReaderGenericRelease(reader) {
20622089
assert(stream !== undefined);
20632090
assert(stream[kState].reader === reader);
20642091

2092+
const releasedStateError = lazyReadableReleasedError();
20652093
if (stream[kState].state === 'readable') {
2066-
reader[kState].close.reject?.(
2067-
new ERR_INVALID_STATE.TypeError('Reader released'));
2094+
reader[kState].close.reject?.(releasedStateError);
20682095
} else {
20692096
reader[kState].close = {
2070-
promise: PromiseReject(
2071-
new ERR_INVALID_STATE.TypeError('Reader released')),
2097+
promise: PromiseReject(releasedStateError),
20722098
resolve: undefined,
20732099
reject: undefined,
20742100
};

lib/internal/webstreams/writablestream.js

+18-4
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const {
3434
createDeferredPromise,
3535
customInspectSymbol: kInspect,
3636
kEnumerableProperty,
37+
SideEffectFreeRegExpPrototypeSymbolReplace,
3738
} = require('internal/util');
3839

3940
const {
@@ -77,6 +78,20 @@ const kAbort = Symbol('kAbort');
7778
const kCloseSentinel = Symbol('kCloseSentinel');
7879
const kError = Symbol('kError');
7980

81+
let releasedError;
82+
83+
function lazyWritableReleasedError() {
84+
if (releasedError) {
85+
return releasedError;
86+
}
87+
const userModuleRegExp = /^ {4}at (?:[^/\\(]+ \()(?!node:(.+):\d+:\d+\)$).*/gm;
88+
89+
releasedError = new ERR_INVALID_STATE.TypeError('Writer has been released');
90+
// Avoid V8 leak and remove userland stackstrace
91+
releasedError.stack = SideEffectFreeRegExpPrototypeSymbolReplace(userModuleRegExp, releasedError.stack, '');
92+
return releasedError;
93+
}
94+
8095
const getNonWritablePropertyDescriptor = (value) => {
8196
return {
8297
__proto__: null,
@@ -970,10 +985,9 @@ function writableStreamDefaultWriterRelease(writer) {
970985
} = writer[kState];
971986
assert(stream !== undefined);
972987
assert(stream[kState].writer === writer);
973-
const releasedError =
974-
new ERR_INVALID_STATE.TypeError('Writer has been released');
975-
writableStreamDefaultWriterEnsureReadyPromiseRejected(writer, releasedError);
976-
writableStreamDefaultWriterEnsureClosedPromiseRejected(writer, releasedError);
988+
const releasedStateError = lazyWritableReleasedError();
989+
writableStreamDefaultWriterEnsureReadyPromiseRejected(writer, releasedStateError);
990+
writableStreamDefaultWriterEnsureClosedPromiseRejected(writer, releasedStateError);
977991
stream[kState].writer = undefined;
978992
writer[kState].stream = undefined;
979993
}

0 commit comments

Comments
 (0)