Skip to content

Commit

Permalink
Avoid sending a new chunk when the body is already done
Browse files Browse the repository at this point in the history
As discussed in servo#26807 (comment), we'd like to
add a new flag, `in_memory_done`, to `TransmitBodyConnectHandler` so
that we can correctly finish and drop the sender correctly.

When we send the bytes, we will mark the body as done and we can
recognize it's already done in next tick so that we can send a Done
request to finish the sender.
  • Loading branch information
CYBAI committed Jun 7, 2020
1 parent 2af7dd8 commit 4835422
Showing 1 changed file with 12 additions and 1 deletion.
13 changes: 12 additions & 1 deletion components/script/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ use js::typedarray::{ArrayBuffer, CreateWith};
use mime::{self, Mime};
use net_traits::request::{BodyChunkRequest, BodySource as NetBodySource, RequestBody};
use script_traits::serializable::BlobImpl;
use std::cell::Cell;
use std::ptr;
use std::rc::Rc;
use std::str;
Expand Down Expand Up @@ -72,6 +73,7 @@ struct TransmitBodyConnectHandler {
bytes_sender: Option<IpcSender<Vec<u8>>>,
control_sender: IpcSender<BodyChunkRequest>,
in_memory: Option<Vec<u8>>,
in_memory_done: Cell<bool>,
source: BodySource,
}

Expand All @@ -91,6 +93,7 @@ impl TransmitBodyConnectHandler {
bytes_sender: None,
control_sender,
in_memory,
in_memory_done: Cell::new(false),
source,
}
}
Expand Down Expand Up @@ -155,6 +158,12 @@ impl TransmitBodyConnectHandler {

/// The entry point to <https://fetch.spec.whatwg.org/#concept-request-transmit-body>
fn transmit_body_chunk(&mut self) {
if self.in_memory_done.get() {
// Step 5.1.3
let _ = self.control_sender.send(BodyChunkRequest::Done);
return;
}

let stream = self.stream.clone();
let control_sender = self.control_sender.clone();
let bytes_sender = self
Expand All @@ -165,7 +174,9 @@ impl TransmitBodyConnectHandler {
// In case of the data being in-memory, send everything in one chunk, by-passing SpiderMonkey.
if let Some(bytes) = self.in_memory.clone() {
let _ = bytes_sender.send(bytes);
let _ = control_sender.send(BodyChunkRequest::Done);
// Mark this body as `done` so that we can correctly make it as Done in next tick
// and we won't leave this stream too early
self.in_memory_done.set(true);
return;
}

Expand Down

0 comments on commit 4835422

Please sign in to comment.