@wevu/web-apis
Version:
Web API polyfills and global installers for mini-program runtimes
164 lines (163 loc) • 5.55 kB
JavaScript
import { t as RequestGlobalsEventTarget, u as resolveRequestGlobalsHost } from "./shared-BB491DgN.mjs";
import { AbortControllerPolyfill } from "./abort.mjs";
import { HeadersPolyfill, headersToObject } from "./http.mjs";
import { fetch } from "./fetch.mjs";
//#region src/xhr.ts
function createProgressEvent(type) {
return {
type,
lengthComputable: false,
loaded: 0,
total: 0
};
}
function createError(type) {
const error = new Error(type);
error.name = type === "abort" ? "AbortError" : type === "timeout" ? "TimeoutError" : "NetworkError";
return error;
}
function resolveFetch() {
const host = resolveRequestGlobalsHost();
return typeof host.fetch === "function" ? host.fetch.bind(host) : fetch;
}
var XMLHttpRequestUploadPolyfill = class extends RequestGlobalsEventTarget {};
var XMLHttpRequestPolyfill = class XMLHttpRequestPolyfill extends RequestGlobalsEventTarget {
static UNSENT = 0;
static OPENED = 1;
static HEADERS_RECEIVED = 2;
static LOADING = 3;
static DONE = 4;
UNSENT = XMLHttpRequestPolyfill.UNSENT;
OPENED = XMLHttpRequestPolyfill.OPENED;
HEADERS_RECEIVED = XMLHttpRequestPolyfill.HEADERS_RECEIVED;
LOADING = XMLHttpRequestPolyfill.LOADING;
DONE = XMLHttpRequestPolyfill.DONE;
upload = new XMLHttpRequestUploadPolyfill();
readyState = XMLHttpRequestPolyfill.UNSENT;
response = null;
responseText = "";
responseType = "";
responseURL = "";
status = 0;
statusText = "";
timeout = 0;
withCredentials = false;
miniProgram = null;
onreadystatechange = null;
onabort = null;
onerror = null;
onload = null;
onloadend = null;
onloadstart = null;
onprogress = null;
ontimeout = null;
method = "GET";
url = "";
requestHeaders = new HeadersPolyfill();
responseHeaders = new HeadersPolyfill();
requestController = null;
timeoutId = null;
sent = false;
open(method, url) {
this.method = String(method || "GET").toUpperCase();
this.url = url;
this.status = 0;
this.statusText = "";
this.response = null;
this.responseText = "";
this.responseURL = "";
this.responseHeaders = new HeadersPolyfill();
this.sent = false;
this.transitionTo(XMLHttpRequestPolyfill.OPENED);
}
setRequestHeader(key, value) {
if (this.readyState !== XMLHttpRequestPolyfill.OPENED || this.sent) throw new Error("Failed to execute setRequestHeader: invalid readyState");
this.requestHeaders.append(key, value);
}
getAllResponseHeaders() {
if (this.readyState < XMLHttpRequestPolyfill.HEADERS_RECEIVED) return "";
let content = "";
this.responseHeaders.forEach((value, key) => {
content += `${key}: ${value}\r\n`;
});
return content;
}
getResponseHeader(key) {
if (this.readyState < XMLHttpRequestPolyfill.HEADERS_RECEIVED) return null;
return this.responseHeaders.get(key);
}
abort() {
if (!this.requestController) return;
this.requestController.abort();
}
async send(body) {
if (this.readyState !== XMLHttpRequestPolyfill.OPENED) throw new Error("Failed to execute send: invalid readyState");
this.sent = true;
this.dispatchEvent({ type: "loadstart" });
this.upload.dispatchEvent(createProgressEvent("loadstart"));
const controller = new (typeof AbortController === "function" ? AbortController : AbortControllerPolyfill)();
this.requestController = controller;
if (this.timeout > 0) this.timeoutId = setTimeout(() => {
controller.abort(createError("timeout"));
}, this.timeout);
try {
const response = await resolveFetch()(this.url, {
method: this.method,
headers: headersToObject(this.requestHeaders),
body,
miniProgram: this.miniProgram ?? void 0,
signal: controller.signal
});
this.responseHeaders = typeof Headers === "function" && response.headers instanceof Headers ? response.headers : new HeadersPolyfill(response.headers);
this.status = response.status;
this.statusText = response.statusText ?? "";
this.responseURL = response.url ?? this.url;
this.transitionTo(XMLHttpRequestPolyfill.HEADERS_RECEIVED);
this.transitionTo(XMLHttpRequestPolyfill.LOADING);
if (this.responseType === "arraybuffer") this.response = await response.arrayBuffer();
else {
const text = await response.text();
this.responseText = text;
this.response = this.responseType === "json" ? text ? JSON.parse(text) : null : text;
}
this.finish("load");
} catch (error) {
const reason = controller.signal && "reason" in controller.signal ? controller.signal.reason : void 0;
if (controller.signal?.aborted) {
const type = reason instanceof Error && reason.name === "TimeoutError" ? "timeout" : "abort";
this.finish(type);
return;
}
this.response = null;
this.responseText = "";
this.status = 0;
this.statusText = "";
this.transitionTo(XMLHttpRequestPolyfill.DONE);
this.dispatchEvent({ type: "error" });
this.dispatchEvent({ type: "loadend" });
throw error;
} finally {
if (this.timeoutId) {
clearTimeout(this.timeoutId);
this.timeoutId = null;
}
this.requestController = null;
}
}
finish(type) {
this.transitionTo(XMLHttpRequestPolyfill.DONE);
if (type === "abort") this.dispatchEvent({ type: "abort" });
else if (type === "timeout") this.dispatchEvent({ type: "timeout" });
else {
this.dispatchEvent(createProgressEvent("progress"));
this.dispatchEvent({ type: "load" });
}
this.dispatchEvent({ type: "loadend" });
}
transitionTo(nextState) {
this.readyState = nextState;
this.dispatchEvent({ type: "readystatechange" });
}
};
//#endregion
export { XMLHttpRequestPolyfill, XMLHttpRequestUploadPolyfill };