(function () {
const { core, internals, primordials } = __bootstrap;
const {
ArrayPrototypeMap,
ArrayPrototypeSlice,
ArrayPrototypeSplice,
FunctionPrototypeCall,
JSONParse,
ObjectDefineProperty,
ObjectKeys,
ObjectPrototypeIsPrototypeOf,
PromiseReject,
PromiseResolve,
RegExpPrototypeExec,
StringPrototypeStartsWith,
StringPrototypeToUpperCase,
Symbol,
SymbolFor,
TypeError,
} = primordials;
const webidl = core.loadExtScript("ext:deno_webidl/00_webidl.js");
const { createFilteredInspectProxy } = core.loadExtScript(
"ext:deno_web/01_console.js",
);
const { HTTP_TOKEN_CODE_POINT_RE } = core.loadExtScript(
"ext:deno_web/00_infra.js",
);
const { URL } = core.loadExtScript("ext:deno_web/00_url.js");
const { extractBody, mixinBody } = core.loadExtScript(
"ext:deno_fetch/22_body.js",
);
const { getLocationHref } = core.loadExtScript("ext:deno_web/12_location.js");
const { extractMimeType } = core.loadExtScript("ext:deno_web/01_mimesniff.js");
const { blobFromObjectUrl } = core.loadExtScript("ext:deno_web/09_file.js");
const {
fillHeaders,
getDecodeSplitHeader,
guardFromHeaders,
headerListFromHeaders,
headersFromHeaderList,
headersFromHeaderListLazyTarget,
} = core.loadExtScript("ext:deno_fetch/20_headers.js");
const { HttpClientPrototype } = core.loadExtScript(
"ext:deno_fetch/22_http_client.js",
);
const {
createDependentAbortSignal,
newSignal,
signalAbort,
} = core.loadExtScript("ext:deno_web/03_abort_signal.js");
const { DOMException } = core.loadExtScript("ext:deno_web/01_dom_exception.js");
const { markNotSerializable } = core.loadExtScript(
"ext:deno_web/13_message_port.js",
);
const { internalRidSymbol } = core;
const _request = Symbol("request");
const _headers = Symbol("headers");
const _getHeaders = Symbol("get headers");
const _headersCache = Symbol("headers cache");
const _headersGuard = Symbol("headers guard");
const _signal = Symbol("signal");
const _signalCache = Symbol("signalCache");
const _mimeType = Symbol("mime type");
const _body = Symbol("body");
const _url = Symbol("url");
const _method = Symbol("method");
const _brand = webidl.brand;
function processUrlList(urlList, urlListProcessed) {
for (let i = 0; i < urlList.length; i++) {
if (urlListProcessed[i] === undefined) {
urlListProcessed[i] = urlList[i]();
}
}
return urlListProcessed;
}
function newInnerRequest(method, url, headerList, body, maybeBlob) {
let blobUrlEntry = null;
if (
maybeBlob &&
typeof url === "string" &&
StringPrototypeStartsWith(url, "blob:")
) {
blobUrlEntry = blobFromObjectUrl(url);
}
return {
methodInner: method,
get method() {
return this.methodInner;
},
set method(value) {
this.methodInner = value;
},
headerListInner: null,
get headerList() {
if (this.headerListInner === null) {
try {
this.headerListInner = headerList();
} catch {
throw new TypeError("Cannot read headers: request closed");
}
}
return this.headerListInner;
},
set headerList(value) {
this.headerListInner = value;
},
body,
redirectMode: "follow",
redirectCount: 0,
urlList: [typeof url === "string" ? () => url : url],
urlListProcessed: [],
clientRid: null,
blobUrlEntry,
url() {
if (this.urlListProcessed[0] === undefined) {
try {
this.urlListProcessed[0] = this.urlList[0]();
} catch {
throw new TypeError("cannot read url: request closed");
}
}
return this.urlListProcessed[0];
},
currentUrl() {
const currentIndex = this.urlList.length - 1;
if (this.urlListProcessed[currentIndex] === undefined) {
try {
this.urlListProcessed[currentIndex] = this.urlList[currentIndex]();
} catch {
throw new TypeError("Cannot read url: request closed");
}
}
return this.urlListProcessed[currentIndex];
},
};
}
function cloneInnerRequest(request, skipBody = false) {
const headerList = ArrayPrototypeMap(
request.headerList,
(x) => [x[0], x[1]],
);
let body = null;
if (request.body !== null && !skipBody) {
body = request.body.clone();
}
const cloned = {
method: request.method,
headerList,
body,
redirectMode: request.redirectMode,
redirectCount: request.redirectCount,
urlList: [() => request.url()],
urlListProcessed: [request.url()],
clientRid: request.clientRid,
blobUrlEntry: request.blobUrlEntry,
url() {
if (this.urlListProcessed[0] === undefined) {
try {
this.urlListProcessed[0] = this.urlList[0]();
} catch {
throw new TypeError("Cannot read url: request closed");
}
}
return this.urlListProcessed[0];
},
currentUrl() {
const currentIndex = this.urlList.length - 1;
if (this.urlListProcessed[currentIndex] === undefined) {
try {
this.urlListProcessed[currentIndex] = this.urlList[currentIndex]();
} catch {
throw new TypeError("Cannot read url: request closed");
}
}
return this.urlListProcessed[currentIndex];
},
};
if (request.cacheMode !== undefined) cloned.cacheMode = request.cacheMode;
if (request.credentialsMode !== undefined) {
cloned.credentialsMode = request.credentialsMode;
}
if (request.integrity !== undefined) cloned.integrity = request.integrity;
if (request.keepalive !== undefined) cloned.keepalive = request.keepalive;
if (request.mode !== undefined) cloned.mode = request.mode;
if (request.priority !== undefined) cloned.priority = request.priority;
if (request.referrer !== undefined) cloned.referrer = request.referrer;
if (request.referrerPolicy !== undefined) {
cloned.referrerPolicy = request.referrerPolicy;
}
return cloned;
}
const KNOWN_METHODS = {
__proto__: null,
"DELETE": "DELETE",
"delete": "DELETE",
"GET": "GET",
"get": "GET",
"HEAD": "HEAD",
"head": "HEAD",
"OPTIONS": "OPTIONS",
"options": "OPTIONS",
"PATCH": "PATCH",
"POST": "POST",
"post": "POST",
"PUT": "PUT",
"put": "PUT",
};
function validateAndNormalizeMethod(m) {
if (RegExpPrototypeExec(HTTP_TOKEN_CODE_POINT_RE, m) === null) {
throw new TypeError("Method is not valid");
}
const upperCase = StringPrototypeToUpperCase(m);
switch (upperCase) {
case "DELETE":
case "GET":
case "HEAD":
case "OPTIONS":
case "POST":
case "PUT":
return upperCase;
case "CONNECT":
case "TRACE":
case "TRACK":
throw new TypeError("Method is forbidden");
}
return m;
}
class Request {
[_request];
[_headersCache];
[_getHeaders];
[_headersGuard];
[_signalCache];
[_url];
[_method];
get [_headers]() {
if (this[_headersCache] === undefined) {
const getHeaders = this[_getHeaders];
if (getHeaders !== undefined && getHeaders !== null) {
this[_headersCache] = getHeaders();
} else {
const inner = this[_request];
const guard = this[_headersGuard];
if (typeof inner.header !== "function") {
this[_headersCache] = headersFromHeaderList(inner.headerList, guard);
} else {
this[_headersCache] = headersFromHeaderListLazyTarget(inner, guard);
}
}
}
return this[_headersCache];
}
set [_headers](value) {
this[_headersCache] = value;
}
get [_signal]() {
const signal = this[_signalCache];
if (signal === false) {
const signal = newSignal();
this[_signalCache] = signal;
signal[signalAbort](
new DOMException(MESSAGE_REQUEST_CANCELLED, "AbortError"),
);
return signal;
}
if (signal === undefined) {
const signal = newSignal();
this[_signalCache] = signal;
this[_request].onCancel?.(() => {
signal[signalAbort](
new DOMException(MESSAGE_REQUEST_CANCELLED, "AbortError"),
);
});
return signal;
}
return signal;
}
get [_mimeType]() {
const values = getDecodeSplitHeader(
headerListFromHeaders(this[_headers]),
"Content-Type",
);
return extractMimeType(values);
}
get [_body]() {
return this[_request].body;
}
constructor(input, init = undefined) {
if (input === _brand) {
this[_brand] = _brand;
return;
}
const prefix = "Failed to construct 'Request'";
webidl.requiredArguments(arguments.length, 1, prefix);
input = webidl.converters["RequestInfo_DOMString"](
input,
prefix,
"Argument 1",
);
init = webidl.converters["RequestInit"](init, prefix, "Argument 2");
this[_brand] = _brand;
let request;
const baseURL = getLocationHref();
let signal = null;
if (typeof input === "string") {
const parsedURL = new URL(input, baseURL);
request = newInnerRequest(
"GET",
parsedURL.href,
() => [],
null,
true,
);
} else { if (!ObjectPrototypeIsPrototypeOf(RequestPrototype, input)) {
throw new TypeError("Unreachable");
}
const originalReq = input[_request];
request = cloneInnerRequest(originalReq, true);
request.redirectCount = 0; signal = input[_signal];
}
if (init.referrer !== undefined) {
const referrer = init.referrer;
if (referrer === "") {
request.referrer = "no-referrer";
} else {
let parsedReferrer;
try {
parsedReferrer = new URL(referrer, baseURL);
} catch (err) {
throw new TypeError(`Referrer "${referrer}" is not a valid URL.`, {
cause: err,
});
}
if (
(parsedReferrer.protocol === "about:" &&
parsedReferrer.pathname === "client")
) {
request.referrer = "client";
} else {
request.referrer = parsedReferrer.href;
}
}
}
if (init.referrerPolicy !== undefined) {
request.referrerPolicy = init.referrerPolicy;
}
if (init.mode !== undefined) {
if (init.mode === "navigate") {
throw new TypeError("Request mode 'navigate' is not allowed");
}
request.mode = init.mode;
}
if (init.credentials !== undefined) {
request.credentialsMode = init.credentials;
}
if (init.cache !== undefined) {
request.cacheMode = init.cache;
}
if (
request.cacheMode === "only-if-cached" && request.mode !== "same-origin"
) {
throw new TypeError(
'Request cache mode "only-if-cached" can only be used with same-origin mode',
);
}
if (init.redirect !== undefined) {
request.redirectMode = init.redirect;
}
if (init.integrity !== undefined) {
request.integrity = init.integrity;
}
if (init.keepalive !== undefined) {
request.keepalive = init.keepalive;
}
if (init.priority !== undefined) {
request.priority = init.priority;
}
if (init.method !== undefined) {
const method = init.method;
request.method = KNOWN_METHODS[method] ??
validateAndNormalizeMethod(method);
}
if (init.signal !== undefined) {
signal = init.signal;
}
if (init.client !== undefined) {
if (
init.client !== null &&
!ObjectPrototypeIsPrototypeOf(HttpClientPrototype, init.client)
) {
throw webidl.makeException(
TypeError,
"`client` must be a Deno.HttpClient",
prefix,
"Argument 2",
);
}
request.clientRid = init.client?.[internalRidSymbol] ?? null;
}
this[_request] = request;
if (signal !== null) {
this[_signalCache] = createDependentAbortSignal([signal], prefix);
}
this[_headers] = headersFromHeaderList(request.headerList, "request");
if (init.headers || ObjectKeys(init).length > 0) {
const headerList = headerListFromHeaders(this[_headers]);
const headers = init.headers ?? ArrayPrototypeSlice(
headerList,
0,
headerList.length,
);
if (headerList.length !== 0) {
ArrayPrototypeSplice(headerList, 0, headerList.length);
}
fillHeaders(this[_headers], headers);
}
let inputBody = null;
if (ObjectPrototypeIsPrototypeOf(RequestPrototype, input)) {
inputBody = input[_body];
}
if (
(request.method === "GET" || request.method === "HEAD") &&
((init.body !== undefined && init.body !== null) ||
inputBody !== null)
) {
throw new TypeError("Request with GET/HEAD method cannot have body");
}
let initBody = null;
if (init.body !== undefined && init.body !== null) {
const res = extractBody(init.body);
initBody = res.body;
if (res.contentType !== null && !this[_headers].has("content-type")) {
this[_headers].append("Content-Type", res.contentType);
}
}
const inputOrInitBody = initBody ?? inputBody;
let finalBody = inputOrInitBody;
if (initBody === null && inputBody !== null) {
if (input[_body] && input[_body].unusable()) {
throw new TypeError("Input request's body is unusable");
}
finalBody = inputBody.createProxy();
}
request.body = finalBody;
}
get method() {
webidl.assertBranded(this, RequestPrototype);
if (this[_method]) {
return this[_method];
}
this[_method] = this[_request].method;
return this[_method];
}
get url() {
webidl.assertBranded(this, RequestPrototype);
if (this[_url]) {
return this[_url];
}
this[_url] = this[_request].url();
return this[_url];
}
get headers() {
webidl.assertBranded(this, RequestPrototype);
return this[_headers];
}
get redirect() {
webidl.assertBranded(this, RequestPrototype);
return this[_request].redirectMode;
}
get cache() {
webidl.assertBranded(this, RequestPrototype);
return this[_request].cacheMode ?? "default";
}
get credentials() {
webidl.assertBranded(this, RequestPrototype);
return this[_request].credentialsMode ?? "same-origin";
}
get integrity() {
webidl.assertBranded(this, RequestPrototype);
return this[_request].integrity ?? "";
}
get keepalive() {
webidl.assertBranded(this, RequestPrototype);
return this[_request].keepalive ?? false;
}
get mode() {
webidl.assertBranded(this, RequestPrototype);
return this[_request].mode ?? "cors";
}
get referrer() {
webidl.assertBranded(this, RequestPrototype);
const referrer = this[_request].referrer;
if (referrer === undefined || referrer === "client") {
return "about:client";
}
if (referrer === "no-referrer") {
return "";
}
return referrer;
}
get referrerPolicy() {
webidl.assertBranded(this, RequestPrototype);
return this[_request].referrerPolicy ?? "";
}
get signal() {
webidl.assertBranded(this, RequestPrototype);
return this[_signal];
}
clone() {
const prefix = "Failed to execute 'Request.clone'";
webidl.assertBranded(this, RequestPrototype);
if (this[_body] && this[_body].unusable()) {
throw new TypeError("Body is unusable");
}
const clonedReq = cloneInnerRequest(this[_request]);
const materializedSignal = this[_signal];
const clonedSignal = createDependentAbortSignal(
[materializedSignal],
prefix,
);
const request = new Request(_brand);
request[_request] = clonedReq;
request[_signalCache] = clonedSignal;
headerListFromHeaders(this[_headers]);
request[_headersGuard] = guardFromHeaders(this[_headers]);
return request;
}
[SymbolFor("Deno.privateCustomInspect")](inspect, inspectOptions) {
return inspect(
createFilteredInspectProxy({
object: this,
evaluate: ObjectPrototypeIsPrototypeOf(RequestPrototype, this),
keys: [
"bodyUsed",
"headers",
"method",
"redirect",
"url",
],
}),
inspectOptions,
);
}
}
webidl.configureInterface(Request);
const RequestPrototype = Request.prototype;
markNotSerializable(RequestPrototype);
mixinBody(RequestPrototype, _body, _mimeType);
const requestJson = RequestPrototype.json;
ObjectDefineProperty(RequestPrototype, "json", {
__proto__: null,
value: function json() {
try {
webidl.assertBranded(this, RequestPrototype);
const text = this[_request].consumeTextBody?.();
if (text !== null && text !== undefined) {
return PromiseResolve(JSONParse(text));
}
} catch (error) {
return PromiseReject(error);
}
return FunctionPrototypeCall(requestJson, this);
},
writable: true,
configurable: true,
enumerable: true,
});
webidl.converters["Request"] = webidl.createInterfaceConverter(
"Request",
RequestPrototype,
);
webidl.converters["RequestInfo_DOMString"] = (V, prefix, context, opts) => {
if (typeof V == "object") {
if (ObjectPrototypeIsPrototypeOf(RequestPrototype, V)) {
return webidl.converters["Request"](V, prefix, context, opts);
}
}
return webidl.converters["DOMString"](V, prefix, context, opts);
};
webidl.converters["RequestRedirect"] = webidl.createEnumConverter(
"RequestRedirect",
[
"follow",
"error",
"manual",
],
);
webidl.converters["RequestCache"] = webidl.createEnumConverter(
"RequestCache",
[
"default",
"no-store",
"reload",
"no-cache",
"force-cache",
"only-if-cached",
],
);
webidl.converters["RequestCredentials"] = webidl.createEnumConverter(
"RequestCredentials",
[
"omit",
"same-origin",
"include",
],
);
webidl.converters["RequestMode"] = webidl.createEnumConverter(
"RequestMode",
[
"navigate",
"same-origin",
"no-cors",
"cors",
],
);
webidl.converters["RequestPriority"] = webidl.createEnumConverter(
"RequestPriority",
[
"auto",
"low",
"high",
],
);
webidl.converters["ReferrerPolicy"] = webidl.createEnumConverter(
"ReferrerPolicy",
[
"",
"no-referrer",
"no-referrer-when-downgrade",
"same-origin",
"origin",
"strict-origin",
"origin-when-cross-origin",
"strict-origin-when-cross-origin",
"unsafe-url",
],
);
webidl.converters["RequestInit"] = webidl.createDictionaryConverter(
"RequestInit",
[
{ key: "method", converter: webidl.converters["ByteString"] },
{ key: "headers", converter: webidl.converters["HeadersInit"] },
{
key: "body",
converter: webidl.createNullableConverter(
webidl.converters["BodyInit_DOMString"],
),
},
{ key: "referrer", converter: webidl.converters["USVString"] },
{ key: "referrerPolicy", converter: webidl.converters["ReferrerPolicy"] },
{ key: "mode", converter: webidl.converters["RequestMode"] },
{ key: "credentials", converter: webidl.converters["RequestCredentials"] },
{ key: "cache", converter: webidl.converters["RequestCache"] },
{ key: "redirect", converter: webidl.converters["RequestRedirect"] },
{ key: "integrity", converter: webidl.converters["DOMString"] },
{ key: "keepalive", converter: webidl.converters["boolean"] },
{ key: "priority", converter: webidl.converters["RequestPriority"] },
{
key: "signal",
converter: webidl.createNullableConverter(
webidl.converters["AbortSignal"],
),
},
{ key: "client", converter: webidl.converters.any },
],
);
function toInnerRequest(request) {
return request[_request];
}
function requestHeadersExposed(request) {
return request?.[_headersCache] !== undefined;
}
function cacheRequestHeaders(request) {
if (request?.[_headersCache] !== undefined) {
headerListFromHeaders(request[_headersCache]);
}
}
function fromInnerRequest(inner, guard) {
const request = new Request(_brand);
request[_request] = inner;
request[_headersGuard] = guard;
return request;
}
const MESSAGE_REQUEST_CANCELLED = "The request has been cancelled.";
function abortRequest(request) {
if (request[_signalCache] !== undefined) {
request[_signal][signalAbort](
new DOMException(MESSAGE_REQUEST_CANCELLED, "AbortError"),
);
} else {
request[_signalCache] = false;
}
}
function getCachedAbortSignal(request) {
return request[_signalCache];
}
internals.getCachedAbortSignal = getCachedAbortSignal;
return {
abortRequest,
cacheRequestHeaders,
fromInnerRequest,
newInnerRequest,
processUrlList,
Request,
RequestPrototype,
requestHeadersExposed,
toInnerRequest,
};
})();