441 lines
13 KiB
JavaScript
441 lines
13 KiB
JavaScript
"use strict";
|
|
|
|
/* eslint-disable mozilla/no-comparison-or-assignment-inside-ok */
|
|
|
|
SimpleTest.waitForExplicitFinish();
|
|
|
|
var gen = runTests();
|
|
function continueTest() {
|
|
gen.next();
|
|
}
|
|
|
|
function* runTests() {
|
|
var expectHttp2Results = location.href.includes("http2");
|
|
|
|
var path = "/tests/dom/xhr/tests/";
|
|
|
|
var passFiles = [
|
|
["file_XHR_pass1.xml", "GET", 200, "OK", "text/xml"],
|
|
["file_XHR_pass2.txt", "GET", 200, "OK", "text/plain"],
|
|
["file_XHR_pass3.txt", "GET", 200, "OK", "text/plain"],
|
|
["data:text/xml,%3Cres%3Ehello%3C/res%3E%0A", "GET", 200, "OK", "text/xml"],
|
|
["data:text/plain,hello%20pass%0A", "GET", 200, "OK", "text/plain"],
|
|
["data:,foo", "GET", 200, "OK", "text/plain;charset=US-ASCII", "foo"],
|
|
["data:text/plain;base64,Zm9v", "GET", 200, "OK", "text/plain", "foo"],
|
|
["data:text/plain,foo#bar", "GET", 200, "OK", "text/plain", "foo"],
|
|
["data:text/plain,foo%23bar", "GET", 200, "OK", "text/plain", "foo#bar"],
|
|
];
|
|
|
|
var blob = new Blob(["foo"], { type: "text/plain" });
|
|
var blobURL = URL.createObjectURL(blob);
|
|
|
|
passFiles.push([blobURL, "GET", 200, "OK", "text/plain", "foo"]);
|
|
|
|
var failFiles = [
|
|
["//example.com" + path + "file_XHR_pass1.xml", "GET"],
|
|
["ftp://localhost" + path + "file_XHR_pass1.xml", "GET"],
|
|
["file_XHR_fail1.txt", "GET"],
|
|
];
|
|
|
|
for (i = 0; i < passFiles.length; ++i) {
|
|
// Function to give our hacked is() a scope
|
|
(function (oldIs) {
|
|
function is(actual, expected, message) {
|
|
oldIs(actual, expected, message + " for " + passFiles[i][0]);
|
|
}
|
|
xhr = new XMLHttpRequest();
|
|
is(xhr.getResponseHeader("Content-Type"), null, "should be null");
|
|
is(xhr.getAllResponseHeaders(), "", "should be empty string");
|
|
is(xhr.responseType, "", "wrong initial responseType");
|
|
xhr.open(passFiles[i][1], passFiles[i][0], false);
|
|
xhr.send(null);
|
|
is(xhr.status, passFiles[i][2], "wrong status");
|
|
|
|
// over HTTP2, no status text is received for network requests (but
|
|
// data/blob URLs default to "200 OK" responses)
|
|
let expectedStatusText = passFiles[i][3];
|
|
if (
|
|
expectHttp2Results &&
|
|
!passFiles[i][0].startsWith("data:") &&
|
|
!passFiles[i][0].startsWith("blob:")
|
|
) {
|
|
expectedStatusText = "";
|
|
}
|
|
is(xhr.statusText, expectedStatusText, "wrong statusText");
|
|
|
|
is(
|
|
xhr.getResponseHeader("Content-Type"),
|
|
passFiles[i][4],
|
|
"wrong content type"
|
|
);
|
|
var headers = xhr.getAllResponseHeaders();
|
|
ok(
|
|
/(?:^|\n)Content-Type:\s*([^\r\n]*)\r\n/i.test(headers) &&
|
|
RegExp.$1 === passFiles[i][4],
|
|
"wrong response headers"
|
|
);
|
|
if (xhr.responseXML) {
|
|
is(
|
|
new XMLSerializer().serializeToString(
|
|
xhr.responseXML.documentElement
|
|
),
|
|
passFiles[i][5] || "<res>hello</res>",
|
|
"wrong responseXML"
|
|
);
|
|
is(
|
|
xhr.response,
|
|
passFiles[i][5] || "<res>hello</res>\n",
|
|
"wrong response"
|
|
);
|
|
} else {
|
|
is(
|
|
xhr.responseText,
|
|
passFiles[i][5] || "hello pass\n",
|
|
"wrong responseText"
|
|
);
|
|
is(xhr.response, passFiles[i][5] || "hello pass\n", "wrong response");
|
|
}
|
|
})(is);
|
|
}
|
|
|
|
URL.revokeObjectURL(blobURL);
|
|
|
|
for (i = 0; i < failFiles.length; ++i) {
|
|
xhr = new XMLHttpRequest();
|
|
let didthrow = false;
|
|
try {
|
|
xhr.open(failFiles[i][1], failFiles[i][0], false);
|
|
xhr.send(null);
|
|
} catch (e) {
|
|
didthrow = true;
|
|
}
|
|
if (!didthrow) {
|
|
is(xhr.status, 301, "wrong status");
|
|
is(xhr.responseText, "redirect file\n", "wrong response");
|
|
} else {
|
|
ok(1, "should have thrown or given incorrect result");
|
|
}
|
|
}
|
|
|
|
function checkResponseTextAccessThrows(xhr) {
|
|
let didthrow = false;
|
|
try {
|
|
xhr.responseText;
|
|
} catch (e) {
|
|
didthrow = true;
|
|
}
|
|
ok(didthrow, "should have thrown when accessing responseText");
|
|
}
|
|
function checkResponseXMLAccessThrows(xhr) {
|
|
let didthrow = false;
|
|
try {
|
|
xhr.responseXML;
|
|
} catch (e) {
|
|
didthrow = true;
|
|
}
|
|
ok(didthrow, "should have thrown when accessing responseXML");
|
|
}
|
|
function checkSetResponseType(xhr, type) {
|
|
let didthrow = false;
|
|
try {
|
|
xhr.responseType = type;
|
|
} catch (e) {
|
|
didthrow = true;
|
|
}
|
|
is(xhr.responseType, type, "responseType should be " + type);
|
|
ok(!didthrow, "should not have thrown when setting responseType");
|
|
}
|
|
function checkSetResponseTypeThrows(xhr, type) {
|
|
let didthrow = false;
|
|
try {
|
|
xhr.responseType = type;
|
|
} catch (e) {
|
|
didthrow = true;
|
|
}
|
|
ok(didthrow, "should have thrown when setting responseType");
|
|
}
|
|
function checkOpenThrows(xhr, method, url, async) {
|
|
let didthrow = false;
|
|
try {
|
|
xhr.open(method, url, async);
|
|
} catch (e) {
|
|
didthrow = true;
|
|
}
|
|
ok(didthrow, "should have thrown when open is called");
|
|
}
|
|
|
|
// test if setting responseType before calling open() works
|
|
xhr = new XMLHttpRequest();
|
|
checkSetResponseType(xhr, "");
|
|
checkSetResponseType(xhr, "text");
|
|
checkSetResponseType(xhr, "document");
|
|
checkSetResponseType(xhr, "arraybuffer");
|
|
checkSetResponseType(xhr, "blob");
|
|
checkSetResponseType(xhr, "json");
|
|
checkOpenThrows(xhr, "GET", "file_XHR_pass2.txt", false);
|
|
|
|
// test response (sync, responseType is not changeable)
|
|
xhr = new XMLHttpRequest();
|
|
xhr.open("GET", "file_XHR_pass2.txt", false);
|
|
checkSetResponseTypeThrows(xhr, "");
|
|
checkSetResponseTypeThrows(xhr, "text");
|
|
checkSetResponseTypeThrows(xhr, "document");
|
|
checkSetResponseTypeThrows(xhr, "arraybuffer");
|
|
checkSetResponseTypeThrows(xhr, "blob");
|
|
checkSetResponseTypeThrows(xhr, "json");
|
|
xhr.send(null);
|
|
checkSetResponseTypeThrows(xhr, "document");
|
|
is(xhr.status, 200, "wrong status");
|
|
is(xhr.response, "hello pass\n", "wrong response");
|
|
|
|
// test response (responseType='document')
|
|
xhr = new XMLHttpRequest();
|
|
xhr.open("GET", "file_XHR_pass1.xml");
|
|
xhr.responseType = "document";
|
|
xhr.onloadend = continueTest;
|
|
xhr.send(null);
|
|
yield undefined;
|
|
checkSetResponseTypeThrows(xhr, "document");
|
|
is(xhr.status, 200, "wrong status");
|
|
checkResponseTextAccessThrows(xhr);
|
|
is(
|
|
new XMLSerializer().serializeToString(xhr.response.documentElement),
|
|
"<res>hello</res>",
|
|
"wrong response"
|
|
);
|
|
|
|
// test response (responseType='text')
|
|
xhr = new XMLHttpRequest();
|
|
xhr.open("GET", "file_XHR_pass2.txt");
|
|
xhr.responseType = "text";
|
|
xhr.onloadend = continueTest;
|
|
xhr.send(null);
|
|
yield undefined;
|
|
is(xhr.status, 200, "wrong status");
|
|
checkResponseXMLAccessThrows(xhr);
|
|
is(xhr.response, "hello pass\n", "wrong response");
|
|
|
|
// test response (responseType='arraybuffer')
|
|
function arraybuffer_equals_to(ab, s) {
|
|
is(ab.byteLength, s.length, "wrong arraybuffer byteLength");
|
|
|
|
var u8v = new Uint8Array(ab);
|
|
is(String.fromCharCode.apply(String, u8v), s, "wrong values");
|
|
}
|
|
|
|
// with a simple text file
|
|
xhr = new XMLHttpRequest();
|
|
xhr.open("GET", "file_XHR_pass2.txt");
|
|
xhr.responseType = "arraybuffer";
|
|
xhr.onloadend = continueTest;
|
|
xhr.send(null);
|
|
yield undefined;
|
|
is(xhr.status, 200, "wrong status");
|
|
checkResponseTextAccessThrows(xhr);
|
|
checkResponseXMLAccessThrows(xhr);
|
|
var ab = xhr.response;
|
|
ok(ab != null, "should have a non-null arraybuffer");
|
|
arraybuffer_equals_to(ab, "hello pass\n");
|
|
|
|
// test reusing the same XHR (Bug 680816)
|
|
xhr.open("GET", "file_XHR_binary1.bin");
|
|
xhr.responseType = "arraybuffer";
|
|
xhr.onloadend = continueTest;
|
|
xhr.send(null);
|
|
yield undefined;
|
|
is(xhr.status, 200, "wrong status");
|
|
var ab2 = xhr.response;
|
|
ok(ab2 != null, "should have a non-null arraybuffer");
|
|
ok(ab2 != ab, "arraybuffer on XHR reuse should be distinct");
|
|
arraybuffer_equals_to(ab, "hello pass\n");
|
|
arraybuffer_equals_to(ab2, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb");
|
|
|
|
// with a binary file
|
|
xhr = new XMLHttpRequest();
|
|
xhr.open("GET", "file_XHR_binary1.bin");
|
|
xhr.responseType = "arraybuffer";
|
|
xhr.onloadend = continueTest;
|
|
xhr.send(null);
|
|
yield undefined;
|
|
is(xhr.status, 200, "wrong status");
|
|
checkResponseTextAccessThrows(xhr);
|
|
checkResponseXMLAccessThrows(xhr);
|
|
ab = xhr.response;
|
|
ok(ab != null, "should have a non-null arraybuffer");
|
|
arraybuffer_equals_to(ab, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb");
|
|
is(xhr.response, xhr.response, "returns the same ArrayBuffer");
|
|
|
|
// test response (responseType='json')
|
|
var xhr = new XMLHttpRequest();
|
|
xhr.open("POST", "responseIdentical.sjs");
|
|
xhr.responseType = "json";
|
|
var jsonObjStr = JSON.stringify({ title: "aBook", author: "john" });
|
|
xhr.onloadend = continueTest;
|
|
xhr.send(jsonObjStr);
|
|
yield undefined;
|
|
is(xhr.status, 200, "wrong status");
|
|
checkResponseTextAccessThrows(xhr);
|
|
checkResponseXMLAccessThrows(xhr);
|
|
is(JSON.stringify(xhr.response), jsonObjStr, "correct result");
|
|
is(xhr.response, xhr.response, "returning the same object on each access");
|
|
|
|
// with invalid json
|
|
xhr = new XMLHttpRequest();
|
|
xhr.open("POST", "responseIdentical.sjs");
|
|
xhr.responseType = "json";
|
|
xhr.onloadend = continueTest;
|
|
xhr.send("{");
|
|
yield undefined;
|
|
is(xhr.status, 200, "wrong status");
|
|
checkResponseTextAccessThrows(xhr);
|
|
checkResponseXMLAccessThrows(xhr);
|
|
is(xhr.response, null, "Bad JSON should result in null response.");
|
|
is(
|
|
xhr.response,
|
|
null,
|
|
"Bad JSON should result in null response even 2nd time."
|
|
);
|
|
|
|
// Test status/statusText in all readyStates
|
|
xhr = new XMLHttpRequest();
|
|
function checkXHRStatus() {
|
|
if (xhr.readyState == xhr.UNSENT || xhr.readyState == xhr.OPENED) {
|
|
is(xhr.status, 0, "should be 0 before getting data");
|
|
is(xhr.statusText, "", "should be empty before getting data");
|
|
} else {
|
|
is(xhr.status, 200, "should be 200 when we have data");
|
|
if (expectHttp2Results) {
|
|
is(xhr.statusText, "", "should be '' when over HTTP2");
|
|
} else {
|
|
is(xhr.statusText, "OK", "should be OK when we have data");
|
|
}
|
|
}
|
|
}
|
|
checkXHRStatus();
|
|
xhr.open("GET", "file_XHR_binary1.bin");
|
|
checkXHRStatus();
|
|
xhr.responseType = "arraybuffer";
|
|
xhr.send(null);
|
|
xhr.onreadystatechange = continueTest;
|
|
while (xhr.readyState != 4) {
|
|
checkXHRStatus();
|
|
yield undefined;
|
|
}
|
|
checkXHRStatus();
|
|
|
|
// test response (responseType='blob')
|
|
// with a simple text file
|
|
xhr = new XMLHttpRequest();
|
|
xhr.open("GET", "file_XHR_pass2.txt");
|
|
xhr.responseType = "blob";
|
|
xhr.onloadend = continueTest;
|
|
xhr.send(null);
|
|
yield undefined;
|
|
is(xhr.status, 200, "wrong status");
|
|
checkResponseTextAccessThrows(xhr);
|
|
checkResponseXMLAccessThrows(xhr);
|
|
var b = xhr.response;
|
|
ok(b, "should have a non-null blob");
|
|
ok(b instanceof Blob, "should be a Blob");
|
|
ok(!(b instanceof File), "should not be a File");
|
|
is(b.size, "hello pass\n".length, "wrong blob size");
|
|
|
|
var fr = new FileReader();
|
|
fr.onload = continueTest;
|
|
fr.readAsBinaryString(b);
|
|
yield undefined;
|
|
is(fr.result, "hello pass\n", "wrong values");
|
|
|
|
// with a binary file
|
|
xhr = new XMLHttpRequest();
|
|
xhr.open("GET", "file_XHR_binary1.bin", true);
|
|
xhr.send(null);
|
|
xhr.onreadystatechange = continueTest;
|
|
while (xhr.readyState != 2) {
|
|
yield undefined;
|
|
}
|
|
|
|
is(xhr.status, 200, "wrong status");
|
|
xhr.responseType = "blob";
|
|
|
|
while (xhr.readyState != 4) {
|
|
yield undefined;
|
|
}
|
|
|
|
xhr.onreadystatechange = null;
|
|
|
|
b = xhr.response;
|
|
ok(b != null, "should have a non-null blob");
|
|
is(b.size, 12, "wrong blob size");
|
|
|
|
fr = new FileReader();
|
|
fr.readAsBinaryString(b);
|
|
xhr = null; // kill the XHR object
|
|
b = null;
|
|
SpecialPowers.gc();
|
|
fr.onload = continueTest;
|
|
yield undefined;
|
|
is(
|
|
fr.result,
|
|
"\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb",
|
|
"wrong values"
|
|
);
|
|
|
|
// with a larger binary file
|
|
xhr = new XMLHttpRequest();
|
|
xhr.open("GET", "file_XHR_binary2.bin", true);
|
|
xhr.responseType = "blob";
|
|
xhr.send(null);
|
|
xhr.onreadystatechange = continueTest;
|
|
|
|
while (xhr.readyState != 4) {
|
|
yield undefined;
|
|
}
|
|
|
|
xhr.onreadystatechange = null;
|
|
|
|
b = xhr.response;
|
|
ok(b != null, "should have a non-null blob");
|
|
is(b.size, 65536, "wrong blob size");
|
|
|
|
fr = new FileReader();
|
|
fr.readAsArrayBuffer(b);
|
|
fr.onload = continueTest;
|
|
xhr = null; // kill the XHR object
|
|
b = null;
|
|
SpecialPowers.gc();
|
|
yield undefined;
|
|
|
|
var u8 = new Uint8Array(fr.result);
|
|
for (var i = 0; i < 65536; i++) {
|
|
if (u8[i] !== (i & 255)) {
|
|
break;
|
|
}
|
|
}
|
|
is(i, 65536, "wrong value at offset " + i);
|
|
|
|
var client = new XMLHttpRequest();
|
|
client.open("GET", "file_XHR_pass1.xml", true);
|
|
client.send();
|
|
client.onreadystatechange = function () {
|
|
if (client.readyState == 4) {
|
|
try {
|
|
is(client.responseXML, null, "responseXML should be null.");
|
|
is(client.responseText, "", "responseText should be empty string.");
|
|
is(client.response, "", "response should be empty string.");
|
|
is(client.status, 0, "status should be 0.");
|
|
is(client.statusText, "", "statusText should be empty string.");
|
|
is(
|
|
client.getAllResponseHeaders(),
|
|
"",
|
|
"getAllResponseHeaders() should return empty string."
|
|
);
|
|
} catch (ex) {
|
|
ok(false, "Shouldn't throw! [" + ex + "]");
|
|
}
|
|
}
|
|
};
|
|
client.abort();
|
|
|
|
SimpleTest.finish();
|
|
} /* runTests */
|