Auto merge of #26794 - gterzian:update_xhr, r=jdm

Update XHR send to use XMLHttpRequestBodyInit

<!-- Please describe your changes on the following line: -->

FIX #26723

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: -->
- [ ] `./mach build -d` does not report any errors
- [ ] `./mach test-tidy` does not report any errors
- [ ] These changes fix #___ (GitHub issue number if applicable)

<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because ___

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
This commit is contained in:
bors-servo 2020-06-09 10:25:11 -04:00 committed by GitHub
commit 8e3d12bfcb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 19 additions and 114 deletions

View file

@ -12,8 +12,11 @@
* 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/#typedefdef-xmlhttprequestbodyinit
typedef (Blob or BufferSource or FormData or DOMString or URLSearchParams) XMLHttpRequestBodyInit;
// https://fetch.spec.whatwg.org/#bodyinit // https://fetch.spec.whatwg.org/#bodyinit
typedef (Blob or BufferSource or FormData or DOMString or URLSearchParams or ReadableStream) BodyInit; typedef (ReadableStream or XMLHttpRequestBodyInit) BodyInit;
enum XMLHttpRequestResponseType { enum XMLHttpRequestResponseType {
"", "",
@ -54,7 +57,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 BodyInit)? data = null); void send(optional (Document or XMLHttpRequestBodyInit)? data = null);
void abort(); void abort();
// response // response

View file

