diff options
-rw-r--r-- | components/script/body.rs | 31 | ||||
-rw-r--r-- | components/script/dom/request.rs | 22 | ||||
-rw-r--r-- | components/script/dom/response.rs | 29 | ||||
-rw-r--r-- | components/script/fetch.rs | 13 | ||||
-rw-r--r-- | tests/wpt/metadata/fetch/api/basic/text-utf8.html.ini | 24 | ||||
-rw-r--r-- | tests/wpt/metadata/fetch/api/request/request-consume-empty.html.ini | 9 | ||||
-rw-r--r-- | tests/wpt/metadata/fetch/api/request/request-disturbed.html.ini | 3 | ||||
-rw-r--r-- | tests/wpt/metadata/fetch/api/response/response-consume-empty.html.ini | 24 | ||||
-rw-r--r-- | tests/wpt/metadata/fetch/api/response/response-consume.html.ini | 6 |
9 files changed, 102 insertions, 59 deletions
diff --git a/components/script/body.rs b/components/script/body.rs index 36a18134c98..276d6425d2f 100644 --- a/components/script/body.rs +++ b/components/script/body.rs @@ -24,6 +24,7 @@ use std::rc::Rc; use std::str; use url::form_urlencoded; +#[derive(Copy, Clone, JSTraceable, HeapSizeOf)] pub enum BodyType { Blob, FormData, @@ -47,14 +48,32 @@ pub fn consume_body<T: BodyOperations + Reflectable>(object: &T, body_type: Body if object.get_body_used() || object.is_locked() { promise.reject_error(promise.global().r().get_cx(), Error::Type( "The response's stream is disturbed or locked".to_string())); + return promise; } + object.set_body_promise(&promise, body_type); + // Steps 2-4 // TODO: Body does not yet have a stream. + consume_body_with_promise(object, body_type, &promise); + + promise +} + +// https://fetch.spec.whatwg.org/#concept-body-consume-body +#[allow(unrooted_must_root)] +pub fn consume_body_with_promise<T: BodyOperations + Reflectable>(object: &T, + body_type: BodyType, + promise: &Promise) { // Step 5 + let body = match object.take_body() { + Some(body) => body, + None => return, + }; + let pkg_data_results = run_package_data_algorithm(object, - object.take_body(), + body, body_type, object.get_mime_type()); @@ -70,20 +89,15 @@ pub fn consume_body<T: BodyOperations + Reflectable>(object: &T, body_type: Body }, Err(err) => promise.reject_error(cx, err), } - promise } // https://fetch.spec.whatwg.org/#concept-body-package-data #[allow(unsafe_code)] fn run_package_data_algorithm<T: BodyOperations + Reflectable>(object: &T, - bytes: Option<Vec<u8>>, + bytes: Vec<u8>, body_type: BodyType, mime_type: Ref<Vec<u8>>) -> Fallible<FetchedData> { - let bytes = match bytes { - Some(b) => b, - _ => vec![], - }; let cx = object.global().r().get_cx(); let mime = &*mime_type; match body_type { @@ -156,6 +170,9 @@ fn run_form_data_algorithm(root: GlobalRef, bytes: Vec<u8>, mime: &[u8]) -> Fall pub trait BodyOperations { fn get_body_used(&self) -> bool; + fn set_body_promise(&self, p: &Rc<Promise>, body_type: BodyType); + /// Returns `Some(_)` if the body is complete, `None` if there is more to + /// come. fn take_body(&self) -> Option<Vec<u8>>; fn is_locked(&self) -> bool; fn get_mime_type(&self) -> Ref<Vec<u8>>; diff --git a/components/script/dom/request.rs b/components/script/dom/request.rs index ebfe0abf49e..fa665679c0d 100644 --- a/components/script/dom/request.rs +++ b/components/script/dom/request.rs @@ -36,7 +36,6 @@ use net_traits::request::Request as NetTraitsRequest; use net_traits::request::RequestMode as NetTraitsRequestMode; use net_traits::request::Type as NetTraitsRequestType; use std::cell::{Cell, Ref}; -use std::mem; use std::rc::Rc; use url::Url; @@ -47,6 +46,8 @@ pub struct Request { body_used: Cell<bool>, headers: MutNullableHeap<JS<Headers>>, mime_type: DOMRefCell<Vec<u8>>, + #[ignore_heap_size_of = "Rc"] + body_promise: DOMRefCell<Option<(Rc<Promise>, BodyType)>>, } impl Request { @@ -62,6 +63,7 @@ impl Request { body_used: Cell::new(false), headers: Default::default(), mime_type: DOMRefCell::new("".to_string().into_bytes()), + body_promise: DOMRefCell::new(None), } } @@ -662,20 +664,20 @@ impl BodyOperations for Request { self.BodyUsed() } + fn set_body_promise(&self, p: &Rc<Promise>, body_type: BodyType) { + assert!(self.body_promise.borrow().is_none()); + self.body_used.set(true); + *self.body_promise.borrow_mut() = Some((p.clone(), body_type)); + } + fn is_locked(&self) -> bool { self.locked() } fn take_body(&self) -> Option<Vec<u8>> { - let ref mut net_traits_req = *self.request.borrow_mut(); - let body: Option<Vec<u8>> = mem::replace(&mut *net_traits_req.body.borrow_mut(), None); - match body { - Some(_) => { - self.body_used.set(true); - body - }, - _ => None, - } + let request = self.request.borrow_mut(); + let body = request.body.borrow_mut().take(); + Some(body.unwrap_or(vec![])) } fn get_mime_type(&self) -> Ref<Vec<u8>> { diff --git a/components/script/dom/response.rs b/components/script/dom/response.rs index 66a7e84f112..2287bb181b4 100644 --- a/components/script/dom/response.rs +++ b/components/script/dom/response.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use body::{BodyOperations, BodyType, consume_body}; +use body::{BodyOperations, BodyType, consume_body, consume_body_with_promise}; use core::cell::Cell; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::HeadersBinding::HeadersMethods; @@ -44,6 +44,8 @@ pub struct Response { url_list: DOMRefCell<Vec<Url>>, // For now use the existing NetTraitsResponseBody enum body: DOMRefCell<NetTraitsResponseBody>, + #[ignore_heap_size_of = "Rc"] + body_promise: DOMRefCell<Option<(Rc<Promise>, BodyType)>>, } impl Response { @@ -59,6 +61,7 @@ impl Response { url: DOMRefCell::new(None), url_list: DOMRefCell::new(vec![]), body: DOMRefCell::new(NetTraitsResponseBody::Empty), + body_promise: DOMRefCell::new(None), } } @@ -194,18 +197,26 @@ impl BodyOperations for Response { self.BodyUsed() } + fn set_body_promise(&self, p: &Rc<Promise>, body_type: BodyType) { + assert!(self.body_promise.borrow().is_none()); + self.body_used.set(true); + *self.body_promise.borrow_mut() = Some((p.clone(), body_type)); + } + fn is_locked(&self) -> bool { self.locked() } fn take_body(&self) -> Option<Vec<u8>> { - let body: NetTraitsResponseBody = mem::replace(&mut *self.body.borrow_mut(), NetTraitsResponseBody::Empty); + let body = mem::replace(&mut *self.body.borrow_mut(), NetTraitsResponseBody::Empty); match body { - NetTraitsResponseBody::Done(bytes) | NetTraitsResponseBody::Receiving(bytes) => { - self.body_used.set(true); + NetTraitsResponseBody::Done(bytes) => { Some(bytes) }, - _ => None, + body => { + mem::replace(&mut *self.body.borrow_mut(), body); + None + }, } } @@ -366,4 +377,12 @@ impl Response { pub fn set_final_url(&self, final_url: Url) { *self.url.borrow_mut() = Some(final_url); } + + #[allow(unrooted_must_root)] + pub fn finish(&self, body: Vec<u8>) { + *self.body.borrow_mut() = NetTraitsResponseBody::Done(body); + if let Some((p, body_type)) = self.body_promise.borrow_mut().take() { + consume_body_with_promise(self, body_type, &p); + } + } } diff --git a/components/script/fetch.rs b/components/script/fetch.rs index d60d174daad..634439c7c7d 100644 --- a/components/script/fetch.rs +++ b/components/script/fetch.rs @@ -24,6 +24,7 @@ use net_traits::CoreResourceMsg::Fetch as NetTraitsFetch; use net_traits::request::Request as NetTraitsRequest; use net_traits::request::RequestInit as NetTraitsRequestInit; use network_listener::{NetworkListener, PreInvoke}; +use std::mem; use std::rc::Rc; use std::sync::{Arc, Mutex}; use url::Url; @@ -31,6 +32,7 @@ use url::Url; struct FetchContext { fetch_promise: Option<TrustedPromise>, response_object: Trusted<Response>, + body: Vec<u8>, } fn from_referrer_to_referrer_url(request: &NetTraitsRequest) -> Option<Url> { @@ -89,6 +91,7 @@ pub fn Fetch(global: GlobalRef, input: RequestOrUSVString, init: &RequestInit) - let fetch_context = Arc::new(Mutex::new(FetchContext { fetch_promise: Some(TrustedPromise::new(promise.clone())), response_object: Trusted::new(&*response), + body: vec![], })); let listener = NetworkListener { context: fetch_context, @@ -153,12 +156,16 @@ impl FetchResponseListener for FetchContext { self.fetch_promise = Some(TrustedPromise::new(promise)); } - fn process_response_chunk(&mut self, _chunk: Vec<u8>) { - // TODO when body is implemented - // ... this will append the chunk to Response's body. + fn process_response_chunk(&mut self, mut chunk: Vec<u8>) { + self.body.append(&mut chunk); } fn process_response_eof(&mut self, _response: Result<(), NetworkError>) { + let response = self.response_object.root(); + let global = response.global(); + let cx = global.r().get_cx(); + let _ac = JSAutoCompartment::new(cx, global.r().reflector().get_jsobject().get()); + response.finish(mem::replace(&mut self.body, vec![])); // TODO // ... trailerObject is not supported in Servo yet. } diff --git a/tests/wpt/metadata/fetch/api/basic/text-utf8.html.ini b/tests/wpt/metadata/fetch/api/basic/text-utf8.html.ini index 5d9acb63606..1bdc4f3f39d 100644 --- a/tests/wpt/metadata/fetch/api/basic/text-utf8.html.ini +++ b/tests/wpt/metadata/fetch/api/basic/text-utf8.html.ini @@ -18,45 +18,21 @@ [UTF-8 without BOM with Response.text()] expected: FAIL - [UTF-8 without BOM with fetched data (UTF-8 charset)] - expected: FAIL - - [UTF-8 without BOM with fetched data (UTF-16 charset)] - expected: FAIL - [UTF-16BE with BOM decoded as UTF-8 with Request.text()] expected: FAIL [UTF-16BE with BOM decoded as UTF-8 with Response.text()] expected: FAIL - [UTF-16BE with BOM decoded as UTF-8 with fetched data (UTF-8 charset)] - expected: FAIL - - [UTF-16BE with BOM decoded as UTF-8 with fetched data (UTF-16 charset)] - expected: FAIL - [UTF-16LE with BOM decoded as UTF-8 with Request.text()] expected: FAIL [UTF-16LE with BOM decoded as UTF-8 with Response.text()] expected: FAIL - [UTF-16LE with BOM decoded as UTF-8 with fetched data (UTF-8 charset)] - expected: FAIL - - [UTF-16LE with BOM decoded as UTF-8 with fetched data (UTF-16 charset)] - expected: FAIL - [UTF-16 without BOM decoded as UTF-8 with Request.text()] expected: FAIL [UTF-16 without BOM decoded as UTF-8 with Response.text()] expected: FAIL - [UTF-16 without BOM decoded as UTF-8 with fetched data (UTF-8 charset)] - expected: FAIL - - [UTF-16 without BOM decoded as UTF-8 with fetched data (UTF-16 charset)] - expected: FAIL - diff --git a/tests/wpt/metadata/fetch/api/request/request-consume-empty.html.ini b/tests/wpt/metadata/fetch/api/request/request-consume-empty.html.ini index 367e9eef15b..848a39ee5a6 100644 --- a/tests/wpt/metadata/fetch/api/request/request-consume-empty.html.ini +++ b/tests/wpt/metadata/fetch/api/request/request-consume-empty.html.ini @@ -12,3 +12,12 @@ [Consume empty text request body as arrayBuffer] expected: FAIL + [Consume request's body as text] + expected: FAIL + + [Consume request's body as blob] + expected: FAIL + + [Consume request's body as json] + expected: FAIL + diff --git a/tests/wpt/metadata/fetch/api/request/request-disturbed.html.ini b/tests/wpt/metadata/fetch/api/request/request-disturbed.html.ini index 60d69c8caef..66204f04702 100644 --- a/tests/wpt/metadata/fetch/api/request/request-disturbed.html.ini +++ b/tests/wpt/metadata/fetch/api/request/request-disturbed.html.ini @@ -12,3 +12,6 @@ [Request construction failure should not set "bodyUsed"] expected: FAIL + [Request without body cannot be disturbed] + expected: FAIL + diff --git a/tests/wpt/metadata/fetch/api/response/response-consume-empty.html.ini b/tests/wpt/metadata/fetch/api/response/response-consume-empty.html.ini index 9ee927624fb..b7af3cd4719 100644 --- a/tests/wpt/metadata/fetch/api/response/response-consume-empty.html.ini +++ b/tests/wpt/metadata/fetch/api/response/response-consume-empty.html.ini @@ -1,14 +1,30 @@ [response-consume-empty.html] type: testharness + expected: TIMEOUT [Consume response's body as arrayBuffer] - expected: FAIL + expected: NOTRUN [Consume response's body as formData] - expected: FAIL + expected: NOTRUN [Consume empty blob response body as arrayBuffer] - expected: FAIL + expected: NOTRUN [Consume empty text response body as arrayBuffer] - expected: FAIL + expected: NOTRUN + + [Consume response's body as text] + expected: TIMEOUT + + [Consume response's body as blob] + expected: NOTRUN + + [Consume response's body as json] + expected: NOTRUN + + [Consume empty blob response body as text] + expected: NOTRUN + + [Consume empty text response body as text] + expected: NOTRUN diff --git a/tests/wpt/metadata/fetch/api/response/response-consume.html.ini b/tests/wpt/metadata/fetch/api/response/response-consume.html.ini index 63000272391..a0956648b51 100644 --- a/tests/wpt/metadata/fetch/api/response/response-consume.html.ini +++ b/tests/wpt/metadata/fetch/api/response/response-consume.html.ini @@ -21,12 +21,6 @@ [Consume stream response's body as arrayBuffer] expected: FAIL - [Consume fetched response's body as blob] - expected: FAIL - - [Consume fetched response's body as text] - expected: FAIL - [Consume fetched response's body as arrayBuffer] expected: FAIL |