Auto merge of #26810 - CYBAI:fix-infinite-stream, r=gterzian

Fix infinite stream and its missing incumbent script environment when newing a new stream

---
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes fix #26807
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because ___
This commit is contained in:
bors-servo 2020-06-13 10:01:33 -04:00 committed by GitHub
commit 581ade575e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 9 deletions

View file

@ -117,7 +117,7 @@ pub enum ParserMetadata {
}
/// <https://fetch.spec.whatwg.org/#concept-body-source>
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
#[derive(Clone, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
pub enum BodySource {
Null,
Object,
@ -178,10 +178,7 @@ impl RequestBody {
}
pub fn source_is_null(&self) -> bool {
if let BodySource::Null = self.source {
return true;
}
false
self.source == BodySource::Null
}
pub fn len(&self) -> Option<usize> {

View file

@ -55,7 +55,7 @@ pub enum BodySource {
Null,
/// Another Dom object as source,
/// TODO: store the actual object
/// and re-exctact a stream on re-direct.
/// and re-extract a stream on re-direct.
Object,
}
@ -72,6 +72,7 @@ struct TransmitBodyConnectHandler {
bytes_sender: Option<IpcSender<Vec<u8>>>,
control_sender: IpcSender<BodyChunkRequest>,
in_memory: Option<Vec<u8>>,
in_memory_done: bool,
source: BodySource,
}
@ -91,14 +92,22 @@ impl TransmitBodyConnectHandler {
bytes_sender: None,
control_sender,
in_memory,
in_memory_done: false,
source,
}
}
/// Reset `in_memory_done`, called when a stream is
/// re-extracted from the source to support a re-direct.
pub fn reset_in_memory_done(&mut self) {
self.in_memory_done = false;
}
/// Re-extract the source to support streaming it again for a re-direct.
/// TODO: actually re-extract the source, instead of just cloning data, to support Blob.
fn re_extract(&self, chunk_request_receiver: IpcReceiver<BodyChunkRequest>) {
fn re_extract(&mut self, chunk_request_receiver: IpcReceiver<BodyChunkRequest>) {
let mut body_handler = self.clone();
body_handler.reset_in_memory_done();
ROUTER.add_route(
chunk_request_receiver.to_opaque(),
@ -126,11 +135,20 @@ impl TransmitBodyConnectHandler {
/// TODO: this method should be deprecated
/// in favor of making `re_extract` actually re-extract a stream from the source.
/// See #26686
fn transmit_source(&self) {
fn transmit_source(&mut self) {
if self.in_memory_done {
// Step 5.1.3
self.stop_reading();
return;
}
if let BodySource::Null = self.source {
panic!("ReadableStream(Null) sources should not re-direct.");
}
if let Some(bytes) = self.in_memory.clone() {
// The memoized bytes are sent so we mark it as done again
self.in_memory_done = true;
let _ = self
.bytes_sender
.as_ref()
@ -155,6 +173,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 {
// Step 5.1.3
self.stop_reading();
return;
}
let stream = self.stream.clone();
let control_sender = self.control_sender.clone();
let bytes_sender = self
@ -165,6 +189,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);
// Mark this body as `done` so that we can stop reading in the next tick,
// matching the behavior of the promise-based flow
self.in_memory_done = true;
return;
}

View file

@ -6,7 +6,7 @@ use crate::dom::bindings::conversions::{ConversionBehavior, ConversionResult};
use crate::dom::bindings::error::Error;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::settings_stack::AutoEntryScript;
use crate::dom::bindings::settings_stack::{AutoEntryScript, AutoIncumbentScript};
use crate::dom::bindings::utils::get_dictionary_property;
use crate::dom::globalscope::GlobalScope;
use crate::dom::promise::Promise;
@ -118,6 +118,7 @@ impl ReadableStream {
source: ExternalUnderlyingSource,
) -> DomRoot<ReadableStream> {
let _ar = enter_realm(global);
let _ais = AutoIncumbentScript::new(global);
let cx = global.get_cx();
let source = Rc::new(ExternalUnderlyingSourceController::new(source));