@@ -19,9 +19,14 @@ struct WritableStreamSinkJsAdapter::Active final {
1919 struct Task {
2020 kj::Function<kj::Promise<void >()> task;
2121 kj::Own<kj::PromiseFulfiller<void >> fulfiller;
22- Task (kj::Function<kj::Promise<void >()> task, kj::Own<kj::PromiseFulfiller<void >> fulfiller)
22+ kj::Maybe<kj::Promise<void >> maybeOutputLock;
23+
24+ Task (kj::Function<kj::Promise<void >()> task,
25+ kj::Own<kj::PromiseFulfiller<void >> fulfiller,
26+ kj::Maybe<kj::Promise<void >> maybeOutputLock = kj::none)
2327 : task(kj::mv(task)),
24- fulfiller (kj::mv(fulfiller)) {}
28+ fulfiller (kj::mv(fulfiller)),
29+ maybeOutputLock(kj::mv(maybeOutputLock)) {}
2530 KJ_DISALLOW_COPY_AND_MOVE (Task);
2631 };
2732 using TaskQueue = workerd::util::Queue<kj::Own<Task>>;
@@ -80,9 +85,11 @@ struct WritableStreamSinkJsAdapter::Active final {
8085 kj::Promise<void > enqueue (kj::Function<kj::Promise<void >()> task) {
8186 KJ_DASSERT (!aborted, " cannot enqueue tasks on an aborted queue" );
8287 auto paf = kj::newPromiseAndFulfiller<void >();
83- queue.push (kj::heap<Task>(kj::mv (task), kj::mv (paf.fulfiller )));
88+ auto & ioContext = IoContext::current ();
89+ queue.push (kj::heap<Task>(
90+ kj::mv (task), kj::mv (paf.fulfiller ), ioContext.waitForOutputLocksIfNecessary ()));
8491 if (!running) {
85- IoContext::current () .addTask (canceler.wrap (run ()));
92+ ioContext .addTask (canceler.wrap (run ()));
8693 }
8794 return kj::mv (paf.promise );
8895 }
@@ -103,6 +110,9 @@ struct WritableStreamSinkJsAdapter::Active final {
103110 });
104111 bool taskFailed = false ;
105112 try {
113+ KJ_IF_SOME (lock, task->maybeOutputLock ) {
114+ co_await lock;
115+ }
106116 co_await task->task ();
107117 task->fulfiller ->fulfill ();
108118 } catch (...) {
0 commit comments