summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuca Casonato <hello@lcas.dev>2022-12-06 09:39:04 +0100
committerGitHub <noreply@github.com>2022-12-06 09:39:04 +0100
commit923370f18fc936e782ed9515744e675aebb59750 (patch)
treeb994a4eec4b58485ddd6e21dfd37da9b64f7f9ba
parent3973ceb634afe7b4f38678efe0394da84d9c60a1 (diff)
fix(ext/fetch): new Request should soft clone (#16869)
Previously the inner request object of the original and the new request were the same, causing the requests to be entangled and mutable changes to one to be visible to the other. This fixes that.
-rw-r--r--cli/tests/unit/fetch_test.ts29
-rw-r--r--ext/fetch/23_request.js12
-rw-r--r--tools/wpt/expectation.json4
3 files changed, 33 insertions, 12 deletions
diff --git a/cli/tests/unit/fetch_test.ts b/cli/tests/unit/fetch_test.ts
index a668bb480..fde119bf1 100644
--- a/cli/tests/unit/fetch_test.ts
+++ b/cli/tests/unit/fetch_test.ts
@@ -1776,9 +1776,7 @@ Deno.test(
Deno.test(
{ permissions: { net: true } },
- async function fetchBlobUrl(): Promise<
- void
- > {
+ async function fetchBlobUrl(): Promise<void> {
const blob = new Blob(["ok"], { type: "text/plain" });
const url = URL.createObjectURL(blob);
const res = await fetch(url);
@@ -1805,3 +1803,28 @@ Deno.test(
await promise;
},
);
+
+Deno.test(
+ { permissions: { net: true } },
+ async function fetchConstructorClones() {
+ const req = new Request("https://example.com", {
+ method: "POST",
+ body: "foo",
+ });
+ assertEquals(await req.text(), "foo");
+ await assertRejects(() => req.text());
+
+ const req2 = new Request(req, { method: "PUT", body: "bar" }); // should not have any impact on req
+ await assertRejects(() => req.text());
+ assertEquals(await req2.text(), "bar");
+
+ assertEquals(req.method, "POST");
+ assertEquals(req2.method, "PUT");
+
+ assertEquals(req.headers.get("x-foo"), null);
+ assertEquals(req2.headers.get("x-foo"), null);
+ req2.headers.set("x-foo", "bar"); // should not have any impact on req
+ assertEquals(req.headers.get("x-foo"), null);
+ assertEquals(req2.headers.get("x-foo"), "bar");
+ },
+);
diff --git a/ext/fetch/23_request.js b/ext/fetch/23_request.js
index 508a29139..c09e3326f 100644
--- a/ext/fetch/23_request.js
+++ b/ext/fetch/23_request.js
@@ -157,14 +157,14 @@
* @param {InnerRequest} request
* @returns {InnerRequest}
*/
- function cloneInnerRequest(request) {
+ function cloneInnerRequest(request, skipBody = false) {
const headerList = ArrayPrototypeMap(
request.headerList,
(x) => [x[0], x[1]],
);
let body = null;
- if (request.body !== null) {
+ if (request.body !== null && !skipBody) {
body = request.body.clone();
}
@@ -315,12 +315,14 @@
if (!ObjectPrototypeIsPrototypeOf(RequestPrototype, input)) {
throw new TypeError("Unreachable");
}
- request = input[_request];
+ const originalReq = input[_request];
+ // fold in of step 12 from below
+ request = cloneInnerRequest(originalReq, true);
+ request.redirectCount = 0; // reset to 0 - cloneInnerRequest copies the value
signal = input[_signal];
}
- // 12.
- // TODO(lucacasonato): create a copy of `request`
+ // 12. is folded into the else statement of step 6 above.
// 22.
if (init.redirect !== undefined) {
diff --git a/tools/wpt/expectation.json b/tools/wpt/expectation.json
index c58b8934f..cc026e988 100644
--- a/tools/wpt/expectation.json
+++ b/tools/wpt/expectation.json
@@ -2555,13 +2555,9 @@
"request-consume.any.html": true,
"request-consume.any.worker.html": true,
"request-disturbed.any.html": [
- "Request construction failure should not set \"bodyUsed\"",
- "Input request used for creating new request became disturbed",
"Input request used for creating new request became disturbed even if body is not used"
],
"request-disturbed.any.worker.html": [
- "Request construction failure should not set \"bodyUsed\"",
- "Input request used for creating new request became disturbed",
"Input request used for creating new request became disturbed even if body is not used"
],
"request-error.any.html": [