@ -8,7 +8,7 @@ use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use crate::dom::bindings::codegen::Bindings::XMLHttpRequestBinding::XMLHttpRequestMethods; use crate::dom::bindings::codegen::Bindings::XMLHttpRequestBinding::XMLHttpRequestMethods;
use crate::dom::bindings::codegen::Bindings::XMLHttpRequestBinding::XMLHttpRequestResponseType; use crate::dom::bindings::codegen::Bindings::XMLHttpRequestBinding::XMLHttpRequestResponseType;
use crate::dom::bindings::codegen::UnionTypes::DocumentOrBodyInit; use crate::dom::bindings::codegen::UnionTypes::DocumentOrXMLHttpRequestBodyInit;
use crate::dom::bindings::conversions::ToJSValConvertible; use crate::dom::bindings::conversions::ToJSValConvertible;
use crate::dom::bindings::error::{Error, ErrorResult, Fallible}; use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::inheritance::Castable;
@ -547,7 +547,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
} }
// https://xhr.spec.whatwg.org/#the-send()-method // https://xhr.spec.whatwg.org/#the-send()-method
fn Send(&self, data: Option<DocumentOrBodyInit>) -> ErrorResult { fn Send(&self, data: Option<DocumentOrXMLHttpRequestBodyInit>) -> ErrorResult {
// Step 1, 2 // Step 1, 2
if self.ready_state.get() != XMLHttpRequestState::Opened || self.send_flag.get() { if self.ready_state.get() != XMLHttpRequestState::Opened || self.send_flag.get() {
return Err(Error::InvalidState); return Err(Error::InvalidState);
@ -560,7 +560,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
}; };
// Step 4 (first half) // Step 4 (first half)
let mut extracted_or_serialized = match data { let mut extracted_or_serialized = match data {
Some(DocumentOrBodyInit::Document(ref doc)) => { Some(DocumentOrXMLHttpRequestBodyInit::Document(ref doc)) => {
let bytes = Vec::from(serialize_document(&doc)?.as_ref()); let bytes = Vec::from(serialize_document(&doc)?.as_ref());
let content_type = if doc.is_html_document() { let content_type = if doc.is_html_document() {
"text/html;charset=UTF-8" "text/html;charset=UTF-8"
@ -577,7 +577,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
source: BodySource::Object, source: BodySource::Object,
}) })
}, },
Some(DocumentOrBodyInit::Blob(ref b)) => { Some(DocumentOrXMLHttpRequestBodyInit::Blob(ref b)) => {
let extracted_body = b.extract(&self.global()).expect("Couldn't extract body."); let extracted_body = b.extract(&self.global()).expect("Couldn't extract body.");
if !extracted_body.in_memory() && self.sync.get() { if !extracted_body.in_memory() && self.sync.get() {
warn!("Sync XHR with not in-memory Blob as body not supported"); warn!("Sync XHR with not in-memory Blob as body not supported");
@ -586,20 +586,20 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
Some(extracted_body) Some(extracted_body)
} }
}, },
Some(DocumentOrBodyInit::FormData(ref formdata)) => Some( Some(DocumentOrXMLHttpRequestBodyInit::FormData(ref formdata)) => Some(
formdata formdata
.extract(&self.global()) .extract(&self.global())
.expect("Couldn't extract body."), .expect("Couldn't extract body."),
), ),
Some(DocumentOrBodyInit::String(ref str)) => { Some(DocumentOrXMLHttpRequestBodyInit::String(ref str)) => {
Some(str.extract(&self.global()).expect("Couldn't extract body.")) Some(str.extract(&self.global()).expect("Couldn't extract body."))
}, },
Some(DocumentOrBodyInit::URLSearchParams(ref urlsp)) => Some( Some(DocumentOrXMLHttpRequestBodyInit::URLSearchParams(ref urlsp)) => Some(
urlsp urlsp
.extract(&self.global()) .extract(&self.global())
.expect("Couldn't extract body."), .expect("Couldn't extract body."),
), ),
Some(DocumentOrBodyInit::ArrayBuffer(ref typedarray)) => { Some(DocumentOrXMLHttpRequestBodyInit::ArrayBuffer(ref typedarray)) => {
let bytes = typedarray.to_vec(); let bytes = typedarray.to_vec();
let total_bytes = bytes.len(); let total_bytes = bytes.len();
let global = self.global(); let global = self.global();
@ -611,7 +611,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
source: BodySource::Object, source: BodySource::Object,
}) })
}, },
Some(DocumentOrBodyInit::ArrayBufferView(ref typedarray)) => { Some(DocumentOrXMLHttpRequestBodyInit::ArrayBufferView(ref typedarray)) => {
let bytes = typedarray.to_vec(); let bytes = typedarray.to_vec();
let total_bytes = bytes.len(); let total_bytes = bytes.len();
let global = self.global(); let global = self.global();
@ -623,25 +623,6 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
source: BodySource::Object, source: BodySource::Object,
}) })
}, },
Some(DocumentOrBodyInit::ReadableStream(ref stream)) => {
if self.sync.get() {
warn!("Sync XHR with ReadableStream as body not supported");
None
} else {
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, None => None,
}; };
@ -725,7 +706,8 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
match content_type { match content_type {
Some(content_type) => { Some(content_type) => {
let encoding = match data { let encoding = match data {
Some(DocumentOrBodyInit::String(_)) | Some(DocumentOrBodyInit::Document(_)) => Some(DocumentOrXMLHttpRequestBodyInit::String(_)) |
Some(DocumentOrXMLHttpRequestBodyInit::Document(_)) =>
// 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. So not // instead of "utf-8", which is what Hyper defaults to. So not
// using content types provided by Hyper. // using content types provided by Hyper.

View file

@ -527006,7 +527006,7 @@
] ]
], ],
"send-data-es-object.any.js": [ "send-data-es-object.any.js": [
"c6fe5de260c212013052f66636b92fb07aa82373", "92286bca6dd00b82b78de39fcf7988ba1c424d07",
[ [
"xhr/send-data-es-object.any.html", "xhr/send-data-es-object.any.html",
{ {
@ -527055,42 +527055,6 @@
} }
] ]
], ],
"send-data-readablestream.any.js": [
"c53b1071828f95669d41a967c51bd352b389bebb",
[
"xhr/send-data-readablestream.any.html",
{
"script_metadata": [
[
"global",
"window,dedicatedworker,sharedworker"
]
]
}
],
[
"xhr/send-data-readablestream.any.sharedworker.html",
{
"script_metadata": [
[
"global",
"window,dedicatedworker,sharedworker"
]
]
}
],
[
"xhr/send-data-readablestream.any.worker.html",
{
"script_metadata": [
[
"global",
"window,dedicatedworker,sharedworker"
]
]
}
]
],
"send-data-sharedarraybuffer.any.js": [ "send-data-sharedarraybuffer.any.js": [
"912f622697d538edbbc038f7ec76c2e63ee6ffa0", "912f622697d538edbbc038f7ec76c2e63ee6ffa0",
[ [
@ -527442,7 +527406,7 @@
] ]
], ],
"setrequestheader-content-type.htm": [ "setrequestheader-content-type.htm": [
"8608c5967d6b29ba4f9d09ae7bf395a6b26876c2", "07238391eb5cc8639edbe996208a18b6d9d26b04",
[ [
null, null,
{ {

View file

@ -27,6 +27,7 @@ function do_test(obj, expected, name) {
do_test({}, '[object Object]', 'sending a plain empty object') do_test({}, '[object Object]', 'sending a plain empty object')
do_test(Math, '[object Math]', 'sending the ES Math object') do_test(Math, '[object Math]', 'sending the ES Math object')
do_test(new XMLHttpRequest, '[object XMLHttpRequest]', 'sending a new XHR instance') do_test(new XMLHttpRequest, '[object XMLHttpRequest]', 'sending a new XHR instance')
do_test(new ReadableStream, '[object ReadableStream]', 'sending a new ReadableStream instance')
do_test({toString:function(){}}, 'undefined', 'sending object that stringifies to undefined') do_test({toString:function(){}}, 'undefined', 'sending object that stringifies to undefined')
do_test({toString:function(){return null}}, 'null', 'sending object that stringifies to null') do_test({toString:function(){return null}}, 'null', 'sending object that stringifies to null')
var ancestor = {toString: function(){ var ancestor = {toString: function(){

View file

@ -1,27 +0,0 @@
// META: global=window,dedicatedworker,sharedworker
function assert_xhr(stream) {
const client = new XMLHttpRequest();
client.open("POST", "...");
assert_throws_js(TypeError, () => client.send(stream));
}
test(() => {
const stream = new ReadableStream();
stream.getReader();
assert_xhr(stream);
}, "XMLHttpRequest: send() with a stream on which getReader() is called");
test(() => {
const stream = new ReadableStream();
stream.getReader().read();
assert_xhr(stream);
}, "XMLHttpRequest: send() with a stream on which read() is called");
promise_test(async () => {
const stream = new ReadableStream({ pull: c => c.enqueue(new Uint8Array()) }),
reader = stream.getReader();
await reader.read();
reader.releaseLock();
assert_xhr(stream);
}, "XMLHttpRequest: send() with a stream on which read() and releaseLock() are called");

View file

@ -215,24 +215,6 @@
// https://fetch.spec.whatwg.org/#bodyinit, so the user's must be changed to match it // https://fetch.spec.whatwg.org/#bodyinit, so the user's must be changed to match it
// as per https://xhr.spec.whatwg.org/#the-send%28%29-method step 4. // as per https://xhr.spec.whatwg.org/#the-send%28%29-method step 4.
) )
request(
function _ReadableStream() { return new ReadableStream() },
{"Content-Type": ""},
"",
'ReadableStream request respects setRequestHeader("")'
)
request(
function _ReadableStream() { return new ReadableStream() },
{},
undefined,
"ReadableStream request with under type sends no Content-Type without setRequestHeader() call"
)
request(
function _ReadableStream() { return new ReadableStream() },
{"Content-Type": "application/xml;charset=ASCII"},
"application/xml;charset=ASCII",
"ReadableStream request keeps setRequestHeader() Content-Type and charset"
)
</script> </script>
</body> </body>
</html> </html>