aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/xmlhttprequest.rs
diff options
context:
space:
mode:
authorGregory Terzian <gterzian@users.noreply.github.com>2020-02-29 11:59:10 +0800
committerGregory Terzian <gterzian@users.noreply.github.com>2020-06-04 11:38:35 +0800
commitbd5796c90b8e8e066a32e7da9cfa5251d1559046 (patch)
treeaa5ed3de6608b8046924ef6e8e8ad43b91cf81a7 /components/script/dom/xmlhttprequest.rs
parent0281acea955085aec01a4fc6da5f89f326a14842 (diff)
downloadservo-bd5796c90b8e8e066a32e7da9cfa5251d1559046.tar.gz
servo-bd5796c90b8e8e066a32e7da9cfa5251d1559046.zip
integrate readablestream with fetch and blob
Diffstat (limited to 'components/script/dom/xmlhttprequest.rs')
-rw-r--r--components/script/dom/xmlhttprequest.rs185
1 files changed, 89 insertions, 96 deletions
diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs
index 336d7a89f22..1bb0ebd60dd 100644
--- a/components/script/dom/xmlhttprequest.rs
+++ b/components/script/dom/xmlhttprequest.rs
@@ -2,11 +2,10 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+use crate::body::{Extractable, ExtractedBody};
use crate::document_loader::DocumentLoader;
use crate::dom::bindings::cell::DomRefCell;
-use crate::dom::bindings::codegen::Bindings::BlobBinding::BlobBinding::BlobMethods;
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
-use crate::dom::bindings::codegen::Bindings::XMLHttpRequestBinding::BodyInit;
use crate::dom::bindings::codegen::Bindings::XMLHttpRequestBinding::XMLHttpRequestMethods;
use crate::dom::bindings::codegen::Bindings::XMLHttpRequestBinding::XMLHttpRequestResponseType;
use crate::dom::bindings::codegen::UnionTypes::DocumentOrBodyInit;
@@ -22,15 +21,13 @@ use crate::dom::document::DocumentSource;
use crate::dom::document::{Document, HasBrowsingContext, IsHTMLDocument};
use crate::dom::event::{Event, EventBubbles, EventCancelable};
use crate::dom::eventtarget::EventTarget;
-use crate::dom::formdata::FormData;
use crate::dom::globalscope::GlobalScope;
use crate::dom::headers::is_forbidden_header_name;
-use crate::dom::htmlformelement::{encode_multipart_form_data, generate_boundary};
use crate::dom::node::Node;
use crate::dom::performanceresourcetiming::InitiatorType;
use crate::dom::progressevent::ProgressEvent;
+use crate::dom::readablestream::ReadableStream;
use crate::dom::servoparser::ServoParser;
-use crate::dom::urlsearchparams::URLSearchParams;
use crate::dom::window::Window;
use crate::dom::workerglobalscope::WorkerGlobalScope;
use crate::dom::xmlhttprequesteventtarget::XMLHttpRequestEventTarget;
@@ -58,7 +55,9 @@ use js::jsval::{JSVal, NullValue, UndefinedValue};
use js::rust::wrappers::JS_ParseJSON;
use js::typedarray::{ArrayBuffer, CreateWith};
use mime::{self, Mime, Name};
-use net_traits::request::{CredentialsMode, Destination, Referrer, RequestBuilder, RequestMode};
+use net_traits::request::{
+ BodySource, CredentialsMode, Destination, Referrer, RequestBuilder, RequestMode,
+};
use net_traits::trim_http_whitespace;
use net_traits::CoreResourceMsg::Fetch;
use net_traits::{FetchChannels, FetchMetadata, FilteredMetadata};
@@ -562,42 +561,96 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
_ => data,
};
// Step 4 (first half)
- let extracted_or_serialized = match data {
+ let mut extracted_or_serialized = match data {
Some(DocumentOrBodyInit::Document(ref doc)) => {
- let data = Vec::from(serialize_document(&doc)?.as_ref());
+ let bytes = Vec::from(serialize_document(&doc)?.as_ref());
let content_type = if doc.is_html_document() {
"text/html;charset=UTF-8"
} else {
"application/xml;charset=UTF-8"
};
- Some((data, Some(DOMString::from(content_type))))
+ let total_bytes = bytes.len();
+ let global = self.global();
+ let stream = ReadableStream::new_from_bytes(&global, bytes);
+ Some(ExtractedBody {
+ stream,
+ total_bytes: Some(total_bytes),
+ content_type: Some(DOMString::from(content_type)),
+ source: BodySource::Null,
+ })
+ },
+ Some(DocumentOrBodyInit::Blob(ref b)) => {
+ Some(b.extract(&self.global()).expect("Couldn't extract body."))
+ },
+ Some(DocumentOrBodyInit::FormData(ref formdata)) => Some(
+ formdata
+ .extract(&self.global())
+ .expect("Couldn't extract body."),
+ ),
+ Some(DocumentOrBodyInit::String(ref str)) => {
+ Some(str.extract(&self.global()).expect("Couldn't extract body."))
},
- Some(DocumentOrBodyInit::Blob(ref b)) => Some(b.extract()),
- Some(DocumentOrBodyInit::FormData(ref formdata)) => Some(formdata.extract()),
- Some(DocumentOrBodyInit::String(ref str)) => Some(str.extract()),
- Some(DocumentOrBodyInit::URLSearchParams(ref urlsp)) => Some(urlsp.extract()),
+ Some(DocumentOrBodyInit::URLSearchParams(ref urlsp)) => Some(
+ urlsp
+ .extract(&self.global())
+ .expect("Couldn't extract body."),
+ ),
Some(DocumentOrBodyInit::ArrayBuffer(ref typedarray)) => {
- Some((typedarray.to_vec(), None))
+ let bytes = typedarray.to_vec();
+ let total_bytes = bytes.len();
+ let global = self.global();
+ let stream = ReadableStream::new_from_bytes(&global, bytes);
+ Some(ExtractedBody {
+ stream,
+ total_bytes: Some(total_bytes),
+ content_type: None,
+ source: BodySource::BufferSource,
+ })
},
Some(DocumentOrBodyInit::ArrayBufferView(ref typedarray)) => {
- Some((typedarray.to_vec(), None))
+ let bytes = typedarray.to_vec();
+ let total_bytes = bytes.len();
+ let global = self.global();
+ let stream = ReadableStream::new_from_bytes(&global, bytes);
+ Some(ExtractedBody {
+ stream,
+ total_bytes: Some(total_bytes),
+ content_type: None,
+ source: BodySource::BufferSource,
+ })
+ },
+ Some(DocumentOrBodyInit::ReadableStream(ref stream)) => {
+ // TODO:
+ // 1. If the keepalive flag is set, then throw a TypeError.
+
+ if stream.is_locked() || stream.is_disturbed() {
+ return Err(Error::Type(
+ "The body's stream is disturbed or locked".to_string(),
+ ));
+ }
+
+ Some(ExtractedBody {
+ stream: stream.clone(),
+ total_bytes: None,
+ content_type: None,
+ source: BodySource::Null,
+ })
},
None => None,
};
- self.request_body_len
- .set(extracted_or_serialized.as_ref().map_or(0, |e| e.0.len()));
+ self.request_body_len.set(
+ extracted_or_serialized
+ .as_ref()
+ .map_or(0, |e| e.total_bytes.unwrap_or(0)),
+ );
// todo preserved headers?
// Step 6
self.upload_complete.set(false);
// Step 7
- self.upload_complete.set(match extracted_or_serialized {
- None => true,
- Some(ref e) if e.0.is_empty() => true,
- _ => false,
- });
+ self.upload_complete.set(extracted_or_serialized.is_none());
// Step 8
self.send_flag.set(true);
@@ -634,12 +687,17 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
unreachable!()
};
+ let content_type = match extracted_or_serialized.as_mut() {
+ Some(body) => body.content_type.take(),
+ None => None,
+ };
+
let mut request = RequestBuilder::new(self.request_url.borrow().clone().unwrap())
.method(self.request_method.borrow().clone())
.headers((*self.request_headers.borrow()).clone())
.unsafe_request(true)
// XXXManishearth figure out how to avoid this clone
- .body(extracted_or_serialized.as_ref().map(|e| e.0.clone()))
+ .body(extracted_or_serialized.map(|e| e.into_net_request_body().0))
// XXXManishearth actually "subresource", but it doesn't exist
// https://github.com/whatwg/xhr/issues/71
.destination(Destination::None)
@@ -658,8 +716,8 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
.pipeline_id(Some(self.global().pipeline_id()));
// step 4 (second half)
- match extracted_or_serialized {
- Some((_, ref content_type)) => {
+ match content_type {
+ Some(content_type) => {
let encoding = match data {
Some(DocumentOrBodyInit::String(_)) | Some(DocumentOrBodyInit::Document(_)) =>
// XHR spec differs from http, and says UTF-8 should be in capitals,
@@ -672,13 +730,12 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
};
let mut content_type_set = false;
- if let Some(ref ct) = *content_type {
- if !request.headers.contains_key(header::CONTENT_TYPE) {
- request
- .headers
- .insert(header::CONTENT_TYPE, HeaderValue::from_str(ct).unwrap());
- content_type_set = true;
- }
+ if !request.headers.contains_key(header::CONTENT_TYPE) {
+ request.headers.insert(
+ header::CONTENT_TYPE,
+ HeaderValue::from_str(&content_type).unwrap(),
+ );
+ content_type_set = true;
}
if !content_type_set {
@@ -1555,56 +1612,6 @@ impl XHRTimeoutCallback {
}
}
-pub trait Extractable {
- fn extract(&self) -> (Vec<u8>, Option<DOMString>);
-}
-
-impl Extractable for Blob {
- fn extract(&self) -> (Vec<u8>, Option<DOMString>) {
- let content_type = if self.Type().as_ref().is_empty() {
- None
- } else {
- Some(self.Type())
- };
- let bytes = self.get_bytes().unwrap_or(vec![]);
- (bytes, content_type)
- }
-}
-
-impl Extractable for DOMString {
- fn extract(&self) -> (Vec<u8>, Option<DOMString>) {
- (
- self.as_bytes().to_owned(),
- Some(DOMString::from("text/plain;charset=UTF-8")),
- )
- }
-}
-
-impl Extractable for FormData {
- fn extract(&self) -> (Vec<u8>, Option<DOMString>) {
- let boundary = generate_boundary();
- let bytes = encode_multipart_form_data(&mut self.datums(), boundary.clone(), UTF_8);
- (
- bytes,
- Some(DOMString::from(format!(
- "multipart/form-data;boundary={}",
- boundary
- ))),
- )
- }
-}
-
-impl Extractable for URLSearchParams {
- fn extract(&self) -> (Vec<u8>, Option<DOMString>) {
- (
- self.serialize_utf8().into_bytes(),
- Some(DOMString::from(
- "application/x-www-form-urlencoded;charset=UTF-8",
- )),
- )
- }
-}
-
fn serialize_document(doc: &Document) -> Fallible<DOMString> {
let mut writer = vec![];
match serialize(&mut writer, &doc.upcast::<Node>(), SerializeOpts::default()) {
@@ -1613,20 +1620,6 @@ fn serialize_document(doc: &Document) -> Fallible<DOMString> {
}
}
-impl Extractable for BodyInit {
- // https://fetch.spec.whatwg.org/#concept-bodyinit-extract
- fn extract(&self) -> (Vec<u8>, Option<DOMString>) {
- match *self {
- BodyInit::String(ref s) => s.extract(),
- BodyInit::URLSearchParams(ref usp) => usp.extract(),
- BodyInit::Blob(ref b) => b.extract(),
- BodyInit::FormData(ref formdata) => formdata.extract(),
- BodyInit::ArrayBuffer(ref typedarray) => ((typedarray.to_vec(), None)),
- BodyInit::ArrayBufferView(ref typedarray) => ((typedarray.to_vec(), None)),
- }
- }
-}
-
/// Returns whether `bs` is a `field-value`, as defined by
/// [RFC 2616](http://tools.ietf.org/html/rfc2616#page-32).
pub fn is_field_value(slice: &[u8]) -> bool {