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

View file

@ -55,7 +55,7 @@ pub enum BodySource {
Null, Null,
/// Another Dom object as source, /// Another Dom object as source,
/// TODO: store the actual object /// TODO: store the actual object
/// and re-exctact a stream on re-direct. /// and re-extract a stream on re-direct.
Object, Object,
} }
@ -72,6 +72,7 @@ struct TransmitBodyConnectHandler {
bytes_sender: Option<IpcSender<Vec<u8>>>, bytes_sender: Option<IpcSender<Vec<u8>>>,
control_sender: IpcSender<BodyChunkRequest>, control_sender: IpcSender<BodyChunkRequest>,
in_memory: Option<Vec<u8>>, in_memory: Option<Vec<u8>>,
in_memory_done: bool,
source: BodySource, source: BodySource,
} }
@ -91,14 +92,22 @@ impl TransmitBodyConnectHandler {
bytes_sender: None, bytes_sender: None,
control_sender, control_sender,
in_memory, in_memory,
in_memory_done: false,
source, 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. /// 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. /// 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(); let mut body_handler = self.clone();
body_handler.reset_in_memory_done();
ROUTER.add_route( ROUTER.add_route(
chunk_request_receiver.to_opaque(), chunk_request_receiver.to_opaque(),
@ -126,11 +135,20 @@ impl TransmitBodyConnectHandler {
/// TODO: this method should be deprecated /// TODO: this method should be deprecated
/// in favor of making `re_extract` actually re-extract a stream from the source. /// in favor of making `re_extract` actually re-extract a stream from the source.
/// See #26686 /// 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 { if let BodySource::Null = self.source {
panic!("ReadableStream(Null) sources should not re-direct."); panic!("ReadableStream(Null) sources should not re-direct.");
} }
if let Some(bytes) = self.in_memory.clone() { 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 let _ = self
.bytes_sender .bytes_sender
.as_ref() .as_ref()
@ -155,6 +173,12 @@ impl TransmitBodyConnectHandler {
/// The entry point to <https://fetch.spec.whatwg.org/#concept-request-transmit-body> /// The entry point to <https://fetch.spec.whatwg.org/#concept-request-transmit-body>
fn transmit_body_chunk(&mut self) { 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 stream = self.stream.clone();
let control_sender = self.control_sender.clone(); let control_sender = self.control_sender.clone();
let bytes_sender = self 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. // In case of the data being in-memory, send everything in one chunk, by-passing SpiderMonkey.
if let Some(bytes) = self.in_memory.clone() { if let Some(bytes) = self.in_memory.clone() {
let _ = bytes_sender.send(bytes); 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; return;
} }

View file

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