@ccheever/exact-ibex-runtime 0.1.0
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.
- package/package.json +63 -0
- package/src/abort/AbortController.ts +23 -0
- package/src/abort/AbortSignal.ts +152 -0
- package/src/abort/index.ts +2 -0
- package/src/accessibility.ts +12 -0
- package/src/arraybuffer-detach.ts +109 -0
- package/src/base64/base64.ts +168 -0
- package/src/base64/index.ts +1 -0
- package/src/blob/Blob.ts +259 -0
- package/src/blob/File.ts +59 -0
- package/src/blob/FormData.ts +323 -0
- package/src/blob/index.ts +3 -0
- package/src/bootstrap.ts +1946 -0
- package/src/broadcast/BroadcastChannel.ts +280 -0
- package/src/broadcast/index.ts +5 -0
- package/src/cache/Cache.ts +349 -0
- package/src/cache/CacheStorage.ts +89 -0
- package/src/cache/index.ts +27 -0
- package/src/camera/index.ts +6202 -0
- package/src/camera/processor.worker.ts +194 -0
- package/src/camera/scene.ts +195 -0
- package/src/clipboard/Clipboard.ts +129 -0
- package/src/clipboard/ClipboardItem.ts +97 -0
- package/src/clipboard/index.ts +6 -0
- package/src/clone/index.ts +1 -0
- package/src/clone/structuredClone.ts +389 -0
- package/src/clone/transferableSymbols.ts +2 -0
- package/src/compression/CompressionStream.ts +146 -0
- package/src/compression/DecompressionStream.ts +342 -0
- package/src/compression/index.ts +4 -0
- package/src/console/Console.ts +341 -0
- package/src/console/index.ts +2 -0
- package/src/core/accessibility-state.ts +263 -0
- package/src/core/accessibility.ts +184 -0
- package/src/core/agent-state.ts +37 -0
- package/src/core/diagnostics-logs.ts +144 -0
- package/src/core/host-call-bridge.ts +16 -0
- package/src/core/i18n-helpers.ts +189 -0
- package/src/core/locale-state.ts +253 -0
- package/src/core/locale.ts +95 -0
- package/src/crypto/Crypto.ts +2743 -0
- package/src/crypto/index.ts +1 -0
- package/src/diagnostics/logs.ts +7 -0
- package/src/encoding/TextDecoder.ts +1181 -0
- package/src/encoding/TextDecoderStream.ts +58 -0
- package/src/encoding/TextEncoder.ts +180 -0
- package/src/encoding/TextEncoderStream.ts +39 -0
- package/src/encoding/index.ts +8 -0
- package/src/events/CloseEvent.ts +91 -0
- package/src/events/DOMException.ts +409 -0
- package/src/events/ErrorEvent.ts +39 -0
- package/src/events/Event.ts +151 -0
- package/src/events/EventTarget.ts +280 -0
- package/src/events/FocusEvent.ts +27 -0
- package/src/events/KeyboardEvent.ts +46 -0
- package/src/events/MessageEvent.ts +61 -0
- package/src/events/ProgressEvent.ts +33 -0
- package/src/events/PromiseRejectionEvent.ts +31 -0
- package/src/events/index.ts +52 -0
- package/src/eventsource/EventSource.ts +371 -0
- package/src/eventsource/index.ts +2 -0
- package/src/fetch/Headers.ts +642 -0
- package/src/fetch/Request.ts +760 -0
- package/src/fetch/Response.ts +543 -0
- package/src/fetch/body.ts +1256 -0
- package/src/fetch/cookie-jar.ts +566 -0
- package/src/fetch/demo.ts +207 -0
- package/src/fetch/errors.ts +101 -0
- package/src/fetch/fetch.ts +2610 -0
- package/src/fetch/index.ts +101 -0
- package/src/fetch/native-bridge.ts +65 -0
- package/src/fetch/types.ts +258 -0
- package/src/filereader/FileReader.ts +236 -0
- package/src/filereader/index.ts +1 -0
- package/src/fs/Dirent.ts +39 -0
- package/src/fs/ExactFile.ts +450 -0
- package/src/fs/Stats.ts +80 -0
- package/src/fs/index.ts +944 -0
- package/src/fs/promises.ts +386 -0
- package/src/fs/shared.ts +328 -0
- package/src/http-server/index.js +697 -0
- package/src/http-server/index.ts +27 -0
- package/src/identity.generated.ts +14 -0
- package/src/index.ts +283 -0
- package/src/indexeddb/IDBCursor.ts +188 -0
- package/src/indexeddb/IDBDatabase.ts +343 -0
- package/src/indexeddb/IDBFactory.ts +269 -0
- package/src/indexeddb/IDBIndex.ts +194 -0
- package/src/indexeddb/IDBKeyRange.ts +109 -0
- package/src/indexeddb/IDBObjectStore.ts +468 -0
- package/src/indexeddb/IDBRequest.ts +163 -0
- package/src/indexeddb/IDBTransaction.ts +207 -0
- package/src/indexeddb/index.ts +34 -0
- package/src/indexeddb/utils.ts +52 -0
- package/src/inspect/index.ts +1 -0
- package/src/inspect/inspect.ts +465 -0
- package/src/internal/detect.ts +104 -0
- package/src/locale.ts +10 -0
- package/src/location/index.ts +1059 -0
- package/src/locks/LockManager.ts +460 -0
- package/src/locks/index.ts +12 -0
- package/src/media/VideoFrame.ts +58 -0
- package/src/messaging/MessageChannel.ts +31 -0
- package/src/messaging/MessagePort.ts +180 -0
- package/src/messaging/index.ts +2 -0
- package/src/messaging.ts +247 -0
- package/src/native/NativeModules.ts +354 -0
- package/src/native/index.ts +1 -0
- package/src/navigator/Navigator.ts +351 -0
- package/src/navigator/index.ts +1 -0
- package/src/node/Buffer.ts +1786 -0
- package/src/node/index.ts +4 -0
- package/src/node/path.ts +495 -0
- package/src/node/process.ts +2528 -0
- package/src/performance/Performance.ts +532 -0
- package/src/performance/index.ts +21 -0
- package/src/polyfills/array.ts +236 -0
- package/src/polyfills/arraybuffer.ts +172 -0
- package/src/polyfills/groupby.ts +85 -0
- package/src/polyfills/index.ts +85 -0
- package/src/polyfills/intl.ts +1956 -0
- package/src/polyfills/iterator.ts +479 -0
- package/src/polyfills/promise.ts +37 -0
- package/src/polyfills/set.ts +245 -0
- package/src/polyfills/string.ts +85 -0
- package/src/polyfills/typedarray.ts +110 -0
- package/src/promise-rejection-tracking.ts +464 -0
- package/src/react-native/index.ts +388 -0
- package/src/runtime-entry.ts +55 -0
- package/src/scheduling/AnimationFrame.ts +105 -0
- package/src/scheduling/IdleCallback.ts +167 -0
- package/src/scheduling/index.ts +13 -0
- package/src/security/Capabilities.ts +1146 -0
- package/src/security/Permissions.ts +392 -0
- package/src/security/capability-bits.generated.ts +63 -0
- package/src/security/index.ts +16 -0
- package/src/sqlite/Database.ts +456 -0
- package/src/sqlite/Statement.ts +206 -0
- package/src/sqlite/constants.ts +79 -0
- package/src/sqlite/errors.ts +25 -0
- package/src/sqlite/index.ts +34 -0
- package/src/sqlite/module.js +438 -0
- package/src/storage/Storage.ts +291 -0
- package/src/storage/StorageManager.ts +91 -0
- package/src/storage/index.ts +3 -0
- package/src/stream-compat.ts +47 -0
- package/src/streams/ReadableStream.ts +4131 -0
- package/src/streams/TransformStream.ts +375 -0
- package/src/streams/WritableStream.ts +866 -0
- package/src/streams/index.ts +41 -0
- package/src/timers/Timers.ts +296 -0
- package/src/timers/index.ts +11 -0
- package/src/url/URL.ts +656 -0
- package/src/url/URLPattern.ts +850 -0
- package/src/url/URLSearchParams.ts +244 -0
- package/src/url/index.ts +9 -0
- package/src/websocket/WebSocket.ts +770 -0
- package/src/websocket/WebSocketError.ts +52 -0
- package/src/websocket/WebSocketStream.ts +628 -0
- package/src/websocket/index.ts +7 -0
- package/src/window/index.ts +872 -0
|
@@ -0,0 +1,760 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* Request API Implementation
|
|
4
|
+
*
|
|
5
|
+
* Implements the WHATWG Fetch Standard Request interface.
|
|
6
|
+
* @see https://fetch.spec.whatwg.org/#request-class
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { Headers } from './Headers.js';
|
|
10
|
+
import {
|
|
11
|
+
BodyMixin,
|
|
12
|
+
arrayBufferViewToUint8Array,
|
|
13
|
+
bodyToUint8Array,
|
|
14
|
+
resolveWithoutThenable,
|
|
15
|
+
isBlob,
|
|
16
|
+
getContentTypeForBody,
|
|
17
|
+
isFormData as isFormDataBody,
|
|
18
|
+
encodeFormData,
|
|
19
|
+
getTextEncoder,
|
|
20
|
+
createReadableStreamFromUint8Array,
|
|
21
|
+
normalizeReadableStreamBody,
|
|
22
|
+
readableStreamToUint8Array,
|
|
23
|
+
isAsyncIterableBody,
|
|
24
|
+
createReadableStreamFromAsyncIterableBody,
|
|
25
|
+
} from './body.js';
|
|
26
|
+
import { Blob } from '../blob';
|
|
27
|
+
import { isReadableStream } from '../streams/index.js';
|
|
28
|
+
import type {
|
|
29
|
+
RequestInit,
|
|
30
|
+
RequestMethod,
|
|
31
|
+
RequestMode,
|
|
32
|
+
RequestCredentials,
|
|
33
|
+
RequestCache,
|
|
34
|
+
RequestRedirect,
|
|
35
|
+
ReferrerPolicy,
|
|
36
|
+
BodyInit,
|
|
37
|
+
} from './types.js';
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* HTTP methods that cannot have a body.
|
|
41
|
+
*/
|
|
42
|
+
const METHODS_WITHOUT_BODY = ['GET', 'HEAD'];
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* HTTP methods that are forbidden per the Fetch spec.
|
|
46
|
+
* These must throw TypeError when used in a Request constructor.
|
|
47
|
+
*/
|
|
48
|
+
const FORBIDDEN_METHODS = ['CONNECT', 'TRACE', 'TRACK'];
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Ports that are considered "bad" per the Fetch spec.
|
|
52
|
+
* Fetching from these ports must be blocked.
|
|
53
|
+
*/
|
|
54
|
+
const BAD_PORTS = new Set([
|
|
55
|
+
0, 1, 7, 9, 11, 13, 15, 17, 19, 20, 21, 22, 23, 25, 37, 42, 43, 53, 69, 77, 79,
|
|
56
|
+
87, 95, 101, 102, 103, 104, 109, 110, 111, 113, 115, 117, 119, 123, 135, 137,
|
|
57
|
+
139, 143, 161, 179, 389, 427, 465, 512, 513, 514, 515, 526, 530, 531, 532, 540,
|
|
58
|
+
548, 556, 563, 587, 601, 636, 989, 990, 993, 995, 1719, 1720, 1723, 2049, 3659, 4045,
|
|
59
|
+
4190, 5060, 5061, 6000, 6566, 6665, 6666, 6667, 6668, 6669, 6679, 6697, 10080,
|
|
60
|
+
]);
|
|
61
|
+
|
|
62
|
+
function isBunCompatRequestTest(): boolean {
|
|
63
|
+
if ((globalThis as { __exactRuntimeContext?: string }).__exactRuntimeContext === 'shell') {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
if (typeof process !== 'object' || !process || typeof process.env !== 'object') {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return process.env.EXACT_COMPAT_TEST === '1' && process.env.EXACT_TEST_SECTION === 'bun';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* The Request interface of the Fetch API represents a resource request.
|
|
75
|
+
*/
|
|
76
|
+
/**
|
|
77
|
+
* Input types for the Request constructor.
|
|
78
|
+
*/
|
|
79
|
+
export type RequestInput = string | URL | Request;
|
|
80
|
+
|
|
81
|
+
type RequestLikeInput = Partial<RequestInit> & {
|
|
82
|
+
url: unknown;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The Request interface of the Fetch API represents a resource request.
|
|
87
|
+
*/
|
|
88
|
+
export class Request extends BodyMixin {
|
|
89
|
+
private _method: RequestMethod;
|
|
90
|
+
private _url: string;
|
|
91
|
+
private _headers: Headers;
|
|
92
|
+
private _mode: RequestMode;
|
|
93
|
+
private _credentials: RequestCredentials;
|
|
94
|
+
private _cache: RequestCache;
|
|
95
|
+
private _redirect: RequestRedirect;
|
|
96
|
+
private _referrer: string;
|
|
97
|
+
private _referrerPolicy: ReferrerPolicy;
|
|
98
|
+
private _integrity: string;
|
|
99
|
+
// Note: _signal is inherited from BodyMixin (public) — do NOT redeclare here
|
|
100
|
+
// so that BodyMixin._checkAbortSignal() can read the abort signal.
|
|
101
|
+
private _priority: 'high' | 'low' | 'auto';
|
|
102
|
+
private _keepalive: boolean;
|
|
103
|
+
private _keepaliveExplicitlySet: boolean;
|
|
104
|
+
private _bodyInit: BodyInit | null = null;
|
|
105
|
+
|
|
106
|
+
constructor(input: RequestInput, init?: RequestInit) {
|
|
107
|
+
super();
|
|
108
|
+
|
|
109
|
+
// Ensure Request() is called with `new` (guard against transpiled classes)
|
|
110
|
+
if (!(this instanceof Request)) {
|
|
111
|
+
throw new TypeError("Failed to construct 'Request': Please use the 'new' operator, this DOM object constructor cannot be called as a function.");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Parse input
|
|
115
|
+
let url: string;
|
|
116
|
+
let inputRequest: Request | null = null;
|
|
117
|
+
let inputRequestLike: RequestLikeInput | null = null;
|
|
118
|
+
|
|
119
|
+
if (typeof input === 'string') {
|
|
120
|
+
url = input;
|
|
121
|
+
} else if (input instanceof URL) {
|
|
122
|
+
url = input.href;
|
|
123
|
+
} else if (input instanceof Request) {
|
|
124
|
+
inputRequest = input;
|
|
125
|
+
url = input.url;
|
|
126
|
+
} else if (
|
|
127
|
+
typeof input === 'object' &&
|
|
128
|
+
input !== null &&
|
|
129
|
+
'url' in (input as Record<string, unknown>)
|
|
130
|
+
) {
|
|
131
|
+
inputRequestLike = input as RequestLikeInput;
|
|
132
|
+
url = String(inputRequestLike.url);
|
|
133
|
+
} else {
|
|
134
|
+
// Per WebIDL spec: convert to USVString
|
|
135
|
+
url = String(input);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Validate and store URL
|
|
139
|
+
// Try to parse with URL class if available, otherwise do basic validation
|
|
140
|
+
if (typeof URL !== 'undefined') {
|
|
141
|
+
try {
|
|
142
|
+
const hasScheme = /^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(url);
|
|
143
|
+
const locationHref =
|
|
144
|
+
typeof (globalThis as any).location === 'object' &&
|
|
145
|
+
(globalThis as any).location !== null &&
|
|
146
|
+
typeof (globalThis as any).location.href === 'string'
|
|
147
|
+
? (globalThis as any).location.href
|
|
148
|
+
: undefined;
|
|
149
|
+
const processEnv =
|
|
150
|
+
(globalThis as { __exactRuntimeContext?: string }).__exactRuntimeContext === 'shell'
|
|
151
|
+
? null
|
|
152
|
+
: typeof process === 'object' && process && typeof process.env === 'object'
|
|
153
|
+
? (process.env as Record<string, string | undefined>)
|
|
154
|
+
: null;
|
|
155
|
+
const defaultBase =
|
|
156
|
+
locationHref ||
|
|
157
|
+
(processEnv?.WPT_SERVER_URL ?? undefined) ||
|
|
158
|
+
(typeof globalThis.location === 'string' ? globalThis.location : null);
|
|
159
|
+
const baseForParse = hasScheme || !defaultBase ? undefined : defaultBase;
|
|
160
|
+
const parsedUrl = baseForParse ? new URL(url, baseForParse) : new URL(url);
|
|
161
|
+
// Per Fetch spec: strip fragment from request URL
|
|
162
|
+
parsedUrl.hash = '';
|
|
163
|
+
this._url = parsedUrl.href;
|
|
164
|
+
} catch {
|
|
165
|
+
throw new TypeError(`Invalid URL: ${url}`);
|
|
166
|
+
}
|
|
167
|
+
} else {
|
|
168
|
+
// Fallback: basic URL validation when URL class is not available
|
|
169
|
+
if (!url || typeof url !== 'string') {
|
|
170
|
+
throw new TypeError(`Invalid URL: ${url}`);
|
|
171
|
+
}
|
|
172
|
+
// Accept any scheme (not just http/https) — the Fetch spec allows constructing
|
|
173
|
+
// Requests with any URL, rejecting unsupported schemes only at fetch() time
|
|
174
|
+
if (!/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(url)) {
|
|
175
|
+
throw new TypeError(`Invalid URL: ${url}`);
|
|
176
|
+
}
|
|
177
|
+
this._url = url;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Validate window option per spec
|
|
181
|
+
if (init && 'window' in init && (init as any).window !== null && (init as any).window !== undefined) {
|
|
182
|
+
throw new TypeError("Failed to construct 'Request': 'window' option must be null");
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Validate duplex option per spec — only 'half' is valid
|
|
186
|
+
if ((init as any)?.duplex !== undefined && (init as any).duplex !== 'half') {
|
|
187
|
+
throw new TypeError("Failed to construct 'Request': The provided value '" + (init as any).duplex + "' is not a valid enum value of type RequestDuplex.");
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Initialize from input request or defaults
|
|
191
|
+
const rawMethod =
|
|
192
|
+
init?.method ??
|
|
193
|
+
inputRequest?.method ??
|
|
194
|
+
inputRequestLike?.method ??
|
|
195
|
+
'GET';
|
|
196
|
+
// Validate method is a valid HTTP token
|
|
197
|
+
if (typeof rawMethod === 'string' && !/^[\w!#$%&'*+.^`|~-]+$/.test(rawMethod)) {
|
|
198
|
+
throw new TypeError(`Failed to construct 'Request': '${rawMethod}' is not a valid HTTP method.`);
|
|
199
|
+
}
|
|
200
|
+
this._method = (rawMethod as string).toUpperCase() as RequestMethod;
|
|
201
|
+
|
|
202
|
+
// Validate forbidden methods per Fetch spec
|
|
203
|
+
if (FORBIDDEN_METHODS.includes(this._method)) {
|
|
204
|
+
throw new TypeError(`Failed to construct 'Request': '${this._method}' HTTP method is unsupported.`);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Validate bad ports
|
|
208
|
+
if (typeof URL !== 'undefined') {
|
|
209
|
+
try {
|
|
210
|
+
const parsedForPort = new URL(this._url);
|
|
211
|
+
if (parsedForPort.port && BAD_PORTS.has(Number(parsedForPort.port))) {
|
|
212
|
+
throw new TypeError(`Failed to construct 'Request': The port ${parsedForPort.port} is not allowed.`);
|
|
213
|
+
}
|
|
214
|
+
// Validate no credentials in URL per Fetch spec
|
|
215
|
+
if (parsedForPort.username || parsedForPort.password) {
|
|
216
|
+
throw new TypeError("Failed to construct 'Request': Request cannot be constructed from a URL that includes credentials.");
|
|
217
|
+
}
|
|
218
|
+
} catch (e) {
|
|
219
|
+
if (e instanceof TypeError) throw e;
|
|
220
|
+
// URL already validated above, ignore parse errors here
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Validate enum values per spec
|
|
225
|
+
const VALID_MODES = ['cors', 'no-cors', 'same-origin', 'navigate'];
|
|
226
|
+
const VALID_CREDENTIALS = ['omit', 'same-origin', 'include'];
|
|
227
|
+
const VALID_CACHE = ['default', 'no-store', 'reload', 'no-cache', 'force-cache', 'only-if-cached'];
|
|
228
|
+
const VALID_REDIRECT = ['follow', 'error', 'manual'];
|
|
229
|
+
const VALID_REFERRER_POLICY = ['', 'no-referrer', 'no-referrer-when-downgrade', 'same-origin', 'origin', 'strict-origin', 'origin-when-cross-origin', 'strict-origin-when-cross-origin', 'unsafe-url'];
|
|
230
|
+
|
|
231
|
+
if (init?.mode !== undefined && !VALID_MODES.includes(init.mode as string)) {
|
|
232
|
+
throw new TypeError(`Failed to construct 'Request': The provided value '${init.mode}' is not a valid enum value of type RequestMode.`);
|
|
233
|
+
}
|
|
234
|
+
if (init?.credentials !== undefined && !VALID_CREDENTIALS.includes(init.credentials as string)) {
|
|
235
|
+
throw new TypeError(`Failed to construct 'Request': The provided value '${init.credentials}' is not a valid enum value of type RequestCredentials.`);
|
|
236
|
+
}
|
|
237
|
+
if (init?.cache !== undefined && !VALID_CACHE.includes(init.cache as string)) {
|
|
238
|
+
throw new TypeError(`Failed to construct 'Request': The provided value '${init.cache}' is not a valid enum value of type RequestCache.`);
|
|
239
|
+
}
|
|
240
|
+
if (init?.redirect !== undefined && !VALID_REDIRECT.includes(init.redirect as string)) {
|
|
241
|
+
throw new TypeError(`Failed to construct 'Request': The provided value '${init.redirect}' is not a valid enum value of type RequestRedirect.`);
|
|
242
|
+
}
|
|
243
|
+
if (init?.referrerPolicy !== undefined && !VALID_REFERRER_POLICY.includes(init.referrerPolicy as string)) {
|
|
244
|
+
throw new TypeError(`Failed to construct 'Request': The provided value '${init.referrerPolicy}' is not a valid enum value of type ReferrerPolicy.`);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Validate mode per spec
|
|
248
|
+
const modeValue = init?.mode ?? inputRequest?.mode ?? inputRequestLike?.mode ?? 'cors';
|
|
249
|
+
if (init?.mode === 'navigate' as any) {
|
|
250
|
+
throw new TypeError("Failed to construct 'Request': 'navigate' mode can only be used in service workers.");
|
|
251
|
+
}
|
|
252
|
+
this._mode = modeValue;
|
|
253
|
+
this._credentials = init?.credentials ?? inputRequest?.credentials ?? inputRequestLike?.credentials ?? 'same-origin';
|
|
254
|
+
this._cache = init?.cache ?? inputRequest?.cache ?? inputRequestLike?.cache ?? 'default';
|
|
255
|
+
this._redirect = init?.redirect ?? inputRequest?.redirect ?? inputRequestLike?.redirect ?? 'follow';
|
|
256
|
+
|
|
257
|
+
// Validate referrer
|
|
258
|
+
const referrer = init?.referrer ?? inputRequest?.referrer ?? inputRequestLike?.referrer ?? 'about:client';
|
|
259
|
+
if (referrer !== '' && referrer !== 'about:client' && referrer !== 'no-referrer') {
|
|
260
|
+
// Must be a valid URL
|
|
261
|
+
if (typeof URL !== 'undefined') {
|
|
262
|
+
try {
|
|
263
|
+
new URL(referrer);
|
|
264
|
+
} catch {
|
|
265
|
+
throw new TypeError(`Failed to construct 'Request': '${referrer}' is not a valid URL.`);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
this._referrer = referrer;
|
|
270
|
+
this._referrerPolicy = init?.referrerPolicy ?? inputRequest?.referrerPolicy ?? inputRequestLike?.referrerPolicy ?? '';
|
|
271
|
+
this._integrity = init?.integrity ?? inputRequest?.integrity ?? inputRequestLike?.integrity ?? '';
|
|
272
|
+
// Per spec: Request creates its own signal that follows the provided signal
|
|
273
|
+
// Use 'in' check so that explicit `signal: null` overrides the input request's signal
|
|
274
|
+
const sourceSignal = (init && 'signal' in init)
|
|
275
|
+
? init.signal
|
|
276
|
+
: (inputRequest?.signal ?? inputRequestLike?.signal ?? null);
|
|
277
|
+
if (sourceSignal && typeof AbortController !== 'undefined') {
|
|
278
|
+
const ac = new AbortController();
|
|
279
|
+
if (sourceSignal.aborted) {
|
|
280
|
+
ac.abort(sourceSignal.reason);
|
|
281
|
+
} else {
|
|
282
|
+
sourceSignal.addEventListener('abort', () => {
|
|
283
|
+
ac.abort(sourceSignal.reason);
|
|
284
|
+
}, { once: true });
|
|
285
|
+
}
|
|
286
|
+
this._signal = ac.signal;
|
|
287
|
+
} else {
|
|
288
|
+
this._signal = sourceSignal;
|
|
289
|
+
}
|
|
290
|
+
const VALID_PRIORITIES = ['high', 'low', 'auto'];
|
|
291
|
+
if ((init as any)?.priority !== undefined && !VALID_PRIORITIES.includes((init as any).priority)) {
|
|
292
|
+
throw new TypeError(`Failed to construct 'Request': The provided value '${(init as any).priority}' is not a valid enum value of type RequestPriority.`);
|
|
293
|
+
}
|
|
294
|
+
this._priority = (init as any)?.priority ?? (inputRequestLike as any)?.priority ?? 'auto';
|
|
295
|
+
const initHasKeepalive = init !== undefined && init !== null && 'keepalive' in init;
|
|
296
|
+
const inputRequestLikeHasKeepalive =
|
|
297
|
+
inputRequestLike !== null &&
|
|
298
|
+
inputRequestLike !== undefined &&
|
|
299
|
+
'keepalive' in inputRequestLike;
|
|
300
|
+
this._keepaliveExplicitlySet =
|
|
301
|
+
initHasKeepalive ||
|
|
302
|
+
(inputRequest ? inputRequest._keepaliveExplicitlySet : inputRequestLikeHasKeepalive);
|
|
303
|
+
this._keepalive = Boolean(
|
|
304
|
+
(init as any)?.keepalive ??
|
|
305
|
+
inputRequest?.keepalive ??
|
|
306
|
+
(inputRequestLike as any)?.keepalive ??
|
|
307
|
+
false
|
|
308
|
+
);
|
|
309
|
+
|
|
310
|
+
// Validate only-if-cached requires same-origin mode
|
|
311
|
+
if (this._cache === 'only-if-cached' && this._mode !== 'same-origin') {
|
|
312
|
+
throw new TypeError("Failed to construct 'Request': 'only-if-cached' cache mode requires 'same-origin' mode.");
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Validate no-cors mode restrictions
|
|
316
|
+
if (this._mode === 'no-cors') {
|
|
317
|
+
const SIMPLE_METHODS = ['GET', 'HEAD', 'POST'];
|
|
318
|
+
if (!SIMPLE_METHODS.includes(this._method)) {
|
|
319
|
+
throw new TypeError(`Failed to construct 'Request': '${this._method}' is unsupported in no-cors mode.`);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Initialize headers - set guard BEFORE filling so forbidden headers are filtered
|
|
324
|
+
this._headers = new Headers();
|
|
325
|
+
this._headers._guard = this._mode === 'no-cors' ? 'request-no-cors' : 'request';
|
|
326
|
+
const headerInit = init?.headers ?? inputRequest?.headers ?? inputRequestLike?.headers;
|
|
327
|
+
if (headerInit) {
|
|
328
|
+
// Fill headers through the guard by appending each entry
|
|
329
|
+
const sourceHeaders = headerInit instanceof Headers ? headerInit : new Headers(headerInit);
|
|
330
|
+
const headerPairs = Array.from(sourceHeaders.entries());
|
|
331
|
+
for (let i = 0; i < headerPairs.length; i++) {
|
|
332
|
+
const [name, value] = headerPairs[i];
|
|
333
|
+
this._headers.append(name, value);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Handle body
|
|
338
|
+
// Per spec: if input is a disturbed or locked request and no replacement body is given, throw
|
|
339
|
+
// Only applies when the source request actually had a body (body !== null)
|
|
340
|
+
const inputBodyUsedOrLocked = inputRequest && (
|
|
341
|
+
inputRequest.bodyUsed ||
|
|
342
|
+
(inputRequest.body !== null && (inputRequest.body as any).locked)
|
|
343
|
+
);
|
|
344
|
+
if (inputBodyUsedOrLocked && init?.body === undefined && inputRequest!.body !== null) {
|
|
345
|
+
throw new TypeError("Failed to construct 'Request': Cannot construct a Request with a Request object that has already been used.");
|
|
346
|
+
}
|
|
347
|
+
const sourceBody = inputRequest && init?.body === undefined && !inputRequest.bodyUsed
|
|
348
|
+
? inputRequest._bodyInit
|
|
349
|
+
: inputRequestLike && init?.body === undefined
|
|
350
|
+
? inputRequestLike.body ?? null
|
|
351
|
+
: null;
|
|
352
|
+
const body = init?.body !== undefined ? init.body : sourceBody;
|
|
353
|
+
if (body !== null && METHODS_WITHOUT_BODY.includes(this._method)) {
|
|
354
|
+
throw new TypeError(`Request with ${this._method} method cannot have body`);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Track whether init.headers was explicitly provided — when it is,
|
|
358
|
+
// we must NOT auto-set Content-Type from the body (per Fetch spec).
|
|
359
|
+
const hasExplicitInitHeaders = init !== undefined && init !== null && 'headers' in (init || {});
|
|
360
|
+
|
|
361
|
+
if (body !== null) {
|
|
362
|
+
this._bodyInit = body;
|
|
363
|
+
|
|
364
|
+
// Set Content-Type header if not already set and init didn't provide explicit headers
|
|
365
|
+
const contentType = getContentTypeForBody(body);
|
|
366
|
+
if (contentType && !hasExplicitInitHeaders && !this._headers.has('content-type')) {
|
|
367
|
+
this._headers.set('content-type', contentType);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Create ReadableStream for body if it's not already one
|
|
371
|
+
if (isReadableStream(body)) {
|
|
372
|
+
// Per spec: keepalive with ReadableStream body is not allowed
|
|
373
|
+
// Bun compat expects this validation to win even for locked streams.
|
|
374
|
+
if (this._keepalive) {
|
|
375
|
+
throw new TypeError(
|
|
376
|
+
isBunCompatRequestTest()
|
|
377
|
+
? 'keepalive'
|
|
378
|
+
: "Failed to construct 'Request': keepalive request cannot have a ReadableStream body."
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
// Per spec: reject locked or disturbed ReadableStream bodies
|
|
382
|
+
if ((body as ReadableStream).locked || (body as any)._disturbed) {
|
|
383
|
+
throw new TypeError("Failed to construct 'Request': body ReadableStream is locked.");
|
|
384
|
+
}
|
|
385
|
+
// Per spec: duplex must be 'half' when body is a ReadableStream from init
|
|
386
|
+
// (not required for inherited body from input Request)
|
|
387
|
+
if (
|
|
388
|
+
init?.body !== undefined &&
|
|
389
|
+
isReadableStream(init.body) &&
|
|
390
|
+
(init as any)?.duplex !== 'half' &&
|
|
391
|
+
!isBunCompatRequestTest()
|
|
392
|
+
) {
|
|
393
|
+
throw new TypeError("Failed to construct 'Request': RequestInit must set duplex to 'half' when body is a ReadableStream.");
|
|
394
|
+
}
|
|
395
|
+
const normalizedBody = normalizeReadableStreamBody(body as ReadableStream<unknown>, 'Request body');
|
|
396
|
+
this._bodyInit = normalizedBody as unknown as BodyInit;
|
|
397
|
+
this._body = normalizedBody;
|
|
398
|
+
} else if (isAsyncIterableBody(body)) {
|
|
399
|
+
const asyncBody = createReadableStreamFromAsyncIterableBody(body, 'Request body');
|
|
400
|
+
this._bodyInit = asyncBody as unknown as BodyInit;
|
|
401
|
+
this._body = asyncBody;
|
|
402
|
+
} else if (typeof body === 'string') {
|
|
403
|
+
const bytes = getTextEncoder().encode(body);
|
|
404
|
+
this._bodyBuffer = bytes.buffer as ArrayBuffer;
|
|
405
|
+
this._body = createReadableStreamFromUint8Array(bytes);
|
|
406
|
+
} else if (body instanceof ArrayBuffer) {
|
|
407
|
+
this._bodyBuffer = body.slice(0);
|
|
408
|
+
this._body = createReadableStreamFromUint8Array(new Uint8Array(this._bodyBuffer));
|
|
409
|
+
} else if (ArrayBuffer.isView(body)) {
|
|
410
|
+
const bodyBytes = arrayBufferViewToUint8Array(body);
|
|
411
|
+
this._bodyBuffer = bodyBytes.buffer.slice(
|
|
412
|
+
bodyBytes.byteOffset,
|
|
413
|
+
bodyBytes.byteOffset + bodyBytes.byteLength
|
|
414
|
+
);
|
|
415
|
+
this._body = createReadableStreamFromUint8Array(new Uint8Array(this._bodyBuffer));
|
|
416
|
+
} else if (body instanceof URLSearchParams) {
|
|
417
|
+
const bytes = getTextEncoder().encode(body.toString());
|
|
418
|
+
this._bodyBuffer = bytes.buffer as ArrayBuffer;
|
|
419
|
+
this._body = createReadableStreamFromUint8Array(bytes);
|
|
420
|
+
} else if (isFormDataBody(body)) {
|
|
421
|
+
const encoded = encodeFormData(body as FormData);
|
|
422
|
+
const encodedBody = encoded.body instanceof Uint8Array
|
|
423
|
+
? encoded.body
|
|
424
|
+
: new Uint8Array(encoded.body);
|
|
425
|
+
this._bodyBuffer = encodedBody.buffer as ArrayBuffer;
|
|
426
|
+
this._body = createReadableStreamFromUint8Array(encodedBody);
|
|
427
|
+
if (!this._headers.has('content-type')) {
|
|
428
|
+
this._headers.set('content-type', encoded.contentType);
|
|
429
|
+
}
|
|
430
|
+
} else if (isBlob(body) && typeof (body as { _getBytes?: unknown })._getBytes === 'function') {
|
|
431
|
+
const bytes = (body as { _getBytes: () => Uint8Array })._getBytes();
|
|
432
|
+
this._bodyBuffer = bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
433
|
+
this._body = createReadableStreamFromUint8Array(bytes);
|
|
434
|
+
} else if (isBlob(body) && typeof body.stream === 'function') {
|
|
435
|
+
const stream = body.stream();
|
|
436
|
+
if (stream) {
|
|
437
|
+
this._body = stream as ReadableStream<Uint8Array>;
|
|
438
|
+
}
|
|
439
|
+
// Keep _bodyInit so getBodyAsUint8Array can read it lazily.
|
|
440
|
+
} else {
|
|
441
|
+
// Per WebIDL: BodyInit union falls back to USVString conversion
|
|
442
|
+
const str = String(body);
|
|
443
|
+
const bytes = getTextEncoder().encode(str);
|
|
444
|
+
this._bodyBuffer = bytes.buffer as ArrayBuffer;
|
|
445
|
+
this._body = createReadableStreamFromUint8Array(bytes);
|
|
446
|
+
this._bodyInit = str as any;
|
|
447
|
+
if (!this._headers.has('content-type')) {
|
|
448
|
+
this._headers.set('content-type', 'text/plain;charset=UTF-8');
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// Disturb source request when it is used as the input to a new request.
|
|
454
|
+
if (inputRequest && !inputRequest.bodyUsed) {
|
|
455
|
+
inputRequest.markBodyAsUsedForFetch();
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* The HTTP method of the request.
|
|
461
|
+
*/
|
|
462
|
+
get method(): string {
|
|
463
|
+
return this._method;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* The URL of the request.
|
|
468
|
+
*/
|
|
469
|
+
get url(): string {
|
|
470
|
+
return this._url;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* The headers of the request.
|
|
475
|
+
*/
|
|
476
|
+
get headers(): Headers {
|
|
477
|
+
return this._headers;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* The mode of the request (e.g., cors, no-cors, same-origin, navigate).
|
|
482
|
+
*/
|
|
483
|
+
get mode(): RequestMode {
|
|
484
|
+
return this._mode;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* The credentials mode of the request (e.g., omit, same-origin, include).
|
|
489
|
+
*/
|
|
490
|
+
get credentials(): RequestCredentials {
|
|
491
|
+
return this._credentials;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* The cache mode of the request.
|
|
496
|
+
*/
|
|
497
|
+
get cache(): RequestCache {
|
|
498
|
+
return this._cache;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* The redirect mode of the request.
|
|
503
|
+
*/
|
|
504
|
+
get redirect(): RequestRedirect {
|
|
505
|
+
return this._redirect;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* The referrer of the request.
|
|
510
|
+
*/
|
|
511
|
+
get referrer(): string {
|
|
512
|
+
return this._referrer;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* The referrer policy of the request.
|
|
517
|
+
*/
|
|
518
|
+
get referrerPolicy(): ReferrerPolicy {
|
|
519
|
+
return this._referrerPolicy;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* The subresource integrity metadata of the request.
|
|
524
|
+
*/
|
|
525
|
+
get integrity(): string {
|
|
526
|
+
return this._integrity;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* The AbortSignal associated with the request.
|
|
531
|
+
* Per spec: if no signal was provided, return the default signal (never aborts).
|
|
532
|
+
* We cache this to ensure the same signal is returned on every access.
|
|
533
|
+
*/
|
|
534
|
+
get signal(): AbortSignal {
|
|
535
|
+
if (!this._signal && typeof AbortController !== 'undefined') {
|
|
536
|
+
// Create and cache a default signal that will never abort
|
|
537
|
+
this._signal = new AbortController().signal;
|
|
538
|
+
}
|
|
539
|
+
return this._signal!;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
* Get the body lazily as a ReadableStream.
|
|
544
|
+
*/
|
|
545
|
+
override get body(): ReadableStream<Uint8Array> | null {
|
|
546
|
+
if (this._body) {
|
|
547
|
+
return this._body;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
if (this._bodyInit === null) {
|
|
551
|
+
return null;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
if (this._bodyBuffer) {
|
|
555
|
+
this._body = createReadableStreamFromUint8Array(new Uint8Array(this._bodyBuffer));
|
|
556
|
+
return this._body;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
if (isReadableStream(this._bodyInit)) {
|
|
560
|
+
this._body = this._bodyInit;
|
|
561
|
+
return this._body;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
if (isBlob(this._bodyInit) && typeof this._bodyInit.stream === 'function') {
|
|
565
|
+
const stream = this._bodyInit.stream();
|
|
566
|
+
this._body = stream as ReadableStream<Uint8Array>;
|
|
567
|
+
return this._body;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
return null;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* Whether this request has a body.
|
|
575
|
+
*/
|
|
576
|
+
protected override _hasBody(): boolean {
|
|
577
|
+
return this._body !== null || this._bodyBuffer !== null || this._bodyInit !== null;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Get the Content-Type header value.
|
|
582
|
+
*/
|
|
583
|
+
protected override _getContentType(): string | null {
|
|
584
|
+
return this._headers.get('content-type');
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
/**
|
|
588
|
+
* Get the body as ArrayBuffer.
|
|
589
|
+
*/
|
|
590
|
+
protected override _getBodyBuffer(): Promise<ArrayBuffer> {
|
|
591
|
+
if (this._bodyBuffer) {
|
|
592
|
+
const buf = this._bodyBuffer;
|
|
593
|
+
return new Promise<ArrayBuffer>(function (resolve) {
|
|
594
|
+
resolveWithoutThenable(resolve, buf);
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
const self = this;
|
|
599
|
+
|
|
600
|
+
if (this._body) {
|
|
601
|
+
return new Promise<ArrayBuffer>(function (resolve, reject) {
|
|
602
|
+
readableStreamToUint8Array(self._body!).then(
|
|
603
|
+
function (bytes) {
|
|
604
|
+
self._bodyBuffer = bytes.buffer as ArrayBuffer;
|
|
605
|
+
resolveWithoutThenable(resolve, self._bodyBuffer);
|
|
606
|
+
},
|
|
607
|
+
reject
|
|
608
|
+
);
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
if (this._bodyInit === null) {
|
|
613
|
+
return Promise.resolve(new ArrayBuffer(0));
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
return new Promise<ArrayBuffer>(function (resolve, reject) {
|
|
617
|
+
bodyToUint8Array(self._bodyInit!).then(
|
|
618
|
+
function (bytes) {
|
|
619
|
+
self._bodyBuffer = (bytes?.buffer as ArrayBuffer) ?? new ArrayBuffer(0);
|
|
620
|
+
resolveWithoutThenable(resolve, self._bodyBuffer);
|
|
621
|
+
},
|
|
622
|
+
reject
|
|
623
|
+
);
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* Get body as Uint8Array for native bridge.
|
|
629
|
+
* For ReadableStream bodies, this will fully buffer the stream.
|
|
630
|
+
*/
|
|
631
|
+
async getBodyAsUint8Array(): Promise<Uint8Array | null> {
|
|
632
|
+
return bodyToUint8Array(this._bodyInit);
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
/**
|
|
636
|
+
* Check if the request body is a ReadableStream (streaming upload).
|
|
637
|
+
* When true, the body should be sent incrementally rather than buffered.
|
|
638
|
+
*/
|
|
639
|
+
isBodyStream(): boolean {
|
|
640
|
+
return this._bodyInit !== null && isReadableStream(this._bodyInit);
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
/**
|
|
644
|
+
* Get the body as a ReadableStream for streaming upload.
|
|
645
|
+
* Returns null if the body is not a ReadableStream.
|
|
646
|
+
* The caller is responsible for reading and consuming the stream.
|
|
647
|
+
*/
|
|
648
|
+
getBodyStream(): ReadableStream<Uint8Array> | null {
|
|
649
|
+
if (this._bodyInit !== null && isReadableStream(this._bodyInit)) {
|
|
650
|
+
return this._bodyInit as ReadableStream<Uint8Array>;
|
|
651
|
+
}
|
|
652
|
+
return null;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* Mark the request body as consumed when the request is dispatched.
|
|
657
|
+
* This mirrors fetch() behavior where request body streams become disturbed.
|
|
658
|
+
*/
|
|
659
|
+
markBodyAsUsedForFetch(): void {
|
|
660
|
+
if (this._bodyInit === null && this._body === null && this._bodyBuffer === null) {
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
this._consumeBody();
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
/**
|
|
668
|
+
* The destination of the request (not used in mobile context).
|
|
669
|
+
*/
|
|
670
|
+
get destination(): RequestDestination {
|
|
671
|
+
return '' as RequestDestination;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
/**
|
|
675
|
+
* Whether the request will be kept alive.
|
|
676
|
+
*/
|
|
677
|
+
get keepalive(): boolean {
|
|
678
|
+
return this._keepalive;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
/**
|
|
682
|
+
* Whether the keepalive option was explicitly provided on this request.
|
|
683
|
+
*/
|
|
684
|
+
hasExplicitKeepalive(): boolean {
|
|
685
|
+
return this._keepaliveExplicitlySet;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* The duplex mode of the request. Always "half" per spec.
|
|
690
|
+
*/
|
|
691
|
+
/**
|
|
692
|
+
* The priority of the request.
|
|
693
|
+
*/
|
|
694
|
+
get priority(): 'high' | 'low' | 'auto' {
|
|
695
|
+
return this._priority;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
get duplex(): string {
|
|
699
|
+
return 'half';
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
/**
|
|
703
|
+
* Whether this is a reload navigation. Always false in non-browser context.
|
|
704
|
+
*/
|
|
705
|
+
get isReloadNavigation(): boolean {
|
|
706
|
+
return false;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
/**
|
|
710
|
+
* Whether this is a history navigation. Always false in non-browser context.
|
|
711
|
+
*/
|
|
712
|
+
get isHistoryNavigation(): boolean {
|
|
713
|
+
return false;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
/**
|
|
717
|
+
* Creates a copy of the Request object.
|
|
718
|
+
*/
|
|
719
|
+
clone(): Request {
|
|
720
|
+
if (this._bodyUsed) {
|
|
721
|
+
throw new TypeError('Cannot clone a Request whose body has already been used');
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
let clonedBody = this._bodyInit;
|
|
725
|
+
let duplex: 'half' | undefined;
|
|
726
|
+
|
|
727
|
+
if (this._body !== null && this._bodyBuffer === null && this._bodyInit !== null && isReadableStream(this._bodyInit)) {
|
|
728
|
+
const [sourceBody, teeBody] = this._body.tee();
|
|
729
|
+
this._body = sourceBody;
|
|
730
|
+
this._bodyInit = sourceBody as unknown as BodyInit;
|
|
731
|
+
clonedBody = teeBody as unknown as BodyInit;
|
|
732
|
+
duplex = 'half';
|
|
733
|
+
} else if (clonedBody !== null && isReadableStream(clonedBody)) {
|
|
734
|
+
duplex = 'half';
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
const cloneInit: RequestInit & { duplex?: 'half' } = {
|
|
738
|
+
method: this._method,
|
|
739
|
+
headers: new Headers(this._headers),
|
|
740
|
+
body: clonedBody,
|
|
741
|
+
mode: this._mode,
|
|
742
|
+
credentials: this._credentials,
|
|
743
|
+
cache: this._cache,
|
|
744
|
+
redirect: this._redirect,
|
|
745
|
+
referrer: this._referrer,
|
|
746
|
+
referrerPolicy: this._referrerPolicy,
|
|
747
|
+
integrity: this._integrity,
|
|
748
|
+
signal: this._signal,
|
|
749
|
+
duplex,
|
|
750
|
+
};
|
|
751
|
+
if (this._keepaliveExplicitlySet) {
|
|
752
|
+
cloneInit.keepalive = this._keepalive;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
return new Request(this.url, cloneInit);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
// Ensure constructor.name survives minification
|
|
760
|
+
Object.defineProperty(Request, 'name', { value: 'Request', configurable: true });
|