mirror of
https://github.com/servo/servo.git
synced 2025-08-15 10:25:32 +01:00
Update web-platform-tests to revision be5419e845d39089ba6dc338c1bd0fa279108317
This commit is contained in:
parent
aa199307c8
commit
2b6f573eb5
3440 changed files with 109438 additions and 41750 deletions
|
@ -31,7 +31,7 @@ promise_test(() => {
|
|||
}, "* for credentialed fetches only matches literally")
|
||||
|
||||
promise_test(() => {
|
||||
const headers = "header(Access-Control-Allow-Origin,*)|header(Access-Control-Expose-Headers,set-cookie)"
|
||||
const headers = "header(Access-Control-Allow-Origin,*)|header(Access-Control-Expose-Headers,set-cookie\\,*)"
|
||||
return fetch(url + sharedHeaders + headers).then(resp => {
|
||||
assert_equals(resp.status, 200)
|
||||
assert_equals(resp.type , "cors")
|
||||
|
|
|
@ -3,14 +3,22 @@ if (this.document === undefined) {
|
|||
importScripts("../resources/utils.js");
|
||||
}
|
||||
|
||||
function redirectMethod(desc, redirectUrl, redirectLocation, redirectStatus, method, expectedMethod) {
|
||||
// Creates a promise_test that fetches a URL that returns a redirect response.
|
||||
//
|
||||
// |opts| has additional options:
|
||||
// |opts.body|: the request body as a string or blob (default is empty body)
|
||||
// |opts.expectedBodyAsString|: the expected response body as a string. The
|
||||
// server is expected to echo the request body. The default is the empty string
|
||||
// if the request after redirection isn't POST; otherwise it's |opts.body|.
|
||||
function redirectMethod(desc, redirectUrl, redirectLocation, redirectStatus, method, expectedMethod, opts) {
|
||||
var url = redirectUrl;
|
||||
var urlParameters = "?redirect_status=" + redirectStatus;
|
||||
urlParameters += "&location=" + encodeURIComponent(redirectLocation);
|
||||
|
||||
var requestInit = {"method": method, "redirect": "follow"};
|
||||
if (method != "GET" && method != "HEAD")
|
||||
requestInit.body = "this is my body";
|
||||
opts = opts || {};
|
||||
if (opts.body)
|
||||
requestInit.body = opts.body;
|
||||
|
||||
promise_test(function(test) {
|
||||
return fetch(url + urlParameters, requestInit).then(function(resp) {
|
||||
|
@ -19,7 +27,10 @@ function redirectMethod(desc, redirectUrl, redirectLocation, redirectStatus, met
|
|||
assert_equals(resp.headers.get("x-request-method"), expectedMethod, "Request method after redirection is " + expectedMethod);
|
||||
assert_true(resp.redirected);
|
||||
return resp.text().then(function(text) {
|
||||
assert_equals(text, expectedMethod == "POST" ? requestInit.body : "");
|
||||
let expectedBody = "";
|
||||
if (expectedMethod == "POST")
|
||||
expectedBody = opts.expectedBodyAsString || requestInit.body;
|
||||
assert_equals(text, expectedBody, "request body");
|
||||
});
|
||||
});
|
||||
}, desc);
|
||||
|
@ -36,20 +47,25 @@ promise_test(function(test) {
|
|||
var redirUrl = RESOURCES_DIR + "redirect.py";
|
||||
var locationUrl = "method.py";
|
||||
|
||||
const stringBody = "this is my body";
|
||||
const blobBody = new Blob(["it's me the blob!", " ", "and more blob!"]);
|
||||
const blobBodyAsString = "it's me the blob! and more blob!";
|
||||
|
||||
redirectMethod("Redirect 301 with GET", redirUrl, locationUrl, 301, "GET", "GET");
|
||||
redirectMethod("Redirect 301 with POST", redirUrl, locationUrl, 301, "POST", "GET");
|
||||
redirectMethod("Redirect 301 with POST", redirUrl, locationUrl, 301, "POST", "GET", { body: stringBody });
|
||||
redirectMethod("Redirect 301 with HEAD", redirUrl, locationUrl, 301, "HEAD", "HEAD");
|
||||
|
||||
redirectMethod("Redirect 302 with GET", redirUrl, locationUrl, 302, "GET", "GET");
|
||||
redirectMethod("Redirect 302 with POST", redirUrl, locationUrl, 302, "POST", "GET");
|
||||
redirectMethod("Redirect 302 with POST", redirUrl, locationUrl, 302, "POST", "GET", { body: stringBody });
|
||||
redirectMethod("Redirect 302 with HEAD", redirUrl, locationUrl, 302, "HEAD", "HEAD");
|
||||
|
||||
redirectMethod("Redirect 303 with GET", redirUrl, locationUrl, 303, "GET", "GET");
|
||||
redirectMethod("Redirect 303 with POST", redirUrl, locationUrl, 303, "POST", "GET");
|
||||
redirectMethod("Redirect 303 with POST", redirUrl, locationUrl, 303, "POST", "GET", { body: stringBody });
|
||||
redirectMethod("Redirect 303 with HEAD", redirUrl, locationUrl, 303, "HEAD", "HEAD");
|
||||
|
||||
redirectMethod("Redirect 307 with GET", redirUrl, locationUrl, 307, "GET", "GET");
|
||||
redirectMethod("Redirect 307 with POST", redirUrl, locationUrl, 307, "POST", "POST");
|
||||
redirectMethod("Redirect 307 with POST (string body)", redirUrl, locationUrl, 307, "POST", "POST", { body: stringBody });
|
||||
redirectMethod("Redirect 307 with POST (blob body)", redirUrl, locationUrl, 307, "POST", "POST", { body: blobBody, expectedBodyAsString: blobBodyAsString });
|
||||
redirectMethod("Redirect 307 with HEAD", redirUrl, locationUrl, 307, "HEAD", "HEAD");
|
||||
|
||||
done();
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Service Worker: the body of FetchEvent using XMLHttpRequest</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/common/get-host-info.sub.js"></script>
|
||||
<script src="/common/media.js"></script>
|
||||
<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
|
||||
<script>
|
||||
let frame;
|
||||
|
||||
// Set up the service worker and the frame.
|
||||
promise_test(t => {
|
||||
const kScope = 'resources/empty.https.html';
|
||||
const kScript = 'resources/fetch-destination-worker.js';
|
||||
return service_worker_unregister_and_register(t, kScript, kScope)
|
||||
.then(registration => {
|
||||
add_completion_callback(() => {
|
||||
registration.unregister();
|
||||
});
|
||||
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(() => {
|
||||
return with_iframe(kScope);
|
||||
})
|
||||
.then(f => {
|
||||
frame = f;
|
||||
add_completion_callback(() => { f.remove(); });
|
||||
});
|
||||
}, 'Initialize global state');
|
||||
|
||||
// Actual tests
|
||||
|
||||
// HTMLImageElement - image destination
|
||||
promise_test(async t => {
|
||||
await new Promise((resolve, reject) => {
|
||||
var node = frame.contentWindow.document.createElement("img");
|
||||
node.onload = resolve;
|
||||
node.onerror = reject;
|
||||
node.src = "dummy.png?dest=image";
|
||||
}).catch(() => {
|
||||
assert_unreached("Fetch errored.");
|
||||
});
|
||||
}, 'HTMLImageElement fetches with an "image" Request.destination');
|
||||
|
||||
// fetch() - empty string destination
|
||||
promise_test(async t => {
|
||||
let response = await frame.contentWindow.fetch("dummy?dest=");
|
||||
assert_true(response.ok);
|
||||
}, 'fetch() fetches with an empty string Request.destination');
|
||||
|
||||
// HTMLAudioElement - audio destination
|
||||
promise_test(async t => {
|
||||
await new Promise((resolve, reject) => {
|
||||
var audioURL = getAudioURI("dummy_audio");
|
||||
var node = frame.contentWindow.document.createElement("audio");
|
||||
node.onloadeddata = resolve;
|
||||
node.onerror = reject;
|
||||
node.src = audioURL + "?dest=audio";
|
||||
}).catch(() => {
|
||||
assert_unreached("Fetch errored.");
|
||||
});
|
||||
}, 'HTMLAudioElement fetches with an "audio" Request.destination');
|
||||
|
||||
// HTMLVideoElement - video destination
|
||||
promise_test(async t => {
|
||||
await new Promise((resolve, reject) => {
|
||||
var videoURL = getVideoURI("dummy_video");
|
||||
var node = frame.contentWindow.document.createElement("video");
|
||||
node.onloadeddata = resolve;
|
||||
node.onerror = reject;
|
||||
node.src = videoURL + "?dest=video";
|
||||
}).catch(() => {
|
||||
assert_unreached("Fetch errored.");
|
||||
});
|
||||
}, 'HTMLVideoElement fetches with a "video" Request.destination');
|
||||
|
||||
// HTMLScriptElement - script destination
|
||||
promise_test(async t => {
|
||||
await new Promise((resolve, reject) => {
|
||||
var node = frame.contentWindow.document.createElement("script");
|
||||
node.onload = resolve;
|
||||
node.onerror = reject;
|
||||
node.src = "dummy?dest=script";
|
||||
frame.contentWindow.document.body.appendChild(node);
|
||||
}).catch(() => {
|
||||
assert_unreached("Fetch errored.");
|
||||
});
|
||||
}, 'HTMLScriptElement fetches with a "script" Request.destination');
|
||||
|
||||
// HTMLLinkElement with rel=stylesheet - script destination
|
||||
promise_test(async t => {
|
||||
await new Promise((resolve, reject) => {
|
||||
var node = frame.contentWindow.document.createElement("link");
|
||||
node.rel = "stylesheet";
|
||||
node.onload = resolve;
|
||||
node.onerror = reject;
|
||||
node.href = "dummy?dest=style";
|
||||
frame.contentWindow.document.body.appendChild(node);
|
||||
}).catch(() => {
|
||||
assert_unreached("Fetch errored.");
|
||||
});
|
||||
}, 'HTMLLinkElement with rel=stylesheet fetches with a "style" Request.destination');
|
||||
|
||||
// HTMLLinkElement with rel=preload and as=fetch - empty string destination
|
||||
promise_test(async t => {
|
||||
await new Promise((resolve, reject) => {
|
||||
var node = frame.contentWindow.document.createElement("link");
|
||||
node.rel = "preload";
|
||||
node.as = "fetch";
|
||||
node.onload = resolve;
|
||||
node.onerror = reject;
|
||||
node.href = "dummy?t=2&dest=";
|
||||
frame.contentWindow.document.body.appendChild(node);
|
||||
}).catch(() => {
|
||||
assert_unreached("Fetch errored.");
|
||||
});
|
||||
}, 'HTMLLinkElement with rel=preload and as=fetch fetches with an empty string Request.destination');
|
||||
|
||||
// HTMLLinkElement with rel=preload and as=style - style destination
|
||||
promise_test(async t => {
|
||||
await new Promise((resolve, reject) => {
|
||||
var node = frame.contentWindow.document.createElement("link");
|
||||
node.rel = "preload";
|
||||
node.as = "style";
|
||||
node.onload = resolve;
|
||||
node.onerror = reject;
|
||||
node.href = "dummy?t=2&dest=style";
|
||||
frame.contentWindow.document.body.appendChild(node);
|
||||
}).catch(() => {
|
||||
assert_unreached("Fetch errored.");
|
||||
});
|
||||
}, 'HTMLLinkElement with rel=preload and as=style fetches with a "style" Request.destination');
|
||||
</script>
|
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,11 @@
|
|||
self.addEventListener('fetch', function(event) {
|
||||
if (event.request.url.includes('dummy')) {
|
||||
let destination = new URL(event.request.url).searchParams.get("dest");
|
||||
if (event.request.destination == destination) {
|
||||
event.respondWith(fetch(event.request));
|
||||
} else {
|
||||
event.respondWith(Response.error());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -15,9 +15,7 @@
|
|||
typedef any JSON;
|
||||
typedef (Blob or BufferSource or FormData or URLSearchParams or USVString) BodyInit;
|
||||
|
||||
[NoInterfaceObject,
|
||||
Exposed=(Window,Worker)]
|
||||
interface Body {
|
||||
interface mixin Body {
|
||||
readonly attribute ReadableStream? body;
|
||||
readonly attribute boolean bodyUsed;
|
||||
[NewObject] Promise<ArrayBuffer> arrayBuffer();
|
||||
|
@ -48,7 +46,7 @@
|
|||
|
||||
[NewObject] Request clone();
|
||||
};
|
||||
Request implements Body;
|
||||
Request includes Body;
|
||||
|
||||
dictionary RequestInit {
|
||||
ByteString method;
|
||||
|
|
|
@ -12,81 +12,80 @@
|
|||
</head>
|
||||
<body>
|
||||
<script>
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
// We want to ensure that our keepalive requests hang slightly before completing so we can validate
|
||||
// the effects of a rolling quota. To do this we will utilize trickle.py with a 1s delay. This should
|
||||
// prevent any of the Fetch's from finishing in this window.
|
||||
var trickleURL = "../resources/trickle.py?count=1&ms=";
|
||||
var standardDelay = 1000;
|
||||
const trickleURL = '../resources/trickle.py?count=1&ms=';
|
||||
const noDelay = 0;
|
||||
const standardDelay = 1000;
|
||||
function wait(ms) {
|
||||
return new Promise(resolve => step_timeout(resolve, ms));
|
||||
}
|
||||
|
||||
// We should expect 64KiB of rolling quota for any type of keep-alive request sent.
|
||||
var expectedQuota = 65536;
|
||||
const expectedQuota = 65536;
|
||||
|
||||
function CreateKeepAliveRequest(delay, bodySize) {
|
||||
function fetchKeepAliveRequest(delay, bodySize) {
|
||||
// Create a body of the specified size that's filled with *'s
|
||||
var requestBody = "*".repeat(bodySize);
|
||||
return new Request(trickleURL+delay, {keepalive: true, body: requestBody, method: "POST"});
|
||||
const body = '*'.repeat(bodySize);
|
||||
return fetch(trickleURL + delay, {keepalive: true, body, method: 'POST'}).then(res => {
|
||||
return res.text();
|
||||
}).then(() => {
|
||||
return wait(1);
|
||||
});
|
||||
}
|
||||
|
||||
// Test 1 Byte
|
||||
promise_test(function(test) {
|
||||
return fetch(CreateKeepAliveRequest(0 /* delay */, 1 /* bodySize */));
|
||||
}, "A Keep-Alive fetch() with a small body should succeed.");
|
||||
return fetchKeepAliveRequest(noDelay, 1 /* bodySize */);
|
||||
}, 'A Keep-Alive fetch() with a small body should succeed.');
|
||||
|
||||
// Test Quota full limit
|
||||
promise_test(function(test) {
|
||||
return fetch(CreateKeepAliveRequest(0 /* delay */, expectedQuota));
|
||||
}, "A Keep-Alive fetch() with a body at the Quota Limit should succeed.");
|
||||
return fetchKeepAliveRequest(noDelay, expectedQuota /* bodySize */);
|
||||
}, 'A Keep-Alive fetch() with a body at the Quota Limit should succeed.');
|
||||
|
||||
// Test Quota + 1 Byte
|
||||
promise_test(function(test) {
|
||||
return promise_rejects(test, new TypeError(), fetch(CreateKeepAliveRequest(0 /* delay */, expectedQuota + 1)));
|
||||
}, "A Keep-Alive fetch() with a body over the Quota Limit should reject.");
|
||||
return promise_rejects(test, TypeError(), fetchKeepAliveRequest(noDelay, expectedQuota + 1));
|
||||
}, 'A Keep-Alive fetch() with a body over the Quota Limit should reject.');
|
||||
|
||||
// Test the Quota becomes available upon promise completion.
|
||||
promise_test(function (test) {
|
||||
// Fill our Quota then try to send a second fetch.
|
||||
var firstFetch = fetch(CreateKeepAliveRequest(standardDelay, expectedQuota)).then(function(response) {
|
||||
return fetchKeepAliveRequest(standardDelay, expectedQuota).then(() => {
|
||||
// Now validate that we can send another Keep-Alive fetch for the full size of the quota.
|
||||
return fetch(CreateKeepAliveRequest(0 /* delay */, expectedQuota));
|
||||
return fetchKeepAliveRequest(noDelay, expectedQuota);
|
||||
});
|
||||
|
||||
return firstFetch;
|
||||
}, "A Keep-Alive fetch() should return it's allocated Quota upon promise resolution.");
|
||||
}, 'A Keep-Alive fetch() should return its allocated Quota upon promise resolution.');
|
||||
|
||||
// Ensure only the correct amount of Quota becomes available when a fetch completes.
|
||||
promise_test(function(test) {
|
||||
var lastFetchSucceeded = false;
|
||||
// Create a fetch that uses all but 1 Byte of the Quota and runs for 2x as long as the other requests.
|
||||
var firstFetch = fetch(CreateKeepAliveRequest(standardDelay * 2, expectedQuota - 1)).then(function(response) {
|
||||
// This should be our last completing fetch(). We need to validate that the last fetch we sent out actually
|
||||
// completed.
|
||||
assert_true(lastFetchSucceeded, "Out last fetch after gaining Quota back should have succeeded.");
|
||||
});
|
||||
const first = fetchKeepAliveRequest(standardDelay * 2, expectedQuota - 1);
|
||||
|
||||
// Now create a single Byte request that will complete quicker.
|
||||
fetch(CreateKeepAliveRequest(standardDelay, 1 /* bodySize */)).then(function(response) {
|
||||
const second = fetchKeepAliveRequest(standardDelay, 1 /* bodySize */).then(() => {
|
||||
// We shouldn't be able to create a 2 Byte request right now as only 1 Byte should have freed up.
|
||||
assert_throws(new TypeError(), fetch(CreateKeepAliveRequest(0 /* delay */, 2 /* bodySize */)), "Only 1 Byte of Quota should be available right now.");
|
||||
|
||||
return promise_rejects(test, TypeError(), fetchKeepAliveRequest(noDelay, 2 /* bodySize */));
|
||||
}).then(() => {
|
||||
// Now validate that we can send another Keep-Alive fetch for just 1 Byte.
|
||||
fetch(CreateKeepAliveRequest(0 /* delay */, 1 /* bodySize */)).then(function(response) {
|
||||
// Flag we got a response from this request.
|
||||
lastFetchSucceeded = true;
|
||||
});
|
||||
return fetchKeepAliveRequest(noDelay, 1 /* bodySize */);
|
||||
});
|
||||
|
||||
return firstFetch;
|
||||
}, "A Keep-Alive fetch() should return only it's allocated Quota upon promise resolution.");
|
||||
return Promise.all([first, second]);
|
||||
}, 'A Keep-Alive fetch() should return only its allocated Quota upon promise resolution.');
|
||||
|
||||
// Test rejecting a fetch() after the quota is used up.
|
||||
promise_test(function (test) {
|
||||
// Fill our Quota then try to send a second fetch.
|
||||
fetch(CreateKeepAliveRequest(standardDelay, expectedQuota));
|
||||
const p = fetchKeepAliveRequest(standardDelay, expectedQuota);
|
||||
|
||||
return promise_rejects(test, new TypeError(), fetch(CreateKeepAliveRequest(0 /* delay */, 1 /* bodySize */)));
|
||||
}, "A Keep-Alive fetch() should not be allowed if the Quota is used up.");
|
||||
const q = promise_rejects(test, TypeError(), fetchKeepAliveRequest(noDelay, 1 /* bodySize */));
|
||||
return Promise.all([p, q]);
|
||||
}, 'A Keep-Alive fetch() should not be allowed if the Quota is used up.');
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -3,6 +3,8 @@ import time
|
|||
def main(request, response):
|
||||
delay = float(request.GET.first("ms", 500)) / 1E3
|
||||
count = int(request.GET.first("count", 50))
|
||||
# Read request body
|
||||
request.body
|
||||
time.sleep(delay)
|
||||
response.headers.set("Content-type", "text/plain")
|
||||
response.write_status_headers()
|
||||
|
|
|
@ -15,9 +15,7 @@
|
|||
typedef any JSON;
|
||||
typedef (Blob or BufferSource or FormData or URLSearchParams or USVString) BodyInit;
|
||||
|
||||
[NoInterfaceObject,
|
||||
Exposed=(Window,Worker)]
|
||||
interface Body {
|
||||
interface mixin Body {
|
||||
readonly attribute ReadableStream? body;
|
||||
readonly attribute boolean bodyUsed;
|
||||
[NewObject] Promise<ArrayBuffer> arrayBuffer();
|
||||
|
@ -45,7 +43,7 @@
|
|||
|
||||
[NewObject] Response clone();
|
||||
};
|
||||
Response implements Body;
|
||||
Response includes Body;
|
||||
|
||||
dictionary ResponseInit {
|
||||
unsigned short status = 200;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue