servo: Merge #9354 - Update XMLHTTPRequest FetchBodyInit and related Impl (#9291) (from stspyder:master); r=KiChjang

Fixes #9291.

Source-Repo: https://github.com/servo/servo
Source-Revision: 55d8228ed6910c72b663dfb4f2b7d140e28a8364
This commit is contained in:
St.Spyder 2016-01-18 03:50:59 +05:01
Родитель 0e37316f1a
Коммит 4d1734e744
3 изменённых файлов: 36 добавлений и 32 удалений

Просмотреть файл

@ -13,8 +13,8 @@
* http://www.openwebfoundation.org/legal/the-owf-1-0-agreements/owfa-1-0. * http://www.openwebfoundation.org/legal/the-owf-1-0-agreements/owfa-1-0.
*/ */
// https://fetch.spec.whatwg.org/#fetchbodyinit // https://fetch.spec.whatwg.org/#bodyinit
typedef (/*ArrayBuffer or ArrayBufferView or Blob or FormData or */DOMString or URLSearchParams) FetchBodyInit; typedef (Blob or /*BufferSource or FormData or */DOMString or URLSearchParams) BodyInit;
enum XMLHttpRequestResponseType { enum XMLHttpRequestResponseType {
"", "",
@ -55,7 +55,7 @@ interface XMLHttpRequest : XMLHttpRequestEventTarget {
attribute boolean withCredentials; attribute boolean withCredentials;
readonly attribute XMLHttpRequestUpload upload; readonly attribute XMLHttpRequestUpload upload;
[Throws] [Throws]
void send(optional /*Document or*/ FetchBodyInit? data = null); void send(optional /*Document or*/ BodyInit? data = null);
void abort(); void abort();
// response // response

Просмотреть файл

@ -6,14 +6,15 @@ use cors::CORSResponse;
use cors::{AsyncCORSResponseListener, CORSRequest, RequestMode, allow_cross_origin_request}; use cors::{AsyncCORSResponseListener, CORSRequest, RequestMode, allow_cross_origin_request};
use document_loader::DocumentLoader; use document_loader::DocumentLoader;
use dom::bindings::cell::DOMRefCell; use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::BlobBinding::BlobMethods;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::codegen::Bindings::XMLHttpRequestBinding; use dom::bindings::codegen::Bindings::XMLHttpRequestBinding;
use dom::bindings::codegen::Bindings::XMLHttpRequestBinding::XMLHttpRequestMethods; use dom::bindings::codegen::Bindings::XMLHttpRequestBinding::XMLHttpRequestMethods;
use dom::bindings::codegen::Bindings::XMLHttpRequestBinding::XMLHttpRequestResponseType; use dom::bindings::codegen::Bindings::XMLHttpRequestBinding::XMLHttpRequestResponseType;
use dom::bindings::codegen::Bindings::XMLHttpRequestBinding::XMLHttpRequestResponseType::{Json, Text, _empty}; use dom::bindings::codegen::Bindings::XMLHttpRequestBinding::XMLHttpRequestResponseType::{Json, Text, _empty};
use dom::bindings::codegen::UnionTypes::StringOrURLSearchParams; use dom::bindings::codegen::UnionTypes::BlobOrStringOrURLSearchParams;
use dom::bindings::codegen::UnionTypes::StringOrURLSearchParams::{eString, eURLSearchParams}; use dom::bindings::codegen::UnionTypes::BlobOrStringOrURLSearchParams::{eBlob, eString, eURLSearchParams};
use dom::bindings::conversions::{ToJSValConvertible}; use dom::bindings::conversions::{ToJSValConvertible};
use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::global::{GlobalRef, GlobalRoot}; use dom::bindings::global::{GlobalRef, GlobalRoot};
@ -64,7 +65,7 @@ use url::Url;
use util::mem::HeapSizeOf; use util::mem::HeapSizeOf;
use util::str::DOMString; use util::str::DOMString;
pub type SendParam = StringOrURLSearchParams; pub type SendParam = BlobOrStringOrURLSearchParams;
#[derive(JSTraceable, PartialEq, Copy, Clone, HeapSizeOf)] #[derive(JSTraceable, PartialEq, Copy, Clone, HeapSizeOf)]
enum XMLHttpRequestState { enum XMLHttpRequestState {
@ -481,14 +482,14 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
_ => data _ => data
}; };
let extracted = data.as_ref().map(|d| d.extract()); let extracted = data.as_ref().map(|d| d.extract());
self.request_body_len.set(extracted.as_ref().map_or(0, |e| e.len())); self.request_body_len.set(extracted.as_ref().map_or(0, |e| e.0.len()));
// Step 6 // Step 6
self.upload_events.set(false); self.upload_events.set(false);
// Step 7 // Step 7
self.upload_complete.set(match extracted { self.upload_complete.set(match extracted {
None => true, None => true,
Some (ref v) if v.is_empty() => true, Some (ref e) if e.0.is_empty() => true,
_ => false _ => false
}); });
@ -526,28 +527,16 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
if load_data.url.origin().ne(&global.r().get_url().origin()) { if load_data.url.origin().ne(&global.r().get_url().origin()) {
load_data.credentials_flag = self.WithCredentials(); load_data.credentials_flag = self.WithCredentials();
} }
load_data.data = extracted; load_data.data = extracted.as_ref().map(|e| e.0.clone());
#[inline]
fn join_raw(a: &str, b: &str) -> Vec<u8> {
let len = a.len() + b.len();
let mut vec = Vec::with_capacity(len);
vec.extend_from_slice(a.as_bytes());
vec.extend_from_slice(b.as_bytes());
vec
}
// XHR spec differs from http, and says UTF-8 should be in capitals, // XHR spec differs from http, and says UTF-8 should be in capitals,
// instead of "utf-8", which is what Hyper defaults to. // instead of "utf-8", which is what Hyper defaults to. So not
let params = ";charset=UTF-8"; // using content types provided by Hyper.
let n = "content-type"; let n = "content-type";
match data { match extracted {
Some(eString(_)) => Some((_, Some(ref content_type))) =>
load_data.headers.set_raw(n.to_owned(), vec![join_raw("text/plain", params)]), load_data.headers.set_raw(n.to_owned(), vec![content_type.bytes().collect()]),
Some(eURLSearchParams(_)) => _ => (),
load_data.headers.set_raw(
n.to_owned(), vec![join_raw("application/x-www-form-urlencoded", params)]),
None => ()
} }
load_data.preserved_headers = (*self.request_headers.borrow()).clone(); load_data.preserved_headers = (*self.request_headers.borrow()).clone();
@ -1245,19 +1234,30 @@ impl XMLHttpRequest {
} }
trait Extractable { trait Extractable {
fn extract(&self) -> Vec<u8>; fn extract(&self) -> (Vec<u8>, Option<DOMString>);
} }
impl Extractable for SendParam { impl Extractable for SendParam {
// https://fetch.spec.whatwg.org/#concept-bodyinit-extract // https://fetch.spec.whatwg.org/#concept-bodyinit-extract
fn extract(&self) -> Vec<u8> { fn extract(&self) -> (Vec<u8>, Option<DOMString>) {
match *self { match *self {
eString(ref s) => { eString(ref s) => {
let encoding = UTF_8 as EncodingRef; let encoding = UTF_8 as EncodingRef;
encoding.encode(s, EncoderTrap::Replace).unwrap() (encoding.encode(s, EncoderTrap::Replace).unwrap(),
Some(DOMString::from("text/plain;charset=UTF-8")))
}, },
eURLSearchParams(ref usp) => { eURLSearchParams(ref usp) => {
// Default encoding is UTF-8. // Default encoding is UTF-8.
usp.serialize(None).into_bytes() (usp.serialize(None).into_bytes(),
Some(DOMString::from("application/x-www-form-urlencoded;charset=UTF-8")))
},
eBlob(ref b) => {
let data = b.get_data();
let content_type = if b.Type().as_ref().is_empty() {
None
} else {
Some(b.Type())
};
(data.get_bytes().to_vec(), content_type)
}, },
} }
} }

Просмотреть файл

@ -14,7 +14,7 @@ use std::ffi::CStr;
use std::fmt; use std::fmt;
use std::iter::{Filter, Peekable}; use std::iter::{Filter, Peekable};
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::str::{CharIndices, FromStr, Split, from_utf8}; use std::str::{Bytes, CharIndices, FromStr, Split, from_utf8};
#[derive(Clone, PartialOrd, Ord, PartialEq, Eq, Deserialize, Serialize, Hash, Debug)] #[derive(Clone, PartialOrd, Ord, PartialEq, Eq, Deserialize, Serialize, Hash, Debug)]
pub struct DOMString(String); pub struct DOMString(String);
@ -35,6 +35,10 @@ impl DOMString {
pub fn clear(&mut self) { pub fn clear(&mut self) {
self.0.clear() self.0.clear()
} }
pub fn bytes(&self) -> Bytes {
self.0.bytes()
}
} }
impl Default for DOMString { impl Default for DOMString {