From 5e02bee29df12e9e7c3fd19c0bcf8696d95888fc Mon Sep 17 00:00:00 2001 From: "Jayson Reis (jaysonsantos)" Date: Thu, 15 Sep 2016 23:18:13 +0200 Subject: [PATCH 1/3] Re-applying patch to avoid old stuff to be included --- components/script/dom/document.rs | 13 +++++++++ .../script/dom/webidls/XMLHttpRequest.webidl | 2 +- components/script/dom/xmlhttprequest.rs | 28 ++++++++++++++++++- .../send-entity-body-document.htm.ini | 16 ----------- 4 files changed, 41 insertions(+), 18 deletions(-) diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index b50b5ec87e12..62515048a7b7 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -88,6 +88,9 @@ use dom::window::{ReflowReason, Window}; use encoding::EncodingRef; use encoding::all::UTF_8; use euclid::point::Point2D; +use html5ever::serialize; +use html5ever::serialize::SerializeOpts; +use html5ever::serialize::TraversalScope::ChildrenOnly; use html5ever::tree_builder::{LimitedQuirks, NoQuirks, Quirks, QuirksMode}; use ipc_channel::ipc::{self, IpcSender}; use js::jsapi::{JSContext, JSObject, JSRuntime}; @@ -1975,6 +1978,16 @@ impl Document { ReflowQueryType::NoQuery, ReflowReason::ElementStateChanged); } + + pub fn serialize(&self) -> Fallible { + let mut writer = vec![]; + if let Ok(()) = serialize(&mut writer, &self.upcast::(), + SerializeOpts { traversal_scope: ChildrenOnly, ..Default::default() }) { + Ok(DOMString::from(String::from_utf8(writer).unwrap())) + } else { + Err(Error::InvalidState) + } + } } diff --git a/components/script/dom/webidls/XMLHttpRequest.webidl b/components/script/dom/webidls/XMLHttpRequest.webidl index 05d7256e7672..3c03682d976c 100644 --- a/components/script/dom/webidls/XMLHttpRequest.webidl +++ b/components/script/dom/webidls/XMLHttpRequest.webidl @@ -53,7 +53,7 @@ interface XMLHttpRequest : XMLHttpRequestEventTarget { attribute boolean withCredentials; readonly attribute XMLHttpRequestUpload upload; [Throws] - void send(optional /*Document or*/ BodyInit? data = null); + void send(optional (Document or Blob or DOMString or URLSearchParams)? data = null); void abort(); // response diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index d034b60aebdf..a84e99d05bf6 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -5,12 +5,13 @@ use document_loader::DocumentLoader; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::BlobBinding::BlobMethods; +use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods; use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::codegen::Bindings::XMLHttpRequestBinding; -use dom::bindings::codegen::Bindings::XMLHttpRequestBinding::BodyInit; use dom::bindings::codegen::Bindings::XMLHttpRequestBinding::XMLHttpRequestMethods; use dom::bindings::codegen::Bindings::XMLHttpRequestBinding::XMLHttpRequestResponseType; +use dom::bindings::codegen::UnionTypes::BodyInit; use dom::bindings::conversions::ToJSValConvertible; use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::global::{GlobalRef, GlobalRoot}; @@ -35,6 +36,7 @@ use encoding::label::encoding_from_whatwg_label; use encoding::types::{DecoderTrap, EncoderTrap, Encoding, EncodingRef}; use euclid::length::Length; use hyper::header::{ContentLength, ContentType}; +use html5ever::serialize::Serializable; use hyper::header::Headers; use hyper::method::Method; use hyper::mime::{self, Attr as MimeAttr, Mime, Value as MimeValue}; @@ -1354,6 +1356,7 @@ impl XHRTimeoutCallback { trait Extractable { fn extract(&self) -> (Vec, Option); } + impl Extractable for BodyInit { // https://fetch.spec.whatwg.org/#concept-bodyinit-extract fn extract(&self) -> (Vec, Option) { @@ -1382,6 +1385,29 @@ impl Extractable for BodyInit { let bytes = encode_multipart_form_data(&mut formdata.datums(), boundary.clone(), UTF_8 as EncodingRef); (bytes, Some(DOMString::from(format!("multipart/form-data;boundary={}", boundary)))) + (data.get_bytes().to_vec(), content_type) + }, + BodyInit::Document(ref d) => { + let data: Vec = d.serialize().unwrap().into(); + let decoded_data: Vec = match &*d.CharacterSet() { + "UTF-8" => { + debug!("Document is already utf-8, skipping conversion {:?}", d.url()); + data + }, + document_charset => { + debug!("Document is {:?} we have to decode", document_charset); + let charset = encoding_from_whatwg_label(&*d.CharacterSet()).unwrap_or(UTF_8); + charset.decode(&*data, DecoderTrap::Replace).unwrap().into_bytes() + } + }; + let mut content_type = String::new(); + if d.is_html_document() { + content_type.push_str("text/html"); + } else { + content_type.push_str("application/xml"); + }; + content_type.push_str(";charset=UTF-8"); + (decoded_data, Some(DOMString::from(content_type))) } } } diff --git a/tests/wpt/metadata/XMLHttpRequest/send-entity-body-document.htm.ini b/tests/wpt/metadata/XMLHttpRequest/send-entity-body-document.htm.ini index 3d6b19f8d72a..0be15fb55bd1 100644 --- a/tests/wpt/metadata/XMLHttpRequest/send-entity-body-document.htm.ini +++ b/tests/wpt/metadata/XMLHttpRequest/send-entity-body-document.htm.ini @@ -2,22 +2,6 @@ type: testharness [XML document, windows-1252] expected: FAIL - - [HTML document, invalid UTF-8] - expected: FAIL - [HTML document, shift-jis] expected: FAIL - [plain text file] - expected: FAIL - - [image file] - expected: FAIL - - [img tag] - expected: FAIL - - [empty div] - expected: FAIL - From de58bcc9012db2b6cd79a134f27b09615c38acff Mon Sep 17 00:00:00 2001 From: "Jayson Reis (jaysonsantos)" Date: Sun, 18 Sep 2016 12:13:11 +0200 Subject: [PATCH 2/3] Change BodyInit to DocumentOrBodyInit --- .../script/dom/webidls/XMLHttpRequest.webidl | 2 +- components/script/dom/xmlhttprequest.rs | 20 +++++++++---------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/components/script/dom/webidls/XMLHttpRequest.webidl b/components/script/dom/webidls/XMLHttpRequest.webidl index 3c03682d976c..d5a70a78be7e 100644 --- a/components/script/dom/webidls/XMLHttpRequest.webidl +++ b/components/script/dom/webidls/XMLHttpRequest.webidl @@ -53,7 +53,7 @@ interface XMLHttpRequest : XMLHttpRequestEventTarget { attribute boolean withCredentials; readonly attribute XMLHttpRequestUpload upload; [Throws] - void send(optional (Document or Blob or DOMString or URLSearchParams)? data = null); + void send(optional (Document or BodyInit)? data = null); void abort(); // response diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index a84e99d05bf6..84d87a1ebff4 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -11,7 +11,7 @@ use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::codegen::Bindings::XMLHttpRequestBinding; use dom::bindings::codegen::Bindings::XMLHttpRequestBinding::XMLHttpRequestMethods; use dom::bindings::codegen::Bindings::XMLHttpRequestBinding::XMLHttpRequestResponseType; -use dom::bindings::codegen::UnionTypes::BodyInit; +use dom::bindings::codegen::UnionTypes::DocumentOrBodyInit; use dom::bindings::conversions::ToJSValConvertible; use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::global::{GlobalRef, GlobalRoot}; @@ -36,7 +36,6 @@ use encoding::label::encoding_from_whatwg_label; use encoding::types::{DecoderTrap, EncoderTrap, Encoding, EncodingRef}; use euclid::length::Length; use hyper::header::{ContentLength, ContentType}; -use html5ever::serialize::Serializable; use hyper::header::Headers; use hyper::method::Method; use hyper::mime::{self, Attr as MimeAttr, Mime, Value as MimeValue}; @@ -501,7 +500,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest { } // https://xhr.spec.whatwg.org/#the-send()-method - fn Send(&self, data: Option) -> ErrorResult { + fn Send(&self, data: Option) -> ErrorResult { // Step 1, 2 if self.ready_state.get() != XMLHttpRequestState::Opened || self.send_flag.get() { return Err(Error::InvalidState); @@ -608,7 +607,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest { match extracted { Some((_, ref content_type)) => { // this should handle Document bodies too, not just BodyInit - let encoding = if let Some(BodyInit::String(_)) = data { + let encoding = if let Some(DocumentOrBodyInit::String(_)) = data { // XHR spec differs from http, and says UTF-8 should be in capitals, // instead of "utf-8", which is what Hyper defaults to. So not // using content types provided by Hyper. @@ -1357,21 +1356,21 @@ trait Extractable { fn extract(&self) -> (Vec, Option); } -impl Extractable for BodyInit { +impl Extractable for DocumentOrBodyInit { // https://fetch.spec.whatwg.org/#concept-bodyinit-extract fn extract(&self) -> (Vec, Option) { match *self { - BodyInit::String(ref s) => { + DocumentOrBodyInit::String(ref s) => { let encoding = UTF_8 as EncodingRef; (encoding.encode(s, EncoderTrap::Replace).unwrap(), Some(DOMString::from("text/plain;charset=UTF-8"))) } - BodyInit::URLSearchParams(ref usp) => { + DocumentOrBodyInit::URLSearchParams(ref usp) => { // Default encoding is UTF-8. (usp.serialize(None).into_bytes(), Some(DOMString::from("application/x-www-form-urlencoded;charset=UTF-8"))) } - BodyInit::Blob(ref b) => { + DocumentOrBodyInit::Blob(ref b) => { let content_type = if b.Type().as_ref().is_empty() { None } else { @@ -1380,14 +1379,13 @@ impl Extractable for BodyInit { let bytes = b.get_bytes().unwrap_or(vec![]); (bytes, content_type) } - BodyInit::FormData(ref formdata) => { + DocumentOrBodyInit::FormData(ref formdata) => { let boundary = generate_boundary(); let bytes = encode_multipart_form_data(&mut formdata.datums(), boundary.clone(), UTF_8 as EncodingRef); (bytes, Some(DOMString::from(format!("multipart/form-data;boundary={}", boundary)))) - (data.get_bytes().to_vec(), content_type) }, - BodyInit::Document(ref d) => { + DocumentOrBodyInit::Document(ref d) => { let data: Vec = d.serialize().unwrap().into(); let decoded_data: Vec = match &*d.CharacterSet() { "UTF-8" => { From 34347b0df84801d35b07d7c67bec3354f763f78b Mon Sep 17 00:00:00 2001 From: "Jayson Reis (jaysonsantos)" Date: Tue, 20 Sep 2016 20:56:49 +0200 Subject: [PATCH 3/3] Move serialize document to be inside xmlhttprequest.rs --- components/script/dom/document.rs | 13 ------------- components/script/dom/xmlhttprequest.rs | 17 ++++++++++++++++- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 62515048a7b7..b50b5ec87e12 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -88,9 +88,6 @@ use dom::window::{ReflowReason, Window}; use encoding::EncodingRef; use encoding::all::UTF_8; use euclid::point::Point2D; -use html5ever::serialize; -use html5ever::serialize::SerializeOpts; -use html5ever::serialize::TraversalScope::ChildrenOnly; use html5ever::tree_builder::{LimitedQuirks, NoQuirks, Quirks, QuirksMode}; use ipc_channel::ipc::{self, IpcSender}; use js::jsapi::{JSContext, JSObject, JSRuntime}; @@ -1978,16 +1975,6 @@ impl Document { ReflowQueryType::NoQuery, ReflowReason::ElementStateChanged); } - - pub fn serialize(&self) -> Fallible { - let mut writer = vec![]; - if let Ok(()) = serialize(&mut writer, &self.upcast::(), - SerializeOpts { traversal_scope: ChildrenOnly, ..Default::default() }) { - Ok(DOMString::from(String::from_utf8(writer).unwrap())) - } else { - Err(Error::InvalidState) - } - } } diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index 84d87a1ebff4..48860dea963b 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -28,6 +28,7 @@ use dom::event::{Event, EventBubbles, EventCancelable}; use dom::eventtarget::EventTarget; use dom::headers::is_forbidden_header_name; use dom::htmlformelement::{encode_multipart_form_data, generate_boundary}; +use dom::node::Node; use dom::progressevent::ProgressEvent; use dom::xmlhttprequesteventtarget::XMLHttpRequestEventTarget; use dom::xmlhttprequestupload::XMLHttpRequestUpload; @@ -35,6 +36,9 @@ use encoding::all::UTF_8; use encoding::label::encoding_from_whatwg_label; use encoding::types::{DecoderTrap, EncoderTrap, Encoding, EncodingRef}; use euclid::length::Length; +use html5ever::serialize; +use html5ever::serialize::SerializeOpts; +use html5ever::serialize::TraversalScope::ChildrenOnly; use hyper::header::{ContentLength, ContentType}; use hyper::header::Headers; use hyper::method::Method; @@ -1386,7 +1390,7 @@ impl Extractable for DocumentOrBodyInit { (bytes, Some(DOMString::from(format!("multipart/form-data;boundary={}", boundary)))) }, DocumentOrBodyInit::Document(ref d) => { - let data: Vec = d.serialize().unwrap().into(); + let data: Vec = serialize_document(d).unwrap().into(); let decoded_data: Vec = match &*d.CharacterSet() { "UTF-8" => { debug!("Document is already utf-8, skipping conversion {:?}", d.url()); @@ -1474,3 +1478,14 @@ pub fn is_field_value(slice: &[u8]) -> bool { } }) } + +// Serialize a Document struct +fn serialize_document(document: &Document) -> Fallible { + let mut writer = vec![]; + if let Ok(()) = serialize(&mut writer, &document.upcast::(), + SerializeOpts { traversal_scope: ChildrenOnly, ..Default::default() }) { + Ok(DOMString::from(String::from_utf8(writer).unwrap())) + } else { + Err(Error::InvalidState) + } +}