UNPKG

@georgestagg/webr

Version:

The statistical programming langauge R compiled into WASM for use in a web browser and node.

1,588 lines (1,576 loc) 65.8 kB
var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) { if (typeof require !== "undefined") return require.apply(this, arguments); throw new Error('Dynamic require of "' + x + '" is not supported'); }); var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod)); var __accessCheck = (obj, member, msg) => { if (!member.has(obj)) throw TypeError("Cannot " + msg); }; var __privateGet = (obj, member, getter) => { __accessCheck(obj, member, "read from private field"); return getter ? getter.call(obj) : member.get(obj); }; var __privateAdd = (obj, member, value) => { if (member.has(obj)) throw TypeError("Cannot add the same private member more than once"); member instanceof WeakSet ? member.add(obj) : member.set(obj, value); }; var __privateSet = (obj, member, value, setter) => { __accessCheck(obj, member, "write to private field"); setter ? setter.call(obj, value) : member.set(obj, value); return value; }; var __privateMethod = (obj, member, method) => { __accessCheck(obj, member, "access private method"); return method; }; // webR/chan/queue.ts var _promises, _resolvers, _add, add_fn; var AsyncQueue = class { constructor() { __privateAdd(this, _add); __privateAdd(this, _promises, void 0); __privateAdd(this, _resolvers, void 0); __privateSet(this, _resolvers, []); __privateSet(this, _promises, []); } put(t) { if (!__privateGet(this, _resolvers).length) { __privateMethod(this, _add, add_fn).call(this); } const resolve = __privateGet(this, _resolvers).shift(); resolve(t); } async get() { if (!__privateGet(this, _promises).length) { __privateMethod(this, _add, add_fn).call(this); } const promise = __privateGet(this, _promises).shift(); return promise; } isEmpty() { return !__privateGet(this, _promises).length; } isBlocked() { return !!__privateGet(this, _resolvers).length; } get length() { return __privateGet(this, _promises).length - __privateGet(this, _resolvers).length; } }; _promises = new WeakMap(); _resolvers = new WeakMap(); _add = new WeakSet(); add_fn = function() { __privateGet(this, _promises).push(new Promise((resolve) => { __privateGet(this, _resolvers).push(resolve); })); }; // webR/compat.ts var IN_NODE = typeof process !== "undefined" && process.release && process.release.name === "node" && typeof process.browser === "undefined"; var loadScript; if (globalThis.document) { loadScript = (url) => new Promise((resolve, reject) => { const script = document.createElement("script"); script.src = url; script.onload = () => resolve(); script.onerror = reject; document.head.appendChild(script); }); } else if (globalThis.importScripts) { loadScript = async (url) => { try { globalThis.importScripts(url); } catch (e) { if (e instanceof TypeError) { await Promise.resolve().then(() => __toESM(__require(url))); } else { throw e; } } }; } else if (IN_NODE) { loadScript = async (url) => { const nodePathMod = (await Promise.resolve().then(() => __toESM(__require("path")))).default; await Promise.resolve().then(() => __toESM(__require(nodePathMod.resolve(url)))); }; } else { throw new Error("Cannot determine runtime environment"); } // webR/utils.ts function promiseHandles() { const out = { resolve: (_value) => { }, reject: (_reason) => { }, promise: null }; const promise = new Promise((resolve, reject) => { out.resolve = resolve; out.reject = reject; }); out.promise = promise; return out; } function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } function replaceInObject(obj, test, replacer, ...replacerArgs) { if (obj === null || typeof obj !== "object") { return obj; } if (test(obj)) { return replacer(obj, ...replacerArgs); } if (Array.isArray(obj) || ArrayBuffer.isView(obj)) { return obj.map((v) => replaceInObject(v, test, replacer, ...replacerArgs)); } return Object.fromEntries(Object.entries(obj).map(([k, v], i) => [k, replaceInObject(v, test, replacer, ...replacerArgs)])); } function unpackScalarVectors(obj) { return replaceInObject(obj, (obj2) => "values" in obj2 && (Array.isArray(obj2.values) || ArrayBuffer.isView(obj2)) && obj2.values.length === 1, (obj2) => obj2.values[0]); } function newCrossOriginWorker(url, cb) { const req = new XMLHttpRequest(); req.open("get", url, true); req.onload = () => { const worker = new Worker(URL.createObjectURL(new Blob([req.responseText]))); cb(worker); }; req.send(); } function isCrossOrigin(urlString) { if (IN_NODE) return false; const url1 = new URL(location.href); const url2 = new URL(urlString, location.origin); if (url1.host === url2.host && url1.port === url2.port && url1.protocol === url2.protocol) { return false; } return true; } // webR/chan/task-common.ts var SZ_BUF_DOESNT_FIT = 0; var SZ_BUF_FITS_IDX = 1; var SZ_BUF_SIZE_IDX = 0; var transferCache = /* @__PURE__ */ new WeakMap(); function transfer(obj, transfers) { transferCache.set(obj, transfers); return obj; } var UUID_LENGTH = 63; function generateUUID() { const result = Array.from({ length: 4 }, randomSegment).join("-"); if (result.length !== UUID_LENGTH) { throw new Error("comlink internal error: UUID has the wrong length"); } return result; } function randomSegment() { let result = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16); const pad = 15 - result.length; if (pad > 0) { result = Array.from({ length: pad }, () => 0).join("") + result; } return result; } // webR/chan/message.ts function newRequest(msg, transferables) { return newRequestResponseMessage({ type: "request", data: { uuid: generateUUID(), msg } }, transferables); } function newResponse(uuid, resp, transferables) { return newRequestResponseMessage({ type: "response", data: { uuid, resp } }, transferables); } function newRequestResponseMessage(msg, transferables) { if (transferables) { transfer(msg, transferables); } return msg; } function newSyncRequest(msg, data) { return { type: "sync-request", data: { msg, reqData: data } }; } var encoder = new TextEncoder(); var decoder = new TextDecoder("utf-8"); function encodeData(data) { return encoder.encode(JSON.stringify(data)); } function decodeData(data) { return JSON.parse(decoder.decode(data)); } // webR/chan/task-main.ts var encoder2 = new TextEncoder(); async function syncResponse(endpoint, data, response) { try { let { taskId, sizeBuffer, dataBuffer, signalBuffer } = data; const bytes = encodeData(response); const fits = bytes.length <= dataBuffer.length; Atomics.store(sizeBuffer, SZ_BUF_SIZE_IDX, bytes.length); Atomics.store(sizeBuffer, SZ_BUF_FITS_IDX, +fits); if (!fits) { const [uuid, dataPromise] = requestResponseMessage(endpoint); dataBuffer.set(encoder2.encode(uuid)); await signalRequester(signalBuffer, taskId); dataBuffer = (await dataPromise).dataBuffer; } dataBuffer.set(bytes); Atomics.store(sizeBuffer, SZ_BUF_FITS_IDX, 1); await signalRequester(signalBuffer, taskId); } catch (e) { console.warn(e); } } function requestResponseMessage(ep) { const id = generateUUID(); return [ id, new Promise((resolve) => { if (IN_NODE) { ep.once("message", (message) => { if (!message.id || message.id !== id) { return; } resolve(message); }); } else { ep.addEventListener("message", function l(ev) { if (!ev.data || !ev.data.id || ev.data.id !== id) { return; } ep.removeEventListener("message", l); resolve(ev.data); }); } if (ep.start) { ep.start(); } }) ]; } async function signalRequester(signalBuffer, taskId) { const index = (taskId >> 1) % 32; let sleepTime = 1; while (Atomics.compareExchange(signalBuffer, index + 1, 0, taskId) !== 0) { await sleep(sleepTime); if (sleepTime < 32) { sleepTime *= 2; } } Atomics.or(signalBuffer, 0, 1 << index); Atomics.notify(signalBuffer, 0); } // webR/chan/task-worker.ts var decoder2 = new TextDecoder("utf-8"); var _scheduled, _resolved, _result, _exception, _syncGen; var SyncTask = class { constructor(endpoint, msg, transfers = []) { __privateAdd(this, _scheduled, false); __privateAdd(this, _resolved, void 0); __privateAdd(this, _result, void 0); __privateAdd(this, _exception, void 0); __privateAdd(this, _syncGen, void 0); this.syncifier = new _Syncifier(); this.endpoint = endpoint; this.msg = msg; this.transfers = transfers; __privateSet(this, _resolved, false); } scheduleSync() { if (__privateGet(this, _scheduled)) { return; } __privateSet(this, _scheduled, true); this.syncifier.scheduleTask(this); __privateSet(this, _syncGen, this.doSync()); __privateGet(this, _syncGen).next(); return this; } poll() { if (!__privateGet(this, _scheduled)) { throw new Error("Task not synchronously scheduled"); } const { done, value } = __privateGet(this, _syncGen).next(); if (!done) { return false; } __privateSet(this, _resolved, true); __privateSet(this, _result, value); return true; } *doSync() { const { endpoint, msg, transfers } = this; const sizeBuffer = new Int32Array(new SharedArrayBuffer(8)); const signalBuffer = this.signalBuffer; const taskId = this.taskId; let dataBuffer = acquireDataBuffer(UUID_LENGTH); const syncMsg = newSyncRequest(msg, { sizeBuffer, dataBuffer, signalBuffer, taskId }); endpoint.postMessage(syncMsg, transfers); yield; if (Atomics.load(sizeBuffer, SZ_BUF_FITS_IDX) === SZ_BUF_DOESNT_FIT) { const id = decoder2.decode(dataBuffer.slice(0, UUID_LENGTH)); releaseDataBuffer(dataBuffer); const size2 = Atomics.load(sizeBuffer, SZ_BUF_SIZE_IDX); dataBuffer = acquireDataBuffer(size2); endpoint.postMessage({ id, dataBuffer }); yield; } const size = Atomics.load(sizeBuffer, SZ_BUF_SIZE_IDX); return decodeData(dataBuffer.slice(0, size)); } get result() { if (__privateGet(this, _exception)) { throw __privateGet(this, _exception); } if (__privateGet(this, _resolved)) { return __privateGet(this, _result); } throw new Error("Not ready."); } syncify() { this.scheduleSync(); this.syncifier.syncifyTask(this); return this.result; } }; _scheduled = new WeakMap(); _resolved = new WeakMap(); _result = new WeakMap(); _exception = new WeakMap(); _syncGen = new WeakMap(); var _Syncifier = class { constructor() { this.nextTaskId = new Int32Array([1]); this.signalBuffer = new Int32Array(new SharedArrayBuffer(32 * 4 + 4)); this.tasks = /* @__PURE__ */ new Map(); } scheduleTask(task) { task.taskId = this.nextTaskId[0]; this.nextTaskId[0] += 2; task.signalBuffer = this.signalBuffer; this.tasks.set(task.taskId, task); } waitOnSignalBuffer() { const timeout = 50; for (; ; ) { const status = Atomics.wait(this.signalBuffer, 0, 0, timeout); switch (status) { case "ok": case "not-equal": return; case "timed-out": if (interruptBuffer[0] !== 0) { handleInterrupt(); } break; default: throw new Error("Unreachable"); } } } *tasksIdsToWakeup() { const flag = Atomics.load(this.signalBuffer, 0); for (let i = 0; i < 32; i++) { const bit = 1 << i; if (flag & bit) { Atomics.and(this.signalBuffer, 0, ~bit); const wokenTask = Atomics.exchange(this.signalBuffer, i + 1, 0); yield wokenTask; } } } pollTasks(task) { let result = false; for (const wokenTaskId of this.tasksIdsToWakeup()) { const wokenTask = this.tasks.get(wokenTaskId); if (!wokenTask) { throw new Error(`Assertion error: unknown taskId ${wokenTaskId}.`); } if (wokenTask.poll()) { this.tasks.delete(wokenTaskId); if (wokenTask === task) { result = true; } } } return result; } syncifyTask(task) { for (; ; ) { this.waitOnSignalBuffer(); if (this.pollTasks(task)) { return; } } } }; var dataBuffers = []; function acquireDataBuffer(size) { const powerof2 = Math.ceil(Math.log2(size)); if (!dataBuffers[powerof2]) { dataBuffers[powerof2] = []; } const result = dataBuffers[powerof2].pop(); if (result) { result.fill(0); return result; } return new Uint8Array(new SharedArrayBuffer(2 ** powerof2)); } function releaseDataBuffer(buffer) { const powerof2 = Math.ceil(Math.log2(buffer.byteLength)); dataBuffers[powerof2].push(buffer); } var interruptBuffer = new Int32Array(new ArrayBuffer(4)); var handleInterrupt = () => { interruptBuffer[0] = 0; throw new Error("Interrupted!"); }; function setInterruptHandler(handler) { handleInterrupt = handler; } function setInterruptBuffer(buffer) { interruptBuffer = new Int32Array(buffer); } // webR/chan/channel-shared.ts if (IN_NODE) { globalThis.Worker = __require("worker_threads").Worker; } var _interruptBuffer, _parked, _resolveResponse, resolveResponse_fn, _handleEventsFromWorker, handleEventsFromWorker_fn, _onMessageFromWorker; var SharedBufferChannelMain = class { constructor(config) { __privateAdd(this, _resolveResponse); __privateAdd(this, _handleEventsFromWorker); this.inputQueue = new AsyncQueue(); this.outputQueue = new AsyncQueue(); __privateAdd(this, _interruptBuffer, void 0); this.close = () => { }; __privateAdd(this, _parked, /* @__PURE__ */ new Map()); __privateAdd(this, _onMessageFromWorker, async (worker, message) => { if (!message || !message.type) { return; } switch (message.type) { case "resolve": __privateSet(this, _interruptBuffer, new Int32Array(message.data)); this.resolve(); return; case "response": __privateMethod(this, _resolveResponse, resolveResponse_fn).call(this, message); return; default: this.outputQueue.put(message); return; case "sync-request": { const msg = message; const payload = msg.data.msg; const reqData = msg.data.reqData; switch (payload.type) { case "read": { const response = await this.inputQueue.get(); await syncResponse(worker, reqData, response); break; } default: throw new TypeError(`Unsupported request type '${payload.type}'.`); } return; } case "request": throw new TypeError("Can't send messages of type 'request' from a worker. Please Use 'sync-request' instead."); } }); const initWorker = (worker) => { __privateMethod(this, _handleEventsFromWorker, handleEventsFromWorker_fn).call(this, worker); this.close = () => worker.terminate(); const msg = { type: "init", data: { config, channelType: ChannelType.SharedArrayBuffer } }; worker.postMessage(msg); }; if (isCrossOrigin(config.WEBR_URL)) { newCrossOriginWorker(`${config.WEBR_URL}webr-worker.js`, (worker) => initWorker(worker)); } else { const worker = new Worker(`${config.WEBR_URL}webr-worker.js`); initWorker(worker); } ({ resolve: this.resolve, promise: this.initialised } = promiseHandles()); } async read() { return await this.outputQueue.get(); } async flush() { const msg = []; while (!this.outputQueue.isEmpty()) { msg.push(await this.read()); } return msg; } interrupt() { if (!__privateGet(this, _interruptBuffer)) { throw new Error("Failed attempt to interrupt before initialising interruptBuffer"); } __privateGet(this, _interruptBuffer)[0] = 1; } write(msg) { this.inputQueue.put(msg); } async request(msg, transferables) { const req = newRequest(msg, transferables); const { resolve, promise: prom } = promiseHandles(); __privateGet(this, _parked).set(req.data.uuid, resolve); this.write(req); return prom; } }; _interruptBuffer = new WeakMap(); _parked = new WeakMap(); _resolveResponse = new WeakSet(); resolveResponse_fn = function(msg) { const uuid = msg.data.uuid; const resolve = __privateGet(this, _parked).get(uuid); if (resolve) { __privateGet(this, _parked).delete(uuid); resolve(msg.data.resp); } else { console.warn("Can't find request."); } }; _handleEventsFromWorker = new WeakSet(); handleEventsFromWorker_fn = function(worker) { if (IN_NODE) { worker.on("message", (message) => { __privateGet(this, _onMessageFromWorker).call(this, worker, message); }); } else { worker.onmessage = (ev) => __privateGet(this, _onMessageFromWorker).call(this, worker, ev.data); } }; _onMessageFromWorker = new WeakMap(); var _ep, _dispatch, _interruptBuffer2, _interrupt; var SharedBufferChannelWorker = class { constructor() { __privateAdd(this, _ep, void 0); __privateAdd(this, _dispatch, () => 0); __privateAdd(this, _interruptBuffer2, new Int32Array(new SharedArrayBuffer(4))); __privateAdd(this, _interrupt, () => { }); __privateSet(this, _ep, IN_NODE ? __require("worker_threads").parentPort : globalThis); setInterruptBuffer(__privateGet(this, _interruptBuffer2).buffer); setInterruptHandler(() => this.handleInterrupt()); } resolve() { this.write({ type: "resolve", data: __privateGet(this, _interruptBuffer2).buffer }); } write(msg, transfer2) { __privateGet(this, _ep).postMessage(msg, transfer2); } read() { const msg = { type: "read" }; const task = new SyncTask(__privateGet(this, _ep), msg); return task.syncify(); } inputOrDispatch() { for (; ; ) { const msg = this.read(); if (msg.type === "stdin") { return Module.allocateUTF8(msg.data); } __privateGet(this, _dispatch).call(this, msg); } } run(args) { Module.callMain(args); } setInterrupt(interrupt) { __privateSet(this, _interrupt, interrupt); } handleInterrupt() { if (__privateGet(this, _interruptBuffer2)[0] !== 0) { __privateGet(this, _interruptBuffer2)[0] = 0; __privateGet(this, _interrupt).call(this); } } setDispatchHandler(dispatch) { __privateSet(this, _dispatch, dispatch); } }; _ep = new WeakMap(); _dispatch = new WeakMap(); _interruptBuffer2 = new WeakMap(); _interrupt = new WeakMap(); // webR/chan/channel-service.ts if (IN_NODE) { globalThis.Worker = __require("worker_threads").Worker; } var _parked2, _syncMessageCache, _registration, _interrupted, _registerServiceWorker, registerServiceWorker_fn, _onMessageFromServiceWorker, onMessageFromServiceWorker_fn, _resolveResponse2, resolveResponse_fn2, _handleEventsFromWorker2, handleEventsFromWorker_fn2, _onMessageFromWorker2; var ServiceWorkerChannelMain = class { constructor(config) { __privateAdd(this, _registerServiceWorker); __privateAdd(this, _onMessageFromServiceWorker); __privateAdd(this, _resolveResponse2); __privateAdd(this, _handleEventsFromWorker2); this.inputQueue = new AsyncQueue(); this.outputQueue = new AsyncQueue(); this.close = () => { }; __privateAdd(this, _parked2, /* @__PURE__ */ new Map()); __privateAdd(this, _syncMessageCache, /* @__PURE__ */ new Map()); __privateAdd(this, _registration, void 0); __privateAdd(this, _interrupted, false); __privateAdd(this, _onMessageFromWorker2, async (worker, message) => { if (!message || !message.type) { return; } switch (message.type) { case "resolve": this.resolve(); return; case "response": __privateMethod(this, _resolveResponse2, resolveResponse_fn2).call(this, message); return; default: this.outputQueue.put(message); return; case "sync-request": { const request = message.data; __privateGet(this, _syncMessageCache).set(request.data.uuid, request.data.msg); return; } case "request": throw new TypeError("Can't send messages of type 'request' from a worker.Use service worker fetch request instead."); } }); const initWorker = (worker) => { __privateMethod(this, _handleEventsFromWorker2, handleEventsFromWorker_fn2).call(this, worker); this.close = () => worker.terminate(); __privateMethod(this, _registerServiceWorker, registerServiceWorker_fn).call(this, `${config.SW_URL}webr-serviceworker.js`).then((clientId) => { const msg = { type: "init", data: { config, channelType: ChannelType.ServiceWorker, clientId, location: window.location.href } }; worker.postMessage(msg); }); }; if (isCrossOrigin(config.SW_URL)) { newCrossOriginWorker(`${config.SW_URL}webr-worker.js`, (worker) => initWorker(worker)); } else { const worker = new Worker(`${config.SW_URL}webr-worker.js`); initWorker(worker); } ({ resolve: this.resolve, promise: this.initialised } = promiseHandles()); } activeRegistration() { var _a; if (!((_a = __privateGet(this, _registration)) == null ? void 0 : _a.active)) { throw new Error("Attempted to obtain a non-existent active registration."); } return __privateGet(this, _registration).active; } async read() { return await this.outputQueue.get(); } async flush() { const msg = []; while (!this.outputQueue.isEmpty()) { msg.push(await this.read()); } return msg; } interrupt() { __privateSet(this, _interrupted, true); } write(msg) { this.inputQueue.put(msg); } async request(msg, transferables) { const req = newRequest(msg, transferables); const { resolve, promise: prom } = promiseHandles(); __privateGet(this, _parked2).set(req.data.uuid, resolve); this.write(req); return prom; } }; _parked2 = new WeakMap(); _syncMessageCache = new WeakMap(); _registration = new WeakMap(); _interrupted = new WeakMap(); _registerServiceWorker = new WeakSet(); registerServiceWorker_fn = async function(url) { __privateSet(this, _registration, await navigator.serviceWorker.register(url)); await navigator.serviceWorker.ready; window.addEventListener("beforeunload", () => { var _a; (_a = __privateGet(this, _registration)) == null ? void 0 : _a.unregister(); }); const clientId = await new Promise((resolve) => { navigator.serviceWorker.addEventListener("message", function listener(event) { if (event.data.type === "registration-successful") { navigator.serviceWorker.removeEventListener("message", listener); resolve(event.data.clientId); } }); this.activeRegistration().postMessage({ type: "register-client-main" }); }); navigator.serviceWorker.addEventListener("message", (event) => { __privateMethod(this, _onMessageFromServiceWorker, onMessageFromServiceWorker_fn).call(this, event); }); return clientId; }; _onMessageFromServiceWorker = new WeakSet(); onMessageFromServiceWorker_fn = async function(event) { if (event.data.type === "request") { const uuid = event.data.data; const message = __privateGet(this, _syncMessageCache).get(uuid); if (!message) { throw new Error("Request not found during service worker XHR request"); } __privateGet(this, _syncMessageCache).delete(uuid); switch (message.type) { case "read": { const response = await this.inputQueue.get(); this.activeRegistration().postMessage({ type: "wasm-webr-fetch-response", uuid, response: newResponse(uuid, response) }); break; } case "interrupt": { const response = __privateGet(this, _interrupted); this.activeRegistration().postMessage({ type: "wasm-webr-fetch-response", uuid, response: newResponse(uuid, response) }); __privateSet(this, _interrupted, false); break; } default: throw new TypeError(`Unsupported request type '${message.type}'.`); } return; } }; _resolveResponse2 = new WeakSet(); resolveResponse_fn2 = function(msg) { const uuid = msg.data.uuid; const resolve = __privateGet(this, _parked2).get(uuid); if (resolve) { __privateGet(this, _parked2).delete(uuid); resolve(msg.data.resp); } else { console.warn("Can't find request."); } }; _handleEventsFromWorker2 = new WeakSet(); handleEventsFromWorker_fn2 = function(worker) { if (IN_NODE) { worker.on("message", (message) => { __privateGet(this, _onMessageFromWorker2).call(this, worker, message); }); } else { worker.onmessage = (ev) => __privateGet(this, _onMessageFromWorker2).call(this, worker, ev.data); } }; _onMessageFromWorker2 = new WeakMap(); var _ep2, _mainThreadId, _location, _dispatch2, _interrupt2; var ServiceWorkerChannelWorker = class { constructor(data) { __privateAdd(this, _ep2, void 0); __privateAdd(this, _mainThreadId, void 0); __privateAdd(this, _location, void 0); __privateAdd(this, _dispatch2, () => 0); __privateAdd(this, _interrupt2, () => { }); this.onMessageFromMainThread = () => { }; if (!data.clientId || !data.location) { throw Error("Unable to start service worker channel"); } __privateSet(this, _mainThreadId, data.clientId); __privateSet(this, _location, data.location); __privateSet(this, _ep2, IN_NODE ? __require("worker_threads").parentPort : globalThis); } resolve() { this.write({ type: "resolve" }); } write(msg, transfer2) { __privateGet(this, _ep2).postMessage(msg, transfer2); } syncRequest(message) { const request = newRequest(message); this.write({ type: "sync-request", data: request }); let retryCount = 0; for (; ; ) { try { const url = new URL("__wasm__/webr-fetch-request/", __privateGet(this, _location)); const xhr = new XMLHttpRequest(); xhr.timeout = 6e4; xhr.responseType = "arraybuffer"; xhr.open("POST", url, false); const fetchReqBody = { clientId: __privateGet(this, _mainThreadId), uuid: request.data.uuid }; xhr.send(encodeData(fetchReqBody)); return decodeData(new Uint8Array(xhr.response)); } catch (e) { if (e instanceof DOMException && retryCount++ < 1e3) { console.log("Service worker request failed - resending request"); } else { throw e; } } } } read() { const response = this.syncRequest({ type: "read" }); return response.data.resp; } inputOrDispatch() { for (; ; ) { const msg = this.read(); if (msg.type === "stdin") { return Module.allocateUTF8(msg.data); } __privateGet(this, _dispatch2).call(this, msg); } } run(args) { Module.callMain(args); } setInterrupt(interrupt) { __privateSet(this, _interrupt2, interrupt); } handleInterrupt() { const response = this.syncRequest({ type: "interrupt" }); const interrupted = response.data.resp; if (interrupted) { __privateGet(this, _interrupt2).call(this); } } setDispatchHandler(dispatch) { __privateSet(this, _dispatch2, dispatch); } }; _ep2 = new WeakMap(); _mainThreadId = new WeakMap(); _location = new WeakMap(); _dispatch2 = new WeakMap(); _interrupt2 = new WeakMap(); // webR/chan/channel.ts var ChannelType = { Automatic: 0, SharedArrayBuffer: 1, ServiceWorker: 2 }; function newChannelMain(data) { switch (data.channelType) { case ChannelType.SharedArrayBuffer: return new SharedBufferChannelMain(data); case ChannelType.ServiceWorker: return new ServiceWorkerChannelMain(data); case ChannelType.Automatic: default: if (IN_NODE || crossOriginIsolated) { return new SharedBufferChannelMain(data); } if ("serviceWorker" in navigator && !isCrossOrigin(data.SW_URL)) { return new ServiceWorkerChannelMain(data); } throw new Error("Unable to initialise main thread communication channel"); } } // webR/config.ts var BASE_URL = "https://cdn.webr.workers.dev/latest/"; var PKG_BASE_URL = "https://repo.webr.workers.dev/"; // webR/robj.ts var RTypeMap = { null: 0, symbol: 1, pairlist: 2, closure: 3, environment: 4, promise: 5, call: 6, special: 7, builtin: 8, string: 9, logical: 10, integer: 13, double: 14, complex: 15, character: 16, dots: 17, any: 18, list: 19, expression: 20, bytecode: 21, pointer: 22, weakref: 23, raw: 24, s4: 25, new: 30, free: 31, function: 99 }; function newRObjFromTarget(target) { const obj = target.obj; if (isRObjectTree(obj)) { return new (getRObjClass(RTypeMap[obj.type]))(obj); } if (obj && typeof obj === "object" && "type" in obj && obj.type === "null") { return new RObjNull(); } if (obj === null) { return new RObjLogical({ type: "logical", names: null, values: [null] }); } if (typeof obj === "boolean") { return new RObjLogical(obj); } if (typeof obj === "number") { return new RObjDouble(obj); } if (typeof obj === "object" && "re" in obj && "im" in obj) { return new RObjComplex(obj); } if (typeof obj === "string") { return new RObjCharacter(obj); } if (Array.isArray(obj)) { const objs = obj.map((el) => newRObjFromTarget({ targetType: "raw", obj: el })); const cString = Module.allocateUTF8("c"); const call = RObjImpl.protect(RObjImpl.wrap(Module._Rf_allocVector(RTypeMap.call, objs.length + 1))); call.setcar(RObjImpl.wrap(Module._Rf_install(cString))); let next = call.cdr(); let i = 0; while (!next.isNull()) { next.setcar(objs[i++]); next = next.cdr(); } const res = RObjImpl.wrap(Module._Rf_eval(call.ptr, RObjImpl.baseEnv.ptr)); RObjImpl.unprotect(1); Module._free(cString); return res; } throw new Error("Robj construction for this JS object is not yet supported"); } var RObjImpl = class { constructor(target) { this.ptr = 0; if (isRTargetObj(target)) { if (target.targetType === "ptr") { this.ptr = target.obj.ptr; return this; } if (target.targetType === "raw") { return newRObjFromTarget(target); } } return newRObjFromTarget({ targetType: "raw", obj: target }); } get [Symbol.toStringTag]() { return `RObj:${this.type()}`; } type() { const typeNumber = Module._TYPEOF(this.ptr); const type = Object.keys(RTypeMap).find((typeName) => RTypeMap[typeName] === typeNumber); return type; } protect() { this.ptr = Module._Rf_protect(this.ptr); } unprotect() { Module._Rf_unprotect_ptr(this.ptr); } preserve() { Module._R_PreserveObject(this.ptr); } release() { Module._R_ReleaseObject(this.ptr); } isNull() { return Module._TYPEOF(this.ptr) === RTypeMap.null; } isUnbound() { return this.ptr === RObjImpl.unboundValue.ptr; } attrs() { return RObjImpl.wrap(Module._ATTRIB(this.ptr)); } setNames(values) { let namesObj; if (values === null) { namesObj = RObjImpl.null; RObjImpl.protect(namesObj); } else if (Array.isArray(values) && values.every((v) => typeof v === "string" || v === null)) { namesObj = new RObjCharacter(values); } else { throw new Error("Argument to setNames must be null or an Array of strings or null"); } Module._Rf_setAttrib(this.ptr, RObjImpl.namesSymbol.ptr, namesObj.ptr); RObjImpl.unprotect(1); return this; } names() { const names = RObjImpl.wrap(Module._Rf_protect(Module._Rf_getAttrib(this.ptr, RObjImpl.namesSymbol.ptr))); if (names.isNull()) { return null; } return names.toArray(); } includes(name) { const names = this.names(); return names && names.includes(name); } toTree(options = { depth: 0 }, depth = 1) { throw new Error("This R object cannot be converted to JS"); } toJs() { return this.toTree(); } subset(prop) { let idx; let char = 0; if (typeof prop === "number") { idx = Module._Rf_protect(Module._Rf_ScalarInteger(prop)); } else { char = Module.allocateUTF8(prop); idx = Module._Rf_protect(Module._Rf_mkString(char)); } const call = Module._Rf_protect(Module._Rf_lang3(RObjImpl.bracketSymbol.ptr, this.ptr, idx)); const sub = RObjImpl.wrap(Module._Rf_eval(call, RObjImpl.baseEnv.ptr)); Module._Rf_unprotect(2); if (char) Module._free(char); return sub; } get(prop) { let idx; let char = 0; if (typeof prop === "number") { idx = Module._Rf_protect(Module._Rf_ScalarInteger(prop)); } else { char = Module.allocateUTF8(prop); idx = Module._Rf_protect(Module._Rf_mkString(char)); } const call = Module._Rf_protect(Module._Rf_lang3(RObjImpl.bracket2Symbol.ptr, this.ptr, idx)); const sub = RObjImpl.wrap(Module._Rf_eval(call, RObjImpl.baseEnv.ptr)); Module._Rf_unprotect(2); if (char) Module._free(char); return sub; } getDollar(prop) { const char = Module.allocateUTF8(prop); const idx = Module._Rf_protect(Module._Rf_mkString(char)); const call = Module._Rf_protect(Module._Rf_lang3(RObjImpl.dollarSymbol.ptr, this.ptr, idx)); const sub = RObjImpl.wrap(Module._Rf_eval(call, RObjImpl.baseEnv.ptr)); Module._Rf_unprotect(2); Module._free(char); return sub; } pluck(...path) { try { const result = path.reduce((obj, prop) => obj.get(prop), this); return result.isNull() ? void 0 : result; } catch (err) { if (err === Infinity) { return void 0; } throw err; } } set(prop, value) { let idx; let char = 0; if (typeof prop === "number") { idx = Module._Rf_protect(Module._Rf_ScalarInteger(prop)); } else { char = Module.allocateUTF8(prop); idx = Module._Rf_protect(Module._Rf_mkString(char)); } const valueObj = isRObjImpl(value) ? value : new RObjImpl({ obj: value, targetType: "raw" }); const assign = Module.allocateUTF8("[[<-"); const call = Module._Rf_protect(Module._Rf_lang4(Module._Rf_install(assign), this.ptr, idx, valueObj.ptr)); const val = RObjImpl.wrap(Module._Rf_eval(call, RObjImpl.baseEnv.ptr)); Module._Rf_unprotect(2); if (char) Module._free(char); Module._free(assign); if (!isRObjImpl(value)) { valueObj.release(); } return val; } static getMethods(obj) { const props = /* @__PURE__ */ new Set(); let cur = obj; do { Object.getOwnPropertyNames(cur).map((p) => props.add(p)); } while (cur = Object.getPrototypeOf(cur)); return [...props.keys()].filter((i) => typeof obj[i] === "function"); } static get globalEnv() { return RObjImpl.wrap(Module.getValue(Module._R_GlobalEnv, "*")); } static get emptyEnv() { return RObjImpl.wrap(Module.getValue(Module._R_EmptyEnv, "*")); } static get baseEnv() { return RObjImpl.wrap(Module.getValue(Module._R_BaseEnv, "*")); } static get null() { return RObjImpl.wrap(Module.getValue(Module._R_NilValue, "*")); } static get naLogical() { return Module.getValue(Module._R_NaInt, "i32"); } static get naInteger() { return Module.getValue(Module._R_NaInt, "i32"); } static get naDouble() { return Module.getValue(Module._R_NaReal, "double"); } static get naString() { return RObjImpl.wrap(Module.getValue(Module._R_NaString, "*")); } static get unboundValue() { return RObjImpl.wrap(Module.getValue(Module._R_UnboundValue, "*")); } static get bracketSymbol() { return RObjImpl.wrap(Module.getValue(Module._R_BracketSymbol, "*")); } static get bracket2Symbol() { return RObjImpl.wrap(Module.getValue(Module._R_Bracket2Symbol, "*")); } static get dollarSymbol() { return RObjImpl.wrap(Module.getValue(Module._R_DollarSymbol, "*")); } static get namesSymbol() { return RObjImpl.wrap(Module.getValue(Module._R_NamesSymbol, "*")); } static wrap(ptr) { const type = Module._TYPEOF(ptr); return new (getRObjClass(type))({ targetType: "ptr", obj: { ptr } }); } static protect(obj) { return RObjImpl.wrap(Module._Rf_protect(obj.ptr)); } static unprotect(n) { Module._Rf_unprotect(n); } static unprotectPtr(obj) { Module._Rf_unprotect_ptr(obj.ptr); } static preserveObject(obj) { Module._R_PreserveObject(obj.ptr); } static releaseObject(obj) { Module._R_ReleaseObject(obj.ptr); } }; var RObjNull = class extends RObjImpl { constructor() { super({ targetType: "ptr", obj: { ptr: Module.getValue(Module._R_NilValue, "*") } }); return this; } toTree() { return { type: "null" }; } }; var RObjSymbol = class extends RObjImpl { toTree() { return this.isUnbound() ? null : this.toObject(); } toObject() { return { printname: this.printname().isUnbound() ? null : this.printname().toString(), symvalue: this.symvalue().isUnbound() ? null : this.symvalue().ptr, internal: this.internal().isNull() ? null : this.internal().ptr }; } printname() { return RObjImpl.wrap(Module._PRINTNAME(this.ptr)); } symvalue() { return RObjImpl.wrap(Module._SYMVALUE(this.ptr)); } internal() { return RObjImpl.wrap(Module._INTERNAL(this.ptr)); } }; var RObjPairlist = class extends RObjImpl { constructor(val) { if (isRTargetObj(val)) { super(val); return this; } const values = isRObjectTree(val) ? val.values : Array.isArray(val) ? val : [val]; const list = RObjImpl.wrap(Module._Rf_allocList(values.length)); list.preserve(); for (let [i, next] = [0, list]; !next.isNull(); [i, next] = [i + 1, next.cdr()]) { next.setcar(new RObjImpl(values[i])); } list.setNames(isRObjectTree(val) ? val.names : null); super({ targetType: "ptr", obj: { ptr: list.ptr } }); } get length() { return this.toArray().length; } toArray(options = { depth: 1 }) { return this.toTree(options).values; } toObject({ allowDuplicateKey = true, allowEmptyKey = false, depth = 1 } = {}) { const entries = this.entries({ depth }); const keys = entries.map(([k, v]) => k); if (!allowDuplicateKey && new Set(keys).size !== keys.length) { throw new Error("Duplicate key when converting pairlist without allowDuplicateKey enabled"); } if (!allowEmptyKey && keys.some((k) => !k)) { throw new Error("Empty or null key when converting pairlist without allowEmptyKey enabled"); } return Object.fromEntries(entries.filter((u, idx) => entries.findIndex((v) => v[0] === u[0]) === idx)); } entries(options = { depth: 1 }) { const obj = this.toTree(options); return obj.values.map((v, i) => [obj.names ? obj.names[i] : null, v]); } toTree(options = { depth: 0 }, depth = 1) { const namesArray = []; let hasNames = false; const values = []; for (let next = this; !next.isNull(); next = next.cdr()) { const symbol = next.tag(); if (symbol.isNull()) { namesArray.push(""); } else { hasNames = true; namesArray.push(symbol.printname().toString()); } if (options.depth && depth >= options.depth) { values.push(next.car()); } else { values.push(next.car().toTree(options, depth + 1)); } } const names = hasNames ? namesArray : null; return { type: this.type(), names, values }; } includes(name) { return name in this.toObject(); } setcar(obj) { Module._SETCAR(this.ptr, obj.ptr); } car() { return RObjImpl.wrap(Module._CAR(this.ptr)); } cdr() { return RObjImpl.wrap(Module._CDR(this.ptr)); } tag() { return RObjImpl.wrap(Module._TAG(this.ptr)); } }; var RObjList = class extends RObjImpl { constructor(val) { if (isRTargetObj(val)) { super(val); return this; } const values = isRObjectTree(val) ? val.values : Array.isArray(val) ? val : [val]; const ptr = Module._Rf_protect(Module._Rf_allocVector(RTypeMap.list, values.length)); values.forEach((v, i) => { Module._SET_VECTOR_ELT(ptr, i, new RObjImpl(v).ptr); }); RObjImpl.wrap(ptr).setNames(isRObjectTree(val) ? val.names : null); Module._Rf_unprotect(1); Module._R_PreserveObject(ptr); super({ targetType: "ptr", obj: { ptr } }); } get length() { return Module._LENGTH(this.ptr); } toArray(options = { depth: 1 }) { return this.toTree(options).values; } toObject({ allowDuplicateKey = true, allowEmptyKey = false, depth = 1 } = {}) { const entries = this.entries({ depth }); const keys = entries.map(([k, v]) => k); if (!allowDuplicateKey && new Set(keys).size !== keys.length) { throw new Error("Duplicate key when converting list without allowDuplicateKey enabled"); } if (!allowEmptyKey && keys.some((k) => !k)) { throw new Error("Empty or null key when converting list without allowEmptyKey enabled"); } return Object.fromEntries(entries.filter((u, idx) => entries.findIndex((v) => v[0] === u[0]) === idx)); } entries(options = { depth: 1 }) { const obj = this.toTree(options); return obj.values.map((v, i) => [obj.names ? obj.names[i] : null, v]); } toTree(options = { depth: 0 }, depth = 1) { return { type: this.type(), names: this.names(), values: [...Array(this.length).keys()].map((i) => { if (options.depth && depth >= options.depth) { return this.get(i + 1); } else { return this.get(i + 1).toTree(options, depth + 1); } }) }; } }; var RObjFunction = class extends RObjImpl { exec(...args) { const argObjs = args.map((arg) => isRObjImpl(arg) ? arg : new RObjImpl({ obj: arg, targetType: "raw" })); const call = RObjImpl.protect(RObjImpl.wrap(Module._Rf_allocVector(RTypeMap.call, args.length + 1))); call.setcar(this); let c = call.cdr(); let i = 0; while (!c.isNull()) { c.setcar(argObjs[i++]); c = c.cdr(); } const res = RObjImpl.wrap(Module._Rf_eval(call.ptr, RObjImpl.baseEnv.ptr)); RObjImpl.unprotect(1); argObjs.forEach((argObj, idx) => { if (!isRObjImpl(args[idx])) { argObj.release(); } }); return res; } }; var RObjString = class extends RObjImpl { toString() { return Module.UTF8ToString(Module._R_CHAR(this.ptr)); } toTree() { return this.toString(); } }; var RObjEnvironment = class extends RObjImpl { constructor(val) { if (isRTargetObj(val)) { super(val); return this; } const ptr = Module._Rf_protect(Module._R_NewEnv(RObjImpl.globalEnv.ptr, 0, 0)); val.values.forEach((v, i) => { const name = val.names ? val.names[i] : null; if (!name) { throw new Error("Unable to create object in new environment with empty symbol name"); } const namePtr = Module.allocateUTF8(name); Module._Rf_defineVar(Module._Rf_install(namePtr), new RObjImpl(v).ptr, ptr); Module._free(namePtr); }); Module._Rf_unprotect(1); Module._R_PreserveObject(ptr); super({ targetType: "ptr", obj: { ptr } }); } ls(all = false, sorted = true) { const ls = RObjImpl.wrap(Module._R_lsInternal3(this.ptr, Number(all), Number(sorted))); return ls.toArray(); } bind(name, value) { const namePtr = Module.allocateUTF8(name); Module._Rf_defineVar(Module._Rf_install(namePtr), isRObjImpl(value) ? value.ptr : new RObjImpl({ targetType: "raw", obj: value }).ptr, this.ptr); Module._free(namePtr); } names() { return this.ls(true, true); } frame() { return RObjImpl.wrap(Module._FRAME(this.ptr)); } subset(prop) { if (typeof prop === "number") { throw new Error("Object of type environment is not subsettable"); } return this.getDollar(prop); } toObject({ depth = 0 } = {}) { const symbols = this.names(); return Object.fromEntries([...Array(symbols.length).keys()].map((i) => { return [symbols[i], this.getDollar(symbols[i]).toTree({ depth })]; })); } toTree(options = { depth: 0 }, depth = 1) { const names = this.names(); const values = [...Array(names.length).keys()].map((i) => { if (options.depth && depth >= options.depth) { return this.getDollar(names[i]); } else { return this.getDollar(names[i]).toTree(options, depth + 1); } }); return { type: this.type(), names, values }; } }; var RObjAtomicVector = class extends RObjImpl { get length() { return Module._LENGTH(this.ptr); } get(prop) { return super.get(prop); } subset(prop) { return super.subset(prop); } getDollar(prop) { throw new Error("$ operator is invalid for atomic vectors"); } detectMissing() { const isna = Module.allocateUTF8("is.na"); const call = Module._Rf_protect(Module._Rf_lang2(Module._Rf_install(isna), this.ptr)); const val = RObjImpl.wrap(Module._Rf_protect(Module._Rf_eval(call, RObjImpl.baseEnv.ptr))); const ret = val.toTypedArray(); RObjImpl.unprotect(2); Module._free(isna); return Array.from(ret).map((elt) => Boolean(elt)); } toArray() { const arr = this.toTypedArray(); return this.detectMissing().map((m, idx) => m ? null : arr[idx]); } toObject({ allowDuplicateKey = true, allowEmptyKey = false } = {}) { const entries = this.entries(); const keys = entries.map(([k, v]) => k); if (!allowDuplicateKey && new Set(keys).size !== keys.length) { throw new Error("Duplicate key when converting atomic vector without allowDuplicateKey enabled"); } if (!allowEmptyKey && keys.some((k) => !k)) { throw new Error("Empty or null key when converting atomic vector without allowEmptyKey enabled"); } return Object.fromEntries(entries.filter((u, idx) => entries.findIndex((v) => v[0] === u[0]) === idx)); } entries() { const values = this.toArray(); const names = this.names(); return values.map((v, i) => [names ? names[i] : null, v]); } toTree() { return { type: this.type(), names: this.names(), values: this.toArray() }; } }; var RObjLogical = class extends RObjAtomicVector { constructor(val) { if (isRTargetObj(val)) { super(val); return this; } const values = isRObjectTree(val) ? val.values : Array.isArray(val) ? val : [val]; const ptr = Module._Rf_protect(Module._Rf_allocVector(RTypeMap.logical, values.length)); const data = Module._LOGICAL(ptr); values.forEach((v, i) => Module.setValue(data + 4 * i, v === null ? RObjImpl.naLogical : Boolean(v), "i32")); RObjImpl.wrap(ptr).setNames(isRObjectTree(val) ? val.names : null); Module._Rf_unprotect(1); Module._R_PreserveObject(ptr); super({ targetType: "ptr", obj: { ptr } }); } getLogical(idx) { return this.get(idx).toArray()[0]; } toLogical() { if (this.length !== 1) { throw new Error("Unable to convert atomic vector of length > 1 to a scalar JS value"); } return this.getLogical(1); } toTypedArray() { return new Int32Array(Module.HEAP32.subarray(Module._LOGICAL(this.ptr) / 4, Module._LOGICAL(this.ptr) / 4 + this.length)); } toArray() { const arr = this.toTypedArray(); return this.detectMissing().map((m, idx) => m ? null : Boolean(arr[idx])); } }; var RObjInteger = class extends RObjAtomicVector { constructor(val) { if (isRTargetObj(val)) { super(val); return this; } const values = isRObjectTree(val) ? val.values : Array.isArray(val) ? val : [val]; const ptr = Module._Rf_protect(Module._Rf_allocVector(RTypeMap