mirror of
https://github.com/servo/servo.git
synced 2025-07-22 23:03:42 +01:00
Propagate CanGc when interacting with readable streams. (#33975)
Signed-off-by: Josh Matthews <josh@joshmatthews.net>
This commit is contained in:
parent
f553bda7eb
commit
12e6ec25aa
10 changed files with 80 additions and 57 deletions
|
@ -438,21 +438,21 @@ impl ExtractedBody {
|
||||||
|
|
||||||
/// <https://fetch.spec.whatwg.org/#concept-bodyinit-extract>
|
/// <https://fetch.spec.whatwg.org/#concept-bodyinit-extract>
|
||||||
pub trait Extractable {
|
pub trait Extractable {
|
||||||
fn extract(&self, global: &GlobalScope) -> Fallible<ExtractedBody>;
|
fn extract(&self, global: &GlobalScope, can_gc: CanGc) -> Fallible<ExtractedBody>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Extractable for BodyInit {
|
impl Extractable for BodyInit {
|
||||||
// https://fetch.spec.whatwg.org/#concept-bodyinit-extract
|
// https://fetch.spec.whatwg.org/#concept-bodyinit-extract
|
||||||
fn extract(&self, global: &GlobalScope) -> Fallible<ExtractedBody> {
|
fn extract(&self, global: &GlobalScope, can_gc: CanGc) -> Fallible<ExtractedBody> {
|
||||||
match self {
|
match self {
|
||||||
BodyInit::String(ref s) => s.extract(global),
|
BodyInit::String(ref s) => s.extract(global, can_gc),
|
||||||
BodyInit::URLSearchParams(ref usp) => usp.extract(global),
|
BodyInit::URLSearchParams(ref usp) => usp.extract(global, can_gc),
|
||||||
BodyInit::Blob(ref b) => b.extract(global),
|
BodyInit::Blob(ref b) => b.extract(global, can_gc),
|
||||||
BodyInit::FormData(ref formdata) => formdata.extract(global),
|
BodyInit::FormData(ref formdata) => formdata.extract(global, can_gc),
|
||||||
BodyInit::ArrayBuffer(ref typedarray) => {
|
BodyInit::ArrayBuffer(ref typedarray) => {
|
||||||
let bytes = typedarray.to_vec();
|
let bytes = typedarray.to_vec();
|
||||||
let total_bytes = bytes.len();
|
let total_bytes = bytes.len();
|
||||||
let stream = ReadableStream::new_from_bytes(global, bytes);
|
let stream = ReadableStream::new_from_bytes(global, bytes, can_gc);
|
||||||
Ok(ExtractedBody {
|
Ok(ExtractedBody {
|
||||||
stream,
|
stream,
|
||||||
total_bytes: Some(total_bytes),
|
total_bytes: Some(total_bytes),
|
||||||
|
@ -463,7 +463,7 @@ impl Extractable for BodyInit {
|
||||||
BodyInit::ArrayBufferView(ref typedarray) => {
|
BodyInit::ArrayBufferView(ref typedarray) => {
|
||||||
let bytes = typedarray.to_vec();
|
let bytes = typedarray.to_vec();
|
||||||
let total_bytes = bytes.len();
|
let total_bytes = bytes.len();
|
||||||
let stream = ReadableStream::new_from_bytes(global, bytes);
|
let stream = ReadableStream::new_from_bytes(global, bytes, can_gc);
|
||||||
Ok(ExtractedBody {
|
Ok(ExtractedBody {
|
||||||
stream,
|
stream,
|
||||||
total_bytes: Some(total_bytes),
|
total_bytes: Some(total_bytes),
|
||||||
|
@ -493,10 +493,10 @@ impl Extractable for BodyInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Extractable for Vec<u8> {
|
impl Extractable for Vec<u8> {
|
||||||
fn extract(&self, global: &GlobalScope) -> Fallible<ExtractedBody> {
|
fn extract(&self, global: &GlobalScope, can_gc: CanGc) -> Fallible<ExtractedBody> {
|
||||||
let bytes = self.clone();
|
let bytes = self.clone();
|
||||||
let total_bytes = self.len();
|
let total_bytes = self.len();
|
||||||
let stream = ReadableStream::new_from_bytes(global, bytes);
|
let stream = ReadableStream::new_from_bytes(global, bytes, can_gc);
|
||||||
Ok(ExtractedBody {
|
Ok(ExtractedBody {
|
||||||
stream,
|
stream,
|
||||||
total_bytes: Some(total_bytes),
|
total_bytes: Some(total_bytes),
|
||||||
|
@ -508,7 +508,7 @@ impl Extractable for Vec<u8> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Extractable for Blob {
|
impl Extractable for Blob {
|
||||||
fn extract(&self, _global: &GlobalScope) -> Fallible<ExtractedBody> {
|
fn extract(&self, _global: &GlobalScope, can_gc: CanGc) -> Fallible<ExtractedBody> {
|
||||||
let blob_type = self.Type();
|
let blob_type = self.Type();
|
||||||
let content_type = if blob_type.as_ref().is_empty() {
|
let content_type = if blob_type.as_ref().is_empty() {
|
||||||
None
|
None
|
||||||
|
@ -517,7 +517,7 @@ impl Extractable for Blob {
|
||||||
};
|
};
|
||||||
let total_bytes = self.Size() as usize;
|
let total_bytes = self.Size() as usize;
|
||||||
Ok(ExtractedBody {
|
Ok(ExtractedBody {
|
||||||
stream: self.get_stream(),
|
stream: self.get_stream(can_gc),
|
||||||
total_bytes: Some(total_bytes),
|
total_bytes: Some(total_bytes),
|
||||||
content_type,
|
content_type,
|
||||||
source: BodySource::Object,
|
source: BodySource::Object,
|
||||||
|
@ -526,11 +526,11 @@ impl Extractable for Blob {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Extractable for DOMString {
|
impl Extractable for DOMString {
|
||||||
fn extract(&self, global: &GlobalScope) -> Fallible<ExtractedBody> {
|
fn extract(&self, global: &GlobalScope, can_gc: CanGc) -> Fallible<ExtractedBody> {
|
||||||
let bytes = self.as_bytes().to_owned();
|
let bytes = self.as_bytes().to_owned();
|
||||||
let total_bytes = bytes.len();
|
let total_bytes = bytes.len();
|
||||||
let content_type = Some(DOMString::from("text/plain;charset=UTF-8"));
|
let content_type = Some(DOMString::from("text/plain;charset=UTF-8"));
|
||||||
let stream = ReadableStream::new_from_bytes(global, bytes);
|
let stream = ReadableStream::new_from_bytes(global, bytes, can_gc);
|
||||||
Ok(ExtractedBody {
|
Ok(ExtractedBody {
|
||||||
stream,
|
stream,
|
||||||
total_bytes: Some(total_bytes),
|
total_bytes: Some(total_bytes),
|
||||||
|
@ -541,7 +541,7 @@ impl Extractable for DOMString {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Extractable for FormData {
|
impl Extractable for FormData {
|
||||||
fn extract(&self, global: &GlobalScope) -> Fallible<ExtractedBody> {
|
fn extract(&self, global: &GlobalScope, can_gc: CanGc) -> Fallible<ExtractedBody> {
|
||||||
let boundary = generate_boundary();
|
let boundary = generate_boundary();
|
||||||
let bytes = encode_multipart_form_data(&mut self.datums(), boundary.clone(), UTF_8);
|
let bytes = encode_multipart_form_data(&mut self.datums(), boundary.clone(), UTF_8);
|
||||||
let total_bytes = bytes.len();
|
let total_bytes = bytes.len();
|
||||||
|
@ -549,7 +549,7 @@ impl Extractable for FormData {
|
||||||
"multipart/form-data;boundary={}",
|
"multipart/form-data;boundary={}",
|
||||||
boundary
|
boundary
|
||||||
)));
|
)));
|
||||||
let stream = ReadableStream::new_from_bytes(global, bytes);
|
let stream = ReadableStream::new_from_bytes(global, bytes, can_gc);
|
||||||
Ok(ExtractedBody {
|
Ok(ExtractedBody {
|
||||||
stream,
|
stream,
|
||||||
total_bytes: Some(total_bytes),
|
total_bytes: Some(total_bytes),
|
||||||
|
@ -560,13 +560,13 @@ impl Extractable for FormData {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Extractable for URLSearchParams {
|
impl Extractable for URLSearchParams {
|
||||||
fn extract(&self, global: &GlobalScope) -> Fallible<ExtractedBody> {
|
fn extract(&self, global: &GlobalScope, can_gc: CanGc) -> Fallible<ExtractedBody> {
|
||||||
let bytes = self.serialize_utf8().into_bytes();
|
let bytes = self.serialize_utf8().into_bytes();
|
||||||
let total_bytes = bytes.len();
|
let total_bytes = bytes.len();
|
||||||
let content_type = Some(DOMString::from(
|
let content_type = Some(DOMString::from(
|
||||||
"application/x-www-form-urlencoded;charset=UTF-8",
|
"application/x-www-form-urlencoded;charset=UTF-8",
|
||||||
));
|
));
|
||||||
let stream = ReadableStream::new_from_bytes(global, bytes);
|
let stream = ReadableStream::new_from_bytes(global, bytes, can_gc);
|
||||||
Ok(ExtractedBody {
|
Ok(ExtractedBody {
|
||||||
stream,
|
stream,
|
||||||
total_bytes: Some(total_bytes),
|
total_bytes: Some(total_bytes),
|
||||||
|
@ -756,7 +756,7 @@ fn consume_body_with_promise<T: BodyMixin + DomObject>(
|
||||||
// Step 2.
|
// Step 2.
|
||||||
let stream = match object.body() {
|
let stream = match object.body() {
|
||||||
Some(stream) => stream,
|
Some(stream) => stream,
|
||||||
None => ReadableStream::new_from_bytes(&global, Vec::with_capacity(0)),
|
None => ReadableStream::new_from_bytes(&global, Vec::with_capacity(0), can_gc),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Step 3.
|
// Step 3.
|
||||||
|
|
|
@ -30,7 +30,7 @@ DOMInterfaces = {
|
||||||
|
|
||||||
'Blob': {
|
'Blob': {
|
||||||
'weakReferenceable': True,
|
'weakReferenceable': True,
|
||||||
'canGc': ['Slice', 'Text', 'ArrayBuffer'],
|
'canGc': ['Slice', 'Text', 'ArrayBuffer', 'Stream'],
|
||||||
},
|
},
|
||||||
|
|
||||||
'Bluetooth': {
|
'Bluetooth': {
|
||||||
|
|
|
@ -86,8 +86,8 @@ impl Blob {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://w3c.github.io/FileAPI/#blob-get-stream>
|
/// <https://w3c.github.io/FileAPI/#blob-get-stream>
|
||||||
pub fn get_stream(&self) -> DomRoot<ReadableStream> {
|
pub fn get_stream(&self, can_gc: CanGc) -> DomRoot<ReadableStream> {
|
||||||
self.global().get_blob_stream(&self.blob_id)
|
self.global().get_blob_stream(&self.blob_id, can_gc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,8 +237,8 @@ impl BlobMethods for Blob {
|
||||||
}
|
}
|
||||||
|
|
||||||
// <https://w3c.github.io/FileAPI/#blob-get-stream>
|
// <https://w3c.github.io/FileAPI/#blob-get-stream>
|
||||||
fn Stream(&self, _cx: JSContext) -> NonNull<JSObject> {
|
fn Stream(&self, _cx: JSContext, can_gc: CanGc) -> NonNull<JSObject> {
|
||||||
self.get_stream().get_js_stream()
|
self.get_stream(can_gc).get_js_stream()
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/FileAPI/#slice-method-algo
|
// https://w3c.github.io/FileAPI/#slice-method-algo
|
||||||
|
|
|
@ -617,10 +617,10 @@ impl MessageListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Callback used to enqueue file chunks to streams as part of FileListener.
|
/// Callback used to enqueue file chunks to streams as part of FileListener.
|
||||||
fn stream_handle_incoming(stream: &ReadableStream, bytes: Fallible<Vec<u8>>) {
|
fn stream_handle_incoming(stream: &ReadableStream, bytes: Fallible<Vec<u8>>, can_gc: CanGc) {
|
||||||
match bytes {
|
match bytes {
|
||||||
Ok(b) => {
|
Ok(b) => {
|
||||||
stream.enqueue_native(b);
|
stream.enqueue_native(b, can_gc);
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
stream.error_native(e);
|
stream.error_native(e);
|
||||||
|
@ -643,7 +643,7 @@ impl FileListener {
|
||||||
|
|
||||||
let task = task!(enqueue_stream_chunk: move || {
|
let task = task!(enqueue_stream_chunk: move || {
|
||||||
let stream = trusted.root();
|
let stream = trusted.root();
|
||||||
stream_handle_incoming(&stream, Ok(blob_buf.bytes));
|
stream_handle_incoming(&stream, Ok(blob_buf.bytes), CanGc::note());
|
||||||
});
|
});
|
||||||
|
|
||||||
let _ = self
|
let _ = self
|
||||||
|
@ -667,7 +667,7 @@ impl FileListener {
|
||||||
|
|
||||||
let task = task!(enqueue_stream_chunk: move || {
|
let task = task!(enqueue_stream_chunk: move || {
|
||||||
let stream = trusted.root();
|
let stream = trusted.root();
|
||||||
stream_handle_incoming(&stream, Ok(bytes_in));
|
stream_handle_incoming(&stream, Ok(bytes_in), CanGc::note());
|
||||||
});
|
});
|
||||||
|
|
||||||
let _ = self
|
let _ = self
|
||||||
|
@ -733,7 +733,7 @@ impl FileListener {
|
||||||
let _ = self.task_source.queue_with_canceller(
|
let _ = self.task_source.queue_with_canceller(
|
||||||
task!(error_stream: move || {
|
task!(error_stream: move || {
|
||||||
let stream = trusted_stream.root();
|
let stream = trusted_stream.root();
|
||||||
stream_handle_incoming(&stream, error);
|
stream_handle_incoming(&stream, error, CanGc::note());
|
||||||
}),
|
}),
|
||||||
&self.task_canceller,
|
&self.task_canceller,
|
||||||
);
|
);
|
||||||
|
@ -1988,11 +1988,11 @@ impl GlobalScope {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://w3c.github.io/FileAPI/#blob-get-stream>
|
/// <https://w3c.github.io/FileAPI/#blob-get-stream>
|
||||||
pub fn get_blob_stream(&self, blob_id: &BlobId) -> DomRoot<ReadableStream> {
|
pub fn get_blob_stream(&self, blob_id: &BlobId, can_gc: CanGc) -> DomRoot<ReadableStream> {
|
||||||
let (file_id, size) = match self.get_blob_bytes_or_file_id(blob_id) {
|
let (file_id, size) = match self.get_blob_bytes_or_file_id(blob_id) {
|
||||||
BlobResult::Bytes(bytes) => {
|
BlobResult::Bytes(bytes) => {
|
||||||
// If we have all the bytes in memory, queue them and close the stream.
|
// If we have all the bytes in memory, queue them and close the stream.
|
||||||
let stream = ReadableStream::new_from_bytes(self, bytes);
|
let stream = ReadableStream::new_from_bytes(self, bytes, can_gc);
|
||||||
return stream;
|
return stream;
|
||||||
},
|
},
|
||||||
BlobResult::File(id, size) => (id, size),
|
BlobResult::File(id, size) => (id, size),
|
||||||
|
|
|
@ -870,6 +870,7 @@ impl HTMLFormElement {
|
||||||
enctype,
|
enctype,
|
||||||
encoding,
|
encoding,
|
||||||
target_window,
|
target_window,
|
||||||
|
can_gc,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
// https://html.spec.whatwg.org/multipage/#submit-get-action
|
// https://html.spec.whatwg.org/multipage/#submit-get-action
|
||||||
|
@ -920,6 +921,7 @@ impl HTMLFormElement {
|
||||||
enctype: FormEncType,
|
enctype: FormEncType,
|
||||||
encoding: &'static Encoding,
|
encoding: &'static Encoding,
|
||||||
target: &Window,
|
target: &Window,
|
||||||
|
can_gc: CanGc,
|
||||||
) {
|
) {
|
||||||
let boundary = generate_boundary();
|
let boundary = generate_boundary();
|
||||||
let bytes = match enctype {
|
let bytes = match enctype {
|
||||||
|
@ -957,7 +959,7 @@ impl HTMLFormElement {
|
||||||
let global = self.global();
|
let global = self.global();
|
||||||
|
|
||||||
let request_body = bytes
|
let request_body = bytes
|
||||||
.extract(&global)
|
.extract(&global, can_gc)
|
||||||
.expect("Couldn't extract body.")
|
.expect("Couldn't extract body.")
|
||||||
.into_net_request_body()
|
.into_net_request_body()
|
||||||
.0;
|
.0;
|
||||||
|
|
|
@ -34,7 +34,7 @@ use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::promise::Promise;
|
use crate::dom::promise::Promise;
|
||||||
use crate::js::conversions::FromJSValConvertible;
|
use crate::js::conversions::FromJSValConvertible;
|
||||||
use crate::realms::{enter_realm, InRealm};
|
use crate::realms::{enter_realm, InRealm};
|
||||||
use crate::script_runtime::JSContext as SafeJSContext;
|
use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
|
||||||
|
|
||||||
static UNDERLYING_SOURCE_TRAPS: ReadableStreamUnderlyingSourceTraps =
|
static UNDERLYING_SOURCE_TRAPS: ReadableStreamUnderlyingSourceTraps =
|
||||||
ReadableStreamUnderlyingSourceTraps {
|
ReadableStreamUnderlyingSourceTraps {
|
||||||
|
@ -101,12 +101,16 @@ impl ReadableStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build a stream backed by a Rust source that has already been read into memory.
|
/// Build a stream backed by a Rust source that has already been read into memory.
|
||||||
pub fn new_from_bytes(global: &GlobalScope, bytes: Vec<u8>) -> DomRoot<ReadableStream> {
|
pub fn new_from_bytes(
|
||||||
|
global: &GlobalScope,
|
||||||
|
bytes: Vec<u8>,
|
||||||
|
can_gc: CanGc,
|
||||||
|
) -> DomRoot<ReadableStream> {
|
||||||
let stream = ReadableStream::new_with_external_underlying_source(
|
let stream = ReadableStream::new_with_external_underlying_source(
|
||||||
global,
|
global,
|
||||||
ExternalUnderlyingSource::Memory(bytes.len()),
|
ExternalUnderlyingSource::Memory(bytes.len()),
|
||||||
);
|
);
|
||||||
stream.enqueue_native(bytes);
|
stream.enqueue_native(bytes, can_gc);
|
||||||
stream.close_native();
|
stream.close_native();
|
||||||
stream
|
stream
|
||||||
}
|
}
|
||||||
|
@ -153,7 +157,7 @@ impl ReadableStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
pub fn enqueue_native(&self, bytes: Vec<u8>) {
|
pub fn enqueue_native(&self, bytes: Vec<u8>, can_gc: CanGc) {
|
||||||
let global = self.global();
|
let global = self.global();
|
||||||
let _ar = enter_realm(&*global);
|
let _ar = enter_realm(&*global);
|
||||||
let cx = GlobalScope::get_cx();
|
let cx = GlobalScope::get_cx();
|
||||||
|
@ -163,7 +167,7 @@ impl ReadableStream {
|
||||||
self.external_underlying_source
|
self.external_underlying_source
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("No external source to enqueue bytes.")
|
.expect("No external source to enqueue bytes.")
|
||||||
.enqueue_chunk(cx, handle, bytes);
|
.enqueue_chunk(cx, handle, bytes, can_gc);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
|
@ -324,7 +328,12 @@ unsafe extern "C" fn request_data(
|
||||||
desired_size: usize,
|
desired_size: usize,
|
||||||
) {
|
) {
|
||||||
let source = &*(source as *const ExternalUnderlyingSourceController);
|
let source = &*(source as *const ExternalUnderlyingSourceController);
|
||||||
source.pull(SafeJSContext::from_ptr(cx), stream, desired_size);
|
source.pull(
|
||||||
|
SafeJSContext::from_ptr(cx),
|
||||||
|
stream,
|
||||||
|
desired_size,
|
||||||
|
CanGc::note(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
|
@ -427,12 +436,15 @@ impl ExternalUnderlyingSourceController {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signal available bytes if the stream is currently readable.
|
/// Signal available bytes if the stream is currently readable.
|
||||||
|
/// The apparently unused CanGc argument represents that the JS API calls like
|
||||||
|
/// `ReadableStreamUpdateDataAvailableFromSource` can trigger a GC.
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
fn maybe_signal_available_bytes(
|
fn maybe_signal_available_bytes(
|
||||||
&self,
|
&self,
|
||||||
cx: SafeJSContext,
|
cx: SafeJSContext,
|
||||||
stream: HandleObject,
|
stream: HandleObject,
|
||||||
available: usize,
|
available: usize,
|
||||||
|
_can_gc: CanGc,
|
||||||
) {
|
) {
|
||||||
if available == 0 {
|
if available == 0 {
|
||||||
return;
|
return;
|
||||||
|
@ -467,17 +479,23 @@ impl ExternalUnderlyingSourceController {
|
||||||
self.maybe_close_js_stream(cx, stream);
|
self.maybe_close_js_stream(cx, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enqueue_chunk(&self, cx: SafeJSContext, stream: HandleObject, mut chunk: Vec<u8>) {
|
fn enqueue_chunk(
|
||||||
|
&self,
|
||||||
|
cx: SafeJSContext,
|
||||||
|
stream: HandleObject,
|
||||||
|
mut chunk: Vec<u8>,
|
||||||
|
can_gc: CanGc,
|
||||||
|
) {
|
||||||
let available = {
|
let available = {
|
||||||
let mut buffer = self.buffer.borrow_mut();
|
let mut buffer = self.buffer.borrow_mut();
|
||||||
buffer.append(&mut chunk);
|
buffer.append(&mut chunk);
|
||||||
buffer.len()
|
buffer.len()
|
||||||
};
|
};
|
||||||
self.maybe_signal_available_bytes(cx, stream, available);
|
self.maybe_signal_available_bytes(cx, stream, available, can_gc);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
fn pull(&self, cx: SafeJSContext, stream: HandleObject, _desired_size: usize) {
|
fn pull(&self, cx: SafeJSContext, stream: HandleObject, _desired_size: usize, can_gc: CanGc) {
|
||||||
// Note: for pull sources,
|
// Note: for pull sources,
|
||||||
// this would be the time to ask for a chunk.
|
// this would be the time to ask for a chunk.
|
||||||
|
|
||||||
|
@ -490,7 +508,7 @@ impl ExternalUnderlyingSourceController {
|
||||||
buffer.len()
|
buffer.len()
|
||||||
};
|
};
|
||||||
|
|
||||||
self.maybe_signal_available_bytes(cx, stream, available);
|
self.maybe_signal_available_bytes(cx, stream, available, can_gc);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_chunk_with_length(&self, length: usize) -> Vec<u8> {
|
fn get_chunk_with_length(&self, length: usize) -> Vec<u8> {
|
||||||
|
|
|
@ -477,7 +477,7 @@ impl RequestMethods for Request {
|
||||||
// Step 37.1 TODO "If init["keepalive"] exists and is true..."
|
// Step 37.1 TODO "If init["keepalive"] exists and is true..."
|
||||||
|
|
||||||
// Step 37.2
|
// Step 37.2
|
||||||
let mut extracted_body = init_body.extract(global)?;
|
let mut extracted_body = init_body.extract(global, can_gc)?;
|
||||||
|
|
||||||
// Step 37.3
|
// Step 37.3
|
||||||
if let Some(contents) = extracted_body.content_type.take() {
|
if let Some(contents) = extracted_body.content_type.take() {
|
||||||
|
|
|
@ -190,7 +190,7 @@ impl ResponseMethods for Response {
|
||||||
total_bytes: _,
|
total_bytes: _,
|
||||||
content_type,
|
content_type,
|
||||||
source: _,
|
source: _,
|
||||||
} = body.extract(global)?;
|
} = body.extract(global, can_gc)?;
|
||||||
|
|
||||||
r.body_stream.set(Some(&*stream));
|
r.body_stream.set(Some(&*stream));
|
||||||
|
|
||||||
|
@ -210,7 +210,7 @@ impl ResponseMethods for Response {
|
||||||
} else {
|
} else {
|
||||||
// Reset FetchResponse to an in-memory stream with empty byte sequence here for
|
// Reset FetchResponse to an in-memory stream with empty byte sequence here for
|
||||||
// no-init-body case
|
// no-init-body case
|
||||||
let stream = ReadableStream::new_from_bytes(global, Vec::with_capacity(0));
|
let stream = ReadableStream::new_from_bytes(global, Vec::with_capacity(0), can_gc);
|
||||||
r.body_stream.set(Some(&*stream));
|
r.body_stream.set(Some(&*stream));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,12 +444,12 @@ impl Response {
|
||||||
*self.stream_consumer.borrow_mut() = sc;
|
*self.stream_consumer.borrow_mut() = sc;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stream_chunk(&self, chunk: Vec<u8>) {
|
pub fn stream_chunk(&self, chunk: Vec<u8>, can_gc: CanGc) {
|
||||||
// Note, are these two actually mutually exclusive?
|
// Note, are these two actually mutually exclusive?
|
||||||
if let Some(stream_consumer) = self.stream_consumer.borrow_mut().as_ref() {
|
if let Some(stream_consumer) = self.stream_consumer.borrow_mut().as_ref() {
|
||||||
stream_consumer.consume_chunk(chunk.as_slice());
|
stream_consumer.consume_chunk(chunk.as_slice());
|
||||||
} else if let Some(body) = self.body_stream.get() {
|
} else if let Some(body) = self.body_stream.get() {
|
||||||
body.enqueue_native(chunk);
|
body.enqueue_native(chunk, can_gc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -576,7 +576,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
|
||||||
};
|
};
|
||||||
let total_bytes = bytes.len();
|
let total_bytes = bytes.len();
|
||||||
let global = self.global();
|
let global = self.global();
|
||||||
let stream = ReadableStream::new_from_bytes(&global, bytes);
|
let stream = ReadableStream::new_from_bytes(&global, bytes, can_gc);
|
||||||
Some(ExtractedBody {
|
Some(ExtractedBody {
|
||||||
stream,
|
stream,
|
||||||
total_bytes: Some(total_bytes),
|
total_bytes: Some(total_bytes),
|
||||||
|
@ -585,7 +585,9 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
Some(DocumentOrXMLHttpRequestBodyInit::Blob(ref b)) => {
|
Some(DocumentOrXMLHttpRequestBodyInit::Blob(ref b)) => {
|
||||||
let extracted_body = b.extract(&self.global()).expect("Couldn't extract body.");
|
let extracted_body = b
|
||||||
|
.extract(&self.global(), can_gc)
|
||||||
|
.expect("Couldn't extract body.");
|
||||||
if !extracted_body.in_memory() && self.sync.get() {
|
if !extracted_body.in_memory() && self.sync.get() {
|
||||||
warn!("Sync XHR with not in-memory Blob as body not supported");
|
warn!("Sync XHR with not in-memory Blob as body not supported");
|
||||||
None
|
None
|
||||||
|
@ -595,22 +597,23 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
|
||||||
},
|
},
|
||||||
Some(DocumentOrXMLHttpRequestBodyInit::FormData(ref formdata)) => Some(
|
Some(DocumentOrXMLHttpRequestBodyInit::FormData(ref formdata)) => Some(
|
||||||
formdata
|
formdata
|
||||||
.extract(&self.global())
|
.extract(&self.global(), can_gc)
|
||||||
|
.expect("Couldn't extract body."),
|
||||||
|
),
|
||||||
|
Some(DocumentOrXMLHttpRequestBodyInit::String(ref str)) => Some(
|
||||||
|
str.extract(&self.global(), can_gc)
|
||||||
.expect("Couldn't extract body."),
|
.expect("Couldn't extract body."),
|
||||||
),
|
),
|
||||||
Some(DocumentOrXMLHttpRequestBodyInit::String(ref str)) => {
|
|
||||||
Some(str.extract(&self.global()).expect("Couldn't extract body."))
|
|
||||||
},
|
|
||||||
Some(DocumentOrXMLHttpRequestBodyInit::URLSearchParams(ref urlsp)) => Some(
|
Some(DocumentOrXMLHttpRequestBodyInit::URLSearchParams(ref urlsp)) => Some(
|
||||||
urlsp
|
urlsp
|
||||||
.extract(&self.global())
|
.extract(&self.global(), can_gc)
|
||||||
.expect("Couldn't extract body."),
|
.expect("Couldn't extract body."),
|
||||||
),
|
),
|
||||||
Some(DocumentOrXMLHttpRequestBodyInit::ArrayBuffer(ref typedarray)) => {
|
Some(DocumentOrXMLHttpRequestBodyInit::ArrayBuffer(ref typedarray)) => {
|
||||||
let bytes = typedarray.to_vec();
|
let bytes = typedarray.to_vec();
|
||||||
let total_bytes = bytes.len();
|
let total_bytes = bytes.len();
|
||||||
let global = self.global();
|
let global = self.global();
|
||||||
let stream = ReadableStream::new_from_bytes(&global, bytes);
|
let stream = ReadableStream::new_from_bytes(&global, bytes, can_gc);
|
||||||
Some(ExtractedBody {
|
Some(ExtractedBody {
|
||||||
stream,
|
stream,
|
||||||
total_bytes: Some(total_bytes),
|
total_bytes: Some(total_bytes),
|
||||||
|
@ -622,7 +625,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
|
||||||
let bytes = typedarray.to_vec();
|
let bytes = typedarray.to_vec();
|
||||||
let total_bytes = bytes.len();
|
let total_bytes = bytes.len();
|
||||||
let global = self.global();
|
let global = self.global();
|
||||||
let stream = ReadableStream::new_from_bytes(&global, bytes);
|
let stream = ReadableStream::new_from_bytes(&global, bytes, can_gc);
|
||||||
Some(ExtractedBody {
|
Some(ExtractedBody {
|
||||||
stream,
|
stream,
|
||||||
total_bytes: Some(total_bytes),
|
total_bytes: Some(total_bytes),
|
||||||
|
|
|
@ -277,7 +277,7 @@ impl FetchResponseListener for FetchContext {
|
||||||
|
|
||||||
fn process_response_chunk(&mut self, _: RequestId, chunk: Vec<u8>) {
|
fn process_response_chunk(&mut self, _: RequestId, chunk: Vec<u8>) {
|
||||||
let response = self.response_object.root();
|
let response = self.response_object.root();
|
||||||
response.stream_chunk(chunk);
|
response.stream_chunk(chunk, CanGc::note());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_response_eof(
|
fn process_response_eof(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue