UNPKG

@georgestagg/webr

Version:

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

1,531 lines (1,519 loc) 80.3 kB
var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; 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; }; // node_modules/xmlhttprequest-ssl/lib/XMLHttpRequest.js var require_XMLHttpRequest = __commonJS({ "node_modules/xmlhttprequest-ssl/lib/XMLHttpRequest.js"(exports, module2) { var fs = require("fs"); var Url = require("url"); var spawn = require("child_process").spawn; module2.exports = XMLHttpRequest2; XMLHttpRequest2.XMLHttpRequest = XMLHttpRequest2; function XMLHttpRequest2(opts) { "use strict"; opts = opts || {}; var self = this; var http = require("http"); var https = require("https"); var request; var response; var settings = {}; var disableHeaderCheck = false; var defaultHeaders = { "User-Agent": "node-XMLHttpRequest", "Accept": "*/*" }; var headers = Object.assign({}, defaultHeaders); var forbiddenRequestHeaders = [ "accept-charset", "accept-encoding", "access-control-request-headers", "access-control-request-method", "connection", "content-length", "content-transfer-encoding", "cookie", "cookie2", "date", "expect", "host", "keep-alive", "origin", "referer", "te", "trailer", "transfer-encoding", "upgrade", "via" ]; var forbiddenRequestMethods = [ "TRACE", "TRACK", "CONNECT" ]; var sendFlag = false; var errorFlag = false; var abortedFlag = false; var listeners = {}; this.UNSENT = 0; this.OPENED = 1; this.HEADERS_RECEIVED = 2; this.LOADING = 3; this.DONE = 4; this.readyState = this.UNSENT; this.onreadystatechange = null; this.responseText = ""; this.responseXML = ""; this.response = Buffer.alloc(0); this.status = null; this.statusText = null; var isAllowedHttpHeader = function(header) { return disableHeaderCheck || header && forbiddenRequestHeaders.indexOf(header.toLowerCase()) === -1; }; var isAllowedHttpMethod = function(method) { return method && forbiddenRequestMethods.indexOf(method) === -1; }; this.open = function(method, url, async, user, password) { this.abort(); errorFlag = false; abortedFlag = false; if (!isAllowedHttpMethod(method)) { throw new Error("SecurityError: Request method not allowed"); } settings = { "method": method, "url": url.toString(), "async": typeof async !== "boolean" ? true : async, "user": user || null, "password": password || null }; setState(this.OPENED); }; this.setDisableHeaderCheck = function(state) { disableHeaderCheck = state; }; this.setRequestHeader = function(header, value) { if (this.readyState != this.OPENED) { throw new Error("INVALID_STATE_ERR: setRequestHeader can only be called when state is OPEN"); } if (!isAllowedHttpHeader(header)) { console.warn('Refused to set unsafe header "' + header + '"'); return false; } if (sendFlag) { throw new Error("INVALID_STATE_ERR: send flag is true"); } headers[header] = value; return true; }; this.getResponseHeader = function(header) { if (typeof header === "string" && this.readyState > this.OPENED && response.headers[header.toLowerCase()] && !errorFlag) { return response.headers[header.toLowerCase()]; } return null; }; this.getAllResponseHeaders = function() { if (this.readyState < this.HEADERS_RECEIVED || errorFlag) { return ""; } var result = ""; for (var i in response.headers) { if (i !== "set-cookie" && i !== "set-cookie2") { result += i + ": " + response.headers[i] + "\r\n"; } } return result.substr(0, result.length - 2); }; this.getRequestHeader = function(name) { if (typeof name === "string" && headers[name]) { return headers[name]; } return ""; }; this.send = function(data) { if (this.readyState != this.OPENED) { throw new Error("INVALID_STATE_ERR: connection must be opened before send() is called"); } if (sendFlag) { throw new Error("INVALID_STATE_ERR: send has already been called"); } var ssl = false, local = false; var url = Url.parse(settings.url); var host; switch (url.protocol) { case "https:": ssl = true; case "http:": host = url.hostname; break; case "file:": local = true; break; case void 0: case "": host = "localhost"; break; default: throw new Error("Protocol not supported."); } if (local) { if (settings.method !== "GET") { throw new Error("XMLHttpRequest: Only GET method is supported"); } if (settings.async) { fs.readFile(unescape(url.pathname), function(error, data2) { if (error) { self.handleError(error, error.errno || -1); } else { self.status = 200; self.responseText = data2.toString("utf8"); self.response = data2; setState(self.DONE); } }); } else { try { this.response = fs.readFileSync(unescape(url.pathname)); this.responseText = this.response.toString("utf8"); this.status = 200; setState(self.DONE); } catch (e) { this.handleError(e, e.errno || -1); } } return; } var port = url.port || (ssl ? 443 : 80); var uri = url.pathname + (url.search ? url.search : ""); headers["Host"] = host; if (!(ssl && port === 443 || port === 80)) { headers["Host"] += ":" + url.port; } if (settings.user) { if (typeof settings.password == "undefined") { settings.password = ""; } var authBuf = new Buffer(settings.user + ":" + settings.password); headers["Authorization"] = "Basic " + authBuf.toString("base64"); } if (settings.method === "GET" || settings.method === "HEAD") { data = null; } else if (data) { headers["Content-Length"] = Buffer.isBuffer(data) ? data.length : Buffer.byteLength(data); if (!headers["Content-Type"]) { headers["Content-Type"] = "text/plain;charset=UTF-8"; } } else if (settings.method === "POST") { headers["Content-Length"] = 0; } var agent = opts.agent || false; var options = { host, port, path: uri, method: settings.method, headers, agent }; if (ssl) { options.pfx = opts.pfx; options.key = opts.key; options.passphrase = opts.passphrase; options.cert = opts.cert; options.ca = opts.ca; options.ciphers = opts.ciphers; options.rejectUnauthorized = opts.rejectUnauthorized === false ? false : true; } errorFlag = false; if (settings.async) { var doRequest = ssl ? https.request : http.request; sendFlag = true; self.dispatchEvent("readystatechange"); var responseHandler = function(resp2) { response = resp2; if (response.statusCode === 302 || response.statusCode === 303 || response.statusCode === 307) { settings.url = response.headers.location; var url2 = Url.parse(settings.url); host = url2.hostname; var newOptions = { hostname: url2.hostname, port: url2.port, path: url2.path, method: response.statusCode === 303 ? "GET" : settings.method, headers }; if (ssl) { newOptions.pfx = opts.pfx; newOptions.key = opts.key; newOptions.passphrase = opts.passphrase; newOptions.cert = opts.cert; newOptions.ca = opts.ca; newOptions.ciphers = opts.ciphers; newOptions.rejectUnauthorized = opts.rejectUnauthorized === false ? false : true; } request = doRequest(newOptions, responseHandler).on("error", errorHandler); request.end(); return; } setState(self.HEADERS_RECEIVED); self.status = response.statusCode; response.on("data", function(chunk) { if (chunk) { var data2 = Buffer.from(chunk); self.responseText += data2.toString("utf8"); self.response = Buffer.concat([self.response, data2]); } if (sendFlag) { setState(self.LOADING); } }); response.on("end", function() { if (sendFlag) { sendFlag = false; setState(self.DONE); } }); response.on("error", function(error) { self.handleError(error); }); }; var errorHandler = function(error) { self.handleError(error); }; request = doRequest(options, responseHandler).on("error", errorHandler); if (opts.autoUnref) { request.on("socket", (socket) => { socket.unref(); }); } if (data) { request.write(data); } request.end(); self.dispatchEvent("loadstart"); } else { var contentFile = ".node-xmlhttprequest-content-" + process.pid; var syncFile = ".node-xmlhttprequest-sync-" + process.pid; fs.writeFileSync(syncFile, "", "utf8"); var execString = "var http = require('http'), https = require('https'), fs = require('fs');var doRequest = http" + (ssl ? "s" : "") + ".request;var options = " + JSON.stringify(options) + ";var responseText = '';var responseData = Buffer.alloc(0);var req = doRequest(options, function(response) {response.on('data', function(chunk) { var data = Buffer.from(chunk); responseText += data.toString('utf8'); responseData = Buffer.concat([responseData, data]);});response.on('end', function() {fs.writeFileSync('" + contentFile + "', JSON.stringify({err: null, data: {statusCode: response.statusCode, headers: response.headers, text: responseText, data: responseData.toString('base64')}}), 'utf8');fs.unlinkSync('" + syncFile + "');});response.on('error', function(error) {fs.writeFileSync('" + contentFile + "', 'NODE-XMLHTTPREQUEST-ERROR:' + JSON.stringify(error), 'utf8');fs.unlinkSync('" + syncFile + "');});}).on('error', function(error) {fs.writeFileSync('" + contentFile + "', 'NODE-XMLHTTPREQUEST-ERROR:' + JSON.stringify(error), 'utf8');fs.unlinkSync('" + syncFile + "');});" + (data ? "req.write('" + JSON.stringify(data).slice(1, -1).replace(/'/g, "\\'") + "');" : "") + "req.end();"; var syncProc = spawn(process.argv[0], ["-e", execString]); var statusText; while (fs.existsSync(syncFile)) { } self.responseText = fs.readFileSync(contentFile, "utf8"); syncProc.stdin.end(); fs.unlinkSync(contentFile); if (self.responseText.match(/^NODE-XMLHTTPREQUEST-ERROR:/)) { var errorObj = JSON.parse(self.responseText.replace(/^NODE-XMLHTTPREQUEST-ERROR:/, "")); self.handleError(errorObj, 503); } else { self.status = self.responseText.replace(/^NODE-XMLHTTPREQUEST-STATUS:([0-9]*),.*/, "$1"); var resp = JSON.parse(self.responseText.replace(/^NODE-XMLHTTPREQUEST-STATUS:[0-9]*,(.*)/, "$1")); response = { statusCode: self.status, headers: resp.data.headers }; self.responseText = resp.data.text; self.response = Buffer.from(resp.data.data, "base64"); setState(self.DONE, true); } } }; this.handleError = function(error, status) { this.status = status || 0; this.statusText = error; this.responseText = error.stack; errorFlag = true; setState(this.DONE); }; this.abort = function() { if (request) { request.abort(); request = null; } headers = Object.assign({}, defaultHeaders); this.responseText = ""; this.responseXML = ""; this.response = Buffer.alloc(0); errorFlag = abortedFlag = true; if (this.readyState !== this.UNSENT && (this.readyState !== this.OPENED || sendFlag) && this.readyState !== this.DONE) { sendFlag = false; setState(this.DONE); } this.readyState = this.UNSENT; }; this.addEventListener = function(event, callback) { if (!(event in listeners)) { listeners[event] = []; } listeners[event].push(callback); }; this.removeEventListener = function(event, callback) { if (event in listeners) { listeners[event] = listeners[event].filter(function(ev) { return ev !== callback; }); } }; this.dispatchEvent = function(event) { if (typeof self["on" + event] === "function") { if (this.readyState === this.DONE && settings.async) setImmediate(function() { self["on" + event](); }); else self["on" + event](); } if (event in listeners) { for (let i = 0, len = listeners[event].length; i < len; i++) { if (this.readyState === this.DONE) setImmediate(function() { listeners[event][i].call(self); }); else listeners[event][i].call(self); } } }; var setState = function(state) { if (self.readyState === state || self.readyState === self.UNSENT && abortedFlag) return; self.readyState = state; if (settings.async || self.readyState < self.OPENED || self.readyState === self.DONE) { self.dispatchEvent("readystatechange"); } if (self.readyState === self.DONE) { let fire; if (abortedFlag) fire = "abort"; else if (errorFlag) fire = "error"; else fire = "load"; self.dispatchEvent(fire); self.dispatchEvent("loadend"); } }; } } }); // 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/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/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 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(dispatch2) { __privateSet(this, _dispatch, dispatch2); } }; _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(dispatch2) { __privateSet(this, _dispatch2, dispatch2); } }; _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 newChannelWorker(msg) { switch (msg.data.channelType) { case ChannelType.SharedArrayBuffer: return new SharedBufferChannelWorker(); case ChannelType.ServiceWorker: return new ServiceWorkerChannelWorker(msg.data); default: throw new Error("Unknown worker channel type recieved"); } } // 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.alloc