aboutsummaryrefslogtreecommitdiffstats
path: root/tests/wpt/web-platform-tests/fetch/api
diff options
context:
space:
mode:
Diffstat (limited to 'tests/wpt/web-platform-tests/fetch/api')
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/cors/cors-expose-star.js2
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/redirect/redirect-method.js32
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/request/destination/fetch-destination.https.html134
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy0
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy.pngbin0 -> 18299 bytes
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_audio.mp3bin0 -> 20498 bytes
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_audio.ogabin0 -> 18541 bytes
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_video.mp4bin0 -> 67369 bytes
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_video.ogvbin0 -> 94372 bytes
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/request/destination/resources/empty.https.html0
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/request/destination/resources/fetch-destination-worker.js11
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/request/request-idl.html6
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/request/request-keepalive-quota.html71
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/resources/trickle.py2
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/response/response-idl.html6
15 files changed, 211 insertions, 53 deletions
diff --git a/tests/wpt/web-platform-tests/fetch/api/cors/cors-expose-star.js b/tests/wpt/web-platform-tests/fetch/api/cors/cors-expose-star.js
index e37ddb4c3f2..edf4d424179 100644
--- a/tests/wpt/web-platform-tests/fetch/api/cors/cors-expose-star.js
+++ b/tests/wpt/web-platform-tests/fetch/api/cors/cors-expose-star.js
@@ -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")
diff --git a/tests/wpt/web-platform-tests/fetch/api/redirect/redirect-method.js b/tests/wpt/web-platform-tests/fetch/api/redirect/redirect-method.js
index 13433a1bb39..0a7f2df2c2b 100644
--- a/tests/wpt/web-platform-tests/fetch/api/redirect/redirect-method.js
+++ b/tests/wpt/web-platform-tests/fetch/api/redirect/redirect-method.js
@@ -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();
diff --git a/tests/wpt/web-platform-tests/fetch/api/request/destination/fetch-destination.https.html b/tests/wpt/web-platform-tests/fetch/api/request/destination/fetch-destination.https.html
new file mode 100644
index 00000000000..b504bb9c238
--- /dev/null
+++ b/tests/wpt/web-platform-tests/fetch/api/request/destination/fetch-destination.https.html
@@ -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>
diff --git a/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy
diff --git a/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy.png b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy.png
new file mode 100644
index 00000000000..01c9666a8de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_audio.mp3 b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_audio.mp3
new file mode 100644
index 00000000000..0091330f1ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_audio.mp3
Binary files differ
diff --git a/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_audio.oga b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_audio.oga
new file mode 100644
index 00000000000..239ad2bd08c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_audio.oga
Binary files differ
diff --git a/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_video.mp4 b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_video.mp4
new file mode 100644
index 00000000000..7022e75c15e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_video.mp4
Binary files differ
diff --git a/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_video.ogv b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_video.ogv
new file mode 100644
index 00000000000..de99616eceb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_video.ogv
Binary files differ
diff --git a/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/empty.https.html b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/empty.https.html
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/empty.https.html
diff --git a/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/fetch-destination-worker.js b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/fetch-destination-worker.js
new file mode 100644
index 00000000000..f8e8e2669d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/fetch-destination-worker.js
@@ -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());
+ }
+ }
+});
+
diff --git a/tests/wpt/web-platform-tests/fetch/api/request/request-idl.html b/tests/wpt/web-platform-tests/fetch/api/request/request-idl.html
index f78f0ca894a..f7833779ce2 100644
--- a/tests/wpt/web-platform-tests/fetch/api/request/request-idl.html
+++ b/tests/wpt/web-platform-tests/fetch/api/request/request-idl.html
@@ -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;
diff --git a/tests/wpt/web-platform-tests/fetch/api/request/request-keepalive-quota.html b/tests/wpt/web-platform-tests/fetch/api/request/request-keepalive-quota.html
index dacc6382667..19596cea2c8 100644
--- a/tests/wpt/web-platform-tests/fetch/api/request/request-keepalive-quota.html
+++ b/tests/wpt/web-platform-tests/fetch/api/request/request-keepalive-quota.html
@@ -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>
diff --git a/tests/wpt/web-platform-tests/fetch/api/resources/trickle.py b/tests/wpt/web-platform-tests/fetch/api/resources/trickle.py
index 0e709445c59..319ecd21f45 100644
--- a/tests/wpt/web-platform-tests/fetch/api/resources/trickle.py
+++ b/tests/wpt/web-platform-tests/fetch/api/resources/trickle.py
@@ -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()
diff --git a/tests/wpt/web-platform-tests/fetch/api/response/response-idl.html b/tests/wpt/web-platform-tests/fetch/api/response/response-idl.html
index 3bbf54e6f3c..bd265fa203d 100644
--- a/tests/wpt/web-platform-tests/fetch/api/response/response-idl.html
+++ b/tests/wpt/web-platform-tests/fetch/api/response/response-idl.html
@@ -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;