@volter/tabnode 0.5.47 → 0.5.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -21191,17 +21191,10 @@ var implementation$1 = function bind2(that) {
|
|
|
21191
21191
|
var implementation = implementation$1;
|
|
21192
21192
|
var functionBind = Function.prototype.bind || implementation;
|
|
21193
21193
|
var functionCall = Function.prototype.call;
|
|
21194
|
-
var functionApply;
|
|
21195
|
-
var hasRequiredFunctionApply;
|
|
21196
|
-
function requireFunctionApply() {
|
|
21197
|
-
if (hasRequiredFunctionApply) return functionApply;
|
|
21198
|
-
hasRequiredFunctionApply = 1;
|
|
21199
|
-
functionApply = Function.prototype.apply;
|
|
21200
|
-
return functionApply;
|
|
21201
|
-
}
|
|
21194
|
+
var functionApply = Function.prototype.apply;
|
|
21202
21195
|
var reflectApply = typeof Reflect !== "undefined" && Reflect && Reflect.apply;
|
|
21203
21196
|
var bind$2 = functionBind;
|
|
21204
|
-
var $apply$1 =
|
|
21197
|
+
var $apply$1 = functionApply;
|
|
21205
21198
|
var $call$2 = functionCall;
|
|
21206
21199
|
var $reflectApply = reflectApply;
|
|
21207
21200
|
var actualApply = $reflectApply || bind$2.call($call$2, $apply$1);
|
|
@@ -21321,7 +21314,7 @@ var hasSymbols = requireHasSymbols()();
|
|
|
21321
21314
|
var getProto = requireGetProto();
|
|
21322
21315
|
var $ObjectGPO = requireObject_getPrototypeOf();
|
|
21323
21316
|
var $ReflectGPO = requireReflect_getPrototypeOf();
|
|
21324
|
-
var $apply =
|
|
21317
|
+
var $apply = functionApply;
|
|
21325
21318
|
var $call = functionCall;
|
|
21326
21319
|
var needsEval = {};
|
|
21327
21320
|
var TypedArray = typeof Uint8Array === "undefined" || !getProto ? undefined$1 : getProto(Uint8Array);
|
|
@@ -21962,7 +21955,7 @@ function requireApplyBind() {
|
|
|
21962
21955
|
if (hasRequiredApplyBind) return applyBind;
|
|
21963
21956
|
hasRequiredApplyBind = 1;
|
|
21964
21957
|
var bind3 = functionBind;
|
|
21965
|
-
var $apply2 =
|
|
21958
|
+
var $apply2 = functionApply;
|
|
21966
21959
|
var actualApply$1 = actualApply;
|
|
21967
21960
|
applyBind = function applyBind2() {
|
|
21968
21961
|
return actualApply$1(bind3, $apply2, arguments);
|
|
@@ -32282,6 +32275,123 @@ function guestFetch(process2, fallback) {
|
|
|
32282
32275
|
return fallback.call(globalThis, input, init);
|
|
32283
32276
|
};
|
|
32284
32277
|
}
|
|
32278
|
+
const INSTALLED = Symbol.for("tabnode.response.keepsSetCookie");
|
|
32279
|
+
function withCookies(own, given) {
|
|
32280
|
+
const headers = new Headers(own);
|
|
32281
|
+
if (!given) return headers;
|
|
32282
|
+
const cookies = [];
|
|
32283
|
+
if (typeof given.getSetCookie === "function") cookies.push(...given.getSetCookie());
|
|
32284
|
+
else given.forEach((value, name) => {
|
|
32285
|
+
if (name === "set-cookie") cookies.push(value);
|
|
32286
|
+
});
|
|
32287
|
+
if (cookies.length) {
|
|
32288
|
+
headers.delete("set-cookie");
|
|
32289
|
+
for (const cookie of cookies) headers.append("set-cookie", cookie);
|
|
32290
|
+
}
|
|
32291
|
+
const cookie2 = given.get("set-cookie2");
|
|
32292
|
+
if (cookie2 !== null) headers.set("set-cookie2", cookie2);
|
|
32293
|
+
return headers;
|
|
32294
|
+
}
|
|
32295
|
+
function givenHeaders(init) {
|
|
32296
|
+
const headers = init == null ? void 0 : init.headers;
|
|
32297
|
+
return headers === void 0 || headers === null ? void 0 : new Headers(headers);
|
|
32298
|
+
}
|
|
32299
|
+
function withHeaders(init, headers) {
|
|
32300
|
+
const status = init == null ? void 0 : init.status;
|
|
32301
|
+
const statusText = init == null ? void 0 : init.statusText;
|
|
32302
|
+
return {
|
|
32303
|
+
headers,
|
|
32304
|
+
...status === void 0 ? {} : { status },
|
|
32305
|
+
...statusText === void 0 ? {} : { statusText }
|
|
32306
|
+
};
|
|
32307
|
+
}
|
|
32308
|
+
function installNodeResponse(target) {
|
|
32309
|
+
var _a3;
|
|
32310
|
+
const Native = target.Response;
|
|
32311
|
+
if (typeof Native !== "function" || Native[INSTALLED]) return;
|
|
32312
|
+
const proto = Native.prototype;
|
|
32313
|
+
const nativeHeaders = (_a3 = Object.getOwnPropertyDescriptor(proto, "headers")) == null ? void 0 : _a3.get;
|
|
32314
|
+
const nativeFormData = proto.formData;
|
|
32315
|
+
const nativeBlob = proto.blob;
|
|
32316
|
+
const nativeArrayBuffer = proto.arrayBuffer;
|
|
32317
|
+
const nativeClone = proto.clone;
|
|
32318
|
+
if (!nativeHeaders) return;
|
|
32319
|
+
const kept = /* @__PURE__ */ new WeakMap();
|
|
32320
|
+
const NodeResponse = function Response2(body, init) {
|
|
32321
|
+
if (!new.target) throw new TypeError("Class constructor Response cannot be invoked without 'new'");
|
|
32322
|
+
const given = givenHeaders(init);
|
|
32323
|
+
const response = Reflect.construct(Native, [body, given ? withHeaders(init, given) : init], new.target === NodeResponse ? Native : new.target);
|
|
32324
|
+
kept.set(response, withCookies(nativeHeaders.call(response), given));
|
|
32325
|
+
return response;
|
|
32326
|
+
};
|
|
32327
|
+
NodeResponse.prototype = proto;
|
|
32328
|
+
Object.defineProperty(NodeResponse, "length", { value: 0, configurable: true });
|
|
32329
|
+
Object.defineProperty(NodeResponse, INSTALLED, { value: true });
|
|
32330
|
+
Object.setPrototypeOf(NodeResponse, Object.getPrototypeOf(Native));
|
|
32331
|
+
Object.defineProperty(NodeResponse, "json", {
|
|
32332
|
+
value: function json(data2, init) {
|
|
32333
|
+
const given = givenHeaders(init);
|
|
32334
|
+
const response = Native.json(data2, given ? withHeaders(init, given) : init);
|
|
32335
|
+
kept.set(response, withCookies(nativeHeaders.call(response), given));
|
|
32336
|
+
return response;
|
|
32337
|
+
},
|
|
32338
|
+
writable: true,
|
|
32339
|
+
configurable: true
|
|
32340
|
+
});
|
|
32341
|
+
Object.defineProperty(NodeResponse, "redirect", { value: function redirect(url2, status) {
|
|
32342
|
+
return Native.redirect(url2, status);
|
|
32343
|
+
}, writable: true, configurable: true });
|
|
32344
|
+
Object.defineProperty(NodeResponse, "error", { value: function error() {
|
|
32345
|
+
return Native.error();
|
|
32346
|
+
}, writable: true, configurable: true });
|
|
32347
|
+
defineOnHost(proto, "headers", {
|
|
32348
|
+
get() {
|
|
32349
|
+
return kept.get(this) ?? nativeHeaders.call(this);
|
|
32350
|
+
},
|
|
32351
|
+
enumerable: true,
|
|
32352
|
+
configurable: true
|
|
32353
|
+
});
|
|
32354
|
+
defineOnHost(proto, "constructor", { value: NodeResponse, writable: true, enumerable: false, configurable: true });
|
|
32355
|
+
defineOnHost(proto, "clone", {
|
|
32356
|
+
value: function clone() {
|
|
32357
|
+
const copy2 = nativeClone.call(this);
|
|
32358
|
+
const headers = kept.get(this);
|
|
32359
|
+
if (headers) kept.set(copy2, new Headers(headers));
|
|
32360
|
+
return copy2;
|
|
32361
|
+
},
|
|
32362
|
+
writable: true,
|
|
32363
|
+
enumerable: true,
|
|
32364
|
+
configurable: true
|
|
32365
|
+
});
|
|
32366
|
+
const changedType = (response) => {
|
|
32367
|
+
const headers = kept.get(response);
|
|
32368
|
+
if (!headers) return void 0;
|
|
32369
|
+
const current3 = headers.get("content-type");
|
|
32370
|
+
return current3 === nativeHeaders.call(response).get("content-type") ? void 0 : current3;
|
|
32371
|
+
};
|
|
32372
|
+
defineOnHost(proto, "formData", {
|
|
32373
|
+
value: async function formData() {
|
|
32374
|
+
const type2 = changedType(this);
|
|
32375
|
+
if (type2 === void 0) return nativeFormData.call(this);
|
|
32376
|
+
const bytes2 = await nativeArrayBuffer.call(this);
|
|
32377
|
+
return nativeFormData.call(Reflect.construct(Native, [bytes2, type2 === null ? {} : { headers: { "content-type": type2 } }]));
|
|
32378
|
+
},
|
|
32379
|
+
writable: true,
|
|
32380
|
+
enumerable: true,
|
|
32381
|
+
configurable: true
|
|
32382
|
+
});
|
|
32383
|
+
defineOnHost(proto, "blob", {
|
|
32384
|
+
value: async function blob() {
|
|
32385
|
+
const type2 = changedType(this);
|
|
32386
|
+
if (type2 === void 0) return nativeBlob.call(this);
|
|
32387
|
+
return new Blob([await nativeArrayBuffer.call(this)], type2 === null ? {} : { type: type2 });
|
|
32388
|
+
},
|
|
32389
|
+
writable: true,
|
|
32390
|
+
enumerable: true,
|
|
32391
|
+
configurable: true
|
|
32392
|
+
});
|
|
32393
|
+
takeFromHost(target, "Response", NodeResponse);
|
|
32394
|
+
}
|
|
32285
32395
|
function simpleHash(str) {
|
|
32286
32396
|
let hash2 = 0;
|
|
32287
32397
|
for (let i10 = 0; i10 < str.length; i10++) {
|
|
@@ -80461,6 +80571,9 @@ forGuestRealm(() => {
|
|
|
80461
80571
|
takeFromHost(globalThis, "Request", NodeRequest);
|
|
80462
80572
|
}
|
|
80463
80573
|
});
|
|
80574
|
+
forGuestRealm(() => {
|
|
80575
|
+
installNodeResponse(globalThis);
|
|
80576
|
+
});
|
|
80464
80577
|
forGuestRealm(() => {
|
|
80465
80578
|
const kIsClosedPromise = Symbol.for("nodejs.webstream.isClosedPromise");
|
|
80466
80579
|
const Native = globalThis.ReadableStream;
|
package/dist/index.mjs
CHANGED
|
@@ -32494,6 +32494,123 @@ function guestFetch(process2, fallback) {
|
|
|
32494
32494
|
return owner === null ? dispatch() : enterRun(owner, dispatch);
|
|
32495
32495
|
};
|
|
32496
32496
|
}
|
|
32497
|
+
const INSTALLED = Symbol.for("tabnode.response.keepsSetCookie");
|
|
32498
|
+
function withCookies(own, given) {
|
|
32499
|
+
const headers = new Headers(own);
|
|
32500
|
+
if (!given) return headers;
|
|
32501
|
+
const cookies = [];
|
|
32502
|
+
if (typeof given.getSetCookie === "function") cookies.push(...given.getSetCookie());
|
|
32503
|
+
else given.forEach((value, name) => {
|
|
32504
|
+
if (name === "set-cookie") cookies.push(value);
|
|
32505
|
+
});
|
|
32506
|
+
if (cookies.length) {
|
|
32507
|
+
headers.delete("set-cookie");
|
|
32508
|
+
for (const cookie of cookies) headers.append("set-cookie", cookie);
|
|
32509
|
+
}
|
|
32510
|
+
const cookie2 = given.get("set-cookie2");
|
|
32511
|
+
if (cookie2 !== null) headers.set("set-cookie2", cookie2);
|
|
32512
|
+
return headers;
|
|
32513
|
+
}
|
|
32514
|
+
function givenHeaders(init) {
|
|
32515
|
+
const headers = init == null ? void 0 : init.headers;
|
|
32516
|
+
return headers === void 0 || headers === null ? void 0 : new Headers(headers);
|
|
32517
|
+
}
|
|
32518
|
+
function withHeaders(init, headers) {
|
|
32519
|
+
const status = init == null ? void 0 : init.status;
|
|
32520
|
+
const statusText = init == null ? void 0 : init.statusText;
|
|
32521
|
+
return {
|
|
32522
|
+
headers,
|
|
32523
|
+
...status === void 0 ? {} : { status },
|
|
32524
|
+
...statusText === void 0 ? {} : { statusText }
|
|
32525
|
+
};
|
|
32526
|
+
}
|
|
32527
|
+
function installNodeResponse(target) {
|
|
32528
|
+
var _a2;
|
|
32529
|
+
const Native = target.Response;
|
|
32530
|
+
if (typeof Native !== "function" || Native[INSTALLED]) return;
|
|
32531
|
+
const proto = Native.prototype;
|
|
32532
|
+
const nativeHeaders = (_a2 = Object.getOwnPropertyDescriptor(proto, "headers")) == null ? void 0 : _a2.get;
|
|
32533
|
+
const nativeFormData = proto.formData;
|
|
32534
|
+
const nativeBlob = proto.blob;
|
|
32535
|
+
const nativeArrayBuffer = proto.arrayBuffer;
|
|
32536
|
+
const nativeClone = proto.clone;
|
|
32537
|
+
if (!nativeHeaders) return;
|
|
32538
|
+
const kept = /* @__PURE__ */ new WeakMap();
|
|
32539
|
+
const NodeResponse = function Response(body, init) {
|
|
32540
|
+
if (!new.target) throw new TypeError("Class constructor Response cannot be invoked without 'new'");
|
|
32541
|
+
const given = givenHeaders(init);
|
|
32542
|
+
const response = Reflect.construct(Native, [body, given ? withHeaders(init, given) : init], new.target === NodeResponse ? Native : new.target);
|
|
32543
|
+
kept.set(response, withCookies(nativeHeaders.call(response), given));
|
|
32544
|
+
return response;
|
|
32545
|
+
};
|
|
32546
|
+
NodeResponse.prototype = proto;
|
|
32547
|
+
Object.defineProperty(NodeResponse, "length", { value: 0, configurable: true });
|
|
32548
|
+
Object.defineProperty(NodeResponse, INSTALLED, { value: true });
|
|
32549
|
+
Object.setPrototypeOf(NodeResponse, Object.getPrototypeOf(Native));
|
|
32550
|
+
Object.defineProperty(NodeResponse, "json", {
|
|
32551
|
+
value: function json(data2, init) {
|
|
32552
|
+
const given = givenHeaders(init);
|
|
32553
|
+
const response = Native.json(data2, given ? withHeaders(init, given) : init);
|
|
32554
|
+
kept.set(response, withCookies(nativeHeaders.call(response), given));
|
|
32555
|
+
return response;
|
|
32556
|
+
},
|
|
32557
|
+
writable: true,
|
|
32558
|
+
configurable: true
|
|
32559
|
+
});
|
|
32560
|
+
Object.defineProperty(NodeResponse, "redirect", { value: function redirect(url2, status) {
|
|
32561
|
+
return Native.redirect(url2, status);
|
|
32562
|
+
}, writable: true, configurable: true });
|
|
32563
|
+
Object.defineProperty(NodeResponse, "error", { value: function error() {
|
|
32564
|
+
return Native.error();
|
|
32565
|
+
}, writable: true, configurable: true });
|
|
32566
|
+
defineOnHost(proto, "headers", {
|
|
32567
|
+
get() {
|
|
32568
|
+
return kept.get(this) ?? nativeHeaders.call(this);
|
|
32569
|
+
},
|
|
32570
|
+
enumerable: true,
|
|
32571
|
+
configurable: true
|
|
32572
|
+
});
|
|
32573
|
+
defineOnHost(proto, "constructor", { value: NodeResponse, writable: true, enumerable: false, configurable: true });
|
|
32574
|
+
defineOnHost(proto, "clone", {
|
|
32575
|
+
value: function clone() {
|
|
32576
|
+
const copy2 = nativeClone.call(this);
|
|
32577
|
+
const headers = kept.get(this);
|
|
32578
|
+
if (headers) kept.set(copy2, new Headers(headers));
|
|
32579
|
+
return copy2;
|
|
32580
|
+
},
|
|
32581
|
+
writable: true,
|
|
32582
|
+
enumerable: true,
|
|
32583
|
+
configurable: true
|
|
32584
|
+
});
|
|
32585
|
+
const changedType = (response) => {
|
|
32586
|
+
const headers = kept.get(response);
|
|
32587
|
+
if (!headers) return void 0;
|
|
32588
|
+
const current3 = headers.get("content-type");
|
|
32589
|
+
return current3 === nativeHeaders.call(response).get("content-type") ? void 0 : current3;
|
|
32590
|
+
};
|
|
32591
|
+
defineOnHost(proto, "formData", {
|
|
32592
|
+
value: async function formData() {
|
|
32593
|
+
const type2 = changedType(this);
|
|
32594
|
+
if (type2 === void 0) return nativeFormData.call(this);
|
|
32595
|
+
const bytes2 = await nativeArrayBuffer.call(this);
|
|
32596
|
+
return nativeFormData.call(Reflect.construct(Native, [bytes2, type2 === null ? {} : { headers: { "content-type": type2 } }]));
|
|
32597
|
+
},
|
|
32598
|
+
writable: true,
|
|
32599
|
+
enumerable: true,
|
|
32600
|
+
configurable: true
|
|
32601
|
+
});
|
|
32602
|
+
defineOnHost(proto, "blob", {
|
|
32603
|
+
value: async function blob() {
|
|
32604
|
+
const type2 = changedType(this);
|
|
32605
|
+
if (type2 === void 0) return nativeBlob.call(this);
|
|
32606
|
+
return new Blob([await nativeArrayBuffer.call(this)], type2 === null ? {} : { type: type2 });
|
|
32607
|
+
},
|
|
32608
|
+
writable: true,
|
|
32609
|
+
enumerable: true,
|
|
32610
|
+
configurable: true
|
|
32611
|
+
});
|
|
32612
|
+
takeFromHost(target, "Response", NodeResponse);
|
|
32613
|
+
}
|
|
32497
32614
|
function simpleHash(str) {
|
|
32498
32615
|
let hash2 = 0;
|
|
32499
32616
|
for (let i2 = 0; i2 < str.length; i2++) {
|
|
@@ -40126,6 +40243,9 @@ forGuestRealm(() => {
|
|
|
40126
40243
|
takeFromHost(globalThis, "Request", NodeRequest);
|
|
40127
40244
|
}
|
|
40128
40245
|
});
|
|
40246
|
+
forGuestRealm(() => {
|
|
40247
|
+
installNodeResponse(globalThis);
|
|
40248
|
+
});
|
|
40129
40249
|
forGuestRealm(() => {
|
|
40130
40250
|
const kIsClosedPromise = Symbol.for("nodejs.webstream.isClosedPromise");
|
|
40131
40251
|
const Native = globalThis.ReadableStream;
|
|
@@ -40428,7 +40548,7 @@ class WorkerRuntime {
|
|
|
40428
40548
|
this.worker = new Worker(
|
|
40429
40549
|
new URL(
|
|
40430
40550
|
/* @vite-ignore */
|
|
40431
|
-
"/assets/runtime-worker-
|
|
40551
|
+
"/assets/runtime-worker-B-BP9mj-.js",
|
|
40432
40552
|
import.meta.url
|
|
40433
40553
|
),
|
|
40434
40554
|
{ type: "module" }
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install the corrected constructor on `target` (the realm's global object),
|
|
3
|
+
* over the `Response` it has. Every property it changes is remembered for the
|
|
4
|
+
* host to have back (`restoreHostGlobals`); a realm that has it already is left.
|
|
5
|
+
*/
|
|
6
|
+
export declare function installNodeResponse(target: {
|
|
7
|
+
Response?: typeof Response;
|
|
8
|
+
}): void;
|
package/package.json
CHANGED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { defineOnHost, takeFromHost } from './host-globals';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A web `Response` that keeps its `Set-Cookie` headers, as Node's does.
|
|
5
|
+
*
|
|
6
|
+
* Node's `Response` (undici's) is built with a `Headers` that holds every
|
|
7
|
+
* header it was given, `Set-Cookie` and `Set-Cookie2` among them, readable
|
|
8
|
+
* through `get` (joined with ", "), iteration (one entry per cookie) and
|
|
9
|
+
* `getSetCookie()`, and mutable afterwards. A browser's applies the fetch
|
|
10
|
+
* specification's response guard, which drops both silently, on construction
|
|
11
|
+
* and on every later `append` or `set`: `new Response('', { headers:
|
|
12
|
+
* { 'set-cookie': 'a=1' } }).headers` is empty in a tab. A server that answers
|
|
13
|
+
* with a web Response (Next's route handlers and middleware, Hono, Remix,
|
|
14
|
+
* SvelteKit's adapters, NextAuth among them) then loses every cookie it sets
|
|
15
|
+
* before its answer is written to the socket, and no one can sign in.
|
|
16
|
+
*
|
|
17
|
+
* The realm's `Response` stays the browser's own class in all but its
|
|
18
|
+
* constructor: the constructor is a function whose `prototype` is the
|
|
19
|
+
* browser's `Response.prototype`, so a fetch's answer, `Response.error()` and
|
|
20
|
+
* a program's subclass are each `instanceof Response`, share its prototype and
|
|
21
|
+
* name it as their `constructor`, as on Node. A response a program constructs
|
|
22
|
+
* keeps a `Headers` of its own, made without a guard (a `Headers` a program
|
|
23
|
+
* constructs is one, in a browser too), holding the browser's headers and every
|
|
24
|
+
* cookie the program gave; `headers` answers it. The body methods whose answer
|
|
25
|
+
* depends on the content type (`formData`, `blob`) read the kept one, as Node
|
|
26
|
+
* reads the response's own headers.
|
|
27
|
+
*/
|
|
28
|
+
const INSTALLED = Symbol.for('tabnode.response.keepsSetCookie');
|
|
29
|
+
|
|
30
|
+
type ResponseConstructor = typeof Response & { [INSTALLED]?: true };
|
|
31
|
+
|
|
32
|
+
/** The browser's headers with the cookies its guard dropped. */
|
|
33
|
+
function withCookies(own: Headers, given: Headers | undefined): Headers {
|
|
34
|
+
const headers = new Headers(own);
|
|
35
|
+
if (!given) return headers;
|
|
36
|
+
const cookies: string[] = [];
|
|
37
|
+
if (typeof given.getSetCookie === 'function') cookies.push(...given.getSetCookie());
|
|
38
|
+
else given.forEach((value, name) => { if (name === 'set-cookie') cookies.push(value); });
|
|
39
|
+
if (cookies.length) {
|
|
40
|
+
headers.delete('set-cookie');
|
|
41
|
+
for (const cookie of cookies) headers.append('set-cookie', cookie);
|
|
42
|
+
}
|
|
43
|
+
const cookie2 = given.get('set-cookie2');
|
|
44
|
+
if (cookie2 !== null) headers.set('set-cookie2', cookie2);
|
|
45
|
+
return headers;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** The headers an init names, read once (an iterable may be a generator), as a guard-free `Headers`. */
|
|
49
|
+
function givenHeaders(init: ResponseInit | undefined): Headers | undefined {
|
|
50
|
+
const headers = init?.headers;
|
|
51
|
+
return headers === undefined || headers === null ? undefined : new Headers(headers);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The init with its headers replaced, read as the platform reads a
|
|
56
|
+
* dictionary: each member by name, inherited ones too (a `Response` passed as
|
|
57
|
+
* the init, as Next's `NextResponse` does, carries its status on a getter of
|
|
58
|
+
* its prototype, which a spread would not copy).
|
|
59
|
+
*/
|
|
60
|
+
function withHeaders(init: ResponseInit | undefined, headers: Headers): ResponseInit {
|
|
61
|
+
const status = init?.status;
|
|
62
|
+
const statusText = init?.statusText;
|
|
63
|
+
return {
|
|
64
|
+
headers,
|
|
65
|
+
...(status === undefined ? {} : { status }),
|
|
66
|
+
...(statusText === undefined ? {} : { statusText }),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Install the corrected constructor on `target` (the realm's global object),
|
|
72
|
+
* over the `Response` it has. Every property it changes is remembered for the
|
|
73
|
+
* host to have back (`restoreHostGlobals`); a realm that has it already is left.
|
|
74
|
+
*/
|
|
75
|
+
export function installNodeResponse(target: { Response?: typeof Response }): void {
|
|
76
|
+
const Native = target.Response as ResponseConstructor | undefined;
|
|
77
|
+
if (typeof Native !== 'function' || Native[INSTALLED]) return;
|
|
78
|
+
const proto = Native.prototype;
|
|
79
|
+
const nativeHeaders = Object.getOwnPropertyDescriptor(proto, 'headers')?.get;
|
|
80
|
+
const nativeFormData = proto.formData;
|
|
81
|
+
const nativeBlob = proto.blob;
|
|
82
|
+
const nativeArrayBuffer = proto.arrayBuffer;
|
|
83
|
+
const nativeClone = proto.clone;
|
|
84
|
+
if (!nativeHeaders) return;
|
|
85
|
+
const kept = new WeakMap<object, Headers>();
|
|
86
|
+
|
|
87
|
+
const NodeResponse = function Response(this: unknown, body?: BodyInit | null, init?: ResponseInit): Response {
|
|
88
|
+
if (!new.target) throw new TypeError("Class constructor Response cannot be invoked without 'new'");
|
|
89
|
+
const given = givenHeaders(init);
|
|
90
|
+
const response = Reflect.construct(Native, [body, given ? withHeaders(init, given) : init], (new.target as unknown) === NodeResponse ? Native : new.target) as Response;
|
|
91
|
+
kept.set(response, withCookies(nativeHeaders.call(response) as Headers, given));
|
|
92
|
+
return response;
|
|
93
|
+
} as unknown as ResponseConstructor;
|
|
94
|
+
NodeResponse.prototype = proto;
|
|
95
|
+
Object.defineProperty(NodeResponse, 'length', { value: 0, configurable: true });
|
|
96
|
+
Object.defineProperty(NodeResponse, INSTALLED, { value: true });
|
|
97
|
+
Object.setPrototypeOf(NodeResponse, Object.getPrototypeOf(Native));
|
|
98
|
+
|
|
99
|
+
// Node's statics answer a response whose headers are as mutable as a
|
|
100
|
+
// constructed one's (json) or immutable (redirect, error), as here.
|
|
101
|
+
Object.defineProperty(NodeResponse, 'json', {
|
|
102
|
+
value: function json(data: unknown, init?: ResponseInit): Response {
|
|
103
|
+
const given = givenHeaders(init);
|
|
104
|
+
const response = Native.json(data, given ? withHeaders(init, given) : init);
|
|
105
|
+
kept.set(response, withCookies(nativeHeaders.call(response) as Headers, given));
|
|
106
|
+
return response;
|
|
107
|
+
},
|
|
108
|
+
writable: true, configurable: true,
|
|
109
|
+
});
|
|
110
|
+
Object.defineProperty(NodeResponse, 'redirect', { value: function redirect(url: string | URL, status?: number): Response { return Native.redirect(url, status); }, writable: true, configurable: true });
|
|
111
|
+
Object.defineProperty(NodeResponse, 'error', { value: function error(): Response { return Native.error(); }, writable: true, configurable: true });
|
|
112
|
+
|
|
113
|
+
defineOnHost(proto, 'headers', {
|
|
114
|
+
get(this: Response): Headers { return kept.get(this) ?? (nativeHeaders.call(this) as Headers); },
|
|
115
|
+
enumerable: true, configurable: true,
|
|
116
|
+
});
|
|
117
|
+
defineOnHost(proto, 'constructor', { value: NodeResponse, writable: true, enumerable: false, configurable: true });
|
|
118
|
+
|
|
119
|
+
// A clone's headers are a copy of the original's, cookies and all.
|
|
120
|
+
defineOnHost(proto, 'clone', {
|
|
121
|
+
value: function clone(this: Response): Response {
|
|
122
|
+
const copy = nativeClone.call(this);
|
|
123
|
+
const headers = kept.get(this);
|
|
124
|
+
if (headers) kept.set(copy, new Headers(headers));
|
|
125
|
+
return copy;
|
|
126
|
+
},
|
|
127
|
+
writable: true, enumerable: true, configurable: true,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
/** The kept content type where it is no longer the one the browser's body was built with. */
|
|
131
|
+
const changedType = (response: Response): string | null | undefined => {
|
|
132
|
+
const headers = kept.get(response);
|
|
133
|
+
if (!headers) return undefined;
|
|
134
|
+
const current = headers.get('content-type');
|
|
135
|
+
return current === (nativeHeaders.call(response) as Headers).get('content-type') ? undefined : current;
|
|
136
|
+
};
|
|
137
|
+
defineOnHost(proto, 'formData', {
|
|
138
|
+
value: async function formData(this: Response): Promise<FormData> {
|
|
139
|
+
const type = changedType(this);
|
|
140
|
+
if (type === undefined) return nativeFormData.call(this);
|
|
141
|
+
const bytes = await nativeArrayBuffer.call(this);
|
|
142
|
+
return nativeFormData.call(Reflect.construct(Native, [bytes, type === null ? {} : { headers: { 'content-type': type } }]) as Response);
|
|
143
|
+
},
|
|
144
|
+
writable: true, enumerable: true, configurable: true,
|
|
145
|
+
});
|
|
146
|
+
defineOnHost(proto, 'blob', {
|
|
147
|
+
value: async function blob(this: Response): Promise<Blob> {
|
|
148
|
+
const type = changedType(this);
|
|
149
|
+
if (type === undefined) return nativeBlob.call(this);
|
|
150
|
+
return new Blob([await nativeArrayBuffer.call(this)], type === null ? {} : { type });
|
|
151
|
+
},
|
|
152
|
+
writable: true, enumerable: true, configurable: true,
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
takeFromHost(target, 'Response', NodeResponse);
|
|
156
|
+
}
|
|
157
|
+
|
package/src/runtime.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import { VirtualFS } from './virtual-fs';
|
|
9
9
|
import { guestPromise, intrinsicPromise } from './promise-ownership';
|
|
10
10
|
import { guestFetch, rememberRequestBodySource } from './fetch-transport';
|
|
11
|
+
import { installNodeResponse } from './node-response';
|
|
11
12
|
import { forGuestRealm, installGuestRealm, takeFromHost, defineOnHost, heldWork } from './host-globals';
|
|
12
13
|
import type { IRuntime, IExecuteResult, IRuntimeOptions } from './runtime-interface';
|
|
13
14
|
import type { PackageJson } from './types/package-json';
|
|
@@ -2974,6 +2975,12 @@ forGuestRealm(() => {
|
|
|
2974
2975
|
}
|
|
2975
2976
|
});
|
|
2976
2977
|
|
|
2978
|
+
forGuestRealm(() => {
|
|
2979
|
+
// A response keeps the Set-Cookie headers it was built with, as Node's
|
|
2980
|
+
// does; the browser's response guard drops them (see node-response.ts).
|
|
2981
|
+
installNodeResponse(globalThis);
|
|
2982
|
+
});
|
|
2983
|
+
|
|
2977
2984
|
forGuestRealm(() => {
|
|
2978
2985
|
// Node's `stream.finished()` on a web stream waits on a promise Node's own
|
|
2979
2986
|
// web streams carry (`nodejs.webstream.isClosedPromise`), settled when the
|