aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/script/body.rs31
-rw-r--r--components/script/dom/request.rs22
-rw-r--r--components/script/dom/response.rs29
-rw-r--r--components/script/fetch.rs13
-rw-r--r--tests/wpt/metadata/fetch/api/basic/text-utf8.html.ini24
-rw-r--r--tests/wpt/metadata/fetch/api/request/request-consume-empty.html.ini9
-rw-r--r--tests/wpt/metadata/fetch/api/request/request-disturbed.html.ini3
-rw-r--r--tests/wpt/metadata/fetch/api/response/response-consume-empty.html.ini24
-rw-r--r--tests/wpt/metadata/fetch/api/response/response-consume.html.ini6
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