mirror of
https://github.com/denoland/deno.git
synced 2024-12-24 08:09:08 -05:00
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.
This commit is contained in:
parent
3973ceb634
commit
923370f18f
3 changed files with 33 additions and 12 deletions
|
@ -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");
|
||||
},
|
||||
);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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": [
|
||||
|
|
Loading…
Reference in a new issue