Skip to content

Commit 6491a18

Browse files
committed
Revert "stream: avoid promise allocation for parked transform writes"
This reverts commit bbb0055. A parked TransformStream write was resumed from the read that lifted the backpressure, so transform(), the writes queued behind it and flush() ran in the reader's async context instead of the writer's, losing AsyncLocalStorage state. The parked write error test is kept, as it covers spec behavior that still holds after the revert. Refs: #65625 Refs: #66906 Signed-off-by: Matteo Collina <hello@matteocollina.com>
1 parent 59e46ca commit 6491a18

1 file changed

Lines changed: 19 additions & 25 deletions

File tree

‎lib/internal/webstreams/transformstream.js‎

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ class TransformStreamState {
264264
// Continuation slots replacing the spec's
265265
// [[backpressureChangePromise]]; see transformStreamSetBackpressure.
266266
pullPending = false;
267-
pendingWriteParked = false;
267+
pendingWrite = undefined;
268268
pendingWriteChunk = undefined;
269269
writeContinuation = undefined;
270270
}
@@ -465,7 +465,7 @@ function transformStreamSetBackpressure(stream, backpressure) {
465465
kResolvedPromise,
466466
state.readable[kState].controller[kState].pullFulfilled);
467467
}
468-
} else if (state.pendingWriteParked) {
468+
} else if (state.pendingWrite !== undefined) {
469469
PromisePrototypeThen(kResolvedPromise, state.writeContinuation);
470470
}
471471
}
@@ -609,41 +609,35 @@ function transformStreamDefaultSinkWriteAlgorithm(stream, chunk) {
609609
} = state;
610610
assert(writable[kState].state === 'writable');
611611
if (state.backpressure) {
612-
// Park the chunk; the backpressure -> false flip delivers the cached
613-
// continuation (see transformStreamSetBackpressure) at the same
614-
// microtask position as the old [[backpressureChangePromise]]
615-
// reaction. The continuation completes the parked write by wiring
616-
// the perform-transform promise directly to the writable
617-
// controller's write reactions (they exist: the controller creates
618-
// them before invoking the write algorithm), replacing the promise
619-
// record the old code allocated and resolved per parked chunk. The
620-
// writable dispatches a single write at a time, so one pending slot
621-
// suffices.
622-
assert(!state.pendingWriteParked);
623-
state.pendingWriteParked = true;
612+
// Park the chunk and one promise record; the backpressure -> false
613+
// flip delivers the cached continuation (see
614+
// transformStreamSetBackpressure) at the same microtask position as
615+
// the old [[backpressureChangePromise]] reaction. The continuation
616+
// resolves the sink promise with the perform-transform promise, so
617+
// adoption reproduces the old derived-chain settle depth exactly.
618+
// The writable dispatches a single write at a time, so one pending
619+
// slot suffices.
620+
assert(state.pendingWrite === undefined);
621+
const pendingWrite = PromiseWithResolvers();
622+
state.pendingWrite = pendingWrite;
624623
state.pendingWriteChunk = chunk;
625624
state.writeContinuation ??= () => {
625+
const pending = state.pendingWrite;
626626
const pendingChunk = state.pendingWriteChunk;
627-
state.pendingWriteParked = false;
627+
state.pendingWrite = undefined;
628628
state.pendingWriteChunk = undefined;
629629
const writableState = state.writable[kState];
630-
const writableControllerState = writableState.controller[kState];
631630
if (writableState.state === 'erroring') {
632-
const error = writableState.storedError;
633-
PromisePrototypeThen(
634-
kResolvedPromise,
635-
() => writableControllerState.writeRejected(error));
631+
pending.reject(writableState.storedError);
636632
return;
637633
}
638634
assert(writableState.state === 'writable');
639-
PromisePrototypeThen(
635+
pending.resolve(
640636
transformStreamDefaultControllerPerformTransform(
641637
controller,
642-
pendingChunk),
643-
writableControllerState.writeFulfilled,
644-
writableControllerState.writeRejected);
638+
pendingChunk));
645639
};
646-
return kParkedAlgorithmResult;
640+
return pendingWrite.promise;
647641
}
648642
return transformStreamDefaultControllerPerformTransform(controller, chunk);
649643
}

0 commit comments

Comments
 (0)