From cf25207ddaacb17737d0539b3f0af479703c9656 Mon Sep 17 00:00:00 2001 From: webreflection Date: Tue, 26 Sep 2023 11:16:38 +0200 Subject: [PATCH] 100% Hooks Coverage --- .gitignore | 3 +- core.js.map | 1 - docs/core.js | 2 +- docs/core.js.map | 2 +- esm/index.js | 23 +++--- esm/worker/_template.js | 4 +- package.json | 2 +- test/integration.html | 2 +- test/integration/_shared.js | 49 ++++++++++++ .../interpreter/micropython/custom-hooks.html | 74 +++++++++++++++++++ test/integration/micropython.js | 2 + 11 files changed, 145 insertions(+), 19 deletions(-) delete mode 100644 core.js.map create mode 100644 test/integration/interpreter/micropython/custom-hooks.html diff --git a/.gitignore b/.gitignore index 1938fc55..9d31c529 100644 --- a/.gitignore +++ b/.gitignore @@ -3,8 +3,7 @@ coverage/ node_modules/ cjs/* !cjs/package.json -core.js -core.js.map +core.* !docs/core.js !docs/core.js.map pyscript.js diff --git a/core.js.map b/core.js.map deleted file mode 100644 index 7fad1c07..00000000 --- a/core.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"core.js","sources":["node_modules/basic-devtools/esm/index.js","node_modules/@ungap/structured-clone/esm/deserialize.js","node_modules/@ungap/structured-clone/esm/types.js","node_modules/@ungap/structured-clone/esm/serialize.js","node_modules/@ungap/structured-clone/esm/json.js","node_modules/coincident/esm/channel.js","node_modules/coincident/esm/fallback.js","node_modules/coincident/esm/index.js","node_modules/coincident/esm/shared/types.js","node_modules/coincident/esm/shared/utils.js","node_modules/coincident/esm/shared/traps.js","node_modules/coincident/esm/shared/main.js","node_modules/coincident/esm/window/main.js","node_modules/coincident/esm/window/thread.js","node_modules/coincident/esm/shared/thread.js","node_modules/coincident/esm/shared/worker.js","node_modules/coincident/esm/window.js","node_modules/@ungap/with-resolvers/index.js","esm/fetch-utils.js","node_modules/codedent/esm/index.js","node_modules/plain-tag/esm/index.js","esm/utils.js","esm/interpreter/_utils.js","esm/interpreter/_python.js","esm/interpreter/micropython.js","esm/interpreter/pyodide.js","esm/interpreter/ruby-wasm-wasi.js","esm/interpreter/wasmoon.js","esm/interpreters.js","esm/toml.js","esm/loader.js","esm/worker/hooks.js","esm/worker/class.js","esm/worker/xworker.js","esm/errors.js","esm/worker/url.js","esm/script-handler.js","esm/listeners.js","esm/custom.js","esm/index.js"],"sourcesContent":["/**\n * Given a CSS selector, returns the first matching node, if any.\n * @param {string} css the CSS selector to query\n * @param {Document | DocumentFragment | Element} [root] the optional parent node to query\n * @returns {Element?} the found element, if any\n */\nconst $ = (css, root = document) => root.querySelector(css);\n\n/**\n * Given a CSS selector, returns a list of all matching nodes.\n * @param {string} css the CSS selector to query\n * @param {Document | DocumentFragment | Element} [root] the optional parent node to query\n * @returns {Element[]} a list of found nodes\n */\nconst $$ = (css, root = document) => [...root.querySelectorAll(css)];\n\n/**\n * Given a XPath selector, returns a list of all matching nodes.\n * @param {string} path the XPath selector to evaluate\n * @param {Document | DocumentFragment | Element} [root] the optional parent node to query\n * @returns {Node[]} a list of found nodes (elements, attributes, text, comments)\n */\nconst $x = (path, root = document) => {\n const expression = (new XPathEvaluator).createExpression(path);\n const xpath = expression.evaluate(root, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);\n const result = [];\n for (let i = 0, {snapshotLength} = xpath; i < snapshotLength; i++)\n result.push(xpath.snapshotItem(i));\n return result;\n};\n\nexport {$, $$, $x};\n","import {\n VOID, PRIMITIVE,\n ARRAY, OBJECT,\n DATE, REGEXP, MAP, SET,\n ERROR, BIGINT\n} from './types.js';\n\nconst env = typeof self === 'object' ? self : globalThis;\n\nconst deserializer = ($, _) => {\n const as = (out, index) => {\n $.set(index, out);\n return out;\n };\n\n const unpair = index => {\n if ($.has(index))\n return $.get(index);\n\n const [type, value] = _[index];\n switch (type) {\n case PRIMITIVE:\n case VOID:\n return as(value, index);\n case ARRAY: {\n const arr = as([], index);\n for (const index of value)\n arr.push(unpair(index));\n return arr;\n }\n case OBJECT: {\n const object = as({}, index);\n for (const [key, index] of value)\n object[unpair(key)] = unpair(index);\n return object;\n }\n case DATE:\n return as(new Date(value), index);\n case REGEXP: {\n const {source, flags} = value;\n return as(new RegExp(source, flags), index);\n }\n case MAP: {\n const map = as(new Map, index);\n for (const [key, index] of value)\n map.set(unpair(key), unpair(index));\n return map;\n }\n case SET: {\n const set = as(new Set, index);\n for (const index of value)\n set.add(unpair(index));\n return set;\n }\n case ERROR: {\n const {name, message} = value;\n return as(new env[name](message), index);\n }\n case BIGINT:\n return as(BigInt(value), index);\n case 'BigInt':\n return as(Object(BigInt(value)), index);\n }\n return as(new env[type](value), index);\n };\n\n return unpair;\n};\n\n/**\n * @typedef {Array} Record a type representation\n */\n\n/**\n * Returns a deserialized value from a serialized array of Records.\n * @param {Record[]} serialized a previously serialized value.\n * @returns {any}\n */\nexport const deserialize = serialized => deserializer(new Map, serialized)(0);\n","export const VOID = -1;\nexport const PRIMITIVE = 0;\nexport const ARRAY = 1;\nexport const OBJECT = 2;\nexport const DATE = 3;\nexport const REGEXP = 4;\nexport const MAP = 5;\nexport const SET = 6;\nexport const ERROR = 7;\nexport const BIGINT = 8;\n// export const SYMBOL = 9;\n","import {\n VOID, PRIMITIVE,\n ARRAY, OBJECT,\n DATE, REGEXP, MAP, SET,\n ERROR, BIGINT\n} from './types.js';\n\nconst EMPTY = '';\n\nconst {toString} = {};\nconst {keys} = Object;\n\nconst typeOf = value => {\n const type = typeof value;\n if (type !== 'object' || !value)\n return [PRIMITIVE, type];\n\n const asString = toString.call(value).slice(8, -1);\n switch (asString) {\n case 'Array':\n return [ARRAY, EMPTY];\n case 'Object':\n return [OBJECT, EMPTY];\n case 'Date':\n return [DATE, EMPTY];\n case 'RegExp':\n return [REGEXP, EMPTY];\n case 'Map':\n return [MAP, EMPTY];\n case 'Set':\n return [SET, EMPTY];\n }\n\n if (asString.includes('Array'))\n return [ARRAY, asString];\n\n if (asString.includes('Error'))\n return [ERROR, asString];\n\n return [OBJECT, asString];\n};\n\nconst shouldSkip = ([TYPE, type]) => (\n TYPE === PRIMITIVE &&\n (type === 'function' || type === 'symbol')\n);\n\nconst serializer = (strict, json, $, _) => {\n\n const as = (out, value) => {\n const index = _.push(out) - 1;\n $.set(value, index);\n return index;\n };\n\n const pair = value => {\n if ($.has(value))\n return $.get(value);\n\n let [TYPE, type] = typeOf(value);\n switch (TYPE) {\n case PRIMITIVE: {\n let entry = value;\n switch (type) {\n case 'bigint':\n TYPE = BIGINT;\n entry = value.toString();\n break;\n case 'function':\n case 'symbol':\n if (strict)\n throw new TypeError('unable to serialize ' + type);\n entry = null;\n break;\n case 'undefined':\n return as([VOID], value);\n }\n return as([TYPE, entry], value);\n }\n case ARRAY: {\n if (type)\n return as([type, [...value]], value);\n \n const arr = [];\n const index = as([TYPE, arr], value);\n for (const entry of value)\n arr.push(pair(entry));\n return index;\n }\n case OBJECT: {\n if (type) {\n switch (type) {\n case 'BigInt':\n return as([type, value.toString()], value);\n case 'Boolean':\n case 'Number':\n case 'String':\n return as([type, value.valueOf()], value);\n }\n }\n\n if (json && ('toJSON' in value))\n return pair(value.toJSON());\n\n const entries = [];\n const index = as([TYPE, entries], value);\n for (const key of keys(value)) {\n if (strict || !shouldSkip(typeOf(value[key])))\n entries.push([pair(key), pair(value[key])]);\n }\n return index;\n }\n case DATE:\n return as([TYPE, value.toISOString()], value);\n case REGEXP: {\n const {source, flags} = value;\n return as([TYPE, {source, flags}], value);\n }\n case MAP: {\n const entries = [];\n const index = as([TYPE, entries], value);\n for (const [key, entry] of value) {\n if (strict || !(shouldSkip(typeOf(key)) || shouldSkip(typeOf(entry))))\n entries.push([pair(key), pair(entry)]);\n }\n return index;\n }\n case SET: {\n const entries = [];\n const index = as([TYPE, entries], value);\n for (const entry of value) {\n if (strict || !shouldSkip(typeOf(entry)))\n entries.push(pair(entry));\n }\n return index;\n }\n }\n\n const {message} = value;\n return as([TYPE, {name: type, message}], value);\n };\n\n return pair;\n};\n\n/**\n * @typedef {Array} Record a type representation\n */\n\n/**\n * Returns an array of serialized Records.\n * @param {any} value a serializable value.\n * @param {{json?: boolean, lossy?: boolean}?} options an object with a `lossy` or `json` property that,\n * if `true`, will not throw errors on incompatible types, and behave more\n * like JSON stringify would behave. Symbol and Function will be discarded.\n * @returns {Record[]}\n */\n export const serialize = (value, {json, lossy} = {}) => {\n const _ = [];\n return serializer(!(json || lossy), !!json, new Map, _)(value), _;\n};\n","/*! (c) Andrea Giammarchi - ISC */\n\nimport {deserialize} from './deserialize.js';\nimport {serialize} from './serialize.js';\n\nconst {parse: $parse, stringify: $stringify} = JSON;\nconst options = {json: true, lossy: true};\n\n/**\n * Revive a previously stringified structured clone.\n * @param {string} str previously stringified data as string.\n * @returns {any} whatever was previously stringified as clone.\n */\nexport const parse = str => deserialize($parse(str));\n\n/**\n * Represent a structured clone value as string.\n * @param {any} any some clone-able value to stringify.\n * @returns {string} the value stringified.\n */\nexport const stringify = any => $stringify(serialize(any, options));\n","// ⚠️ AUTOMATICALLY GENERATED - DO NOT CHANGE\nexport const CHANNEL = '3099687a-04a9-4406-a08e-fd1602cb2a81';\n\nexport const MAIN = 'M' + CHANNEL;\nexport const THREAD = 'T' + CHANNEL;\n","// encodeURIComponent('onmessage=({data:b})=>(Atomics.wait(b,0),postMessage(0))')\n\nexport default buffer => ({\n value: new Promise(onmessage => {\n let w = new Worker('data:application/javascript,onmessage%3D(%7Bdata%3Ab%7D)%3D%3E(Atomics.wait(b%2C0)%2CpostMessage(0))');\n w.onmessage = onmessage;\n w.postMessage(buffer);\n })\n});\n","/*! (c) Andrea Giammarchi - ISC */\n\nimport {CHANNEL} from './channel.js';\nimport waitAsyncFallback from './fallback.js';\n\n// just minifier friendly for Blob Workers' cases\nconst {Int32Array, Map, SharedArrayBuffer, Uint16Array} = globalThis;\n\n// common constants / utilities for repeated operations\nconst {BYTES_PER_ELEMENT: I32_BYTES} = Int32Array;\nconst {BYTES_PER_ELEMENT: UI16_BYTES} = Uint16Array;\n\nconst {isArray} = Array;\nconst {notify, wait, waitAsync} = Atomics;\nconst {fromCharCode} = String;\n\n// automatically uses sync wait (worker -> main)\n// or fallback to async wait (main -> worker)\nconst waitFor = (isAsync, sb) => isAsync ?\n (waitAsync || waitAsyncFallback)(sb, 0) :\n (wait(sb, 0), {value: {then: fn => fn()}});\n\n// retain buffers to transfer\nconst buffers = new WeakSet;\n\n// retain either main threads or workers global context\nconst context = new WeakMap;\n\n// used to generate a unique `id` per each worker `postMessage` \"transaction\"\nlet uid = 0;\n\n/**\n * Create once a `Proxy` able to orchestrate synchronous `postMessage` out of the box.\n * @param {globalThis | Worker} self the context in which code should run\n * @param {{parse: (serialized: string) => any, stringify: (serializable: any) => string, transform?: (value:any) => any}} [JSON] an optional `JSON` like interface to `parse` or `stringify` content with extra `transform` ability.\n * @returns {ProxyHandler | ProxyHandler}\n */\nconst coincident = (self, {parse, stringify, transform} = JSON) => {\n // create a Proxy once for the given context (globalThis or Worker instance)\n if (!context.has(self)) {\n // ensure the CHANNEL and data are posted correctly\n const post = (transfer, ...args) => self.postMessage({[CHANNEL]: args}, {transfer});\n\n // prevent Harakiri https://github.com/WebReflection/coincident/issues/18\n let harakiri = false;\n\n context.set(self, new Proxy(new Map, {\n // there is very little point in checking prop in proxy for this very specific case\n // and I don't want to orchestrate a whole roundtrip neither, as stuff would fail\n // regardless if from Worker we access non existent Main callback, and vice-versa.\n // This is here mostly to guarantee that if such check is performed, at least the\n // get trap goes through and then it's up to developers guarantee they are accessing\n // stuff that actually exists elsewhere.\n has: (_, action) => typeof action === 'string' && !action.startsWith('_'),\n\n // worker related: get any utility that should be available on the main thread\n get: (_, action) => action === 'then' ? null : ((...args) => {\n // transaction id\n const id = uid++;\n\n // first contact: just ask for how big the buffer should be\n let sb = new Int32Array(new SharedArrayBuffer(I32_BYTES));\n\n // if a transfer list has been passed, drop it from args\n let transfer = [];\n if (buffers.has(args.at(-1) || transfer))\n buffers.delete(transfer = args.pop());\n\n // ask for invoke with arguments and wait for it\n post(transfer, id, sb, action, transform ? args.map(transform) : args);\n\n // helps deciding how to wait for results\n const isAsync = self !== globalThis;\n\n // warn users about possible deadlock still allowing them\n // to explicitly `proxy.invoke().then(...)` without blocking\n let deadlock = 0;\n if (harakiri && isAsync)\n deadlock = setTimeout(console.warn, 1000, `💀🔒 - Possible deadlock if proxy.${action}(...args) is awaited`);\n\n return waitFor(isAsync, sb).value.then(() => {\n clearTimeout(deadlock);\n\n // commit transaction using the returned / needed buffer length\n const length = sb[0];\n\n // filter undefined results\n if (!length) return;\n\n // calculate the needed ui16 bytes length to store the result string\n const bytes = UI16_BYTES * length;\n\n // round up to the next amount of bytes divided by 4 to allow i32 operations\n sb = new Int32Array(new SharedArrayBuffer(bytes + (bytes % I32_BYTES)));\n\n // ask for results and wait for it\n post([], id, sb);\n return waitFor(isAsync, sb).value.then(\n // transform the shared buffer into a string and return it parsed\n () => parse(fromCharCode(...new Uint16Array(sb.buffer).slice(0, length)))\n );\n });\n }),\n\n // main thread related: react to any utility a worker is asking for\n set(actions, action, callback) {\n // lazy event listener and logic handling, triggered once by setters actions\n if (!actions.size) {\n // maps results by `id` as they are asked for\n const results = new Map;\n // add the event listener once (first defined setter, all others work the same)\n self.addEventListener('message', async (event) => {\n // grub the very same library CHANNEL; ignore otherwise\n const details = event.data?.[CHANNEL];\n if (isArray(details)) {\n // if early enough, avoid leaking data to other listeners\n event.stopImmediatePropagation();\n const [id, sb, ...rest] = details;\n // action available: it must be defined/known on the main thread\n if (rest.length) {\n const [action, args] = rest;\n if (actions.has(action)) {\n harakiri = true;\n try {\n // await for result either sync or async and serialize it\n const result = await actions.get(action)(...args);\n if (result !== void 0) {\n const serialized = stringify(transform ? transform(result) : result);\n // store the result for \"the very next\" event listener call\n results.set(id, serialized);\n // communicate the required SharedArrayBuffer length out of the\n // resulting serialized string\n sb[0] = serialized.length;\n }\n }\n finally {\n harakiri = false;\n }\n }\n // unknown action should be notified as missing on the main thread\n else {\n throw new Error(`Unsupported action: ${action}`);\n }\n }\n // no action means: get results out of the well known `id`\n else {\n const result = results.get(id);\n results.delete(id);\n // populate the SharedArrayBuffer with utf-16 chars code\n for (let ui16a = new Uint16Array(sb.buffer), i = 0; i < result.length; i++)\n ui16a[i] = result.charCodeAt(i);\n }\n // release te worker waiting either the length or the result\n notify(sb, 0);\n }\n });\n }\n // store this action callback allowing the setter in the process\n return !!actions.set(action, callback);\n }\n }));\n }\n return context.get(self);\n};\n\ncoincident.transfer = (...args) => (buffers.add(args), args);\n\nexport default coincident;\n","export const OBJECT = 'object';\nexport const FUNCTION = 'function';\nexport const BOOLEAN = 'boolean';\nexport const NUMBER = 'number';\nexport const STRING = 'string';\nexport const UNDEFINED = 'undefined';\nexport const BIGINT = 'bigint';\nexport const SYMBOL = 'symbol';\nexport const NULL = 'null';\n","\nimport {\n OBJECT,\n FUNCTION,\n BOOLEAN,\n NUMBER,\n STRING,\n UNDEFINED,\n BIGINT,\n SYMBOL,\n NULL\n} from './types.js';\n\nconst {\n defineProperty,\n getOwnPropertyDescriptor,\n getPrototypeOf,\n isExtensible,\n ownKeys,\n preventExtensions,\n set,\n setPrototypeOf\n} = Reflect;\n\nconst {assign, create} = Object;\n\nexport const TypedArray = getPrototypeOf(Int8Array);\n\nexport const isArray = 'isArray';\n\nexport {\n assign,\n create,\n defineProperty,\n getOwnPropertyDescriptor,\n getPrototypeOf,\n isExtensible,\n ownKeys,\n preventExtensions,\n set,\n setPrototypeOf\n};\n\nexport const augment = (descriptor, how) => {\n const {get, set, value} = descriptor;\n if (get) descriptor.get = how(get);\n if (set) descriptor.set = how(set);\n if (value) descriptor.value = how(value);\n return descriptor;\n};\n\nexport const entry = (type, value) => [type, value];\n\nexport const asEntry = transform => value => {\n const type = typeof value;\n switch (type) {\n case OBJECT:\n if (value == null)\n return entry(NULL, value);\n if (value === globalThis)\n return entry(OBJECT, null);\n case FUNCTION:\n return transform(type, value);\n case BOOLEAN:\n case NUMBER:\n case STRING:\n case UNDEFINED:\n case BIGINT:\n return entry(type, value);\n case SYMBOL: {\n if (symbols.has(value))\n return entry(type, symbols.get(value));\n }\n }\n throw new Error(`Unable to handle this ${type} type`);\n};\n\nconst symbols = new Map(\n ownKeys(Symbol)\n .filter(s => typeof Symbol[s] === SYMBOL)\n .map(s => [Symbol[s], s])\n);\n \nexport const symbol = value => {\n for (const [symbol, name] of symbols) {\n if (name === value)\n return symbol;\n }\n};\n\nexport function Bound() {\n return this;\n}\n","export const APPLY = 'apply';\nexport const CONSTRUCT = 'construct';\nexport const DEFINE_PROPERTY = 'defineProperty';\nexport const DELETE_PROPERTY = 'deleteProperty';\nexport const GET = 'get';\nexport const GET_OWN_PROPERTY_DESCRIPTOR = 'getOwnPropertyDescriptor';\nexport const GET_PROTOTYPE_OF = 'getPrototypeOf';\nexport const HAS = 'has';\nexport const IS_EXTENSIBLE = 'isExtensible';\nexport const OWN_KEYS = 'ownKeys';\nexport const PREVENT_EXTENSION = 'preventExtensions';\nexport const SET = 'set';\nexport const SET_PROTOTYPE_OF = 'setPrototypeOf';\nexport const DELETE = 'delete';\n","import {\n TypedArray,\n defineProperty,\n getOwnPropertyDescriptor,\n getPrototypeOf,\n isExtensible,\n ownKeys,\n preventExtensions,\n set,\n setPrototypeOf,\n\n assign,\n create,\n augment,\n entry,\n asEntry,\n symbol\n} from './utils.js';\n\nimport {\n OBJECT,\n FUNCTION,\n NUMBER,\n STRING,\n SYMBOL,\n UNDEFINED\n} from './types.js';\n\nimport {\n APPLY,\n CONSTRUCT,\n DEFINE_PROPERTY,\n DELETE_PROPERTY,\n GET,\n GET_OWN_PROPERTY_DESCRIPTOR,\n GET_PROTOTYPE_OF,\n HAS,\n IS_EXTENSIBLE,\n OWN_KEYS,\n PREVENT_EXTENSION,\n SET,\n SET_PROTOTYPE_OF,\n DELETE\n} from './traps.js';\n\nexport default (name, patch) => {\n const eventsHandler = patch && new WeakMap;\n\n // patch once main UI tread\n if (patch) {\n const {addEventListener} = EventTarget.prototype;\n // this should never be on the way as it's extremely light and fast\n // but it's necessary to allow \"preventDefault\" or other event invokes at distance\n defineProperty(EventTarget.prototype, 'addEventListener', {\n value(type, listener, ...options) {\n if (options.at(0)?.invoke) {\n if (!eventsHandler.has(this))\n eventsHandler.set(this, new Map);\n eventsHandler.get(this).set(type, [].concat(options[0].invoke));\n delete options[0].invoke;\n }\n return addEventListener.call(this, type, listener, ...options);\n }\n });\n }\n\n const handleEvent = patch && (event => {\n const {currentTarget, target, type} = event;\n for (const method of eventsHandler.get(currentTarget || target)?.get(type) || [])\n event[method]();\n });\n\n return (thread, MAIN, THREAD, ...args) => {\n let id = 0;\n const ids = new Map;\n const values = new Map;\n\n const {[THREAD]: __thread__} = thread;\n\n const global = args.length ? assign(create(globalThis), ...args) : globalThis;\n\n const result = asEntry((type, value) => {\n if (!ids.has(value)) {\n let sid;\n // a bit apocalyptic scenario but if this main runs forever\n // and the id does a whole int32 roundtrip we might have still\n // some reference danglign around\n while (values.has(sid = id++));\n ids.set(value, sid);\n values.set(sid, value);\n }\n return entry(type, ids.get(value));\n });\n\n const registry = new FinalizationRegistry(id => {\n __thread__(DELETE, entry(STRING, id));\n });\n\n const target = ([type, value]) => {\n switch (type) {\n case OBJECT:\n if (value == null)\n return global;\n if (typeof value === NUMBER)\n return values.get(value);\n if (!(value instanceof TypedArray)) {\n for (const key in value)\n value[key] = target(value[key]);\n }\n return value;\n case FUNCTION:\n if (typeof value === STRING) {\n if (!values.has(value)) {\n const cb = function (...args) {\n if (patch && args.at(0) instanceof Event) handleEvent(...args);\n return __thread__(\n APPLY,\n entry(FUNCTION, value),\n result(this),\n args.map(result)\n );\n };\n const ref = new WeakRef(cb);\n values.set(value, ref);\n registry.register(cb, value, ref);\n }\n return values.get(value).deref();\n }\n return values.get(value);\n case SYMBOL:\n return symbol(value);\n }\n return value;\n };\n\n const trapsHandler = {\n [APPLY]: (target, thisArg, args) => result(target.apply(thisArg, args)),\n [CONSTRUCT]: (target, args) => result(new target(...args)),\n [DEFINE_PROPERTY]: (target, name, descriptor) => result(defineProperty(target, name, descriptor)),\n [DELETE_PROPERTY]: (target, name) => result(delete target[name]),\n [GET_PROTOTYPE_OF]: target => result(getPrototypeOf(target)),\n [GET]: (target, name) => result(target[name]),\n [GET_OWN_PROPERTY_DESCRIPTOR]: (target, name) => {\n const descriptor = getOwnPropertyDescriptor(target, name);\n return descriptor ? entry(OBJECT, augment(descriptor, result)) : entry(UNDEFINED, descriptor);\n },\n [HAS]: (target, name) => result(name in target),\n [IS_EXTENSIBLE]: target => result(isExtensible(target)),\n [OWN_KEYS]: target => entry(OBJECT, ownKeys(target).map(result)),\n [PREVENT_EXTENSION]: target => result(preventExtensions(target)),\n [SET]: (target, name, value) => result(set(target, name, value)),\n [SET_PROTOTYPE_OF]: (target, proto) => result(setPrototypeOf(target, proto)),\n [DELETE](id) {\n ids.delete(values.get(id));\n values.delete(id);\n }\n };\n\n thread[MAIN] = (trap, entry, ...args) => {\n switch (trap) {\n case APPLY:\n args[0] = target(args[0]);\n args[1] = args[1].map(target);\n break;\n case CONSTRUCT:\n args[0] = args[0].map(target);\n break;\n case DEFINE_PROPERTY: {\n const [name, descriptor] = args;\n args[0] = target(name);\n const {get, set, value} = descriptor;\n if (get) descriptor.get = target(get);\n if (set) descriptor.set = target(set);\n if (value) descriptor.value = target(value);\n break;\n }\n default:\n args = args.map(target);\n break;\n }\n return trapsHandler[trap](target(entry), ...args);\n };\n\n return {\n proxy: thread,\n [name.toLowerCase()]: global,\n [`is${name}Proxy`]: () => false\n };\n };\n};\n","import main from '../shared/main.js';\n\nexport default main('Window', true);\n","import thread from '../shared/thread.js';\n\nexport default thread('Window');\n","import {\n Bound,\n TypedArray,\n augment,\n defineProperty,\n entry,\n asEntry,\n symbol,\n isArray\n} from './utils.js';\n\nimport {\n OBJECT,\n FUNCTION,\n NUMBER,\n STRING,\n SYMBOL\n} from './types.js';\n\nimport {\n APPLY,\n CONSTRUCT,\n DEFINE_PROPERTY,\n DELETE_PROPERTY,\n GET,\n GET_OWN_PROPERTY_DESCRIPTOR,\n GET_PROTOTYPE_OF,\n HAS,\n IS_EXTENSIBLE,\n OWN_KEYS,\n PREVENT_EXTENSION,\n SET,\n SET_PROTOTYPE_OF,\n DELETE\n} from './traps.js';\n\nexport default name => {\n let id = 0;\n const ids = new Map;\n const values = new Map;\n\n const __proxied__ = Symbol();\n\n const bound = target => typeof target === FUNCTION ? target() : target;\n\n const isProxy = value => typeof value === OBJECT && !!value && __proxied__ in value;\n\n const localArray = Array[isArray];\n\n const argument = asEntry(\n (type, value) => {\n if (__proxied__ in value)\n return bound(value[__proxied__]);\n if (type === FUNCTION) {\n if (!values.has(value)) {\n let sid;\n // a bit apocalyptic scenario but if this thread runs forever\n // and the id does a whole int32 roundtrip we might have still\n // some reference dangling around\n while (values.has(sid = String(id++)));\n ids.set(value, sid);\n values.set(sid, value);\n }\n return entry(type, ids.get(value));\n }\n if (!(value instanceof TypedArray)) {\n for(const key in value)\n value[key] = argument(value[key]);\n }\n return entry(type, value);\n }\n );\n\n return (main, MAIN, THREAD) => {\n const { [MAIN]: __main__ } = main;\n\n const proxies = new Map;\n\n const registry = new FinalizationRegistry(id => {\n proxies.delete(id);\n __main__(DELETE, argument(id));\n });\n\n const register = (entry) => {\n const [type, value] = entry;\n if (!proxies.has(value)) {\n const target = type === FUNCTION ? Bound.bind(entry) : entry;\n const proxy = new Proxy(target, proxyHandler);\n const ref = new WeakRef(proxy);\n proxies.set(value, ref);\n registry.register(proxy, value, ref);\n }\n return proxies.get(value).deref();\n };\n\n const fromEntry = entry => {\n const [type, value] = entry;\n switch (type) {\n case OBJECT:\n return value === null ? globalThis : (\n typeof value === NUMBER ? register(entry) : value\n );\n case FUNCTION:\n return typeof value === STRING ? values.get(value) : register(entry);\n case SYMBOL:\n return symbol(value);\n }\n return value;\n };\n\n const result = (TRAP, target, ...args) => fromEntry(__main__(TRAP, bound(target), ...args));\n\n const proxyHandler = {\n [APPLY]: (target, thisArg, args) => result(APPLY, target, argument(thisArg), args.map(argument)),\n [CONSTRUCT]: (target, args) => result(CONSTRUCT, target, args.map(argument)),\n [DEFINE_PROPERTY]: (target, name, descriptor) => {\n const { get, set, value } = descriptor;\n if (typeof get === FUNCTION) descriptor.get = argument(get);\n if (typeof set === FUNCTION) descriptor.set = argument(set);\n if (typeof value === FUNCTION) descriptor.value = argument(value);\n return result(DEFINE_PROPERTY, target, argument(name), descriptor);\n },\n [DELETE_PROPERTY]: (target, name) => result(DELETE_PROPERTY, target, argument(name)),\n [GET_PROTOTYPE_OF]: target => result(GET_PROTOTYPE_OF, target),\n [GET]: (target, name) => name === __proxied__ ? target : result(GET, target, argument(name)),\n [GET_OWN_PROPERTY_DESCRIPTOR]: (target, name) => {\n const descriptor = result(GET_OWN_PROPERTY_DESCRIPTOR, target, argument(name));\n return descriptor && augment(descriptor, fromEntry);\n },\n [HAS]: (target, name) => name === __proxied__ || result(HAS, target, argument(name)),\n [IS_EXTENSIBLE]: target => result(IS_EXTENSIBLE, target),\n [OWN_KEYS]: target => result(OWN_KEYS, target).map(fromEntry),\n [PREVENT_EXTENSION]: target => result(PREVENT_EXTENSION, target),\n [SET]: (target, name, value) => result(SET, target, argument(name), argument(value)),\n [SET_PROTOTYPE_OF]: (target, proto) => result(SET_PROTOTYPE_OF, target, argument(proto)),\n };\n\n main[THREAD] = (trap, entry, ctx, args) => {\n switch (trap) {\n case APPLY:\n return fromEntry(entry).apply(fromEntry(ctx), args.map(fromEntry));\n case DELETE: {\n const id = fromEntry(entry);\n ids.delete(values.get(id));\n values.delete(id);\n }\n }\n };\n\n const global = new Proxy([OBJECT, null], proxyHandler);\n\n // this is needed to avoid confusion when new Proxy([type, value])\n // passes through `isArray` check, as that would return always true\n // by specs and there's no Proxy trap to avoid it.\n const remoteArray = global.Array[isArray];\n defineProperty(Array, isArray, {\n value: ref => isProxy(ref) ? remoteArray(ref) : localArray(ref)\n });\n\n return {\n [name.toLowerCase()]: global,\n [`is${name}Proxy`]: isProxy,\n proxy: main\n };\n };\n};\n","export default typeof Worker === 'function' ? Worker : class {};\n","import {MAIN, THREAD} from './channel.js';\nimport $coincident from './index.js';\nimport main from './window/main.js';\nimport thread from './window/thread.js';\nimport Worker from './shared/worker.js';\n\nconst proxies = new WeakMap;\n\n/**\n * @typedef {object} Coincident\n * @property {ProxyHandler} proxy\n * @property {ProxyHandler} window\n * @property {(value: any) => boolean} isWindowProxy\n */\n\n/**\n * Create once a `Proxy` able to orchestrate synchronous `postMessage` out of the box.\n * In workers, returns a `{proxy, window, isWindowProxy}` namespace to reach main globals synchronously.\n * @param {Worker | globalThis} self the context in which code should run\n * @returns {ProxyHandler | Coincident}\n */\nconst coincident = (self, ...args) => {\n const proxy = $coincident(self, ...args);\n if (!proxies.has(proxy)) {\n const util = self instanceof Worker ? main : thread;\n proxies.set(proxy, util(proxy, MAIN, THREAD));\n }\n return proxies.get(proxy);\n}\n\ncoincident.transfer = $coincident.transfer;\n\nexport default coincident;\n","Promise.withResolvers || (Promise.withResolvers = function withResolvers() {\n var a, b, c = new this(function (resolve, reject) {\n a = resolve;\n b = reject;\n });\n return {resolve: a, reject: b, promise: c};\n});\n","/** @param {Response} response */\nexport const getBuffer = (response) => response.arrayBuffer();\n\n/** @param {Response} response */\nexport const getJSON = (response) => response.json();\n\n/** @param {Response} response */\nexport const getText = (response) => response.text();\n","import content from 'plain-tag';\n\nconst dedent = {\n object(...args) {\n return this.string(content(...args));\n },\n string(content) {\n for (const line of content.split(/[\\r\\n]+/)) {\n // skip initial empty lines\n if (line.trim().length) {\n // trap indentation at the very first line of code\n if (/^(\\s+)/.test(line))\n content = content.replace(new RegExp('^' + RegExp.$1, 'gm'), '');\n // no indentation? all good: get out of here!\n break;\n }\n }\n return content;\n }\n};\n\n/**\n * Usable both as template literal tag or just as callback for strings, removes all spaces found\n * at the very first line of code encountered while sanitizing, keeping everything else around.\n * @param {string | TemplateStringsArray} tpl either code as string or as template, when used as tag\n * @param {...any} values the template interpolations, when used as tag\n * @returns {string} code without undesired indentation\n */\nconst codedent = (tpl, ...values) => dedent[typeof tpl](tpl, ...values);\n\nexport default codedent;\n","export default function (t) {\n for (var s = t[0], i = 1, l = arguments.length; i < l; i++)\n s += arguments[i] + t[i];\n return s;\n};\n","import dedent from 'codedent';\n\nconst { isArray } = Array;\n\nconst { assign, create, defineProperties, defineProperty, entries } = Object;\n\nconst { all, resolve } = new Proxy(Promise, {\n get: ($, name) => $[name].bind($),\n});\n\nconst absoluteURL = (path, base = location.href) =>\n new URL(path, base.replace(/^blob:/, '')).href;\n\n/* c8 ignore start */\nlet id = 0;\nconst nodeInfo = (node, type) => ({\n id: node.id || (node.id = `${type}-w${id++}`),\n tag: node.tagName\n});\n\n/**\n * Notify the main thread about element \"readiness\".\n * @param {HTMLScriptElement | HTMLElement} target the script or custom-type element\n * @param {string} type the custom/type as event prefix\n * @param {boolean} [worker = false] `true` if dispatched form a worker, `false` by default if in main\n * @param {globalThis.CustomEvent} [CustomEvent = globalThis.CustomEvent] the `CustomEvent` to use\n */\nconst dispatch = (target, type, worker = false, CE = CustomEvent) => {\n target.dispatchEvent(\n new CE(`${type}:ready`, {\n bubbles: true,\n detail: { worker },\n })\n );\n};\n/* c8 ignore stop */\n\nexport {\n dedent,\n dispatch,\n isArray,\n assign,\n create,\n defineProperties,\n defineProperty,\n entries,\n all,\n resolve,\n absoluteURL,\n nodeInfo,\n};\n","import '@ungap/with-resolvers';\n\nimport { getBuffer } from '../fetch-utils.js';\nimport { absoluteURL } from '../utils.js';\n\n// REQUIRES INTEGRATION TEST\n/* c8 ignore start */\nexport const io = new WeakMap();\nexport const stdio = (init) => {\n const context = init || console;\n const localIO = {\n stderr: (context.stderr || console.error).bind(context),\n stdout: (context.stdout || console.log).bind(context),\n };\n return {\n stderr: (...args) => localIO.stderr(...args),\n stdout: (...args) => localIO.stdout(...args),\n async get(engine) {\n const interpreter = await engine;\n io.set(interpreter, localIO);\n return interpreter;\n },\n };\n};\n\n// This should be the only helper needed for all Emscripten based FS exports\nexport const writeFile = ({ FS, PATH, PATH_FS }, path, buffer) => {\n const absPath = PATH_FS.resolve(path);\n FS.mkdirTree(PATH.dirname(absPath));\n return FS.writeFile(absPath, new Uint8Array(buffer), {\n canOwn: true,\n });\n};\n/* c8 ignore stop */\n\n// This is instead a fallback for Lua or others\nexport const writeFileShim = (FS, path, buffer) => {\n mkdirTree(FS, dirname(path));\n path = resolve(FS, path);\n return FS.writeFile(path, new Uint8Array(buffer), { canOwn: true });\n};\n\nconst dirname = (path) => {\n const tree = path.split('/');\n tree.pop();\n return tree.join('/');\n};\n\nconst mkdirTree = (FS, path) => {\n const current = [];\n for (const branch of path.split('/')) {\n if (branch === '.') continue;\n current.push(branch);\n if (branch) FS.mkdir(current.join('/'));\n }\n};\n\nconst resolve = (FS, path) => {\n const tree = [];\n for (const branch of path.split('/')) {\n switch (branch) {\n case '':\n break;\n case '.':\n break;\n case '..':\n tree.pop();\n break;\n default:\n tree.push(branch);\n }\n }\n return [FS.cwd()].concat(tree).join('/').replace(/^\\/+/, '/');\n};\n\nimport { all, isArray } from '../utils.js';\n\nconst calculateFetchPaths = (config_fetch) => {\n // REQUIRES INTEGRATION TEST\n /* c8 ignore start */\n for (const { files, to_file, from = '' } of config_fetch) {\n if (files !== undefined && to_file !== undefined)\n throw new Error(\n 'Cannot use \\'to_file\\' and \\'files\\' parameters together!',\n );\n if (files === undefined && to_file === undefined && from.endsWith('/'))\n throw new Error(\n `Couldn't determine the filename from the path ${from}, please supply 'to_file' parameter.`,\n );\n }\n /* c8 ignore stop */\n return config_fetch.flatMap(\n ({ from = '', to_folder = '.', to_file, files }) => {\n if (isArray(files))\n return files.map((file) => ({\n url: joinPaths([from, file]),\n path: joinPaths([to_folder, file]),\n }));\n const filename = to_file || from.slice(1 + from.lastIndexOf('/'));\n return [{ url: from, path: joinPaths([to_folder, filename]) }];\n },\n );\n};\n\nconst joinPaths = (parts) => {\n const res = parts\n .map((part) => part.trim().replace(/(^[/]*|[/]*$)/g, ''))\n .filter((p) => p !== '' && p !== '.')\n .join('/');\n\n return parts[0].startsWith('/') ? `/${res}` : res;\n};\n\nconst fetchResolved = (config_fetch, url) =>\n fetch(absoluteURL(url, base.get(config_fetch)));\n\nexport const base = new WeakMap();\n\nexport const fetchPaths = (module, interpreter, config_fetch) =>\n all(\n calculateFetchPaths(config_fetch).map(({ url, path }) =>\n fetchResolved(config_fetch, url)\n .then(getBuffer)\n .then((buffer) => module.writeFile(interpreter, path, buffer)),\n ),\n );\n/* c8 ignore stop */\n","import { dedent } from '../utils.js';\nimport { io } from './_utils.js';\n\n// REQUIRES INTEGRATION TEST\n/* c8 ignore start */\nexport const registerJSModule = (interpreter, name, value) => {\n interpreter.registerJsModule(name, value);\n};\n\nexport const run = (interpreter, code, ...args) => {\n try {\n return interpreter.runPython(dedent(code), ...args);\n }\n catch (error) {\n io.get(interpreter).stderr(error);\n }\n};\n\nexport const runAsync = async (interpreter, code, ...args) => {\n try {\n return await interpreter.runPythonAsync(dedent(code), ...args);\n }\n catch (error) {\n io.get(interpreter).stderr(error);\n }\n};\n\nexport const runEvent = async (interpreter, code, event) => {\n // allows method(event) as well as namespace.method(event)\n // it does not allow fancy brackets names for now\n const [name, ...keys] = code.split('.');\n let target = interpreter.globals.get(name);\n let context;\n for (const key of keys) [context, target] = [target, target[key]];\n try {\n await target.call(context, event);\n }\n catch (error) {\n io.get(interpreter).stderr(error);\n }\n};\n/* c8 ignore stop */\n","import { fetchPaths, stdio, writeFile } from './_utils.js';\nimport { registerJSModule, run, runAsync, runEvent } from './_python.js';\n\nconst type = 'micropython';\n\n// REQUIRES INTEGRATION TEST\n/* c8 ignore start */\nexport default {\n type,\n module: (version = '1.20.0-297') =>\n `https://cdn.jsdelivr.net/npm/@micropython/micropython-webassembly-pyscript@${version}/micropython.mjs`,\n async engine({ loadMicroPython }, config, url) {\n const { stderr, stdout, get } = stdio();\n url = url.replace(/\\.m?js$/, '.wasm');\n const interpreter = await get(loadMicroPython({ stderr, stdout, url }));\n if (config.fetch) await fetchPaths(this, interpreter, config.fetch);\n return interpreter;\n },\n registerJSModule,\n run,\n runAsync,\n runEvent,\n transform: (_, value) => value,\n writeFile: ({ FS, _module: { PATH, PATH_FS } }, path, buffer) =>\n writeFile({ FS, PATH, PATH_FS }, path, buffer),\n};\n/* c8 ignore stop */\n","import { fetchPaths, stdio, writeFile } from './_utils.js';\nimport { registerJSModule, run, runAsync, runEvent } from './_python.js';\n\nconst type = 'pyodide';\nconst toJsOptions = { dict_converter: Object.fromEntries };\n\n// REQUIRES INTEGRATION TEST\n/* c8 ignore start */\nexport default {\n type,\n module: (version = '0.23.4') =>\n `https://cdn.jsdelivr.net/pyodide/v${version}/full/pyodide.mjs`,\n async engine({ loadPyodide }, config, url) {\n const { stderr, stdout, get } = stdio();\n const indexURL = url.slice(0, url.lastIndexOf('/'));\n const interpreter = await get(\n loadPyodide({ stderr, stdout, indexURL }),\n );\n if (config.fetch) await fetchPaths(this, interpreter, config.fetch);\n if (config.packages) {\n await interpreter.loadPackage('micropip');\n const micropip = await interpreter.pyimport('micropip');\n await micropip.install(config.packages);\n micropip.destroy();\n }\n return interpreter;\n },\n registerJSModule,\n run,\n runAsync,\n runEvent,\n transform: (interpreter, value) => (\n value instanceof interpreter.ffi.PyProxy ?\n value.toJs(toJsOptions) :\n value\n ),\n writeFile: ({ FS, PATH, _module: { PATH_FS } }, path, buffer) =>\n writeFile({ FS, PATH, PATH_FS }, path, buffer),\n};\n/* c8 ignore stop */\n","import { dedent } from '../utils.js';\nimport { fetchPaths } from './_utils.js';\n\nconst type = 'ruby-wasm-wasi';\nconst jsType = type.replace(/\\W+/g, '_');\n\n// MISSING:\n// * there is no VFS apparently or I couldn't reach any\n// * I've no idea how to override the stderr and stdout\n// * I've no idea how to import packages\n\n// REQUIRES INTEGRATION TEST\n/* c8 ignore start */\nexport default {\n type,\n experimental: true,\n module: (version = '2.0.0') =>\n `https://cdn.jsdelivr.net/npm/ruby-3_2-wasm-wasi@${version}/dist/browser.esm.js`,\n async engine({ DefaultRubyVM }, config, url) {\n const response = await fetch(\n `${url.slice(0, url.lastIndexOf('/'))}/ruby.wasm`,\n );\n const module = await WebAssembly.compile(await response.arrayBuffer());\n const { vm: interpreter } = await DefaultRubyVM(module);\n if (config.fetch) await fetchPaths(this, interpreter, config.fetch);\n return interpreter;\n },\n // Fallback to globally defined module fields (i.e. $xworker)\n registerJSModule(interpreter, name, value) {\n const id = `__module_${jsType}_${name}`;\n globalThis[id] = value;\n this.run(interpreter, `require \"js\";$${name}=JS.global[:${id}]`);\n delete globalThis[id];\n },\n run: (interpreter, code, ...args) => interpreter.eval(dedent(code), ...args),\n runAsync: (interpreter, code, ...args) => interpreter.evalAsync(dedent(code), ...args),\n async runEvent(interpreter, code, event) {\n // patch common xworker.onmessage/onerror cases\n if (/^xworker\\.(on\\w+)$/.test(code)) {\n const { $1: name } = RegExp;\n const id = `__module_${jsType}_event`;\n globalThis[id] = event;\n this.run(\n interpreter,\n `require \"js\";$xworker.call(\"${name}\",JS.global[:${id}])`,\n );\n delete globalThis[id];\n } else {\n // Experimental: allows only events by fully qualified method name\n const method = this.run(interpreter, `method(:${code})`);\n await method.call(code, interpreter.wrap(event));\n }\n },\n transform: (_, value) => value,\n writeFile: () => {\n throw new Error(`writeFile is not supported in ${type}`);\n },\n};\n/* c8 ignore stop */\n","import { dedent } from '../utils.js';\nimport { fetchPaths, io, stdio, writeFileShim } from './_utils.js';\n\nconst type = 'wasmoon';\n\n// MISSING:\n// * I've no idea how to import packages\n\n// REQUIRES INTEGRATION TEST\n/* c8 ignore start */\nexport default {\n type,\n module: (version = '1.15.0') =>\n `https://cdn.jsdelivr.net/npm/wasmoon@${version}/+esm`,\n async engine({ LuaFactory, LuaLibraries }, config) {\n const { stderr, stdout, get } = stdio();\n const interpreter = await get(new LuaFactory().createEngine());\n interpreter.global.getTable(LuaLibraries.Base, (index) => {\n interpreter.global.setField(index, 'print', stdout);\n interpreter.global.setField(index, 'printErr', stderr);\n });\n if (config.fetch) await fetchPaths(this, interpreter, config.fetch);\n return interpreter;\n },\n // Fallback to globally defined module fields\n registerJSModule: (interpreter, name, value) => {\n interpreter.global.set(name, value);\n },\n run: (interpreter, code, ...args) => {\n try {\n return interpreter.doStringSync(dedent(code), ...args);\n }\n catch (error) {\n io.get(interpreter).stderr(error);\n }\n },\n runAsync: async (interpreter, code, ...args) => {\n try {\n return await interpreter.doString(dedent(code), ...args);\n }\n catch (error) {\n io.get(interpreter).stderr(error);\n }\n },\n runEvent: async (interpreter, code, event) => {\n // allows method(event) as well as namespace.method(event)\n // it does not allow fancy brackets names for now\n const [name, ...keys] = code.split('.');\n let target = interpreter.global.get(name);\n let context;\n for (const key of keys) [context, target] = [target, target[key]];\n try {\n await target.call(context, event);\n }\n catch (error) {\n io.get(interpreter).stderr(error);\n }\n },\n transform: (_, value) => value,\n writeFile: (\n {\n cmodule: {\n module: { FS },\n },\n },\n path,\n buffer,\n ) => writeFileShim(FS, path, buffer),\n};\n/* c8 ignore stop */\n","// ⚠️ Part of this file is automatically generated\n// The :RUNTIMES comment is a delimiter and no code should be written/changed after\n// See rollup/build_interpreters.cjs to know more\n\nimport { base } from './interpreter/_utils.js';\n\n/** @type {Map} */\nexport const registry = new Map();\n\n/** @type {Map} */\nexport const configs = new Map();\n\n/** @type {string[]} */\nexport const selectors = [];\n\n/** @type {string[]} */\nexport const prefixes = [];\n\nexport const interpreter = new Proxy(new Map(), {\n get(map, id) {\n if (!map.has(id)) {\n const [type, ...rest] = id.split('@');\n const interpreter = registry.get(type);\n const url = /^https?:\\/\\//i.test(rest)\n ? rest.join('@')\n : interpreter.module(...rest);\n map.set(id, {\n url,\n module: import(/* webpackIgnore: true */url),\n engine: interpreter.engine.bind(interpreter),\n });\n }\n const { url, module, engine } = map.get(id);\n return (config, baseURL) =>\n module.then((module) => {\n configs.set(id, config);\n const fetch = config?.fetch;\n if (fetch) base.set(fetch, baseURL);\n return engine(module, config, url);\n });\n },\n});\n\nconst register = (interpreter) => {\n for (const type of [].concat(interpreter.type)) {\n registry.set(type, interpreter);\n selectors.push(`script[type=\"${type}\"]`);\n prefixes.push(`${type}-`);\n }\n};\n\n//:RUNTIMES\nimport micropython from './interpreter/micropython.js';\nimport pyodide from './interpreter/pyodide.js';\nimport ruby_wasm_wasi from './interpreter/ruby-wasm-wasi.js';\nimport wasmoon from './interpreter/wasmoon.js';\nfor (const interpreter of [micropython, pyodide, ruby_wasm_wasi, wasmoon])\n register(interpreter);\n","// lazy TOML parser (fast-toml might be a better alternative)\nconst TOML_LIB = 'https://cdn.jsdelivr.net/npm/basic-toml@0.3.1/es.js';\n\n/**\n * @param {string} text TOML text to parse\n * @returns {object} the resulting JS object\n */\nexport const parse = async (text) => (await import(/* webpackIgnore: true */TOML_LIB)).parse(text);\n","import { interpreter } from './interpreters.js';\nimport { absoluteURL, resolve } from './utils.js';\nimport { parse } from './toml.js';\nimport { getJSON, getText } from './fetch-utils.js';\n\nexport const getConfigURLAndType = config => {\n // REQUIRES INTEGRATION TEST\n /* c8 ignore start */\n let type = typeof config;\n if (type === 'string' && /\\.(json|toml|txt)$/.test(config))\n type = RegExp.$1;\n else\n config = './config.txt';\n return [absoluteURL(config), type];\n /* c8 ignore stop */\n};\n\n/**\n * Parse a generic config if it came from an attribute either as URL\n * or as a serialized string. In XWorker case, accepts a pre-defined\n * options to use as it is to avoid needing at all a fetch operation.\n * In latter case, config will be suffixed as `config.txt`.\n * @param {string} id the interpreter name @ version identifier\n * @param {string} [config] optional config file to parse\n * @param {object} [options] optional options used to bootstrap XWorker\n * @returns\n */\nexport const getRuntime = (id, config, options = {}) => {\n if (config) {\n // REQUIRES INTEGRATION TEST\n /* c8 ignore start */\n const [absolute, type] = getConfigURLAndType(config);\n if (type === 'json') {\n options = fetch(absolute).then(getJSON);\n } else if (type === 'toml') {\n options = fetch(absolute).then(getText).then(parse);\n } else if (type === 'string') {\n try {\n options = JSON.parse(config);\n } catch (_) {\n options = parse(config);\n }\n } else if (type === 'object' && config) {\n options = config;\n }\n config = absolute;\n /* c8 ignore stop */\n }\n return resolve(options).then(options => interpreter[id](options, config));\n};\n\n/**\n * @param {string} type the interpreter type\n * @param {string} [version] the optional interpreter version\n * @returns\n */\nexport const getRuntimeID = (type, version = '') =>\n `${type}@${version}`.replace(/@$/, '');\n","import { dedent } from '../utils.js';\n\n// REQUIRES INTEGRATION TEST\n/* c8 ignore start */\nconst workerHooks = [\n ['beforeRun', 'codeBeforeRunWorker'],\n ['beforeRunAsync', 'codeBeforeRunWorkerAsync'],\n ['afterRun', 'codeAfterRunWorker'],\n ['afterRunAsync', 'codeAfterRunWorkerAsync'],\n];\n\nexport class Hook {\n constructor(interpreter, options) {\n this.interpreter = interpreter;\n this.onWorkerReady = options.onWorkerReady;\n for (const [key, value] of workerHooks)\n this[key] = options[value]?.();\n }\n get stringHooks() {\n const hooks = {};\n for (const [key] of workerHooks) {\n if (this[key]) hooks[key] = dedent(this[key]);\n }\n return hooks;\n }\n}\n/* c8 ignore stop */\n","import * as JSON from '@ungap/structured-clone/json';\nimport coincident from 'coincident/window';\nimport xworker from './xworker.js';\nimport { getConfigURLAndType } from '../loader.js';\nimport { assign, defineProperties } from '../utils.js';\nimport { getText } from '../fetch-utils.js';\nimport { Hook } from './hooks.js';\n\n/**\n * @typedef {Object} WorkerOptions custom configuration\n * @prop {string} type the interpreter type to use\n * @prop {string} [version] the optional interpreter version to use\n * @prop {string} [config] the optional config to use within such interpreter\n */\n\nexport default (...args) =>\n /**\n * A XWorker is a Worker facade able to bootstrap a channel with any desired interpreter.\n * @param {string} url the remote file to evaluate on bootstrap\n * @param {WorkerOptions} [options] optional arguments to define the interpreter to use\n * @returns {Worker}\n */\n function XWorker(url, options) {\n const worker = xworker();\n const { postMessage } = worker;\n const isHook = this instanceof Hook;\n\n if (args.length) {\n const [type, version] = args;\n options = assign({}, options || { type, version });\n if (!options.type) options.type = type;\n }\n\n // provide a base url to fetch or load config files from a Worker\n // because there's no location at all in the Worker as it's embedded.\n // fallback to a generic, ignored, config.txt file to still provide a URL.\n const [ config ] = getConfigURLAndType(options.config);\n\n const bootstrap = fetch(url)\n .then(getText)\n .then(code => {\n const hooks = isHook ? this.stringHooks : void 0;\n postMessage.call(worker, { options, config, code, hooks });\n });\n\n defineProperties(worker, {\n postMessage: {\n value: (data, ...rest) =>\n bootstrap.then(() =>\n postMessage.call(worker, data, ...rest),\n ),\n },\n sync: {\n value: coincident(worker, JSON).proxy,\n },\n onerror: {\n writable: true,\n configurable: true,\n value: console.error\n }\n });\n\n if (isHook) this.onWorkerReady?.(this.interpreter, worker);\n\n worker.addEventListener('message', event => {\n const { data } = event;\n if (data instanceof Error) {\n event.stopImmediatePropagation();\n worker.onerror(Object.create(event, {\n type: { value: 'error' },\n error: { value: data }\n }));\n }\n });\n\n return worker;\n };\n","/* c8 ignore next */\nexport default () => new Worker(URL.createObjectURL(new Blob([\"const e=\\\"object\\\"==typeof self?self:globalThis,t=t=>((t,r)=>{const n=(e,r)=>(t.set(r,e),e),s=o=>{if(t.has(o))return t.get(o);const[a,i]=r[o];switch(a){case 0:case-1:return n(i,o);case 1:{const e=n([],o);for(const t of i)e.push(s(t));return e}case 2:{const e=n({},o);for(const[t,r]of i)e[s(t)]=s(r);return e}case 3:return n(new Date(i),o);case 4:{const{source:e,flags:t}=i;return n(new RegExp(e,t),o)}case 5:{const e=n(new Map,o);for(const[t,r]of i)e.set(s(t),s(r));return e}case 6:{const e=n(new Set,o);for(const t of i)e.add(s(t));return e}case 7:{const{name:t,message:r}=i;return n(new e[t](r),o)}case 8:return n(BigInt(i),o);case\\\"BigInt\\\":return n(Object(BigInt(i)),o)}return n(new e[a](i),o)};return s})(new Map,t)(0),r=\\\"\\\",{toString:n}={},{keys:s}=Object,o=e=>{const t=typeof e;if(\\\"object\\\"!==t||!e)return[0,t];const s=n.call(e).slice(8,-1);switch(s){case\\\"Array\\\":return[1,r];case\\\"Object\\\":return[2,r];case\\\"Date\\\":return[3,r];case\\\"RegExp\\\":return[4,r];case\\\"Map\\\":return[5,r];case\\\"Set\\\":return[6,r]}return s.includes(\\\"Array\\\")?[1,s]:s.includes(\\\"Error\\\")?[7,s]:[2,s]},a=([e,t])=>0===e&&(\\\"function\\\"===t||\\\"symbol\\\"===t),i=(e,{json:t,lossy:r}={})=>{const n=[];return((e,t,r,n)=>{const i=(e,t)=>{const s=n.push(e)-1;return r.set(t,s),s},c=n=>{if(r.has(n))return r.get(n);let[l,u]=o(n);switch(l){case 0:{let t=n;switch(u){case\\\"bigint\\\":l=8,t=n.toString();break;case\\\"function\\\":case\\\"symbol\\\":if(e)throw new TypeError(\\\"unable to serialize \\\"+u);t=null;break;case\\\"undefined\\\":return i([-1],n)}return i([l,t],n)}case 1:{if(u)return i([u,[...n]],n);const e=[],t=i([l,e],n);for(const t of n)e.push(c(t));return t}case 2:{if(u)switch(u){case\\\"BigInt\\\":return i([u,n.toString()],n);case\\\"Boolean\\\":case\\\"Number\\\":case\\\"String\\\":return i([u,n.valueOf()],n)}if(t&&\\\"toJSON\\\"in n)return c(n.toJSON());const r=[],f=i([l,r],n);for(const t of s(n))!e&&a(o(n[t]))||r.push([c(t),c(n[t])]);return f}case 3:return i([l,n.toISOString()],n);case 4:{const{source:e,flags:t}=n;return i([l,{source:e,flags:t}],n)}case 5:{const t=[],r=i([l,t],n);for(const[r,s]of n)(e||!a(o(r))&&!a(o(s)))&&t.push([c(r),c(s)]);return r}case 6:{const t=[],r=i([l,t],n);for(const r of n)!e&&a(o(r))||t.push(c(r));return r}}const{message:f}=n;return i([l,{name:u,message:f}],n)};return c})(!(t||r),!!t,new Map,n)(e),n},{parse:c,stringify:l}=JSON,u={json:!0,lossy:!0};var f=Object.freeze({__proto__:null,parse:e=>t(c(e)),stringify:e=>l(i(e,u))});const p=\\\"3099687a-04a9-4406-a08e-fd1602cb2a81\\\",d=\\\"M\\\"+p,g=\\\"T\\\"+p;var y=e=>({value:new Promise((t=>{let r=new Worker(\\\"data:application/javascript,onmessage%3D(%7Bdata%3Ab%7D)%3D%3E(Atomics.wait(b%2C0)%2CpostMessage(0))\\\");r.onmessage=t,r.postMessage(e)}))})\\n/*! (c) Andrea Giammarchi - ISC */;const{Int32Array:w,Map:h,SharedArrayBuffer:m,Uint16Array:b}=globalThis,{BYTES_PER_ELEMENT:v}=w,{BYTES_PER_ELEMENT:S}=b,{isArray:E}=Array,{notify:P,wait:A,waitAsync:$}=Atomics,{fromCharCode:M}=String,j=(e,t)=>e?($||y)(t,0):(A(t,0),{value:{then:e=>e()}}),k=new WeakSet,x=new WeakMap;let T=0;const _=(e,{parse:t,stringify:r,transform:n}=JSON)=>{if(!x.has(e)){const s=(t,...r)=>e.postMessage({[p]:r},{transfer:t});let o=!1;x.set(e,new Proxy(new h,{has:(e,t)=>\\\"string\\\"==typeof t&&!t.startsWith(\\\"_\\\"),get:(r,a)=>\\\"then\\\"===a?null:(...r)=>{const i=T++;let c=new w(new m(v)),l=[];k.has(r.at(-1)||l)&&k.delete(l=r.pop()),s(l,i,c,a,n?r.map(n):r);const u=e!==globalThis;let f=0;return o&&u&&(f=setTimeout(console.warn,1e3,`💀🔒 - Possible deadlock if proxy.${a}(...args) is awaited`)),j(u,c).value.then((()=>{clearTimeout(f);const e=c[0];if(!e)return;const r=S*e;return c=new w(new m(r+r%v)),s([],i,c),j(u,c).value.then((()=>t(M(...new b(c.buffer).slice(0,e)))))}))},set(t,s,a){if(!t.size){const s=new h;e.addEventListener(\\\"message\\\",(async e=>{const a=e.data?.[p];if(E(a)){e.stopImmediatePropagation();const[i,c,...l]=a;if(l.length){const[e,a]=l;if(!t.has(e))throw new Error(`Unsupported action: ${e}`);o=!0;try{const o=await t.get(e)(...a);if(void 0!==o){const e=r(n?n(o):o);s.set(i,e),c[0]=e.length}}finally{o=!1}}else{const e=s.get(i);s.delete(i);for(let t=new b(c.buffer),r=0;r(k.add(e),e);const O=\\\"object\\\",F=\\\"function\\\",R=\\\"number\\\",W=\\\"string\\\",B=\\\"undefined\\\",J=\\\"symbol\\\",{defineProperty:C,getOwnPropertyDescriptor:I,getPrototypeOf:L,isExtensible:H,ownKeys:D,preventExtensions:N,set:U,setPrototypeOf:z}=Reflect,{assign:q,create:K}=Object,Y=L(Int8Array),G=\\\"isArray\\\",V=(e,t)=>{const{get:r,set:n,value:s}=e;return r&&(e.get=t(r)),n&&(e.set=t(n)),s&&(e.value=t(s)),e},Q=(e,t)=>[e,t],X=e=>t=>{const r=typeof t;switch(r){case O:if(null==t)return Q(\\\"null\\\",t);if(t===globalThis)return Q(O,null);case F:return e(r,t);case\\\"boolean\\\":case R:case W:case B:case\\\"bigint\\\":return Q(r,t);case J:if(Z.has(t))return Q(r,Z.get(t))}throw new Error(`Unable to handle this ${r} type`)},Z=new Map(D(Symbol).filter((e=>typeof Symbol[e]===J)).map((e=>[Symbol[e],e]))),ee=e=>{for(const[t,r]of Z)if(r===e)return t};function te(){return this}const re=\\\"apply\\\",ne=\\\"construct\\\",se=\\\"defineProperty\\\",oe=\\\"deleteProperty\\\",ae=\\\"get\\\",ie=\\\"getOwnPropertyDescriptor\\\",ce=\\\"getPrototypeOf\\\",le=\\\"has\\\",ue=\\\"isExtensible\\\",fe=\\\"ownKeys\\\",pe=\\\"preventExtensions\\\",de=\\\"set\\\",ge=\\\"setPrototypeOf\\\",ye=\\\"delete\\\";var we=((e,t)=>{const r=t&&new WeakMap;if(t){const{addEventListener:e}=EventTarget.prototype;C(EventTarget.prototype,\\\"addEventListener\\\",{value(t,n,...s){return s.at(0)?.invoke&&(r.has(this)||r.set(this,new Map),r.get(this).set(t,[].concat(s[0].invoke)),delete s[0].invoke),e.call(this,t,n,...s)}})}const n=t&&(e=>{const{currentTarget:t,target:n,type:s}=e;for(const o of r.get(t||n)?.get(s)||[])e[o]()});return(r,s,o,...a)=>{let i=0;const c=new Map,l=new Map,{[o]:u}=r,f=a.length?q(K(globalThis),...a):globalThis,p=X(((e,t)=>{if(!c.has(t)){let e;for(;l.has(e=i++););c.set(t,e),l.set(e,t)}return Q(e,c.get(t))})),d=new FinalizationRegistry((e=>{u(ye,Q(W,e))})),g=([e,r])=>{switch(e){case O:if(null==r)return f;if(typeof r===R)return l.get(r);if(!(r instanceof Y))for(const e in r)r[e]=g(r[e]);return r;case F:if(typeof r===W){if(!l.has(r)){const e=function(...e){return t&&e.at(0)instanceof Event&&n(...e),u(re,Q(F,r),p(this),e.map(p))},s=new WeakRef(e);l.set(r,s),d.register(e,r,s)}return l.get(r).deref()}return l.get(r);case J:return ee(r)}return r},y={[re]:(e,t,r)=>p(e.apply(t,r)),[ne]:(e,t)=>p(new e(...t)),[se]:(e,t,r)=>p(C(e,t,r)),[oe]:(e,t)=>p(delete e[t]),[ce]:e=>p(L(e)),[ae]:(e,t)=>p(e[t]),[ie]:(e,t)=>{const r=I(e,t);return r?Q(O,V(r,p)):Q(B,r)},[le]:(e,t)=>p(t in e),[ue]:e=>p(H(e)),[fe]:e=>Q(O,D(e).map(p)),[pe]:e=>p(N(e)),[de]:(e,t,r)=>p(U(e,t,r)),[ge]:(e,t)=>p(z(e,t)),[ye](e){c.delete(l.get(e)),l.delete(e)}};return r[s]=(e,t,...r)=>{switch(e){case re:r[0]=g(r[0]),r[1]=r[1].map(g);break;case ne:r[0]=r[0].map(g);break;case se:{const[e,t]=r;r[0]=g(e);const{get:n,set:s,value:o}=t;n&&(t.get=g(n)),s&&(t.set=g(s)),o&&(t.value=g(o));break}default:r=r.map(g)}return y[e](g(t),...r)},{proxy:r,[e.toLowerCase()]:f,[`is${e}Proxy`]:()=>!1}}})(\\\"Window\\\",!0),he=(e=>{let t=0;const r=new Map,n=new Map,s=Symbol(),o=e=>typeof e===F?e():e,a=e=>typeof e===O&&!!e&&s in e,i=Array[G],c=X(((e,a)=>{if(s in a)return o(a[s]);if(e===F){if(!n.has(a)){let e;for(;n.has(e=String(t++)););r.set(a,e),n.set(e,a)}return Q(e,r.get(a))}if(!(a instanceof Y))for(const e in a)a[e]=c(a[e]);return Q(e,a)}));return(t,l,u)=>{const{[l]:f}=t,p=new Map,d=new FinalizationRegistry((e=>{p.delete(e),f(ye,c(e))})),g=e=>{const[t,r]=e;if(!p.has(r)){const n=t===F?te.bind(e):e,s=new Proxy(n,h),o=new WeakRef(s);p.set(r,o),d.register(s,r,o)}return p.get(r).deref()},y=e=>{const[t,r]=e;switch(t){case O:return null===r?globalThis:typeof r===R?g(e):r;case F:return typeof r===W?n.get(r):g(e);case J:return ee(r)}return r},w=(e,t,...r)=>y(f(e,o(t),...r)),h={[re]:(e,t,r)=>w(re,e,c(t),r.map(c)),[ne]:(e,t)=>w(ne,e,t.map(c)),[se]:(e,t,r)=>{const{get:n,set:s,value:o}=r;return typeof n===F&&(r.get=c(n)),typeof s===F&&(r.set=c(s)),typeof o===F&&(r.value=c(o)),w(se,e,c(t),r)},[oe]:(e,t)=>w(oe,e,c(t)),[ce]:e=>w(ce,e),[ae]:(e,t)=>t===s?e:w(ae,e,c(t)),[ie]:(e,t)=>{const r=w(ie,e,c(t));return r&&V(r,y)},[le]:(e,t)=>t===s||w(le,e,c(t)),[ue]:e=>w(ue,e),[fe]:e=>w(fe,e).map(y),[pe]:e=>w(pe,e),[de]:(e,t,r)=>w(de,e,c(t),c(r)),[ge]:(e,t)=>w(ge,e,c(t))};t[u]=(e,t,s,o)=>{switch(e){case re:return y(t).apply(y(s),o.map(y));case ye:{const e=y(t);r.delete(n.get(e)),n.delete(e)}}};const m=new Proxy([O,null],h),b=m.Array[G];return C(Array,G,{value:e=>a(e)?b(e):i(e)}),{[e.toLowerCase()]:m,[`is${e}Proxy`]:a,proxy:t}}})(\\\"Window\\\"),me=\\\"function\\\"==typeof Worker?Worker:class{};const be=new WeakMap,ve=(e,...t)=>{const r=_(e,...t);if(!be.has(r)){const t=e instanceof me?we:he;be.set(r,t(r,d,g))}return be.get(r)};ve.transfer=_.transfer;const Se={object(...e){return this.string(function(e){for(var t=e[0],r=1,n=arguments.length;rSe[typeof e](e,...t),{isArray:Pe}=Array,{assign:Ae,create:$e,defineProperties:Me,defineProperty:je,entries:ke}=Object,{all:xe,resolve:Te}=new Proxy(Promise,{get:(e,t)=>e[t].bind(e)}),_e=(e,t=location.href)=>new URL(e,t.replace(/^blob:/,\\\"\\\")).href,Oe=(e,t,r=!1,n=CustomEvent)=>{e.dispatchEvent(new n(`${t}:ready`,{bubbles:!0,detail:{worker:r}}))};Promise.withResolvers||(Promise.withResolvers=function(){var e,t,r=new this((function(r,n){e=r,t=n}));return{resolve:e,reject:t,promise:r}});const Fe=e=>e.arrayBuffer(),Re=e=>e.json(),We=e=>e.text(),Be=new WeakMap,Je=e=>{const t=e||console,r={stderr:(t.stderr||console.error).bind(t),stdout:(t.stdout||console.log).bind(t)};return{stderr:(...e)=>r.stderr(...e),stdout:(...e)=>r.stdout(...e),async get(e){const t=await e;return Be.set(t,r),t}}},Ce=({FS:e,PATH:t,PATH_FS:r},n,s)=>{const o=r.resolve(n);return e.mkdirTree(t.dirname(o)),e.writeFile(o,new Uint8Array(s),{canOwn:!0})},Ie=e=>{const t=e.split(\\\"/\\\");return t.pop(),t.join(\\\"/\\\")},Le=(e,t)=>{const r=[];for(const n of t.split(\\\"/\\\"))\\\".\\\"!==n&&(r.push(n),n&&e.mkdir(r.join(\\\"/\\\")))},He=(e,t)=>{const r=[];for(const e of t.split(\\\"/\\\"))switch(e){case\\\"\\\":case\\\".\\\":break;case\\\"..\\\":r.pop();break;default:r.push(e)}return[e.cwd()].concat(r).join(\\\"/\\\").replace(/^\\\\/+/,\\\"/\\\")},De=e=>{const t=e.map((e=>e.trim().replace(/(^[/]*|[/]*$)/g,\\\"\\\"))).filter((e=>\\\"\\\"!==e&&\\\".\\\"!==e)).join(\\\"/\\\");return e[0].startsWith(\\\"/\\\")?`/${t}`:t},Ne=new WeakMap,Ue=(e,t,r)=>xe((e=>{for(const{files:t,to_file:r,from:n=\\\"\\\"}of e){if(void 0!==t&&void 0!==r)throw new Error(\\\"Cannot use 'to_file' and 'files' parameters together!\\\");if(void 0===t&&void 0===r&&n.endsWith(\\\"/\\\"))throw new Error(`Couldn't determine the filename from the path ${n}, please supply 'to_file' parameter.`)}return e.flatMap((({from:e=\\\"\\\",to_folder:t=\\\".\\\",to_file:r,files:n})=>{if(Pe(n))return n.map((r=>({url:De([e,r]),path:De([t,r])})));const s=r||e.slice(1+e.lastIndexOf(\\\"/\\\"));return[{url:e,path:De([t,s])}]}))})(r).map((({url:n,path:s})=>((e,t)=>fetch(_e(t,Ne.get(e))))(r,n).then(Fe).then((r=>e.writeFile(t,s,r)))))),ze=(e,t,r)=>{e.registerJsModule(t,r)},qe=(e,t,...r)=>{try{return e.runPython(Ee(t),...r)}catch(t){Be.get(e).stderr(t)}},Ke=async(e,t,...r)=>{try{return await e.runPythonAsync(Ee(t),...r)}catch(t){Be.get(e).stderr(t)}},Ye=async(e,t,r)=>{const[n,...s]=t.split(\\\".\\\");let o,a=e.globals.get(n);for(const e of s)[o,a]=[a,a[e]];try{await a.call(o,r)}catch(t){Be.get(e).stderr(t)}};var Ge={type:\\\"micropython\\\",module:(e=\\\"1.20.0-297\\\")=>`https://cdn.jsdelivr.net/npm/@micropython/micropython-webassembly-pyscript@${e}/micropython.mjs`,async engine({loadMicroPython:e},t,r){const{stderr:n,stdout:s,get:o}=Je();r=r.replace(/\\\\.m?js$/,\\\".wasm\\\");const a=await o(e({stderr:n,stdout:s,url:r}));return t.fetch&&await Ue(this,a,t.fetch),a},registerJSModule:ze,run:qe,runAsync:Ke,runEvent:Ye,transform:(e,t)=>t,writeFile:({FS:e,_module:{PATH:t,PATH_FS:r}},n,s)=>Ce({FS:e,PATH:t,PATH_FS:r},n,s)};const Ve={dict_converter:Object.fromEntries};var Qe={type:\\\"pyodide\\\",module:(e=\\\"0.23.4\\\")=>`https://cdn.jsdelivr.net/pyodide/v${e}/full/pyodide.mjs`,async engine({loadPyodide:e},t,r){const{stderr:n,stdout:s,get:o}=Je(),a=r.slice(0,r.lastIndexOf(\\\"/\\\")),i=await o(e({stderr:n,stdout:s,indexURL:a}));if(t.fetch&&await Ue(this,i,t.fetch),t.packages){await i.loadPackage(\\\"micropip\\\");const e=await i.pyimport(\\\"micropip\\\");await e.install(t.packages),e.destroy()}return i},registerJSModule:ze,run:qe,runAsync:Ke,runEvent:Ye,transform:(e,t)=>t instanceof e.ffi.PyProxy?t.toJs(Ve):t,writeFile:({FS:e,PATH:t,_module:{PATH_FS:r}},n,s)=>Ce({FS:e,PATH:t,PATH_FS:r},n,s)};const Xe=\\\"ruby-wasm-wasi\\\",Ze=Xe.replace(/\\\\W+/g,\\\"_\\\");var et={type:Xe,experimental:!0,module:(e=\\\"2.0.0\\\")=>`https://cdn.jsdelivr.net/npm/ruby-3_2-wasm-wasi@${e}/dist/browser.esm.js`,async engine({DefaultRubyVM:e},t,r){const n=await fetch(`${r.slice(0,r.lastIndexOf(\\\"/\\\"))}/ruby.wasm`),s=await WebAssembly.compile(await n.arrayBuffer()),{vm:o}=await e(s);return t.fetch&&await Ue(this,o,t.fetch),o},registerJSModule(e,t,r){const n=`__module_${Ze}_${t}`;globalThis[n]=r,this.run(e,`require \\\"js\\\";$${t}=JS.global[:${n}]`),delete globalThis[n]},run:(e,t,...r)=>e.eval(Ee(t),...r),runAsync:(e,t,...r)=>e.evalAsync(Ee(t),...r),async runEvent(e,t,r){if(/^xworker\\\\.(on\\\\w+)$/.test(t)){const{$1:t}=RegExp,n=`__module_${Ze}_event`;globalThis[n]=r,this.run(e,`require \\\"js\\\";$xworker.call(\\\"${t}\\\",JS.global[:${n}])`),delete globalThis[n]}else{const n=this.run(e,`method(:${t})`);await n.call(t,e.wrap(r))}},transform:(e,t)=>t,writeFile:()=>{throw new Error(`writeFile is not supported in ${Xe}`)}};var tt={type:\\\"wasmoon\\\",module:(e=\\\"1.15.0\\\")=>`https://cdn.jsdelivr.net/npm/wasmoon@${e}/+esm`,async engine({LuaFactory:e,LuaLibraries:t},r){const{stderr:n,stdout:s,get:o}=Je(),a=await o((new e).createEngine());return a.global.getTable(t.Base,(e=>{a.global.setField(e,\\\"print\\\",s),a.global.setField(e,\\\"printErr\\\",n)})),r.fetch&&await Ue(this,a,r.fetch),a},registerJSModule:(e,t,r)=>{e.global.set(t,r)},run:(e,t,...r)=>{try{return e.doStringSync(Ee(t),...r)}catch(t){Be.get(e).stderr(t)}},runAsync:async(e,t,...r)=>{try{return await e.doString(Ee(t),...r)}catch(t){Be.get(e).stderr(t)}},runEvent:async(e,t,r)=>{const[n,...s]=t.split(\\\".\\\");let o,a=e.global.get(n);for(const e of s)[o,a]=[a,a[e]];try{await a.call(o,r)}catch(t){Be.get(e).stderr(t)}},transform:(e,t)=>t,writeFile:({cmodule:{module:{FS:e}}},t,r)=>((e,t,r)=>(Le(e,Ie(t)),t=He(e,t),e.writeFile(t,new Uint8Array(r),{canOwn:!0})))(e,t,r)};const rt=new Map,nt=new Map,st=new Proxy(new Map,{get(e,t){if(!e.has(t)){const[r,...n]=t.split(\\\"@\\\"),s=rt.get(r),o=/^https?:\\\\/\\\\//i.test(n)?n.join(\\\"@\\\"):s.module(...n);e.set(t,{url:o,module:import(o),engine:s.engine.bind(s)})}const{url:r,module:n,engine:s}=e.get(t);return(e,o)=>n.then((n=>{nt.set(t,e);const a=e?.fetch;return a&&Ne.set(a,o),s(n,e,r)}))}}),ot=e=>{for(const t of[].concat(e.type))rt.set(t,e)};for(const e of[Ge,Qe,et,tt])ot(e);const at=async e=>(await import(\\\"https://cdn.jsdelivr.net/npm/basic-toml@0.3.1/es.js\\\")).parse(e),it=(e,t,r={})=>{if(t){const[e,n]=(e=>{let t=typeof e;return\\\"string\\\"===t&&/\\\\.(json|toml|txt)$/.test(e)?t=RegExp.$1:e=\\\"./config.txt\\\",[_e(e),t]})(t);if(\\\"json\\\"===n)r=fetch(e).then(Re);else if(\\\"toml\\\"===n)r=fetch(e).then(We).then(at);else if(\\\"string\\\"===n)try{r=JSON.parse(t)}catch(e){r=at(t)}else\\\"object\\\"===n&&t&&(r=t);t=e}return Te(r).then((r=>st[e](r,t)))};try{new SharedArrayBuffer(4)}catch(e){throw new Error([\\\"Unable to use SharedArrayBuffer due insecure environment.\\\",\\\"Please read requirements in MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer#security_requirements\\\"].join(\\\"\\\\n\\\"))}let ct,lt,ut;const ft=(e,t)=>{addEventListener(e,t||(async t=>{try{await ct,lt(`xworker.on${e}`,t)}catch(e){postMessage(e)}}),!!t&&{once:!0})},{parse:pt,stringify:dt}=f,{proxy:gt,window:yt,isWindowProxy:wt}=ve(self,{parse:pt,stringify:dt,transform:e=>ut?ut(e):e}),ht={sync:gt,window:yt,isWindowProxy:wt,onmessage:console.info,onerror:console.error,onmessageerror:console.warn,postMessage:postMessage.bind(self)};ft(\\\"message\\\",(({data:{options:e,config:t,code:r,hooks:n}})=>{ct=(async()=>{try{const{id:s,tag:o,type:a,custom:i,version:c,config:l,async:u}=e,f=await it(((e,t=\\\"\\\")=>`${e}@${t}`.replace(/@$/,\\\"\\\"))(a,c),t,l),p=$e(rt.get(a)),d=\\\"run\\\"+(u?\\\"Async\\\":\\\"\\\");if(n){const{beforeRun:e,beforeRunAsync:t,afterRun:r,afterRunAsync:s}=n,o=r||s,a=e||t;if(o){const e=p[d].bind(p);p[d]=(t,r,...n)=>e(t,`${r}\\\\n${o}`,...n)}if(a){const e=p[d].bind(p);p[d]=(t,r,...n)=>e(t,`${a}\\\\n${r}`,...n)}}const{CustomEvent:g,document:y}=yt,w=s&&y.getElementById(s)||null;let h=\\\"\\\";return p.registerJSModule(f,\\\"polyscript\\\",{xworker:ht,get target(){return!h&&w&&(\\\"SCRIPT\\\"===o?w.after(Ae(y.createElement(`script-${i||a}`),{id:h=`${s}-target`})):(h=s,w.replaceChildren(),w.style.display=\\\"block\\\")),h}}),lt=p.runEvent.bind(p,f),ut=p.transform.bind(p,f),w&&Oe(w,i||a,!0,g),await p[d](f,r),f}catch(e){postMessage(e)}})(),ft(\\\"error\\\"),ft(\\\"message\\\"),ft(\\\"messageerror\\\")}));\\n\"],{type:'application/javascript'})),{type:'module'});","export const INVALID_CONTENT = 'Invalid content';\nexport const INVALID_SRC_ATTR = 'Invalid worker attribute';\nexport const INVALID_WORKER_ATTR = 'Invalid worker attribute';\n","import { INVALID_CONTENT, INVALID_SRC_ATTR, INVALID_WORKER_ATTR } from '../errors.js';\n\nimport { dedent } from '../utils.js';\n\nconst hasCommentsOnly = text => !text\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .replace(/^\\s*(?:\\/\\/|#).*/gm, '')\n .trim()\n;\n\n/* c8 ignore start */ // tested via integration\nexport default element => {\n const { src, worker } = element.attributes;\n if (worker) {\n let { value } = worker;\n // throw on worker values as ambiguous\n // @see https://github.com/pyscript/polyscript/issues/43\n if (value) throw new SyntaxError(INVALID_WORKER_ATTR);\n value = src?.value;\n if (!value) {\n // throw on empty src attributes\n if (src) throw new SyntaxError(INVALID_SRC_ATTR);\n if (!element.childElementCount)\n value = element.textContent;\n else {\n const { innerHTML, localName, type } = element;\n const name = type || localName.replace(/-script$/, '');\n console.warn(\n `Deprecated: use + + + diff --git a/test/integration/micropython.js b/test/integration/micropython.js index 77ddb43e..99cd61ff 100644 --- a/test/integration/micropython.js +++ b/test/integration/micropython.js @@ -7,6 +7,8 @@ module.exports = (playwright, baseURL) => { test('MicroPython bootstrap', python.bootstrap(playwright, baseURL)); + test('MicroPython custom hooks', python.customHooks(playwright, baseURL)); + test('MicroPython fetch', python.fetch(playwright, `${baseURL}/fetch.html`)); test('MicroPython to MicroPython Worker', shared.worker(playwright, `${baseURL}/worker.html`));