diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml deleted file mode 100644 index 5b8bad5..0000000 --- a/.github/workflows/node.js.yml +++ /dev/null @@ -1,26 +0,0 @@ -# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node -# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions - -name: build - -on: [push, pull_request] - -jobs: - build: - - runs-on: ubuntu-latest - - strategy: - matrix: - node-version: [20] - - steps: - - uses: actions/checkout@v2 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v2 - with: - node-version: ${{ matrix.node-version }} - cache: 'npm' - - run: npm ci - - run: npx playwright install chromium - - run: npm run build --if-present diff --git a/.gitignore b/.gitignore index 96ec6d8..f099858 100644 --- a/.gitignore +++ b/.gitignore @@ -1,20 +1,6 @@ .DS_Store .nyc_output +v8.log coverage/ node_modules/ -cjs/ -!cjs/package.json -es.js -!test/dist/es.js -!esm/es.js -server.js -!test/dist/server.js -!esm/server.js -structured.js -!test/dist/structured.js -!esm/structured.js -!test/dist/uhtml.js -!esm/uhtml.js -window.js -!test/dist/window.js -!esm/window.js +coincident-* diff --git a/.npmignore b/.npmignore index d715cbd..bcb0a7f 100644 --- a/.npmignore +++ b/.npmignore @@ -3,10 +3,8 @@ .eslintrc.json .github/ .travis.yml +v8.log +build/ coverage/ node_modules/ -rollup/ test/ -index.html -favicon.ico -tsconfig.json diff --git a/.npmrc b/.npmrc index cafe685..43c97e7 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1 @@ -package-lock=true +package-lock=false diff --git a/LICENSE b/LICENSE index 94c54df..cc22f15 100644 --- a/LICENSE +++ b/LICENSE @@ -1,15 +1,21 @@ -ISC License +MIT License -Copyright (c) 2023, Andrea Giammarchi, @WebReflection +Copyright © 2024-today, Andrea Giammarchi, @WebReflection -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the “Software”), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following conditions: -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. diff --git a/README.md b/README.md index 6bc778b..ffe2bee 100644 --- a/README.md +++ b/README.md @@ -1,362 +1,203 @@ # coincident -[![build](https://github.com/WebReflection/coincident/actions/workflows/node.js.yml/badge.svg)](https://github.com/WebReflection/coincident/actions/workflows/node.js.yml) - **Social Media Photo by [bady abbas](https://unsplash.com/@bady) on [Unsplash](https://unsplash.com/)** An [Atomics](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics) based [Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) to simplify, and synchronize, [Worker](https://developer.mozilla.org/en-US/docs/Web/API/Worker) related tasks. -#### Example - -```html - - - - - - - - -``` - -```js -// worker.js -import coincident from 'https://unpkg.com/coincident'; - -console.log('asking for an input'); -// pauses in a non blocking way the worker until the answer has been received -console.log('input', coincident(self).input('what is 1 + 2 ?')); -console.log('input received'); -``` - ## API -The module exports a utility/helper able to *Proxy* once a generic *worker* or *globalThis* / *self* context, adding an unobtrusive listener, providing orchestration out of the box for bootstrapped *workers* that use such module. - -#### Worker -> Main - -```js -import coincident from 'coincident'; -// or const coincident = require('coincident'); - -// on the main thread -const worker = new Worker('./any-worker.js'); -coincident(worker).enabler = async (...args) => { - // do something sync or async with received args - return {some: 'value'}; -}; - -// on the worker side -const result = coincident(self).enabler('one', {or_more: 'args'}); -console.log(result); -// {some: 'value'} -``` - -The second optional argument of the `coincident(context[, JSON])` helper can be any *JSON* like namespace able to `parse` and `stringify` data, such as [flatted](https://www.npmjs.com/package/flatted) or [@ungap/structured-clone/json](https://github.com/ungap/structured-clone/#tojson) (or use `coincident/structured`). - -Additionally, it can contain a `transform` callback that will be used to change arguments into something else via `(value: any) => any` operation per each of them. - -Moreover, it can also contain an `interrupt` callback or object that will be used to check some internal state while waiting synchronously from a worker (it's not used when main invokes a worker, it's only used when workers invokes and wait-block itself for main). +Following the description of all different imports to use either on the *main* or the *worker* thread. -**Additionally**, the exported function has a `coincident.tranfer(...buffers)` helper that if used as last argument of any worker demanded task will transfer buffers instead of cloning/copying these. +### coincident/main -on top of that, the `setInterruptHandler(callback)` field allows any foreign code to periodically check on awaited main tasks, from a *worker*. - -#### Main -> Worker - -This module can also communicate from a *main* thread to a *worker*, but in this case the *main* thread needs to `await` for results because [Atomics.wait() cannot be used in main](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics/wait). - -```html - -``` +This is the *import* that provides the ability to expose *main* thread's callbacks to the *worker* thread and to also await callbacks exposed via the *worker* code. ```js -// worker.js -import coincident from 'coincident'; +import coincident from 'coincident/main'; -// expose a specific function to the main thread -coincident(self).compute = (a, b) => (a + b); +const { + // the Worker to be used (this extends the global one) + Worker, + // a boolean indicating if sabayon is being used + polyfill, + // a utility to transfer values directly via `postMessage` + // (...args: Transferable[]) => Transferable[] + transfer, +} = coincident({ + // a utility to parse text, default: JSON.parse + parse: JSON.parse, + // a utility to stringify values, default: JSON.stringify + stringify: JSON.stringify, + // an optional utility to transform values (FFI / Proxy related) + transform: value => value, +}); ``` +#### coincident/main - Worker class -### coincident/structured - -This entry point exports the exact same module except it uses [@ungap/structured-clone/json](https://github.com/ungap/structured-clone/#tojson) `parse` and `stringify` functions, allowing more complex, or recursive, objects to be passed along as result to, or from, the *worker*. +The `Worker` class returned by `coincident()` has these features: -Please keep in mind not all complex types are supported by the polyfill but also any other export could use this version with ease: + * it always starts a *Worker* as `{ type: "module" }` ( mostly because the worker needs to `await coincident()` on bootstrap ) + * it optionally accepts a `{ serviceWorker: "../sw.js" }` to help *sabayon* falling back to synchronous behavior, which is mandatory to use any *DOM* or `window` related functionality + * it provides to each instance a `proxy` reference where utilities, as *callbacks*, can be assigned or asynchronously awaited if exposed within *worker*'s code ```js -import * as JSON from '@ungap/structured-clone/json'; -import coincident from 'coincident/uhtml'; +const { proxy } = new Worker('./worker.js'); -// bootstrap in both main / workers like this -const {proxy, window, isWindowProxy} = coincident(self, JSON); +// can be invoked from the worker +proxy.location = () => location.href; -// that's it: structured-clone enabled for responses! +// exposed via worker code +await proxy.compute(); ``` +### coincident/worker -### coincident/window - -This entry point exports the same `coincident` module (using *JSON* as default) **but** the utility returns an obejct with 3 fields: - - * **proxy** it's the usual proxy utility to expose or invoke functions defined in the main counter-part. - * **window** it's the proxy that orchestrates access to the *main* world in *Workers*, including the ability to pass callbacks from the *Worker*, with the only caveat these will be inevitably executed asynchronously on the main thread, so that *Promise* or *thenable* work out of the box but *accessors* or defined callbacks will need to be awaited from the worker too. DOM listeners should be also handled with no issues but the `event` can't *preventDefault* or *stopPropagation* as the listener will be asynchronous too. All well known *Symbol* also cross boundaries so that `[...window.document.querySelectorAll('*')]` or any other *Symbol* based functionality should be preserved, as long as the `symbol` is known as runtime symbols can't cross paths in any meaningful way. In the *main* thread, this is just a reference to the `globalThis` object. - * **isWindowProxy** is an utility that helps introspecting window proxies, callbacks, classes, or main thread references in general. This returns always `false` in the *main* thread. - -While the initial utility/behavior is preserved on both sides via `proxy`, the *Worker* can seamlessly use `window` utility to operate on *DOM*, *localStorage*, or literally anything else, included *Promise* based operations, DOM listeners, and so on. - - -```html - - -``` +This is the *import* that provides the ability to expose *worker* thread's callbacks to the *main* thread and to also directly invoke callbacks exposed via the *main* proxied reference. ```js -// The worker.js !!! -import coincident from 'coincident/window'; - -const {proxy, window, isWindowProxy} = coincident(self); -// the proxy can expose or answer to main proxy counter part +import coincident from 'coincident/worker'; -// ... but here is the fun part ... -const {document} = window; -document.body.innerHTML = '

Hello World!

'; +const { + // the counter-part of the main worker.proxy reference + proxy, + // a boolean indicating if sabayon is being used + polyfill, + // a boolean indicating if it's possible to do synchronous operations + sync, + // a utility to transfer values directly via `postMessage` + // (...args: Transferable[]) => Transferable[] + transfer, +} = await coincident({ + // a utility to parse text, default: JSON.parse + parse: JSON.parse, + // a utility to stringify values, default: JSON.stringify + stringify: JSON.stringify, + // an optional utility to transform values (FFI / Proxy related) + transform: value => value, + // an optional interrupt reference that is used via `Atomic.wait(sb)` + interrupt: { handler() {}, timeout: 42 }, +}); -document.body.appendChild( - document.createElement('div') -).textContent = '😱'; +// exposed to the main thread +proxy.compute = async () => { + // super expensive task ... + return 'result'; +}; -const scoped = true; -document.body.addEventListener('click', event => { - console.log(event.type, 'running in a worker', scoped); -}); +// consumed from the main thread +// synchronous if COI is enabled or +// the Service Worker was passed +console.log(proxy.location()); ``` -See the [test/window.js](./test/window.js) file, try it [live](https://webreflection.github.io/coincident/test/window.html) or reach `http://localhost:8080/test/window.html` locally to play around this feature. +### coincident/window/main -#### Extra features - -Beside providing some handy utility, the `window` (and other exports such as `uhtml`) allows *Workers*' listeners to synchronously invoke methods on the **event** on the main thread, before the proxied worker function gets a chance to get executed (remember, functions form the *worker* are inevitably async when executed from *main*). +When the *worker* code expects the *main* `window` reference, this import is needed to allow just that. ```js -document.body.addEventListener( - 'click', - event => console.log(event.type), - {invoke: ['preventDefault', 'stopImmediatePropagation']} -); -``` - -When options are passed, be sure these contains [all the details you need](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#parameters) *plus* an `invoke` *string* or array of strings. - +import coincident from 'coincident/window/main'; +// ^^^^^^ -### coincident/uhtml +const { Worker, polyfill, transfer } = coincident(); +``` -This export includes [uhtml](https://github.com/WebReflection/uhtml#readme) to fully drive reactive UI from a Worker. +The signature, on the *main* thread, is identical. -The `uhtml` field is added to the returned object after `coincident(self)` call. +### coincident/window/worker -```html - - -``` +On the *worker* side, this import is also identical to the non-window variant but it's returned namespace, after bootstrap, contains two extra utilities: ```js -// The worker.js !!! -import coincident from 'coincident/window'; +import coincident from 'coincident/window/worker'; +// ^^^^^^ -const {proxy, window, uhtml} = coincident(self); - -// uhtml directly from the thread -const {render, html} = uhtml; +const { + proxy, polyfill, sync, transfer, + // it's a synchronous, Atomic.wait based, Proxy + // to the actual globalThis reference on the main + window, + // it's an introspection helper that returns `true` + // only when a reference points at the main thread + // (value: any) => boolean + isWindowProxy, +} = await coincident(); -const {document} = window; +// direct synchronous access to the main `window` +console.log(window.location.href); -render(document.body, html` -

Hello uhtml!

-`); +window.document.body.textContent = 'Hello World 👋'; ``` -See [test/uhtml.js](./test/uhtml.js) page, try it [live](https://webreflection.github.io/coincident/test/uhtml.html), or test it locally via `http://localhost:8080/test/uhtml.html` after `npm run server`. +#### A note about performance +Every single property retrieved via the `window` reference is a whole *worker* ↔ *main* roundtrip and this is inevitable. There is no "*smart caching*" ability backed in the project, because everytrhing could be suddenly different at any point in time due side effects that both the worker, or the main thread, could have around previously retrieved references. -### coincident/server +Especially when *SharedArrayBuffer* is polyfilled, and the `serviceWorker` provided as option, an average *PC* would perform up to ~1000 roundtrips per second. That seems like a lot but operations can easily pile up and make the program feel unnecessary slower than it could be (if run on the *main* thread directly, as comparison). -⚠️ **WARNING - THIS EXPORT SHOULD NOT BE PUBLICLY AVAILABLE** +When native *SharedArrayBuffer* is enabled though, an average *PC* would be able to do ~50000 (50x) roundtrips per second .... and yet that could also easily degrade with more complex logic involved. -This export, automatically based on `structured` export to allow passing more complex data around, allows a *Worker* to drive not just the *main* thread (UI/DOM/global page namespace) but also a *server* such as *NodeJS* or *Bun* (both successfully tested) and likely more, as long as a *WebSocketServer* like reference is passed along while creating the connection. - - -**HTML example** - see [test/server/index.html](./test/server/index.html) -```html - - - - - - - - - -``` +An easy way to prevent repeated roundtrips, when we already assume a reference will not change by any mean over time, we can take over that "*smart caching*" explicit operation: -**Worker example** - see [test/server/worker.js](./test/server/worker.js) ```js -import coincident from 'coincident/server'; +const { window } = await coincident(); -const { - proxy, // the main thread (UI/DOM) proxy - window, // the window reference - isWindowProxy, // the window introspection helper - server, // the server reference - isServerProxy, // the server introspection helper -} = coincident(self); - -// deal directly with the server modules out of the box -const os = server.require('os'); - -// deal directly with the main UI/DOM thread out of the box -window.document.body.innerHTML = ` -

coincident/server

-

Platform Info

- -`; +const { document } = window; +const { head, body } = document; +// any time we need to change the content +body.textContent = 'Hello World 👋'; ``` -**NodeJS / Bun example** - see [test/server/main.cjs](./test/server/main.cjs) -```js -const {createServer} = require('http'); -const {join} = require('path'); -const {WebSocketServer} = require('ws'); - -// static file server utility + headers for SharedArrayBuffer -const staticHandler = require('static-handler'); -const handler = staticHandler(join(__dirname, '..', '..'), { - 'Access-Control-Allow-Origin': '*', - 'Cross-Origin-Opener-Policy': 'same-origin', - 'Cross-Origin-Embedder-Policy': 'require-corp', - 'Cross-Origin-Resource-Policy': 'cross-origin' -}); +Please note that because those references won't likely ever change on the *main* thread, there are also no *memory leaks* hazard, and that's true with every other reference that might live forefer on the *main* thread. -const server = createServer(handler); +- - - -// require the coincident export -const coincident = require('coincident/server'); +### About 💀🔒 Deadlock Message -// pass along the wss to instrument with listeners -// and a list of globals utilities to make available -// whenever the Worker tries to reach these -coincident(new WebSocketServer({server}), {require}); +This module allows different worlds to expose utilities that can be invoked elsewhere and there are two ways this can work: -// bootstrap the server and that's it! -server.listen(8080, () => { - console.log(`http://localhost:8080/test/server/`); -}); -``` + * `Atomics.wait` is usable, from a *worker*, and it will be preferred over `Atomics.waitAsync` for the simple reason that it unlocks much more than trivial *async* exchanges between the two worlds. In this case, if the worker is invoking a foreign exposed utility, it will be fully unresponsive until that utility returned a value and there's no possible workaround. When this happens, the module understands that the requested utility comes from a *worker* that is paused until such invoke returns, and if this invoke relies on a *synchronous* *worker* utility there won't be any chance to complete that request: the *worker* is stuck and the *main* can't use it until is not stuck anymore. In this case, an error is thrown with details around which *worker* utility was invoked while the *main* utility was executing, and the program won't just block itself forever. This is the most meaningful and reasonable deadlock case to `throw` errors unconditionally ... but ... + * if this module runs without `Atomics.wait` ability, meaning no *COI* headers are enabled and no `serviceWorker` fallback has been used, it is possible for a *main* exported utility to query a *worker* exported utility one once executed, assuming there is no recursion in doing so (i.e. the *worker* calls `main()` that internally calls `worker()` which in turns calls `main()` again). These cases are rather infinite loops/recursions than deadlocks but if you are sure your *main* utility is invoking something in the *worker* that won't cause such infinite recursion, no *deadlock* error would be shown, as that would not be the case, strictly speaking, but also recursions won't be tracked so ... be careful with your logic! -The main goal of this export is **IoT** related projects, *KIOSK* like project, *Electron* like project, *Tauri* integration, and so on ... there's the possibility to fully orchestrate from a worker listeners on the page that result into *Server* operations and so on and so forth, so please be aware while this is an **achievement unlocked** from my side, it's also potentially dangerous if used in any open space where evil attackers can try to operate Server side operations on "*your*" behalf, as if it was the *Worker* itself asking for such operations. +As rule of thumb, do not ever invoke other world utilities while one of your exported utility is executing, so that code will be guaranteed to work in both `Atomics.wait` and `Atomics.waitAsync` scenarios without ever worrying about future deadlock, once all headers are available or the `serviceWorker` helper will be used. -That being said, in Apps where no foreign code is allowed, this export unlocks an infinite amount of potentials for any sort of project. +It is, however, always possible to execute foreign utilities on the next tick, micro-task, timeout, idle state or listener, so that if a *main* exposed utility needs to invoke a *worker* utility right after, there are ways to do that. -Alternatively, please consider strict *CSP* rules to be sure no code evaluation can arrive from a console, from foreign injected files, from users' input, and so on. +### About SharedArrayBuffer -Thanks for trying this feature out as no other projects (to date) can do in a cross platform, cross browser, cross environment way what this module currently offer. +Unfortunately not enabled by default on the Web, the *SharedArrayBuffer* primitive requires either special *headers* permissions to be trusted or a *polyfill* that can always enable the *async* abilities of the *Atomics* specifications and eventually grant the *sync* abilities too, as long as a *ServiceWorker* able to handle those requests is installed. -### Local Only +This primitive is needed to enable notifications about data cross realms, notifications that are expected to be *sync*, in the best case scenario, or *async* as least possible fallback. -If worried about possible foreign scripts doing weird things it is possible to use these headers instead so that only local files would be able to execute any content. +#### Enable both sync & async SharedArrayBuffer features -```js -{ - 'Cross-Origin-Opener-Policy': 'same-origin', - 'Cross-Origin-Embedder-Policy': 'require-corp', - 'Cross-Origin-Resource-Policy': 'same-origin' -} -``` +This is the preferred way to use this module or any module depending on it, meaning all headers to enable *SAB* are in place. To do so: -### coincident/bun + * be sure your server is providing those headers as explained in *MDN* + * bootstrap a local server that provides such headers for local tests: `npx mini-coi ./` is all you need to enable these headers locally, but the utility doesn't do much more than serving files with those headers enabled + * use `` on top of your `` node in your *HTML* templates to use automatically a *ServiceWorker* that force-enable those headers for any request made frm any client. This woks on *GitHub* pages too, and every other static files handler for local projects + * use the *ServiceWorker* logic enabled out of the box by passing the file `npx sabayon ./public/sw.js` to *Worker* constructors, so that such *SW* can be used to polyfill the *sync* case + * provide your own *ServiceWorker* file whenever a *Worker* is created, out of the `{ serviceWorker: '../sw.js' }` extra option, as long as it imports utilities from [sabayon](https://github.com/WebReflection/sabayon#readme), as explained in its [ServiceWorker related details](https://github.com/WebReflection/sabayon?tab=readme-ov-file#service-worker) -Same as *coincident/server* except it's 100% based on *Bun* primitives (*websocket*): +The latter 2 points will inevitably fallback to a *polyfilled* version of the native possible performance but it should be *god enough* to enable your logic around *workers* invoking, or reaching, synchronous *main* thread related tasks. -```js -import { serve, file } from 'bun'; -import coincidentWS from 'coincident/bun'; - -const port = 8080; -const headers = { - 'Cross-Origin-Opener-Policy': 'same-origin', - 'Cross-Origin-Embedder-Policy': 'require-corp', - 'Cross-Origin-Resource-Policy': 'same-origin' -}; +#### Enable only async SharedArrayBuffer features -serve({ - port, - fetch(req, server) { - // upgrade sockets if possible - if (server.upgrade(req)) return; - // do anything else you'd do with Bun - let path = '.' + new URL(req.url).pathname; - if (path.endsWith('/')) path += 'index.html'; - return new Response(file(path), {headers}); - }, - // create automatically the websocket utility - websocket: coincidentWS({import: name => import(name)}), -}); +This module by default does fallback to a *SAB* polyfill, meaning *async* notification of any buffer are still granted to be executed or succeed, thanks to [sabayon](https://github.com/WebReflection/sabayon#readme) underlying module. -console.log(`http://localhost:${port}/test/server/`); -``` +This scenario is **ideal** when: -### A quick way to test SharedArrayBuffer + * no special headers are allowed in your project + * no *Serviceworker* is allowed in your project + * you only need to *await* *asynchronous* utilities from a *Worker*, never the other way around + * you never need to reach, or execute, code on the *main* thread, from a *worker* -If you would like to just test locally *SharedArrayBuffer* you can also use [mini-coi](https://github.com/WebReflection/mini-coi#readme), now enriched with a *CLI* that bootstraps locally in a snap: +As long as these enabled use cases are clear, here the caveats: -```sh -npx mini-coi . + * your *worker* can't ever reach directly anything coming from the *main* thread + * your *worker* doesn't ever receive a *main* thread reference as an argument -# or even ... -bunx mini-coi . -``` +If all of this is clear, it's possible to use *coincident* module as bridge between *worker* exported features / utilities consumed asynchronously by the *main* thread any time it needs to. -If you would like to bring *SharedArrayBuffer* to your GitHub pages or any other hosting space where you can't configure headers, you can use the *Service Worker* approach currently tested to work already here and elsewhere. - -To copy the **script** that must be used on the page locally as Service Worker, you can also use *mini-coi*: - -```sh -# put mini-coi.js into ./public/mini-coi.js -npx mini-coi -sw ./public/ -``` +This still unlocks tons of use cases out there, but it's definitively a constrained and limited experience. diff --git a/build/constants.cjs b/build/constants.cjs new file mode 100644 index 0000000..01707c5 --- /dev/null +++ b/build/constants.cjs @@ -0,0 +1,18 @@ +const { join } = require('path'); +const { readFileSync, writeFileSync } = require('fs'); +const { randomUUID } = require('crypto'); + +const CHANNEL = join(__dirname, '..', 'src', 'window', 'constants.js'); + +writeFileSync( + CHANNEL, + readFileSync(CHANNEL).toString().replace( + /const CHANNEL = (['"]).*?\1;/, + `const CHANNEL = $1${randomUUID()}$1;` + ) +); + +writeFileSync( + join(__dirname, '..', 'src', 'debug.js'), + `export default ${!!process.env.DEBUG};\n` +); diff --git a/build/dist.js b/build/dist.js new file mode 100644 index 0000000..3c4e529 --- /dev/null +++ b/build/dist.js @@ -0,0 +1,39 @@ +import {nodeResolve} from '@rollup/plugin-node-resolve'; +import terser from '@rollup/plugin-terser'; + +const plugins = [nodeResolve()].concat(process.env.NO_MIN ? [] : [terser()]); + +export default [ + { + plugins, + input: './src/main.js', + output: { + esModule: true, + file: './dist/main.js', + } + }, + { + plugins, + input: './src/worker.js', + output: { + esModule: true, + file: './dist/worker.js', + } + }, + { + plugins, + input: './src/window/main.js', + output: { + esModule: true, + file: './dist/window/main.js', + } + }, + { + plugins, + input: './src/window/worker.js', + output: { + esModule: true, + file: './dist/window/worker.js', + } + }, +]; diff --git a/build/index.cjs b/build/index.cjs new file mode 100644 index 0000000..bea1e75 --- /dev/null +++ b/build/index.cjs @@ -0,0 +1,43 @@ +const { existsSync, readdirSync, writeFileSync } = require('fs'); +const { join } = require('path'); + +const TEST = join(__dirname, '..', 'test'); +const list = []; + +for (const file of readdirSync(TEST)) { + try { + if (existsSync(join(TEST, file, 'index.html'))) + list.push(`${file}`); + } + catch (_) {} +} + +writeFileSync( + join(__dirname, '..', 'index.html'), + ` + + + Coincident Tests + + + + + \n`.replace(/^ /gm, '') +); + +writeFileSync( + join(__dirname, '..', 'test', 'index.html'), + ` + + + Coincident Tests + + + + + \n`.replace(/^ /gm, '') +); diff --git a/cjs/package.json b/cjs/package.json deleted file mode 100644 index 0292b99..0000000 --- a/cjs/package.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"commonjs"} \ No newline at end of file diff --git a/dist/main.js b/dist/main.js new file mode 100644 index 0000000..11dd116 --- /dev/null +++ b/dist/main.js @@ -0,0 +1 @@ +const{ArrayBuffer:e,Atomics:t,Promise:s}=globalThis,{isArray:r}=Array,{create:n,getPrototypeOf:a,values:o}=Object,c=a(Int32Array),i=n(t),l=()=>s.withResolvers();let p=0;const f=new Map,u=(e,t)=>class extends e{constructor(e,...s){super(e,...s),e instanceof t&&f.set(this,[p++,0,l()])}},g=new WeakSet,d=e=>(g.add(e),e),y=(e,t)=>{const{data:s}=e,n=r(s)&&(s.at(0)===t||0===s.at(1)&&!t);return n&&(e.stopImmediatePropagation(),e.preventDefault()),n},h=e=>null!==e&&"object"==typeof e&&!g.has(e),w=new WeakMap,v=(t,s,r)=>{if(f.has(t))s.set(t,f.get(t)[0]);else if(!(t instanceof c||t instanceof e))for(const e of o(t))h(e)&&!r.has(e)&&(r.add(e),v(e,s,r))},m=(...e)=>({value:new s((t=>{let s=new Worker("data:application/javascript,onmessage%3De%3D%3EpostMessage(!Atomics.wait(...e.data))");s.onmessage=()=>t("ok"),s.postMessage(e)}))}),M=(e,t,s)=>{for(const[s,r]of t)w.set(s,[r,e.currentTarget]);(({currentTarget:e,type:t,origin:s,lastEventId:r,source:n,ports:a},o)=>{e.dispatchEvent(new MessageEvent(t,{data:o,origin:s,lastEventId:r,source:n,ports:a}))})(e,s)};let{BigInt64Array:A,Int32Array:E,SharedArrayBuffer:k,Worker:x}=globalThis,T=e=>e,b=!1;const I=e=>({...e,type:"module"});try{new k(4),x=class extends x{constructor(e,t){super(e,I(t))}},i.waitAsync||(i.waitAsync=m)}catch(t){const s=crypto.randomUUID(),r=new Map,n=(e,t,s,...r)=>{e.addEventListener(t,s,...r)},a=({serviceWorker:e},t,a)=>{let o;n(e,"message",(e=>{if(y(e,s)){const[t,n,a]=e.data,c=[n,a].join(","),i=e=>{r.delete(c),o.postMessage([s,n,a,e])},p=r.get(c);if(p)i(p);else{const{promise:e,resolve:t}=l();r.set(c,t),e.then(i)}}})),e.getRegistration(t).then((s=>s??e.register(t))).then((function e(t){o=t.installing||t.waiting||t.active,"activated"===o.state?a():n(o,"statechange",(()=>e(t)),{once:!0})}))};T=d,b=!0,i.notify=(e,t)=>{const[n,a]=(e=>w.get(e))(e),o=[n,t].join(","),c=r.get(o);return c?c(e):r.set(o,e),a.postMessage([s,1,e,n,t]),0},i.waitAsync=(e,...t)=>{const[s,r]=((e,t)=>{const s=f.get(e),[r,n,{promise:a}]=s;return s[1]=t,[r,a]})(e,...t);return{value:r}},k=class extends e{},A=u(A,k),E=u(E,k);let o=null;x=class extends x{constructor(e,t){let r=t?.serviceWorker||"";if(r){if(r=new URL(r,location.href).href,t={...t,serviceWorker:r},!o){const{promise:e,resolve:t}=l();a(navigator,r,t),o=e}o.then((()=>super.postMessage([s,3])))}super(e,I(t)),super.postMessage([s,0,t]),n(this,"message",(e=>{if(y(e,s)){const[t,s,...r]=e.data;switch(s){case 1:((e,t,s)=>{for(const[r,[n,a,{resolve:o}]]of f)if(t===n&&s===a){for(let t=0;t{const s=new Map;return h(t)&&v(t,s,new Set),s.size?[e,2,s,t]:t})(s,e),...t)}}}const{BYTES_PER_ELEMENT:U}=Int32Array,{BYTES_PER_ELEMENT:W}=Uint16Array,{notify:S}=i,D=new TextDecoder("utf-16"),P=new WeakSet,j=(...e)=>(P.add(e),e);let B="";let L=0;const R=([e,t,s,r,n,a,o,c,i],l)=>(...p)=>{let f=""!==B,u=0;f&&(u=((e,t)=>setTimeout(console.warn,1e3,`💀🔒 - proxy.${e}() in proxy.${t}()`))(l,B));const g=L++,d=[];P.has(p.at(-1)||d)&&P.delete(d=p.pop());const y=s(c?p.map(c):p);let h=t(2*U);return o([e,2,l,g,h,y,r],{transfer:d}),i(h,0).value.then((()=>{f&&clearTimeout(u);const s=h[1];if(!s)return;const r=W*s;return h=t(r+r%U),o([e,1,g,h]),i(h,0).value.then((()=>{const e=new Uint16Array(h.buffer),t=a?e.subarray(0,s):e.slice(0,s);return n(D.decode(t))}))}))};var _=({parse:e,stringify:t,transform:s}=JSON)=>{const r=((e,t)=>async(s,r,[n,a,o,c,i])=>{i&&(B=n);try{const n=await s(...c);if(void 0!==n){const s=e(t?t(n):n);r.set(a,s),o[1]=s.length}}finally{i&&(B=""),o[0]=1,S(o,0)}})(t,s),n=crypto.randomUUID();return{Worker:class extends x{constructor(t,a){const o=new Map,c=new Map;super(t,a),this.proxy=((e,t)=>new Proxy(t,{get:(t,s)=>{let r;return"then"!==s&&(r=t.get(s),r||(r=R(e,s),t.set(s,r))),r},set:(e,t,s)=>"then"!==t&&!!e.set(t,s)}))([n,e=>new E(new k(e)),T,!1,e,b,(...e)=>this.postMessage(...e),s,i.waitAsync],o),this.postMessage(T([n,0,a])),this.addEventListener("message",(e=>{if(y(e,n)){const[t,s,...n]=e.data;switch(s){case 2:((e,t,s,r)=>{const[n]=r,a=s.get(n);if(!a)throw new Error(`Unknown proxy.${n}()`);e(a,t,r)})(r,c,o,n);break;case 1:((e,[t,s])=>{const r=e.get(t);e.delete(t);for(let e=new Uint16Array(s.buffer),t=0,{length:n}=r;tu.get(e),p=e=>{if(!l.has(e)){let t;for(;u.has(t=i++););l.set(e,t),u.set(t,e)}return l.get(e)},{ArrayBuffer:g,Atomics:d,Promise:y}=globalThis,{isArray:h}=Array,{create:w,getPrototypeOf:v,values:m}=Object,b=v(Int32Array),M=w(d),k=()=>y.withResolvers();let E=0;const A=new Map,T=(e,t)=>class extends e{constructor(e,...r){super(e,...r),e instanceof t&&A.set(this,[E++,0,k()])}},x=new WeakSet,W=e=>(x.add(e),e),S=(e,t)=>{const{data:r}=e,s=h(r)&&(r.at(0)===t||0===r.at(1)&&!t);return s&&(e.stopImmediatePropagation(),e.preventDefault()),s},P=e=>null!==e&&"object"==typeof e&&!x.has(e),R=new WeakMap,I=(e,t,r)=>{if(A.has(e))t.set(e,A.get(e)[0]);else if(!(e instanceof b||e instanceof g))for(const s of m(e))P(s)&&!r.has(s)&&(r.add(s),I(s,t,r))},U=(...e)=>({value:new y((t=>{let r=new Worker("data:application/javascript,onmessage%3De%3D%3EpostMessage(!Atomics.wait(...e.data))");r.onmessage=()=>t("ok"),r.postMessage(e)}))}),j=(e,t,r)=>{for(const[r,s]of t)R.set(r,[s,e.currentTarget]);(({currentTarget:e,type:t,origin:r,lastEventId:s,source:n,ports:a},o)=>{e.dispatchEvent(new MessageEvent(t,{data:o,origin:r,lastEventId:s,source:n,ports:a}))})(e,r)};let{BigInt64Array:D,Int32Array:L,SharedArrayBuffer:O,Worker:B}=globalThis,$=e=>e,_=!1;const N=e=>({...e,type:"module"});try{new O(4),B=class extends B{constructor(e,t){super(e,N(t))}},M.waitAsync||(M.waitAsync=U)}catch(e){const t=crypto.randomUUID(),r=new Map,s=(e,t,r,...s)=>{e.addEventListener(t,r,...s)},n=({serviceWorker:e},n,a)=>{let o;s(e,"message",(e=>{if(S(e,t)){const[s,n,a]=e.data,c=[n,a].join(","),i=e=>{r.delete(c),o.postMessage([t,n,a,e])},l=r.get(c);if(l)i(l);else{const{promise:e,resolve:t}=k();r.set(c,t),e.then(i)}}})),e.getRegistration(n).then((t=>t??e.register(n))).then((function e(t){o=t.installing||t.waiting||t.active,"activated"===o.state?a():s(o,"statechange",(()=>e(t)),{once:!0})}))};$=W,_=!0,M.notify=(e,s)=>{const[n,a]=(e=>R.get(e))(e),o=[n,s].join(","),c=r.get(o);return c?c(e):r.set(o,e),a.postMessage([t,1,e,n,s]),0},M.waitAsync=(e,...t)=>{const[r,s]=((e,t)=>{const r=A.get(e),[s,n,{promise:a}]=r;return r[1]=t,[s,a]})(e,...t);return{value:s}},O=class extends g{},D=T(D,O),L=T(L,O);let a=null;B=class extends B{constructor(e,r){let o=r?.serviceWorker||"";if(o){if(o=new URL(o,location.href).href,r={...r,serviceWorker:o},!a){const{promise:e,resolve:t}=k();n(navigator,o,t),a=e}a.then((()=>super.postMessage([t,3])))}super(e,N(r)),super.postMessage([t,0,r]),s(this,"message",(e=>{if(S(e,t)){const[t,r,...s]=e.data;switch(r){case 1:((e,t,r)=>{for(const[s,[n,a,{resolve:o}]]of A)if(t===n&&r===a){for(let t=0;t{const r=new Map;return P(t)&&I(t,r,new Set),r.size?[e,2,r,t]:t})(t,e),...r)}}}const{BYTES_PER_ELEMENT:z}=Int32Array,{BYTES_PER_ELEMENT:F}=Uint16Array,{notify:Y}=M,C=new TextDecoder("utf-16"),H=new WeakSet,J=(...e)=>(H.add(e),e);let K="";let q=0;const G=([e,t,r,s,n,a,o,c,i],l)=>(...u)=>{let f=""!==K,p=0;f&&(p=((e,t)=>setTimeout(console.warn,1e3,`💀🔒 - proxy.${e}() in proxy.${t}()`))(l,K));const g=q++,d=[];H.has(u.at(-1)||d)&&H.delete(d=u.pop());const y=r(c?u.map(c):u);let h=t(2*z);return o([e,2,l,g,h,y,s],{transfer:d}),i(h,0).value.then((()=>{f&&clearTimeout(p);const r=h[1];if(!r)return;const s=F*r;return h=t(s+s%z),o([e,1,g,h]),i(h,0).value.then((()=>{const e=new Uint16Array(h.buffer),t=a?e.subarray(0,r):e.slice(0,r);return n(C.decode(t))}))}))};var Q=({parse:e,stringify:t,transform:r}=JSON)=>{const s=((e,t)=>async(r,s,[n,a,o,c,i])=>{i&&(K=n);try{const n=await r(...c);if(void 0!==n){const r=e(t?t(n):n);s.set(a,r),o[1]=r.length}}finally{i&&(K=""),o[0]=1,Y(o,0)}})(t,r),n=crypto.randomUUID();return{Worker:class extends B{constructor(t,a){const o=new Map,c=new Map;super(t,a),this.proxy=((e,t)=>new Proxy(t,{get:(t,r)=>{let s;return"then"!==r&&(s=t.get(r),s||(s=G(e,r),t.set(r,s))),s},set:(e,t,r)=>"then"!==t&&!!e.set(t,r)}))([n,e=>new L(new O(e)),$,!1,e,_,(...e)=>this.postMessage(...e),r,M.waitAsync],o),this.postMessage($([n,0,a])),this.addEventListener("message",(e=>{if(S(e,n)){const[t,r,...n]=e.data;switch(r){case 2:((e,t,r,s)=>{const[n]=s,a=r.get(n);if(!a)throw new Error(`Unknown proxy.${n}()`);e(a,t,s)})(s,c,o,n);break;case 1:((e,[t,r])=>{const s=e.get(t);e.delete(t);for(let e=new Uint16Array(r.buffer),t=0,{length:n}=s;t[e,t])));const X="ownKeys",Z="destruct",{[X]:ee}=Reflect,te=new Map(ee(Symbol).filter((e=>typeof Symbol[e]===o)).map((e=>[Symbol[e],e]))),re=e=>te.get(e)||`.${Symbol.keyFor(e)||""}`,se="8d26f914-addd-4e13-a753-010b90b835f2",ne="M"+se,ae="W"+se,oe=new FinalizationRegistry((([e,t,r])=>{r&&console.debug(`Held value ${String(t)} not relevant anymore`),e(t)})),ce=Object.create(null),{addEventListener:ie}=EventTarget.prototype,le=new WeakMap;Reflect.defineProperty(EventTarget.prototype,"addEventListener",{value(e,t,...r){const s=r.at(0)?.invoke;if(s){let t=le.get(this);t||(t=new Map,le.set(this,t)),t.set(e,[].concat(s)),delete r[0].invoke}return ie.call(this,e,t,...r)}});const{isArray:ue}=Array;var fe=i=>{const g=Q(i),d=s=>{const a=typeof s;switch(a){case n:return null===s?[V[r],s]:s===globalThis?[V[n],null]:ue(s)?[V[e],p(s)]:[V[n],s instanceof b?s:p(s)];case t:return[V[t],p(s)];case o:return[V[o],re(s)];default:return[V[a],s]}};class y extends g.Worker{constructor(r,i){const{proxy:p}=super(r,i),{[ae]:g}=p,y=new Map,h=e=>{y.delete(e),g(Z,e)},w=([r,c])=>{switch(r){case V[n]:if(null===c)return globalThis;if(typeof c===s)return f(c);if(!(c instanceof b))for(const e in c)c[e]=w(c[e]);return c;case V[e]:return typeof c===s?f(c):c.map(w);case V[t]:switch(typeof c){case s:return f(c);case a:{let e=y.get(c)?.deref();return e||(e=((e,t,{debug:r,handler:s,return:n,token:a=e}=ce)=>{const o=n||new Proxy(e,s||ce),c=[o,[t,e,!!r]];return!1!==a&&c.push(a),oe.register(...c),o})(c,h,{token:!1,return:function(...e){return e.length&&e[0]instanceof Event&&(e=>{const{currentTarget:t,target:r,type:s}=e,n=le.get(t||r)?.get(s);if(n)for(const t of n)e[t]()})(e[0]),g("apply",c,d(this),e.map(d)).then(w)}}),y.set(c,new WeakRef(e))),e}}case V[o]:return(e=>{if(e.startsWith("."))return Symbol.for(e.slice(1));for(const[t,r]of te)if(r===e)return t})(c);default:return c}};p[ne]=(t,r,...a)=>{if(t===Z)(e=>{const[t,r]=typeof e===s?[u,l]:[l,u],n=t.has(e);n&&(r.delete(t.get(e)),t.delete(e))})(r);else{const s=Reflect[t],o=null==r?globalThis:f(r);switch(t){case"defineProperty":{const[e,t]=a.map(w);return d(s(o,e,t))}case"getOwnPropertyDescriptor":{const e=s(o,...a.map(w));if(e){const{get:t,set:r,value:s}=e;t&&(e.get=d(t)),r&&(e.set=d(r)),s&&(e.value=d(s))}return[V[e?n:c],e]}case X:return[V[e],s(o).map(d)];default:return((e,t,r)=>d(e(t,...r.map(w))))(s,o,a)}}}}}return{...g,Worker:y}};export{fe as default}; diff --git a/dist/window/worker.js b/dist/window/worker.js new file mode 100644 index 0000000..6ea14f7 --- /dev/null +++ b/dist/window/worker.js @@ -0,0 +1 @@ +const e="array",t="function",r="null",n="number",s="object",a="symbol",o="undefined",c="apply",l="construct",i="defineProperty",u="deleteProperty",f="get",p="getOwnPropertyDescriptor",y="getPrototypeOf",d="has",w="isExtensible",g="ownKeys",h="preventExtensions",b="set",E="setPrototypeOf";var v=Object.freeze({__proto__:null,APPLY:c,CONSTRUCT:l,DEFINE_PROPERTY:i,DELETE_PROPERTY:u,GET:f,GET_OWN_PROPERTY_DESCRIPTOR:p,GET_PROTOTYPE_OF:y,HAS:d,IS_EXTENSIBLE:w,OWN_KEYS:g,PREVENT_EXTENSION:h,SET:b,SET_PROTOTYPE_OF:E});function T(){return this}const m=new FinalizationRegistry((([e,t,r])=>{r&&console.debug(`Held value ${String(t)} not relevant anymore`),e(t)})),O=Object.create(null),{Object:P,Proxy:k,Reflect:S}=globalThis,{isArray:A}=Array,{ownKeys:R}=S,{create:x,hasOwn:_,values:M}=P,I=(r,n)=>n===e?r[0]:n===t?r():n===s?r.$:r,j=(e,t,r,n)=>{const s={type:{value:t}},a=_(e,"valueOf");for(const o of M(v)){let c=n(e[o]||S[o]);if(a&&o===f){const{valueOf:n}=e,{value:s}=c;c={value(e,a,...o){return a===r?n.call(this,I(e,t)):s.call(this,e,a,...o)}}}s[o]=c}return x(e,s)},W=(e,r,n,a=e)=>{if(a===e)switch(typeof e){case s:case o:a||(a=!1);case t:break;default:a=!1,r===e&&(r=P(e))}const c=new k(r,n),{destruct:l}=n;return l?((e,t,{debug:r,handler:n,return:s,token:a=e}=O)=>{const o=s||new Proxy(e,n||O),c=[o,[t,e,!!r]];return!1!==a&&c.push(a),m.register(...c),o})(e,l,{token:a,return:c}):c},$=t=>n=>{const a=typeof n;return a===s?n?t.get(n)?.[0]??(t=>A(t)?e:s)(n):r:a},N=e=>n=>{let a=typeof n;switch(a){case s:if(!n){a=r;break}case t:const o=e.get(n);o&&([a,n]=o)}return[a,n]},Y=e=>((e=>{m.unregister(e)})(e),e);var D=r=>{const n=new WeakMap,a=Symbol(),o={},c=(e,t,r)=>(n.set(e,[t,r]),e),l={proxy:o,release:Y,pair:N(n),typeOf:$(n),isProxy:e=>n.has(e),valueOf:e=>e[a]??e.valueOf()};for(const n of R(r)){if(_(l,n))continue;const i=r[n];switch(n){case e:{const t=j(i,n,a,(e=>({value([t],...r){return e.call(this,t,...r)}})));o[n]=(r,...n)=>c(W(r,[r],t,...n),e,r);break}case t:{const e=j(i,n,a,(e=>({value(t,...r){return e.call(this,t(),...r)}})));o[n]=(r,...n)=>{return c(W(r,(s=r,T.bind(s)),e,...n),t,r);var s};break}case s:{const e=j(i,n,a,(e=>({value({$:t},...r){return e.call(this,t,...r)}})));o[n]=(t,...r)=>c(W(t,{$:t},e,...r),s,t);break}default:{const e=j(i,n,a,(e=>({value:e})));o[n]=(t,...r)=>c(W(t,t,e,...r),n,t);break}}}return l};let L=0;const B=new Map,C=new Map,F=e=>C.get(e),U=e=>{if(!B.has(e)){let t;for(;C.has(t=L++););B.set(e,t),C.set(t,e)}return B.get(e)},{ArrayBuffer:z,Atomics:H,Promise:G}=globalThis,{isArray:K}=Array,{create:X,getPrototypeOf:q,values:J}=Object,V=q(Int32Array),Q=X(H),Z=({currentTarget:e,type:t,origin:r,lastEventId:n,source:s,ports:a},o)=>e.dispatchEvent(new MessageEvent(t,{data:o,origin:r,lastEventId:n,source:s,ports:a})),ee=()=>G.withResolvers();let te=0;const re=new Map,ne=(e,t)=>class extends e{constructor(e,...r){super(e,...r),e instanceof t&&re.set(this,[te++,0,ee()])}},se=new WeakSet,ae=e=>(se.add(e),e),oe=(e,t)=>{const{data:r}=e,n=K(r)&&(r.at(0)===t||0===r.at(1)&&!t);return n&&(e.stopImmediatePropagation(),e.preventDefault()),n},ce=e=>null!==e&&"object"==typeof e&&!se.has(e),le=new WeakMap,ie=(e,t,r)=>{if(re.has(e))t.set(e,re.get(e)[0]);else if(!(e instanceof V||e instanceof z))for(const n of J(e))ce(n)&&!r.has(n)&&(r.add(n),ie(n,t,r))},ue=(...e)=>({value:new G((t=>{let r=new Worker("data:application/javascript,onmessage%3De%3D%3EpostMessage(!Atomics.wait(...e.data))");r.onmessage=()=>t("ok"),r.postMessage(e)}))}),fe=(e,t)=>{const r=re.get(e),[n,s,{promise:a}]=r;return r[1]=t,[n,a]};let{BigInt64Array:pe,Int32Array:ye,SharedArrayBuffer:de,addEventListener:we,postMessage:ge}=globalThis,he=!0,be=e=>e,Ee=!1;const ve=ee();try{new de(4),Q.waitAsync||(Q.waitAsync=ue),ve.resolve()}catch(e){const t=ge,r=we,n=[];let s="",a="";de=class extends z{},pe=ne(pe,de),ye=ne(ye,de),be=ae,Ee=!0,Q.notify=(e,r)=>{const[n]=(e=>le.get(e))(e);return t([s,1,e,n,r]),0},Q.waitAsync=(...e)=>{const[t,r]=fe(...e);return{value:r}},Q.wait=(e,t,...r)=>{const[n]=fe(e,t,...r),o=new XMLHttpRequest;o.responseType="json",o.open("POST",`${a}?sabayon`,!1),o.setRequestHeader("Content-Type","application/json"),o.send(`["${s}",${n},${t}]`);const{response:c}=o;re.delete(e);for(let t=0;t{if(oe(e,s)){const[t,r,...n]=e.data;switch(r){case 0:s=t,a=n.at(0)?.serviceWorker||"",a||(Q.wait=null,ve.resolve());break;case 1:((e,t,r)=>{for(const[n,[s,a,{resolve:o}]]of re)if(t===s&&r===a){for(let t=0;t{for(const[r,n]of t)le.set(r,[n,e.currentTarget]);Z(e,r)})(e,...n);break;case 3:ve.resolve()}}else if(he){const{currentTarget:t,type:r,origin:s,lastEventId:a,source:o,ports:c}=e;n.push([{currentTarget:t,type:r,origin:s,lastEventId:a,source:o,ports:c},e.data])}})),we=(e,...t)=>{if(r(e,...t),n.length)for(const e of n.splice(0))Z(...e)},ge=(e,...r)=>t(((e,t)=>{const r=new Map;return ce(t)&&ie(t,r,new Set),r.size?[e,2,r,t]:t})(s,e),...r)}await ve.promise,he=!1;const{BYTES_PER_ELEMENT:Te}=Int32Array,{BYTES_PER_ELEMENT:me}=Uint16Array,{notify:Oe}=Q,Pe=new TextDecoder("utf-16"),ke=new WeakSet,Se=(...e)=>(ke.add(e),e);let Ae="";const Re=(e,t,r,n)=>{const[s]=n,a=r.get(s);if(!a)throw new Error(`Unknown proxy.${s}()`);e(a,t,n)};let xe=0;const _e=([e,t,r,n,s,a,o,c,l],i)=>(...u)=>{let f=""!==Ae,p=0;f&&(p=((e,t)=>setTimeout(console.warn,1e3,`💀🔒 - proxy.${e}() in proxy.${t}()`))(i,Ae));const y=xe++,d=[];ke.has(u.at(-1)||d)&&ke.delete(d=u.pop());const w=r(c?u.map(c):u);let g=t(2*Te);return o([e,2,i,y,g,w,n],{transfer:d}),l(g,0).value.then((()=>{f&&clearTimeout(p);const r=g[1];if(!r)return;const n=me*r;return g=t(n+n%Te),o([e,1,y,g]),l(g,0).value.then((()=>{const e=new Uint16Array(g.buffer),t=a?e.subarray(0,r):e.slice(0,r);return s(Pe.decode(t))}))}))},Me=(e,t)=>new Proxy(t,{get:(t,r)=>{let n;return"then"!==r&&(n=t.get(r),n||(n=_e(e,r),t.set(r,n))),n},set:(e,t,r)=>"then"!==t&&!!e.set(t,r)}),{wait:Ie,waitAsync:je}=Q;var We=({parse:e,stringify:t,transform:r,interrupt:n}=JSON)=>{const s=((e,t)=>async(r,n,[s,a,o,c,l])=>{l&&(Ae=s);try{const s=await r(...c);if(void 0!==s){const r=e(t?t(s):s);n.set(a,r),o[1]=r.length}}finally{l&&(Ae=""),o[0]=1,Oe(o,0)}})(t,r),a=ee(),o=new Map,c=new Map;let l="",i=Ie;if(Ie&&n){const{handler:e,timeout:t=42}=n;i=(r,n,s)=>{for(;"timed-out"===(s=Ie(r,n,0,t));)e();return s}}return we("message",(t=>{if(oe(t,l)){const[n,u,...f]=t.data;switch(u){case 0:{const t=!!Ie;l=n,a.resolve({polyfill:Ee,sync:t,transfer:Se,proxy:Me([l,e=>new ye(new de(e)),be,t,e,Ee,ge,r,t?(...e)=>({value:{then:t=>t(i(...e))}}):je],o)});break}case 2:o.size?Re(s,c,o,f):setTimeout(Re,0,s,c,o,f);break;case 1:((e,[t,r])=>{const n=e.get(t);e.delete(t);for(let e=new Uint16Array(r.buffer),t=0,{length:s}=n;t[e,t])));const Ne="destruct",{[g]:Ye}=Reflect,De=new Map(Ye(Symbol).filter((e=>typeof Symbol[e]===a)).map((e=>[Symbol[e],e]))),Le=e=>De.get(e)||`.${Symbol.keyFor(e)||""}`,Be="8d26f914-addd-4e13-a753-010b90b835f2",Ce="M"+Be,Fe="W"+Be,{[c]:Ue}=Reflect;var ze=async r=>{const o=await We(r),v=r?.transform||(e=>e),{[Ce]:T}=o.proxy,m=new Map,O=(e,t)=>{let r=m.get(e)?.deref();return r||m.set(e,new WeakRef(r=t(e))),r},P=([r,o])=>{switch(r){case $e[s]:return null==o?globalThis:typeof o===n?O(o,x.object):o;case $e[e]:return typeof o===n?O(o,x.array):o;case $e[t]:return typeof o===n?O(o,x.function):F(parseInt(o));case $e[a]:return(e=>{if(e.startsWith("."))return Symbol.for(e.slice(1));for(const[t,r]of De)if(r===e)return t})(o);default:return o}},k=r=>{let[o,c]=M(r);switch(o){case s:if(c==globalThis||null==c)c=null;else if(typeof c===s&&!(c instanceof V)){c=v(c);for(const e in c)c[e]=k(c[e])}return[$e[s],c];case e:return[$e[e],typeof c===n?c:v(c).map(k)];case t:return[$e[t],typeof c===t?String(U(v(c))):c];case a:return[$e[a],Le(r)];default:return[$e[o],c]}},S=(...e)=>P(T(...e)),A={[i]:(e,t,r)=>S(i,e,k(t),k(r)),[u]:(e,t)=>S(u,e,k(t)),[f]:(e,t)=>S(f,e,k(t)),[y]:e=>S(y,e),[p]:(e,t)=>{const r=S(p,e,k(t));if(r){const{get:e,set:t,value:n}=r;e&&(r.get=P(e)),t&&(r.set=P(t)),n&&(r.value=P(n))}return r},[d]:(e,t)=>S(d,e,k(t)),[w]:e=>S(w,e),[g]:e=>S(g,e).map(P),[h]:e=>S(h,e),[b]:(e,t,r)=>S(b,e,k(t),k(r)),[E]:(e,t)=>S(E,e,k(t)),[Ne](e){m.delete(e),T(Ne,e)}},R={object:A,array:A,function:{...A,[c]:(e,...t)=>S(c,e,...t.map(k)),[l]:(e,...t)=>S(l,e,...t.map(k))}},{proxy:x,isProxy:_,pair:M}=D(R),I=x.object(null);return o.proxy[Fe]=(e,t,...r)=>{const s=parseInt(t);switch(e){case c:{const[e,t]=r;return k(Ue(F(s),P(e),t.map(P)))}case Ne:(e=>{const[t,r]=typeof e===n?[C,B]:[B,C],s=t.has(e);s&&(r.delete(t.get(e)),t.delete(e))})(s)}},{...o,window:I,isWindowProxy:_}};export{ze as default}; diff --git a/dist/worker.js b/dist/worker.js new file mode 100644 index 0000000..6990d56 --- /dev/null +++ b/dist/worker.js @@ -0,0 +1 @@ +const{ArrayBuffer:e,Atomics:t,Promise:s}=globalThis,{isArray:r}=Array,{create:n,getPrototypeOf:a,values:o}=Object,c=a(Int32Array),i=n(t),l=({currentTarget:e,type:t,origin:s,lastEventId:r,source:n,ports:a},o)=>e.dispatchEvent(new MessageEvent(t,{data:o,origin:s,lastEventId:r,source:n,ports:a})),p=()=>s.withResolvers();let u=0;const f=new Map,d=(e,t)=>class extends e{constructor(e,...s){super(e,...s),e instanceof t&&f.set(this,[u++,0,p()])}},y=new WeakSet,w=e=>(y.add(e),e),g=(e,t)=>{const{data:s}=e,n=r(s)&&(s.at(0)===t||0===s.at(1)&&!t);return n&&(e.stopImmediatePropagation(),e.preventDefault()),n},h=e=>null!==e&&"object"==typeof e&&!y.has(e),v=new WeakMap,m=(t,s,r)=>{if(f.has(t))s.set(t,f.get(t)[0]);else if(!(t instanceof c||t instanceof e))for(const e of o(t))h(e)&&!r.has(e)&&(r.add(e),m(e,s,r))},E=(...e)=>({value:new s((t=>{let s=new Worker("data:application/javascript,onmessage%3De%3D%3EpostMessage(!Atomics.wait(...e.data))");s.onmessage=()=>t("ok"),s.postMessage(e)}))}),A=(e,t)=>{const s=f.get(e),[r,n,{promise:a}]=s;return s[1]=t,[r,a]};let{BigInt64Array:T,Int32Array:k,SharedArrayBuffer:b,addEventListener:M,postMessage:x}=globalThis,I=!0,S=e=>e,P=!1;const $=p();try{new b(4),i.waitAsync||(i.waitAsync=E),$.resolve()}catch(t){const s=x,r=M,n=[];let a="",o="";b=class extends e{},T=d(T,b),k=d(k,b),S=w,P=!0,i.notify=(e,t)=>{const[r]=(e=>v.get(e))(e);return s([a,1,e,r,t]),0},i.waitAsync=(...e)=>{const[t,s]=A(...e);return{value:s}},i.wait=(e,t,...s)=>{const[r]=A(e,t,...s),n=new XMLHttpRequest;n.responseType="json",n.open("POST",`${o}?sabayon`,!1),n.setRequestHeader("Content-Type","application/json"),n.send(`["${a}",${r},${t}]`);const{response:c}=n;f.delete(e);for(let t=0;t{if(g(e,a)){const[t,s,...r]=e.data;switch(s){case 0:a=t,o=r.at(0)?.serviceWorker||"",o||(i.wait=null,$.resolve());break;case 1:((e,t,s)=>{for(const[r,[n,a,{resolve:o}]]of f)if(t===n&&s===a){for(let t=0;t{for(const[s,r]of t)v.set(s,[r,e.currentTarget]);l(e,s)})(e,...r);break;case 3:$.resolve()}}else if(I){const{currentTarget:t,type:s,origin:r,lastEventId:a,source:o,ports:c}=e;n.push([{currentTarget:t,type:s,origin:r,lastEventId:a,source:o,ports:c},e.data])}})),M=(e,...t)=>{if(r(e,...t),n.length)for(const e of n.splice(0))l(...e)},x=(e,...t)=>s(((e,t)=>{const s=new Map;return h(t)&&m(t,s,new Set),s.size?[e,2,s,t]:t})(a,e),...t)}await $.promise,I=!1;const{BYTES_PER_ELEMENT:j}=Int32Array,{BYTES_PER_ELEMENT:B}=Uint16Array,{notify:R}=i,W=new TextDecoder("utf-16"),D=new WeakSet,L=(...e)=>(D.add(e),e);let O="";const U=(e,t,s,r)=>{const[n]=r,a=s.get(n);if(!a)throw new Error(`Unknown proxy.${n}()`);e(a,t,r)};let _=0;const N=([e,t,s,r,n,a,o,c,i],l)=>(...p)=>{let u=""!==O,f=0;u&&(f=((e,t)=>setTimeout(console.warn,1e3,`💀🔒 - proxy.${e}() in proxy.${t}()`))(l,O));const d=_++,y=[];D.has(p.at(-1)||y)&&D.delete(y=p.pop());const w=s(c?p.map(c):p);let g=t(2*j);return o([e,2,l,d,g,w,r],{transfer:y}),i(g,0).value.then((()=>{u&&clearTimeout(f);const s=g[1];if(!s)return;const r=B*s;return g=t(r+r%j),o([e,1,d,g]),i(g,0).value.then((()=>{const e=new Uint16Array(g.buffer),t=a?e.subarray(0,s):e.slice(0,s);return n(W.decode(t))}))}))},q=(e,t)=>new Proxy(t,{get:(t,s)=>{let r;return"then"!==s&&(r=t.get(s),r||(r=N(e,s),t.set(s,r))),r},set:(e,t,s)=>"then"!==t&&!!e.set(t,s)}),{wait:z,waitAsync:C}=i;var H=({parse:e,stringify:t,transform:s,interrupt:r}=JSON)=>{const n=((e,t)=>async(s,r,[n,a,o,c,i])=>{i&&(O=n);try{const n=await s(...c);if(void 0!==n){const s=e(t?t(n):n);r.set(a,s),o[1]=s.length}}finally{i&&(O=""),o[0]=1,R(o,0)}})(t,s),a=p(),o=new Map,c=new Map;let i="",l=z;if(z&&r){const{handler:e,timeout:t=42}=r;l=(s,r,n)=>{for(;"timed-out"===(n=z(s,r,0,t));)e();return n}}return M("message",(t=>{if(g(t,i)){const[r,p,...u]=t.data;switch(p){case 0:{const t=!!z;i=r,a.resolve({polyfill:P,sync:t,transfer:L,proxy:q([i,e=>new k(new b(e)),S,t,e,P,x,s,t?(...e)=>({value:{then:t=>t(l(...e))}}):C],o)});break}case 2:o.size?U(n,c,o,u):setTimeout(U,0,n,c,o,u);break;case 1:((e,[t,s])=>{const r=e.get(t);e.delete(t);for(let e=new Uint16Array(s.buffer),t=0,{length:n}=r;t worker() use cases. -// This still cannot possibly solve the sync -// worker -> main() use case if SharedArrayBuffer -// is not available or usable. - -import {CHANNEL} from './channel.js'; - -const {isArray} = Array; - -let {SharedArrayBuffer, window} = globalThis; -let {notify, wait, waitAsync} = Atomics; -let postPatched = null; - -// This is needed for some version of Firefox -if (!waitAsync) { - waitAsync = buffer => ({ - value: new Promise(onmessage => { - // encodeURIComponent('onmessage=({data:b})=>(Atomics.wait(b,0),postMessage(0))') - let w = new Worker('data:application/javascript,onmessage%3D(%7Bdata%3Ab%7D)%3D%3E(Atomics.wait(b%2C0)%2CpostMessage(0))'); - w.onmessage = onmessage; - w.postMessage(buffer); - }) - }); -} - -// Monkey-patch SharedArrayBuffer if needed -try { - new SharedArrayBuffer(4); -} -catch (_) { - SharedArrayBuffer = ArrayBuffer; - - const ids = new WeakMap; - // patch only main -> worker():async use case - if (window) { - const resolvers = new Map; - const {prototype: {postMessage}} = Worker; - - const listener = event => { - const details = event.data?.[CHANNEL]; - if (!isArray(details)) { - event.stopImmediatePropagation(); - const { id, sb } = details; - resolvers.get(id)(sb); - } - }; - - postPatched = function (data, ...rest) { - const details = data?.[CHANNEL]; - if (isArray(details)) { - const [id, sb] = details; - ids.set(sb, id); - this.addEventListener('message', listener); - } - return postMessage.call(this, data, ...rest); - }; - - waitAsync = sb => ({ - value: new Promise(resolve => { - resolvers.set(ids.get(sb), resolve); - }).then(buff => { - resolvers.delete(ids.get(sb)); - ids.delete(sb); - for (let i = 0; i < buff.length; i++) sb[i] = buff[i]; - return 'ok'; - }) - }); - } - else { - const as = (id, sb) => ({[CHANNEL]: { id, sb }}); - - notify = sb => { - postMessage(as(ids.get(sb), sb)); - }; - - addEventListener('message', event => { - const details = event.data?.[CHANNEL]; - if (isArray(details)) { - const [id, sb] = details; - ids.set(sb, id); - } - }); - } -} - -export {SharedArrayBuffer, isArray, notify, postPatched, wait, waitAsync}; diff --git a/esm/bun.js b/esm/bun.js deleted file mode 100644 index fc08ea6..0000000 --- a/esm/bun.js +++ /dev/null @@ -1,68 +0,0 @@ -import coincident from './server.js'; - -class DirectEmitter { - on(type, handler) { - this[type] = handler; - return this; - } -} - -class WebSocketServer extends DirectEmitter { - constructor() { - super(); - this.connection = null; - } - } - -class WebSocketClient extends DirectEmitter { - constructor(ws) { - super(); - this.ws = ws; - this.close = null; - this.message = null; - this.error = null; - } - once(_, handler) { - this.message = message => { - this.send(message); - handler(message); - }; - } - send(message) { - this.ws.send(message); - } -} - -/** - * @param {object} globals Globals to expose via coincident - * @returns - */ -export default globals => { - const sockets = new Map; - const wss = new WebSocketServer; - coincident(wss, globals); - return { - /** - * @param {WebSocket} ws - * @param {string} message - */ - message(ws, message) { - sockets.get(ws).message(message); - }, - /** - * @param {WebSocket} ws - */ - open(ws) { - const wsc = new WebSocketClient(ws); - sockets.set(ws, wsc); - wss.connection(wsc); - }, - /** - * @param {WebSocket} ws - */ - close(ws) { - sockets.get(ws).close(); - sockets.delete(ws); - }, - }; -}; diff --git a/esm/channel.js b/esm/channel.js deleted file mode 100644 index 1c005a2..0000000 --- a/esm/channel.js +++ /dev/null @@ -1,5 +0,0 @@ -// ⚠️ AUTOMATICALLY GENERATED - DO NOT CHANGE -export const CHANNEL = '566fc334-5147-4e86-bb9b-c7d24c13127d'; - -export const MAIN = 'M' + CHANNEL; -export const THREAD = 'T' + CHANNEL; diff --git a/esm/index.js b/esm/index.js deleted file mode 100644 index 1d0f53a..0000000 --- a/esm/index.js +++ /dev/null @@ -1,199 +0,0 @@ -/*! (c) Andrea Giammarchi - ISC */ - -import {FUNCTION} from 'proxy-target/types'; - -import {CHANNEL} from './channel.js'; -import {GET, HAS, SET} from './shared/traps.js'; - -import {SharedArrayBuffer, isArray, notify, postPatched, wait, waitAsync} from './bridge.js'; - -// just minifier friendly for Blob Workers' cases -const {Int32Array, Map, Uint16Array} = globalThis; - -// common constants / utilities for repeated operations -const {BYTES_PER_ELEMENT: I32_BYTES} = Int32Array; -const {BYTES_PER_ELEMENT: UI16_BYTES} = Uint16Array; - -const waitInterrupt = (sb, delay, handler) => { - while (wait(sb, 0, 0, delay) === 'timed-out') - handler(); -}; - -// retain buffers to transfer -const buffers = new WeakSet; - -// retain either main threads or workers global context -const context = new WeakMap; - -const syncResult = {value: {then: fn => fn()}}; - -// used to generate a unique `id` per each worker `postMessage` "transaction" -let uid = 0; - -/** - * @typedef {Object} Interrupt used to sanity-check interrupts while waiting synchronously. - * @prop {function} [handler] a callback invoked every `delay` milliseconds. - * @prop {number} [delay=42] define `handler` invokes in terms of milliseconds. - */ - -/** - * Create once a `Proxy` able to orchestrate synchronous `postMessage` out of the box. - * @param {globalThis | Worker} self the context in which code should run - * @param {{parse: (serialized: string) => any, stringify: (serializable: any) => string, transform?: (value:any) => any, interrupt?: () => void | Interrupt}} [JSON] an optional `JSON` like interface to `parse` or `stringify` content with extra `transform` ability. - * @returns {ProxyHandler | ProxyHandler} - */ -const coincident = (self, {parse = JSON.parse, stringify = JSON.stringify, transform, interrupt} = JSON) => { - // create a Proxy once for the given context (globalThis or Worker instance) - if (!context.has(self)) { - // ensure no SAB gets a chance to pass through this call - const sendMessage = postPatched || self.postMessage; - // ensure the CHANNEL and data are posted correctly - const post = (transfer, ...args) => sendMessage.call(self, {[CHANNEL]: args}, {transfer}); - - const handler = typeof interrupt === FUNCTION ? interrupt : interrupt?.handler; - const delay = interrupt?.delay || 42; - const decoder = new TextDecoder('utf-16'); - - // automatically uses sync wait (worker -> main) - // or fallback to async wait (main -> worker) - const waitFor = (isAsync, sb) => isAsync ? - waitAsync(sb, 0) : - ((handler ? waitInterrupt(sb, delay, handler) : wait(sb, 0)), syncResult); - - // prevent Harakiri https://github.com/WebReflection/coincident/issues/18 - let seppuku = false; - - context.set(self, new Proxy(new Map, { - // there is very little point in checking prop in proxy for this very specific case - // and I don't want to orchestrate a whole roundtrip neither, as stuff would fail - // regardless if from Worker we access non existent Main callback, and vice-versa. - // This is here mostly to guarantee that if such check is performed, at least the - // get trap goes through and then it's up to developers guarantee they are accessing - // stuff that actually exists elsewhere. - [HAS]: (_, action) => typeof action === 'string' && !action.startsWith('_'), - - // worker related: get any utility that should be available on the main thread - [GET]: (_, action) => action === 'then' ? null : ((...args) => { - // transaction id - const id = uid++; - - // first contact: just ask for how big the buffer should be - // the value would be stored at index [1] while [0] is just control - let sb = new Int32Array(new SharedArrayBuffer(I32_BYTES * 2)); - - // if a transfer list has been passed, drop it from args - let transfer = []; - if (buffers.has(args.at(-1) || transfer)) - buffers.delete(transfer = args.pop()); - - // ask for invoke with arguments and wait for it - post(transfer, id, sb, action, transform ? args.map(transform) : args); - - // helps deciding how to wait for results - const isAsync = self !== globalThis; - - // warn users about possible deadlock still allowing them - // to explicitly `proxy.invoke().then(...)` without blocking - let deadlock = 0; - if (seppuku && isAsync) - deadlock = setTimeout(console.warn, 1000, `💀🔒 - Possible deadlock if proxy.${action}(...args) is awaited`); - - return waitFor(isAsync, sb).value.then(() => { - clearTimeout(deadlock); - - // commit transaction using the returned / needed buffer length - const length = sb[1]; - - // filter undefined results - if (!length) return; - - // calculate the needed ui16 bytes length to store the result string - const bytes = UI16_BYTES * length; - - // round up to the next amount of bytes divided by 4 to allow i32 operations - sb = new Int32Array(new SharedArrayBuffer(bytes + (bytes % I32_BYTES))); - - // ask for results and wait for it - post([], id, sb); - return waitFor(isAsync, sb).value.then(() => parse( - decoder.decode(new Uint16Array(sb.buffer).slice(0, length))) - ); - }); - }), - - // main thread related: react to any utility a worker is asking for - [SET](actions, action, callback) { - const type = typeof callback; - if (type !== FUNCTION) - throw new Error(`Unable to assign ${action} as ${type}`); - // lazy event listener and logic handling, triggered once by setters actions - if (!actions.size) { - // maps results by `id` as they are asked for - const results = new Map; - // add the event listener once (first defined setter, all others work the same) - self.addEventListener('message', async (event) => { - // grub the very same library CHANNEL; ignore otherwise - const details = event.data?.[CHANNEL]; - if (isArray(details)) { - // if early enough, avoid leaking data to other listeners - event.stopImmediatePropagation(); - const [id, sb, ...rest] = details; - let error; - // action available: it must be defined/known on the main thread - if (rest.length) { - const [action, args] = rest; - if (actions.has(action)) { - seppuku = true; - try { - // await for result either sync or async and serialize it - const result = await actions.get(action)(...args); - if (result !== void 0) { - const serialized = stringify(transform ? transform(result) : result); - // store the result for "the very next" event listener call - results.set(id, serialized); - // communicate the required SharedArrayBuffer length out of the - // resulting serialized string - sb[1] = serialized.length; - } - } - catch (_) { - error = _; - } - finally { - seppuku = false; - } - } - // unknown action should be notified as missing on the main thread - else { - error = new Error(`Unsupported action: ${action}`); - } - // unlock the wait lock later on - sb[0] = 1; - } - // no action means: get results out of the well known `id` - // wait lock automatically unlocked here as no `0` value would - // possibly ever land at index `0` - else { - const result = results.get(id); - results.delete(id); - // populate the SharedArrayBuffer with utf-16 chars code - for (let ui16a = new Uint16Array(sb.buffer), i = 0; i < result.length; i++) - ui16a[i] = result.charCodeAt(i); - } - // release te worker waiting either the length or the result - notify(sb, 0); - if (error) throw error; - } - }); - } - // store this action callback allowing the setter in the process - return !!actions.set(action, callback); - } - })); - } - return context.get(self); -}; - -coincident.transfer = (...args) => (buffers.add(args), args); - -export default coincident; diff --git a/esm/json.js b/esm/json.js deleted file mode 100644 index 0df3fd4..0000000 --- a/esm/json.js +++ /dev/null @@ -1,3 +0,0 @@ -import * as JSON from '@ungap/structured-clone/json'; - -export default JSON; diff --git a/esm/server.js b/esm/server.js deleted file mode 100644 index f9c90d0..0000000 --- a/esm/server.js +++ /dev/null @@ -1,168 +0,0 @@ -import '@ungap/with-resolvers'; -import {MAIN, THREAD} from './channel.js'; -import {APPLY} from './shared/traps.js'; -import {assign} from './shared/utils.js'; -import $coincident from './structured.js'; -import JSON from './json.js'; -import main from './window/main.js'; -import thread from './window/thread.js'; -import serverMain from './server/main.js'; -import serverThread from './server/thread.js'; -import Worker from './shared/worker.js'; - -const {notify, wait} = Atomics; -const {parse, stringify} = JSON; - -const isServer = !!globalThis.process; -const proxies = new WeakMap; - -/** - * @typedef {object} Coincident - * @property {ProxyHandler} proxy - * @property {ProxyHandler} window - * @property {(value: any) => boolean} isWindowProxy - */ - -/** - * @typedef {object & Coincident} CoincidentWorker - * @property {ProxyHandler} proxy - * @property {ProxyHandler} window - * @property {(value: any) => boolean} isWindowProxy - * @property {ProxyHandler} server - * @property {(value: any) => boolean} isServerProxy - */ - -/** - * @callback CoincidentServer - * @param {WebSocketServer} wss the WebSocketServer to use to handle Worker/Server calls - * @param {object} [globals] optional globals to expose through the Worker via the proxy - * @returns {WebSocketServer} - */ - -/** - * @callback CoincidentWeb - * @param {globalThis | Worker} self either the main thread (Worker)or a worker (in main thread UI) - * @param {WebSocket} [ws] the optional WebSocket to use when `self` is `globalThis` - * @returns {Coincident | CoincidentWorker} - */ - -const parseData = data => { - let id; - if (/^!(-?\d+)?/.test(data)) { - id = RegExp.$1; - data = data.slice(1 + id.length); - } - return {id, result: data ? parse(data) : void 0}; -}; - -const coincident = isServer ? - /** @type {CoincidentServer} */ - (wss, globals) => wss.on('connection', ws => { - // wait for the cross-hand-shake from the main thread - ws.once('message', buffer => { - let id = 0; - const [SERVER_MAIN, SERVER_THREAD] = parse(buffer); - const resolvers = new Map; - // bootstrap a dedicated channel for this socket - const {[SERVER_MAIN]: __main__} = serverMain( - {[SERVER_THREAD]: async (trap, ...args) => { - const data = stringify([trap, ...args]); - // allow return values from thread's callbacks - if (trap === APPLY) { - const {promise, resolve} = Promise.withResolvers(); - const uid = String(id++); - resolvers.set(uid, resolve); - ws.send('!' + uid + data); - return await promise; - } - ws.send('!' + data); - }}, - SERVER_MAIN, - SERVER_THREAD, - globals - ).proxy; - // setup the socket and terminate the hand-shake - ws - // resolve dangling promises on close - .on('close', () => { - for (const [_, resolve] of resolvers) resolve(); - }) - // resolve or forward results - .on('message', buffer => { - const {id, result} = parseData(String(buffer)); - if (id) { - const resolve = resolvers.get(id); - resolvers.delete(id); - resolve(result); - } - else - ws.send(stringify(__main__(...result))); - }) - // end cross-hand-shake - .send(''); - }); - }) : - - /** @type {CoincidentWeb} */ - (self, ws, ...args) => { - const proxy = $coincident(self, ...args); - if (!proxies.has(proxy)) { - const util = self instanceof Worker ? mainBridge : threadBridge; - proxies.set(proxy, util(self, proxy, MAIN, THREAD, ws)); - } - return proxies.get(proxy); - } -; - -if (!isServer) - coincident.transfer = $coincident.transfer; - -export default coincident; - -const mainBridge = (self, thread, MAIN, THREAD, ws) => { - // wait for the cross-hand-shake from the worker - self.addEventListener('message', ({data: [CHANNEL, i32]}) => { - const SERVER_MAIN = 'M' + CHANNEL; - const SERVER_THREAD = 'T' + CHANNEL; - const {[SERVER_THREAD]: __thread__} = thread; - let resolve; - thread[SERVER_MAIN] = (...args) => new Promise($ => { - resolve = $; - ws.send(stringify(args)); - }); - // wait for the cross-hand-shake from the server - ws.addEventListener('message', () => { - // setup regular listener for all socket's interactions - ws.addEventListener('message', async ({data}) => { - const {id, result} = parseData(data); - if (id != null) { - const invoke = __thread__(...result); - if (id) { - const out = await invoke; - ws.send('!' + id + (out === void 0 ? '' : stringify(out))); - } - } - else if (resolve) resolve = resolve(result); - }); - // unlock the Worker now that all channels have been defined - i32[0] = 1; - notify(i32, 0); - }, {once: true}); - ws.send(stringify([SERVER_MAIN, SERVER_THREAD])); - }, {once: true}); - return main(thread, MAIN, THREAD); -}; - -const threadBridge = (self, proxy, MAIN, THREAD) => { - // create a unique channel to reflect on the server - // through the main WebSocket (cross-hand-shake) - const CHANNEL = 'S' + crypto.randomUUID(); - const i32 = new Int32Array(new SharedArrayBuffer(4)); - self.postMessage([CHANNEL, i32]); - wait(i32, 0); - // merge server and worker namespace - return assign( - serverThread(proxy, 'M' + CHANNEL, 'T' + CHANNEL), - thread(proxy, MAIN, THREAD) - ); -}; diff --git a/esm/server/main.js b/esm/server/main.js deleted file mode 100644 index 07486ff..0000000 --- a/esm/server/main.js +++ /dev/null @@ -1,3 +0,0 @@ -import main from '../shared/main.js'; - -export default main('Server', false); diff --git a/esm/server/thread.js b/esm/server/thread.js deleted file mode 100644 index 2fbccd0..0000000 --- a/esm/server/thread.js +++ /dev/null @@ -1,3 +0,0 @@ -import thread from '../shared/thread.js'; - -export default thread('Server'); diff --git a/esm/shared/main.js b/esm/shared/main.js deleted file mode 100644 index b42798b..0000000 --- a/esm/shared/main.js +++ /dev/null @@ -1,197 +0,0 @@ -import { target as tv, unwrap } from 'proxy-target/array'; -import { create as createGCHook } from 'gc-hook'; - -import { - ARRAY, - OBJECT, - FUNCTION, - NUMBER, - STRING, - SYMBOL, - UNDEFINED, -} from 'proxy-target/types'; - -import { - TypedArray, - defineProperty, - deleteProperty, - getOwnPropertyDescriptor, - getPrototypeOf, - isExtensible, - ownKeys, - preventExtensions, - set, - setPrototypeOf, - - assign, - create, - augment, - asEntry, - symbol, - transform -} from './utils.js'; - -import { - APPLY, - CONSTRUCT, - DEFINE_PROPERTY, - DELETE_PROPERTY, - GET, - GET_OWN_PROPERTY_DESCRIPTOR, - GET_PROTOTYPE_OF, - HAS, - IS_EXTENSIBLE, - OWN_KEYS, - PREVENT_EXTENSION, - SET, - SET_PROTOTYPE_OF, - DELETE -} from './traps.js'; - -export default (name, patch) => { - const eventsHandler = patch && new WeakMap; - - // patch once main UI tread - if (patch) { - const { addEventListener } = EventTarget.prototype; - // this should never be on the way as it's extremely light and fast - // but it's necessary to allow "preventDefault" or other event invokes at distance - defineProperty(EventTarget.prototype, 'addEventListener', { - value(type, listener, ...options) { - if (options.at(0)?.invoke) { - if (!eventsHandler.has(this)) - eventsHandler.set(this, new Map); - eventsHandler.get(this).set(type, [].concat(options[0].invoke)); - delete options[0].invoke; - } - return addEventListener.call(this, type, listener, ...options); - } - }); - } - - const handleEvent = patch && (event => { - const {currentTarget, target, type} = event; - for (const method of eventsHandler.get(currentTarget || target)?.get(type) || []) - event[method](); - }); - - return function (thread, MAIN, THREAD, ...args) { - let id = 0, $ = this?.transform || transform; - const ids = new Map; - const values = new Map; - - const {[THREAD]: __thread__} = thread; - - const global = args.length ? assign(create(globalThis), ...args) : globalThis; - - const result = asEntry((type, value) => { - if (!ids.has(value)) { - let sid; - // a bit apocalyptic scenario but if this main runs forever - // and the id does a whole int32 roundtrip we might have still - // some reference dangling around - while (values.has(sid = id++)); - ids.set(value, sid); - values.set(sid, type === FUNCTION ? value : $(value)); - } - return tv(type, ids.get(value)); - }); - - const onGarbageCollected = value => { - __thread__(DELETE, tv(STRING, value)); - }; - - const asValue = (type, value) => { - switch (type) { - case OBJECT: - if (value == null) return global; - case ARRAY: - if (typeof value === NUMBER) return values.get(value); - if (!(value instanceof TypedArray)) { - for (const key in value) - value[key] = target(value[key]); - } - return value; - case FUNCTION: - if (typeof value === STRING) { - const retained = values.get(value)?.deref(); - if (retained) return retained; - const cb = function (...args) { - if (patch && args.at(0) instanceof Event) handleEvent(...args); - return __thread__( - APPLY, - tv(FUNCTION, value), - result(this), - args.map(result) - ); - }; - values.set(value, new WeakRef(cb)); - return createGCHook(value, onGarbageCollected, { - return: cb, - token: false, - }); - } - return values.get(value); - case SYMBOL: - return symbol(value); - } - return value; - }; - - const target = entry => unwrap(entry, asValue); - - const trapsHandler = { - [APPLY]: (target, thisArg, args) => result(target.apply(thisArg, args)), - [CONSTRUCT]: (target, args) => result(new target(...args)), - [DEFINE_PROPERTY]: (target, name, descriptor) => result(defineProperty(target, name, descriptor)), - [DELETE_PROPERTY]: (target, name) => result(deleteProperty(target, name)), - [GET_PROTOTYPE_OF]: target => result(getPrototypeOf(target)), - [GET]: (target, name) => result(target[name]), - [GET_OWN_PROPERTY_DESCRIPTOR]: (target, name) => { - const descriptor = getOwnPropertyDescriptor(target, name); - return descriptor ? tv(OBJECT, augment(descriptor, result)) : tv(UNDEFINED, descriptor); - }, - [HAS]: (target, name) => result(name in target), - [IS_EXTENSIBLE]: target => result(isExtensible(target)), - [OWN_KEYS]: target => tv(ARRAY, ownKeys(target).map(result)), - [PREVENT_EXTENSION]: target => result(preventExtensions(target)), - [SET]: (target, name, value) => result(set(target, name, value)), - [SET_PROTOTYPE_OF]: (target, proto) => result(setPrototypeOf(target, proto)), - [DELETE](id) { - ids.delete(values.get(id)); - values.delete(id); - } - }; - - thread[MAIN] = (trap, entry, ...args) => { - switch (trap) { - case APPLY: - args[0] = target(args[0]); - args[1] = args[1].map(target); - break; - case CONSTRUCT: - args[0] = args[0].map(target); - break; - case DEFINE_PROPERTY: { - const [name, descriptor] = args; - args[0] = target(name); - const {get, set, value} = descriptor; - if (get) descriptor.get = target(get); - if (set) descriptor.set = target(set); - if (value) descriptor.value = target(value); - break; - } - default: - args = args.map(target); - break; - } - return trapsHandler[trap](target(entry), ...args); - }; - - return { - proxy: thread, - [name.toLowerCase()]: global, - [`is${name}Proxy`]: () => false - }; - }; -}; diff --git a/esm/shared/thread.js b/esm/shared/thread.js deleted file mode 100644 index c3f8da1..0000000 --- a/esm/shared/thread.js +++ /dev/null @@ -1,155 +0,0 @@ -import { target as tv, unwrap, bound, unbound } from 'proxy-target/array'; -import { create as createGCHook } from 'gc-hook'; - -import { - ARRAY, - OBJECT, - FUNCTION, - NUMBER, - STRING, - SYMBOL, -} from 'proxy-target/types'; - -import { - TypedArray, - augment, - asEntry, - symbol, - transform, -} from './utils.js'; - -import { - APPLY, - CONSTRUCT, - DEFINE_PROPERTY, - DELETE_PROPERTY, - GET, - GET_OWN_PROPERTY_DESCRIPTOR, - GET_PROTOTYPE_OF, - HAS, - IS_EXTENSIBLE, - OWN_KEYS, - PREVENT_EXTENSION, - SET, - SET_PROTOTYPE_OF, - DELETE -} from './traps.js'; - -export default name => { - let id = 0; - const ids = new Map; - const values = new Map; - - const __proxy__ = Symbol(); - - return function (main, MAIN, THREAD) { - const $ = this?.transform || transform; - const { [MAIN]: __main__ } = main; - - const proxies = new Map; - - const onGarbageCollected = value => { - proxies.delete(value); - __main__(DELETE, argument(value)); - }; - - const argument = asEntry( - (type, value) => { - if (__proxy__ in value) - return unbound(value[__proxy__]); - if (type === FUNCTION) { - value = $(value); - if (!values.has(value)) { - let sid; - // a bit apocalyptic scenario but if this thread runs forever - // and the id does a whole int32 roundtrip we might have still - // some reference dangling around - while (values.has(sid = String(id++))); - ids.set(value, sid); - values.set(sid, value); - } - return tv(type, ids.get(value)); - } - if (!(value instanceof TypedArray)) { - value = $(value); - for(const key in value) - value[key] = argument(value[key]); - } - return tv(type, value); - } - ); - - const register = (entry, type, value) => { - const retained = proxies.get(value)?.deref(); - if (retained) return retained; - const target = type === FUNCTION ? bound(entry) : entry; - const proxy = new Proxy(target, proxyHandler); - proxies.set(value, new WeakRef(proxy)); - return createGCHook(value, onGarbageCollected, { - return: proxy, - token: false, - }); - }; - - const fromEntry = entry => unwrap(entry, (type, value) => { - switch (type) { - case OBJECT: - if (value === null) return globalThis; - case ARRAY: - return typeof value === NUMBER ? register(entry, type, value) : value; - case FUNCTION: - return typeof value === STRING ? values.get(value) : register(entry, type, value); - case SYMBOL: - return symbol(value); - } - return value; - }); - - const result = (TRAP, target, ...args) => fromEntry(__main__(TRAP, unbound(target), ...args)); - - const proxyHandler = { - [APPLY]: (target, thisArg, args) => result(APPLY, target, argument(thisArg), args.map(argument)), - [CONSTRUCT]: (target, args) => result(CONSTRUCT, target, args.map(argument)), - [DEFINE_PROPERTY]: (target, name, descriptor) => { - const { get, set, value } = descriptor; - if (typeof get === FUNCTION) descriptor.get = argument(get); - if (typeof set === FUNCTION) descriptor.set = argument(set); - if (typeof value === FUNCTION) descriptor.value = argument(value); - return result(DEFINE_PROPERTY, target, argument(name), descriptor); - }, - [DELETE_PROPERTY]: (target, name) => result(DELETE_PROPERTY, target, argument(name)), - [GET_PROTOTYPE_OF]: target => result(GET_PROTOTYPE_OF, target), - [GET]: (target, name) => name === __proxy__ ? target : result(GET, target, argument(name)), - [GET_OWN_PROPERTY_DESCRIPTOR]: (target, name) => { - const descriptor = result(GET_OWN_PROPERTY_DESCRIPTOR, target, argument(name)); - return descriptor && augment(descriptor, fromEntry); - }, - [HAS]: (target, name) => name === __proxy__ || result(HAS, target, argument(name)), - [IS_EXTENSIBLE]: target => result(IS_EXTENSIBLE, target), - [OWN_KEYS]: target => result(OWN_KEYS, target).map(fromEntry), - [PREVENT_EXTENSION]: target => result(PREVENT_EXTENSION, target), - [SET]: (target, name, value) => result(SET, target, argument(name), argument(value)), - [SET_PROTOTYPE_OF]: (target, proto) => result(SET_PROTOTYPE_OF, target, argument(proto)), - }; - - main[THREAD] = (trap, entry, ctx, args) => { - switch (trap) { - case APPLY: - return fromEntry(entry).apply(fromEntry(ctx), args.map(fromEntry)); - case DELETE: { - const id = fromEntry(entry); - ids.delete(values.get(id)); - values.delete(id); - } - } - }; - - const global = new Proxy(tv(OBJECT, null), proxyHandler); - - return { - [name.toLowerCase()]: global, - [`is${name}Proxy`]: value => typeof value === OBJECT && !!value && __proxy__ in value, - proxy: main - }; - }; -}; diff --git a/esm/shared/traps.js b/esm/shared/traps.js deleted file mode 100644 index f520eac..0000000 --- a/esm/shared/traps.js +++ /dev/null @@ -1,2 +0,0 @@ -export * from 'proxy-target/traps'; -export const DELETE = 'delete'; diff --git a/esm/shared/utils.js b/esm/shared/utils.js deleted file mode 100644 index cd4d73d..0000000 --- a/esm/shared/utils.js +++ /dev/null @@ -1,98 +0,0 @@ -import { target as tv, wrap } from 'proxy-target/array'; - -import { - ARRAY, - OBJECT, - FUNCTION, - BOOLEAN, - NUMBER, - STRING, - UNDEFINED, - BIGINT, - SYMBOL, - NULL, -} from 'proxy-target/types'; - -const { - defineProperty, - deleteProperty, - getOwnPropertyDescriptor, - getPrototypeOf, - isExtensible, - ownKeys, - preventExtensions, - set, - setPrototypeOf -} = Reflect; - -const { assign, create } = Object; - -export const TypedArray = getPrototypeOf(Int8Array); - -export { - assign, - create, - defineProperty, - deleteProperty, - getOwnPropertyDescriptor, - getPrototypeOf, - isExtensible, - ownKeys, - preventExtensions, - set, - setPrototypeOf -}; - -export const augment = (descriptor, how) => { - const {get, set, value} = descriptor; - if (get) descriptor.get = how(get); - if (set) descriptor.set = how(set); - if (value) descriptor.value = how(value); - return descriptor; -}; - -export const asEntry = transform => value => wrap(value, (type, value) => { - switch (type) { - case NULL: - return tv(NULL, value); - case OBJECT: - if (value === globalThis) - return tv(type, null); - case ARRAY: - case FUNCTION: - return transform(type, value); - case BOOLEAN: - case NUMBER: - case STRING: - case UNDEFINED: - case BIGINT: - return tv(type, value); - case SYMBOL: { - // handle known symbols - if (symbols.has(value)) - return tv(type, symbols.get(value)); - // handle `Symbol.for('...')` cases - let key = Symbol.keyFor(value); - if (key) - return tv(type, `.${key}`); - } - } - throw new TypeError(`Unable to handle this ${type}: ${String(value)}`); -}); - -const symbols = new Map( - ownKeys(Symbol) - .filter(s => typeof Symbol[s] === SYMBOL) - .map(s => [Symbol[s], s]) -); - -export const symbol = value => { - if (value.startsWith('.')) - return Symbol.for(value.slice(1)); - for (const [symbol, name] of symbols) { - if (name === value) - return symbol; - } -}; - -export const transform = o => o; diff --git a/esm/shared/worker.js b/esm/shared/worker.js deleted file mode 100644 index 0cd6884..0000000 --- a/esm/shared/worker.js +++ /dev/null @@ -1,2 +0,0 @@ -import {FUNCTION} from 'proxy-target/types'; -export default typeof Worker === FUNCTION ? Worker : class {}; diff --git a/esm/structured.js b/esm/structured.js deleted file mode 100644 index 7e8937f..0000000 --- a/esm/structured.js +++ /dev/null @@ -1,13 +0,0 @@ -import JSON from './json.js'; -import $coincident from './index.js'; - -/** - * Create once a `Proxy` able to orchestrate synchronous `postMessage` out of the box. - * @param {globalThis | Worker} self the context in which code should run - * @returns {ProxyHandler | ProxyHandler} - */ -const coincident = (self, options) => $coincident(self, {...JSON, ...options}); - -coincident.transfer = $coincident.transfer; - -export default coincident; diff --git a/esm/uhtml.js b/esm/uhtml.js deleted file mode 100644 index 01e41b5..0000000 --- a/esm/uhtml.js +++ /dev/null @@ -1,18 +0,0 @@ -import $coincident from './window.js'; -import init from 'uhtml/init'; - -/** - * Create once a `Proxy` able to orchestrate synchronous `postMessage` out of the box. - * In workers, returns a `{proxy, window, isWindowProxy}` namespace to reach main globals synchronously. - * @param {Worker | globalThis} self the context in which code should run - */ -const coincident = (self, ...args) => { - const utilities = $coincident(self, ...args); - if (!utilities.uhtml) - utilities.uhtml = init(utilities.window.document); - return utilities; -} - -coincident.transfer = $coincident.transfer; - -export default coincident; diff --git a/esm/window.js b/esm/window.js deleted file mode 100644 index 63a8dec..0000000 --- a/esm/window.js +++ /dev/null @@ -1,33 +0,0 @@ -import {MAIN, THREAD} from './channel.js'; -import $coincident from './index.js'; -import main from './window/main.js'; -import thread from './window/thread.js'; -import Worker from './shared/worker.js'; - -const proxies = new WeakMap; - -/** - * @typedef {object} Coincident - * @property {ProxyHandler} proxy - * @property {ProxyHandler} window - * @property {(value: any) => boolean} isWindowProxy - */ - -/** - * Create once a `Proxy` able to orchestrate synchronous `postMessage` out of the box. - * In workers, returns a `{proxy, window, isWindowProxy}` namespace to reach main globals synchronously. - * @param {Worker | globalThis} self the context in which code should run - * @returns {ProxyHandler | Coincident} - */ -const coincident = (self, ...args) => { - const proxy = $coincident(self, ...args); - if (!proxies.has(proxy)) { - const util = self instanceof Worker ? main : thread; - proxies.set(proxy, util.call(args.at(0), proxy, MAIN, THREAD)); - } - return proxies.get(proxy); -} - -coincident.transfer = $coincident.transfer; - -export default coincident; diff --git a/esm/window/main.js b/esm/window/main.js deleted file mode 100644 index 66596e3..0000000 --- a/esm/window/main.js +++ /dev/null @@ -1,3 +0,0 @@ -import main from '../shared/main.js'; - -export default main('Window', true); diff --git a/esm/window/thread.js b/esm/window/thread.js deleted file mode 100644 index 9345276..0000000 --- a/esm/window/thread.js +++ /dev/null @@ -1,3 +0,0 @@ -import thread from '../shared/thread.js'; - -export default thread('Window'); diff --git a/favicon.ico b/favicon.ico deleted file mode 100644 index d9800d5..0000000 Binary files a/favicon.ico and /dev/null differ diff --git a/index.html b/index.html index 6c22de2..2539e4d 100644 --- a/index.html +++ b/index.html @@ -1,23 +1,23 @@ - - - - - - coincident smoke tests - - + + + + Coincident Tests + + - + diff --git a/mini-coi.js b/mini-coi.js deleted file mode 100644 index b7a23bf..0000000 --- a/mini-coi.js +++ /dev/null @@ -1,28 +0,0 @@ -/*! coi-serviceworker v0.1.7 - Guido Zuidhof and contributors, licensed under MIT */ -/*! mini-coi - Andrea Giammarchi and contributors, licensed under MIT */ -(({ document: d, navigator: { serviceWorker: s } }) => { - if (d) { - const { currentScript: c } = d; - s.register(c.src, { scope: c.getAttribute('scope') || '.' }).then(r => { - r.addEventListener('updatefound', () => location.reload()); - if (r.active && !s.controller) location.reload(); - }); - } - else { - addEventListener('install', () => skipWaiting()); - addEventListener('activate', e => e.waitUntil(clients.claim())); - addEventListener('fetch', e => { - const { request: r } = e; - if (r.cache === 'only-if-cached' && r.mode !== 'same-origin') return; - e.respondWith(fetch(r).then(r => { - const { body, status, statusText } = r; - if (!status || status > 399) return r; - const h = new Headers(r.headers); - h.set('Cross-Origin-Opener-Policy', 'same-origin'); - h.set('Cross-Origin-Embedder-Policy', 'require-corp'); - h.set('Cross-Origin-Resource-Policy', 'cross-origin'); - return new Response(body, { status, statusText, headers: h }); - })); - }); - } -})(self); diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 27549be..0000000 --- a/package-lock.json +++ /dev/null @@ -1,2062 +0,0 @@ -{ - "name": "coincident", - "version": "1.2.3", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "coincident", - "version": "1.2.3", - "license": "ISC", - "dependencies": { - "@ungap/structured-clone": "^1.2.0", - "@ungap/with-resolvers": "^0.1.0", - "gc-hook": "^0.3.1", - "proxy-target": "^3.0.2", - "ws": "8.18.0" - }, - "devDependencies": { - "@playwright/test": "^1.45.2", - "@rollup/plugin-node-resolve": "^15.2.3", - "@rollup/plugin-terser": "^0.4.4", - "ascjs": "^6.0.3", - "c8": "^10.1.2", - "rollup": "^4.18.1", - "static-handler": "^0.4.3", - "typescript": "^5.5.3", - "uhtml": "^4.5.9" - }, - "optionalDependencies": { - "ws": "^8.18.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz", - "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==", - "dev": true, - "license": "MIT", - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@playwright/test": { - "version": "1.45.2", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.45.2.tgz", - "integrity": "sha512-JxG9eq92ET75EbVi3s+4sYbcG7q72ECeZNbdBlaMkGcNbiDQ4cAi8U2QP5oKkOx+1gpaiL1LDStmzCaEM1Z6fQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "playwright": "1.45.2" - }, - "bin": { - "playwright": "cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@preact/signals-core": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.7.0.tgz", - "integrity": "sha512-bEZLgmJGSBVP5PUPDowhPW3bVdMmp9Tr5OEl+SQK+8Tv9T7UsIfyN905cfkmmeqw8z4xp8T6zrl4M1uj9+HAfg==", - "dev": true, - "license": "MIT", - "optional": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/preact" - } - }, - "node_modules/@rollup/plugin-node-resolve": { - "version": "15.2.3", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz", - "integrity": "sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "@types/resolve": "1.20.2", - "deepmerge": "^4.2.2", - "is-builtin-module": "^3.2.1", - "is-module": "^1.0.0", - "resolve": "^1.22.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^2.78.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/plugin-terser": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", - "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==", - "dev": true, - "license": "MIT", - "dependencies": { - "serialize-javascript": "^6.0.1", - "smob": "^1.0.0", - "terser": "^5.17.4" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/pluginutils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", - "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.1.tgz", - "integrity": "sha512-lncuC4aHicncmbORnx+dUaAgzee9cm/PbIqgWz1PpXuwc+sa1Ct83tnqUDy/GFKleLiN7ZIeytM6KJ4cAn1SxA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.1.tgz", - "integrity": "sha512-F/tkdw0WSs4ojqz5Ovrw5r9odqzFjb5LIgHdHZG65dFI1lWTWRVy32KDJLKRISHgJvqUeUhdIvy43fX41znyDg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.1.tgz", - "integrity": "sha512-vk+ma8iC1ebje/ahpxpnrfVQJibTMyHdWpOGZ3JpQ7Mgn/3QNHmPq7YwjZbIE7km73dH5M1e6MRRsnEBW7v5CQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.1.tgz", - "integrity": "sha512-IgpzXKauRe1Tafcej9STjSSuG0Ghu/xGYH+qG6JwsAUxXrnkvNHcq/NL6nz1+jzvWAnQkuAJ4uIwGB48K9OCGA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.1.tgz", - "integrity": "sha512-P9bSiAUnSSM7EmyRK+e5wgpqai86QOSv8BwvkGjLwYuOpaeomiZWifEos517CwbG+aZl1T4clSE1YqqH2JRs+g==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.1.tgz", - "integrity": "sha512-5RnjpACoxtS+aWOI1dURKno11d7krfpGDEn19jI8BuWmSBbUC4ytIADfROM1FZrFhQPSoP+KEa3NlEScznBTyQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.1.tgz", - "integrity": "sha512-8mwmGD668m8WaGbthrEYZ9CBmPug2QPGWxhJxh/vCgBjro5o96gL04WLlg5BA233OCWLqERy4YUzX3bJGXaJgQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.1.tgz", - "integrity": "sha512-dJX9u4r4bqInMGOAQoGYdwDP8lQiisWb9et+T84l2WXk41yEej8v2iGKodmdKimT8cTAYt0jFb+UEBxnPkbXEQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.1.tgz", - "integrity": "sha512-V72cXdTl4EI0x6FNmho4D502sy7ed+LuVW6Ym8aI6DRQ9hQZdp5sj0a2usYOlqvFBNKQnLQGwmYnujo2HvjCxQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.1.tgz", - "integrity": "sha512-f+pJih7sxoKmbjghrM2RkWo2WHUW8UbfxIQiWo5yeCaCM0TveMEuAzKJte4QskBp1TIinpnRcxkquY+4WuY/tg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.1.tgz", - "integrity": "sha512-qb1hMMT3Fr/Qz1OKovCuUM11MUNLUuHeBC2DPPAWUYYUAOFWaxInaTwTQmc7Fl5La7DShTEpmYwgdt2hG+4TEg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.1.tgz", - "integrity": "sha512-7O5u/p6oKUFYjRbZkL2FLbwsyoJAjyeXHCU3O4ndvzg2OFO2GinFPSJFGbiwFDaCFc+k7gs9CF243PwdPQFh5g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.1.tgz", - "integrity": "sha512-pDLkYITdYrH/9Cv/Vlj8HppDuLMDUBmgsM0+N+xLtFd18aXgM9Nyqupb/Uw+HeidhfYg2lD6CXvz6CjoVOaKjQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.1.tgz", - "integrity": "sha512-W2ZNI323O/8pJdBGil1oCauuCzmVd9lDmWBBqxYZcOqWD6aWqJtVBQ1dFrF4dYpZPks6F+xCZHfzG5hYlSHZ6g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.1.tgz", - "integrity": "sha512-ELfEX1/+eGZYMaCIbK4jqLxO1gyTSOIlZr6pbC4SRYFaSIDVKOnZNMdoZ+ON0mrFDp4+H5MhwNC1H/AhE3zQLg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.1.tgz", - "integrity": "sha512-yjk2MAkQmoaPYCSu35RLJ62+dz358nE83VfTePJRp8CG7aMg25mEJYpXFiD+NcevhX8LxD5OP5tktPXnXN7GDw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/resolve": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", - "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "license": "ISC" - }, - "node_modules/@ungap/with-resolvers": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@ungap/with-resolvers/-/with-resolvers-0.1.0.tgz", - "integrity": "sha512-g7f0IkJdPW2xhY7H4iE72DAsIyfuwEFc6JWc2tYFwKDMWWAF699vGjrM348cwQuOXgHpe1gWFe+Eiyjx/ewvvw==", - "license": "ISC" - }, - "node_modules/@webreflection/signal": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@webreflection/signal/-/signal-2.1.2.tgz", - "integrity": "sha512-0dW0fstQQkIt588JwhDiPS4xgeeQcQnBHn6MVInrBzmFlnLtzoSJL9G7JqdAlZVVi19tfb8R1QisZIT31cgiug==", - "dev": true, - "license": "ISC", - "optional": true - }, - "node_modules/@webreflection/uparser": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@webreflection/uparser/-/uparser-0.3.3.tgz", - "integrity": "sha512-XxGfo8jr2eVuvP5lrmwjgMAM7QjtZ0ngFD+dd9Fd3GStcEb4QhLlTiqZYF5O3l5k4sU/V6ZiPrVCzCWXWFEmCw==", - "dev": true, - "license": "ISC", - "dependencies": { - "domconstants": "^1.1.6" - } - }, - "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ascjs": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/ascjs/-/ascjs-6.0.3.tgz", - "integrity": "sha512-lAIyi1j7oT0OtF9yFLiRf93LEcK7xTb/gPFwmfdi2T/BQmxJi1YcIES+VnP/kgGJkxq9Oh2DEK6GrZ6l2OVhVQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "@babel/parser": "^7.12.5" - }, - "bin": { - "ascjs": "bin.js" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/c8": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/c8/-/c8-10.1.2.tgz", - "integrity": "sha512-Qr6rj76eSshu5CgRYvktW0uM0CFY0yi4Fd5D0duDXO6sYinyopmftUiJVuzBQxQcwQLor7JWDVRP+dUfCmzgJw==", - "dev": true, - "license": "ISC", - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@istanbuljs/schema": "^0.1.3", - "find-up": "^5.0.0", - "foreground-child": "^3.1.1", - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-report": "^3.0.1", - "istanbul-reports": "^3.1.6", - "test-exclude": "^7.0.1", - "v8-to-istanbul": "^9.0.0", - "yargs": "^17.7.2", - "yargs-parser": "^21.1.1" - }, - "bin": { - "c8": "bin/c8.js" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "monocart-coverage-reports": "^2" - }, - "peerDependenciesMeta": { - "monocart-coverage-reports": { - "optional": true - } - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/custom-function": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/custom-function/-/custom-function-1.0.6.tgz", - "integrity": "sha512-styyvwOki/EYr+VBe7/m9xAjq6uKx87SpDKIpFRdTQnofBDSZpBEFc9qJLmaJihjjTeEpAIJ+nz+9fUXj+BPNQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, - "license": "MIT", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domconstants": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/domconstants/-/domconstants-1.1.6.tgz", - "integrity": "sha512-CuaDrThJ4VM+LyZ4ax8n52k0KbLJZtffyGkuj1WhpTRRcSfcy/9DfOBa68jenhX96oNUTunblSJEUNC4baFdmQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" - }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, - "license": "MIT" - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT" - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true, - "license": "MIT" - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/foreground-child": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", - "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", - "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gc-hook": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/gc-hook/-/gc-hook-0.3.1.tgz", - "integrity": "sha512-E5M+O/h2o7eZzGhzRZGex6hbB3k4NWqO0eA+OzLRLXxhdbYPajZnynPwAtphnh+cRHPwsj5Z80dqZlfI4eK55A==", - "license": "ISC" - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true, - "license": "MIT" - }, - "node_modules/htmlparser2": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", - "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "MIT", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.1.0", - "entities": "^4.5.0" - } - }, - "node_modules/is-builtin-module": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", - "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", - "dev": true, - "license": "MIT", - "dependencies": { - "builtin-modules": "^3.3.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-core-module": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", - "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", - "dev": true, - "license": "MIT" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/package-json-from-dist": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", - "dev": true, - "license": "BlueOak-1.0.0" - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/playwright": { - "version": "1.45.2", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.2.tgz", - "integrity": "sha512-ReywF2t/0teRvNBpfIgh5e4wnrI/8Su8ssdo5XsQKpjxJj+jspm00jSoz9BTg91TT0c9HRjXO7LBNVrgYj9X0g==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "playwright-core": "1.45.2" - }, - "bin": { - "playwright": "cli.js" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "fsevents": "2.3.2" - } - }, - "node_modules/playwright-core": { - "version": "1.45.2", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.2.tgz", - "integrity": "sha512-ha175tAWb0dTK0X4orvBIqi3jGEt701SMxMhyujxNrgd8K0Uy5wMSwwcQHtyB4om7INUkfndx02XnQ2p6dvLDw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "playwright-core": "cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/proxy-target": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/proxy-target/-/proxy-target-3.0.2.tgz", - "integrity": "sha512-FFE1XNwXX/FNC3/P8HiKaJSy/Qk68RitG/QEcLy/bVnTAPlgTAWPZKh0pARLAnpfXQPKyalBhk009NRTgsk8vQ==", - "license": "MIT" - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/rollup": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.1.tgz", - "integrity": "sha512-Elx2UT8lzxxOXMpy5HWQGZqkrQOtrVDDa/bm9l10+U4rQnVzbL/LgZ4NOM1MPIDyHk69W4InuYDF5dzRh4Kw1A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.5" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.18.1", - "@rollup/rollup-android-arm64": "4.18.1", - "@rollup/rollup-darwin-arm64": "4.18.1", - "@rollup/rollup-darwin-x64": "4.18.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.18.1", - "@rollup/rollup-linux-arm-musleabihf": "4.18.1", - "@rollup/rollup-linux-arm64-gnu": "4.18.1", - "@rollup/rollup-linux-arm64-musl": "4.18.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.18.1", - "@rollup/rollup-linux-riscv64-gnu": "4.18.1", - "@rollup/rollup-linux-s390x-gnu": "4.18.1", - "@rollup/rollup-linux-x64-gnu": "4.18.1", - "@rollup/rollup-linux-x64-musl": "4.18.1", - "@rollup/rollup-win32-arm64-msvc": "4.18.1", - "@rollup/rollup-win32-ia32-msvc": "4.18.1", - "@rollup/rollup-win32-x64-msvc": "4.18.1", - "fsevents": "~2.3.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/smob": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz", - "integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==", - "dev": true, - "license": "MIT" - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/static-handler": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/static-handler/-/static-handler-0.4.3.tgz", - "integrity": "sha512-rHi6vtxW/kjC+L18cRVAICAp/ymTjyvZHCPXIrejrlVrRrNxrVGk9FNCg+rC9wM7SpZ9euyjsr7tNVtqpA2iLA==", - "dev": true, - "license": "ISC", - "dependencies": { - "mime-types": "^2.1.35" - }, - "bin": { - "static-handler": "static-handler.cjs" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/string-width-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/terser": { - "version": "5.31.3", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.3.tgz", - "integrity": "sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/test-exclude": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", - "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", - "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^10.4.1", - "minimatch": "^9.0.4" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/udomdiff": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/udomdiff/-/udomdiff-1.1.0.tgz", - "integrity": "sha512-aqjTs5x/wsShZBkVagdafJkP8S3UMGhkHKszsu1cszjjZ7iOp86+Qb3QOFYh01oWjPMy5ZTuxD6hw5uTKxd+VA==", - "dev": true, - "license": "ISC" - }, - "node_modules/uhtml": { - "version": "4.5.9", - "resolved": "https://registry.npmjs.org/uhtml/-/uhtml-4.5.9.tgz", - "integrity": "sha512-WAfIK/E3ZJpaFl0MSzGSB54r7I8Vc8ZyUlOsN8GnLnEaxuioOUyKAS6q/N/xQ5GD9vFFBnx6q+3N3Eq9KNCvTQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webreflection/uparser": "^0.3.3", - "custom-function": "^1.0.6", - "domconstants": "^1.1.6", - "gc-hook": "^0.3.1", - "html-escaper": "^3.0.3", - "htmlparser2": "^9.1.0", - "udomdiff": "^1.1.0" - }, - "optionalDependencies": { - "@preact/signals-core": "^1.6.0", - "@webreflection/signal": "^2.1.2" - } - }, - "node_modules/uhtml/node_modules/html-escaper": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", - "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/v8-to-istanbul": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", - "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", - "dev": true, - "license": "ISC", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/wrap-ansi-cjs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/package.json b/package.json index f6ed922..650dd28 100644 --- a/package.json +++ b/package.json @@ -1,92 +1,38 @@ { "name": "coincident", - "version": "1.2.3", + "version": "2.0.0", "description": "An Atomics based Proxy to simplify, and synchronize, Worker related tasks", - "main": "./cjs/index.js", - "types": "./types/index.d.ts", "scripts": { - "build": "node rollup/channel.cjs && npm run cjs && npm run rollup:es && npm run rollup:window && npm run rollup:structured && npm run rollup:uhtml && npm run rollup:server && npm run ts && npm run test:integration && cp *.js test/dist/ && npm run size", - "cjs": "ascjs --no-default esm cjs", - "rollup:es": "rollup --config rollup/es.config.js", - "rollup:server": "rollup --config rollup/server.config.js", - "rollup:structured": "rollup --config rollup/structured.config.js", - "rollup:uhtml": "rollup --config rollup/uhtml.config.js", - "rollup:window": "rollup --config rollup/window.config.js", - "test": "c8 node test/index.js", - "test:integration": "static-handler --coi . 2>/dev/null & SH_PID=$!; EXIT_CODE=0; playwright test test/ || EXIT_CODE=$?; kill $SH_PID 2>/dev/null; exit $EXIT_CODE", - "test:server": "node test/server/main.cjs", - "ts": "tsc -p .", - "server": "npx static-handler --coi .", - "size": "echo -e \"\\x1b[1mfile size\\x1b[0m\"; echo \"es $(cat es.js | brotli | wc -c)\"; echo \"structured $(cat structured.js | brotli | wc -c)\"; echo \"window $(cat window.js | brotli | wc -c)\"; echo \"server $(cat server.js | brotli | wc -c)\"; echo \"uhtml $(cat uhtml.js | brotli | wc -c)\";", - "coverage": "mkdir -p ./coverage; c8 report --reporter=text-lcov > ./coverage/lcov.info" + "build": "node build/index.cjs && node build/constants.cjs && rollup --config build/dist.js && sabayon ./test/sw.js && npm run size", + "coi": "npx mini-coi .", + "server": "static-handler .", + "size": "echo -e \"\\x1b[1mfile size\\x1b[0m\"; echo \"main $(cat dist/main.js | brotli | wc -c)\"; echo \"worker $(cat dist/worker.js | brotli | wc -c)\"; echo \"window/worker $(cat dist/window/worker.js | brotli | wc -c)\"; echo \"window/main $(cat dist/window/main.js | brotli | wc -c)\";" }, "keywords": [ "Atomics", "Worker", - "sync", - "synchronize" + "sync" ], "author": "Andrea Giammarchi", - "license": "ISC", + "license": "MIT", "devDependencies": { - "@playwright/test": "^1.45.2", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^0.4.4", - "ascjs": "^6.0.3", - "c8": "^10.1.2", - "rollup": "^4.18.1", - "static-handler": "^0.4.3", - "typescript": "^5.5.3", - "uhtml": "^4.5.9" + "mini-coi": "^0.3.3", + "rollup": "^4.19.0", + "static-handler": "^0.4.3" }, - "module": "./esm/index.js", "type": "module", "exports": { - ".": { - "types": "./types/index.d.ts", - "import": "./esm/index.js", - "default": "./cjs/index.js" - }, - "./window": { - "types": "./types/window.d.ts", - "import": "./esm/window.js", - "default": "./cjs/window.js" - }, - "./bun": { - "types": "./types/bun.d.ts", - "import": "./esm/bun.js", - "default": "./cjs/bun.js" - }, - "./server": { - "types": "./types/server.d.ts", - "import": "./esm/server.js", - "default": "./cjs/server.js" - }, - "./structured": { - "types": "./types/structured.d.ts", - "import": "./esm/structured.js", - "default": "./cjs/structured.js" - }, - "./json": { - "types": "./types/json.d.ts", - "import": "./esm/json.js", - "default": "./cjs/json.js" - }, - "./uhtml": { - "types": "./types/window.d.ts", - "import": "./esm/uhtml.js", - "default": "./cjs/uhtml.js" - }, + "./main": "./src/main.js", + "./worker": "./src/worker.js", + "./window/main": "./src/window/main.js", + "./window/worker": "./src/window/worker.js", "./package.json": "./package.json" }, - "unpkg": "es.js", "dependencies": { - "@ungap/structured-clone": "^1.2.0", - "@ungap/with-resolvers": "^0.1.0", "gc-hook": "^0.3.1", - "proxy-target": "^3.0.2" - }, - "optionalDependencies": { - "ws": "^8.18.0" + "js-proxy": "^0.4.3", + "sabayon": "^0.5.0" } } diff --git a/rollup/channel.cjs b/rollup/channel.cjs deleted file mode 100644 index 64faf42..0000000 --- a/rollup/channel.cjs +++ /dev/null @@ -1,13 +0,0 @@ -const {join} = require('node:path'); -const {readFileSync, writeFileSync} = require('node:fs'); -const {randomUUID} = require('node:crypto'); - -const CHANNEL = join(__dirname, '..', 'esm', 'channel.js'); - -writeFileSync( - CHANNEL, - readFileSync(CHANNEL).toString().replace( - /(['"]).*?\1/, - `$1${randomUUID()}$1` - ) -); diff --git a/rollup/es.config.js b/rollup/es.config.js deleted file mode 100644 index 46c5501..0000000 --- a/rollup/es.config.js +++ /dev/null @@ -1,11 +0,0 @@ -import {nodeResolve} from '@rollup/plugin-node-resolve'; -import terser from '@rollup/plugin-terser'; - -export default { - input: './esm/index.js', - plugins: [nodeResolve()].concat(process.env.NO_MIN ? [] : [terser()]), - output: { - esModule: true, - file: './es.js', - } -}; diff --git a/rollup/server.config.js b/rollup/server.config.js deleted file mode 100644 index 26b987e..0000000 --- a/rollup/server.config.js +++ /dev/null @@ -1,11 +0,0 @@ -import {nodeResolve} from '@rollup/plugin-node-resolve'; -import terser from '@rollup/plugin-terser'; - -export default { - input: './esm/server.js', - plugins: [nodeResolve()].concat(process.env.NO_MIN ? [] : [terser()]), - output: { - esModule: true, - file: './server.js', - } -}; diff --git a/rollup/structured.config.js b/rollup/structured.config.js deleted file mode 100644 index ace9b61..0000000 --- a/rollup/structured.config.js +++ /dev/null @@ -1,11 +0,0 @@ -import {nodeResolve} from '@rollup/plugin-node-resolve'; -import terser from '@rollup/plugin-terser'; - -export default { - input: './esm/structured.js', - plugins: [nodeResolve()].concat(process.env.NO_MIN ? [] : [terser()]), - output: { - esModule: true, - file: './structured.js', - } -}; diff --git a/rollup/uhtml.config.js b/rollup/uhtml.config.js deleted file mode 100644 index 776edc0..0000000 --- a/rollup/uhtml.config.js +++ /dev/null @@ -1,11 +0,0 @@ -import {nodeResolve} from '@rollup/plugin-node-resolve'; -import terser from '@rollup/plugin-terser'; - -export default { - input: './esm/uhtml.js', - plugins: [nodeResolve()].concat(process.env.NO_MIN ? [] : [terser()]), - output: { - esModule: true, - file: './uhtml.js', - } -}; diff --git a/rollup/window.config.js b/rollup/window.config.js deleted file mode 100644 index 15092e7..0000000 --- a/rollup/window.config.js +++ /dev/null @@ -1,11 +0,0 @@ -import {nodeResolve} from '@rollup/plugin-node-resolve'; -import terser from '@rollup/plugin-terser'; - -export default { - input: './esm/window.js', - plugins: [nodeResolve()].concat(process.env.NO_MIN ? [] : [terser()]), - output: { - esModule: true, - file: './window.js', - } -}; diff --git a/src/debug.js b/src/debug.js new file mode 100644 index 0000000..3313654 --- /dev/null +++ b/src/debug.js @@ -0,0 +1 @@ +export default false; diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..5aee217 --- /dev/null +++ b/src/main.js @@ -0,0 +1,92 @@ +// (c) Andrea Giammarchi - MIT + +import { + Atomics, + Int32Array, + SharedArrayBuffer, + Worker as $Worker, + ignore, + polyfill, +} from 'sabayon/main'; + +import { + ACTION_INIT, + ACTION_WAIT, + ACTION_NOTIFY, + + actionLength, + actionFill, + actionWait, + + createProxy, + + isChannel, + transfer, +} from './shared.js'; + +/** + * @typedef {Object} MainOptions + * @prop {(text: string, ...args:any) => any} [parse=JSON.parse] + * @prop {(value: any, ...args:any) => string} [stringify=JSON.stringify] + * @prop {(value: any) => any} [transform] + */ + +/** + * @callback Coincident + * @param {MainOptions} [options] + * @returns {{Worker: import('./ts.js').CoincidentWorker, polyfill: boolean, transfer: (...args: Transferable[]) => Transferable[]}} + */ + +export default /** @type {Coincident} */ ({ + parse, + stringify, + transform, +} = JSON) => { + const waitLength = actionLength(stringify, transform); + + const CHANNEL = crypto.randomUUID(); + + class Worker extends $Worker { + constructor(url, options) { + const map = new Map; + const results = new Map; + super(url, options); + this.proxy = createProxy( + [ + CHANNEL, + bytes => new Int32Array(new SharedArrayBuffer(bytes)), + ignore, + false, + parse, + polyfill, + (...args) => this.postMessage(...args), + transform, + Atomics.waitAsync, + ], + map, + ); + this.postMessage(ignore([CHANNEL, ACTION_INIT, options])); + this.addEventListener('message', event => { + if (isChannel(event, CHANNEL)) { + const [_, ACTION, ...rest] = event.data; + switch (ACTION) { + case ACTION_WAIT: { + actionWait(waitLength, results, map, rest); + break; + } + case ACTION_NOTIFY: { + actionFill(results, rest); + break; + } + } + } + }); + } + } + + return { + Worker, + polyfill, + transfer, + }; +}; diff --git a/src/shared.js b/src/shared.js new file mode 100644 index 0000000..4f48892 --- /dev/null +++ b/src/shared.js @@ -0,0 +1,134 @@ +// (c) Andrea Giammarchi - MIT + +import { + ACTION_INIT, + ACTION_NOTIFY, + ACTION_WAIT, + Atomics, + isChannel, + withResolvers, +} from 'sabayon/shared'; + +const { BYTES_PER_ELEMENT: I32_BYTES } = Int32Array; +const { BYTES_PER_ELEMENT: UI16_BYTES } = Uint16Array; + +const { notify } = Atomics; + +const decoder = new TextDecoder('utf-16'); + +const buffers = new WeakSet; + +const transfer = (...args) => (buffers.add(args), args); + +let seppuku = ''; +const actionLength = (stringify, transform) => async (callback, results, [name, id, sb, args, isSync]) => { + if (isSync) seppuku = name; + try { + const result = await callback(...args); + if (result !== void 0) { + const serialized = stringify(transform ? transform(result) : result); + results.set(id, serialized); + sb[1] = serialized.length; + } + } + finally { + if (isSync) seppuku = ''; + sb[0] = 1; + notify(sb, 0); + } +}; +const actionFill = (results, [id, sb]) => { + const result = results.get(id); + results.delete(id); + for (let ui16a = new Uint16Array(sb.buffer), i = 0, { length } = result; i < length; i++) + ui16a[i] = result.charCodeAt(i); + notify(sb, 0); +}; +const actionWait = (waitLength, results, map, rest) => { + const [name] = rest; + const callback = map.get(name); + if (!callback) throw new Error(`Unknown proxy.${name}()`); + waitLength(callback, results, rest); +}; + +const warn = (name, seppuku) => setTimeout( + console.warn, + 1000, + `💀🔒 - proxy.${name}() in proxy.${seppuku}()` +); + +let uid = 0; +const invoke = ( + [ + CHANNEL, + i32View, + ignore, + isSync, + parse, + polyfill, + postMessage, + transform, + waitAsync, + ], + name, +) => (...args) => { + let deadlock = seppuku !== '', timer = 0; + if (deadlock) timer = warn(name, seppuku); + const id = uid++; + const transfer = []; + if (buffers.has(args.at(-1) || transfer)) + buffers.delete(transfer = args.pop()); + const data = ignore(transform ? args.map(transform) : args); + let sb = i32View(I32_BYTES * 2); + postMessage([CHANNEL, ACTION_WAIT, name, id, sb, data, isSync], { transfer }); + return waitAsync(sb, 0).value.then(() => { + if (deadlock) clearTimeout(timer); + const length = sb[1]; + if (!length) return; + const bytes = UI16_BYTES * length; + sb = i32View(bytes + (bytes % I32_BYTES)); + postMessage([CHANNEL, ACTION_NOTIFY, id, sb]); + return waitAsync(sb, 0).value.then(() =>{ + const ui16a = new Uint16Array(sb.buffer); + const sub = polyfill ? ui16a.subarray(0, length) : ui16a.slice(0, length); + return parse(decoder.decode(sub)); + }); + }); +}; + +const createProxy = (details, map) => new Proxy(map, { + get: (map, name) => { + let cb; + // the curse of potentially awaiting proxies in the wild + // requires this ugly guard around `then` + if (name !== 'then') { + cb = map.get(name); + if (!cb) { + cb = invoke(details, name); + map.set(name, cb); + } + } + return cb; + }, + set: (map, name, callback) => ( + name !== 'then' && + !!map.set(name, callback) + ), +}); + +export { + ACTION_INIT, + ACTION_WAIT, + ACTION_NOTIFY, + + actionLength, + actionFill, + actionWait, + + createProxy, + + isChannel, + transfer, + + withResolvers, +}; diff --git a/src/ts.js b/src/ts.js new file mode 100644 index 0000000..ed18819 --- /dev/null +++ b/src/ts.js @@ -0,0 +1,11 @@ +// this file exists only to please JSDoc TS + +/** @typedef {Record} Proxy */ + +export class CoincidentWorker extends Worker { + constructor(url, options) { + super(url, { ...options, type: 'module' }); + /** @type {Proxy} */ + this.proxy = {}; + } +} diff --git a/src/window/constants.js b/src/window/constants.js new file mode 100644 index 0000000..f9a99ca --- /dev/null +++ b/src/window/constants.js @@ -0,0 +1,4 @@ +// ⚠️ AUTOMATICALLY GENERATED - DO NOT CHANGE +const CHANNEL = '8d26f914-addd-4e13-a753-010b90b835f2'; +export const MAIN = 'M' + CHANNEL; +export const WORKER = 'W' + CHANNEL; diff --git a/src/window/events.js b/src/window/events.js new file mode 100644 index 0000000..bbf5a8c --- /dev/null +++ b/src/window/events.js @@ -0,0 +1,23 @@ +const { addEventListener } = EventTarget.prototype; +const eventsHandler = new WeakMap; +Reflect.defineProperty(EventTarget.prototype, 'addEventListener', { + value(type, listener, ...options) { + const invoke = options.at(0)?.invoke; + if (invoke) { + let map = eventsHandler.get(this); + if (!map) { + map = new Map; + eventsHandler.set(this, map); + } + map.set(type, [].concat(invoke)); + delete options[0].invoke; + } + return addEventListener.call(this, type, listener, ...options); + }, +}); + +export default event => { + const { currentTarget, target, type } = event; + const methods = eventsHandler.get(currentTarget || target)?.get(type); + if (methods) for (const method of methods) event[method](); +}; diff --git a/src/window/main.js b/src/window/main.js new file mode 100644 index 0000000..34a37dd --- /dev/null +++ b/src/window/main.js @@ -0,0 +1,148 @@ +import { drop, get, hold } from 'js-proxy/heap'; +import { TypedArray } from 'sabayon/shared'; + +import coincident from '../main.js'; +import numeric from './types.js'; +import { fromSymbol, toSymbol } from './symbol.js'; + +import { + APPLY, + DEFINE_PROPERTY, + GET_OWN_PROPERTY_DESCRIPTOR, + OWN_KEYS, + DESTRUCT, +} from 'js-proxy/traps'; + +import { + ARRAY, + FUNCTION, + NULL, + NUMBER, + OBJECT, + STRING, + SYMBOL, + UNDEFINED, +} from 'js-proxy/types'; + +import { MAIN, WORKER } from './constants.js'; + +import { create } from 'gc-hook'; + +import handleEvent from './events.js'; + +import DEBUG from '../debug.js'; + +const { isArray } = Array; + +export default /** @type {import('../main.js').Coincident} */ options => { + const exports = coincident(options); + + const toEntry = value => { + const TYPE = typeof value; + switch (TYPE) { + case OBJECT: { + if (value === null) return [numeric[NULL], value]; + if (value === globalThis) return [numeric[OBJECT], null]; + if (isArray(value)) return [numeric[ARRAY], hold(value)]; + return [numeric[OBJECT], value instanceof TypedArray ? value : hold(value)]; + } + case FUNCTION: return [numeric[FUNCTION], hold(value)]; + case SYMBOL: return [numeric[SYMBOL], toSymbol(value)]; + default: return [numeric[TYPE], value]; + } + }; + + class Worker extends exports.Worker { + constructor(url, options) { + const { proxy } = super(url, options); + const { [WORKER]: __worker__ } = proxy; + + const proxies = new Map; + const onGC = ref => { + proxies.delete(ref); + __worker__(DESTRUCT, ref); + } + + const fromEntry = ([numericTYPE, value]) => { + switch (numericTYPE) { + case numeric[OBJECT]: { + if (value === null) return globalThis; + if (typeof value === NUMBER) return get(value); + if (!(value instanceof TypedArray)) { + for (const key in value) + value[key] = fromEntry(value[key]); + } + return value; + }; + case numeric[ARRAY]: { + if (typeof value === NUMBER) return get(value); + return value.map(fromEntry); + }; + case numeric[FUNCTION]: { + switch (typeof value) { + case NUMBER: return get(value); + case STRING: { + let fn = proxies.get(value)?.deref(); + if (!fn) { + fn = create(value, onGC, { + token: false, + return: function (...args) { + if (args.length && args[0] instanceof Event) handleEvent(args[0]); + return __worker__(APPLY, value, toEntry(this), args.map(toEntry)).then(fromEntry); + } + }); + proxies.set(value, new WeakRef(fn)); + } + return fn; + } + } + }; + case numeric[SYMBOL]: return fromSymbol(value); + default: return value; + } + }; + + const asEntry = (method, target, args) => toEntry(method(target, ...args.map(fromEntry))); + + proxy[MAIN] = (TRAP, ref, ...args) => { + if (TRAP === DESTRUCT) drop(ref); + else { + const method = Reflect[TRAP]; + const target = ref == null ? globalThis : get(ref); + switch (TRAP) { + case DEFINE_PROPERTY: { + const [name, descriptor] = args.map(fromEntry); + return toEntry(method(target, name, descriptor)); + } + case GET_OWN_PROPERTY_DESCRIPTOR: { + const descriptor = method(target, ...args.map(fromEntry)); + if (descriptor) { + const { get, set, value } = descriptor; + if (get) descriptor.get = toEntry(get); + if (set) descriptor.set = toEntry(set); + if (value) descriptor.value = toEntry(value); + } + return [numeric[descriptor ? OBJECT : UNDEFINED], descriptor]; + } + case OWN_KEYS: return [numeric[ARRAY], method(target).map(toEntry)]; + default: return asEntry(method, target, args); + } + } + }; + + if (DEBUG) { + const debug = proxy[MAIN]; + proxy[MAIN] = (TRAP, ...args) => { + const destructing = TRAP === DESTRUCT; + const method = destructing ? console.warn : console.log; + method('Main before', TRAP, ...args); + const result = debug(TRAP, ...args); + if (!destructing) method('Main after', TRAP, result); + return result; + }; + } + } + } + + return { ...exports, Worker }; +}; diff --git a/src/window/symbol.js b/src/window/symbol.js new file mode 100644 index 0000000..0a0fe0a --- /dev/null +++ b/src/window/symbol.js @@ -0,0 +1,24 @@ +import { OWN_KEYS } from 'js-proxy/traps'; +import { SYMBOL } from 'js-proxy/types'; + +const { [OWN_KEYS]: ownKeys } = Reflect; + +const known = new Map( + ownKeys(Symbol) + .filter(s => typeof Symbol[s] === SYMBOL) + .map(s => [Symbol[s], s]) +); + +export const fromSymbol = value => { + if (value.startsWith('.')) + return Symbol.for(value.slice(1)); + for (const [symbol, name] of known) { + if (name === value) + return symbol; + } +}; + +export const toSymbol = value => ( + known.get(value) || + `.${Symbol.keyFor(value) || ''}` +); diff --git a/src/window/types.js b/src/window/types.js new file mode 100644 index 0000000..aad1fe1 --- /dev/null +++ b/src/window/types.js @@ -0,0 +1,34 @@ +import { + ARRAY, + BIGINT, + BOOLEAN, + FUNCTION, + NULL, + NUMBER, + OBJECT, + STRING, + SYMBOL, + UNDEFINED, +} from 'js-proxy/types'; + +// this literal allows mapping right away +// string types into numeric values so that +// the transported and transformed arrays +// would use less bytes to satisfy te same +// contract while exchanging information. +// basically this is an home-made ENUM like +// object literal ... that's it. +// TBD: should this be part of js-proxy? it feels +// to me like it would rather belong in there. +export default Object.fromEntries([ + ARRAY, + BIGINT, + BOOLEAN, + FUNCTION, + NULL, + NUMBER, + OBJECT, + STRING, + SYMBOL, + UNDEFINED, +].map((k, i) => [k, i])); diff --git a/src/window/worker.js b/src/window/worker.js new file mode 100644 index 0000000..0ff8597 --- /dev/null +++ b/src/window/worker.js @@ -0,0 +1,187 @@ +import define from 'js-proxy'; +import { drop, get, hold } from 'js-proxy/heap'; +import { TypedArray } from 'sabayon/shared'; + +import coincident from '../worker.js'; +import numeric from './types.js'; +import { fromSymbol, toSymbol } from './symbol.js'; + +import { + APPLY, + CONSTRUCT, + DEFINE_PROPERTY, + DELETE_PROPERTY, + GET, + GET_OWN_PROPERTY_DESCRIPTOR, + GET_PROTOTYPE_OF, + HAS, + IS_EXTENSIBLE, + OWN_KEYS, + PREVENT_EXTENSION, + SET, + SET_PROTOTYPE_OF, + DESTRUCT, +} from 'js-proxy/traps'; + +import { ARRAY, FUNCTION, NUMBER, OBJECT, SYMBOL } from 'js-proxy/types'; + +import { MAIN, WORKER } from './constants.js'; + +import DEBUG from '../debug.js'; + +const { [APPLY]: apply } = Reflect; + +/** + * @callback Coincident + * @param {import('../worker.js').WorkerOptions} [options] + * @returns {Promise<{polyfill: boolean, sync: boolean, transfer: (...args: Transferable[]) => Transferable[], proxy: {}, window: Window, isWindowProxy: (value: any) => boolean}>} + */ + +export default /** @type {Coincident} */ async options => { + const exports = await coincident(options); + const $ = options?.transform || ((o) => o); + const { [MAIN]: __main__ } = exports.proxy; + + const proxies = new Map; + const proxied = (value, proxy) => { + let ref = proxies.get(value)?.deref(); + if (!ref) proxies.set(value, new WeakRef((ref = proxy(value)))); + return ref; + }; + + const fromEntry = ([numericTYPE, value]) => { + switch (numericTYPE) { + case numeric[OBJECT]: return ( + value == null ? + globalThis : + typeof value === NUMBER ? + proxied(value, proxy.object) : + value + ); + case numeric[ARRAY]: return typeof value === NUMBER ? proxied(value, proxy.array) : value; + case numeric[FUNCTION]: return ( + typeof value === NUMBER ? + proxied(value, proxy.function) : + get(parseInt(value)) + ); + case numeric[SYMBOL]: return fromSymbol(value); + default: return value; + } + }; + + const toEntry = value => { + let [TYPE, ref] = pair(value); + switch (TYPE) { + case OBJECT: { + if (ref == globalThis || ref == null) ref = null; + else if ((typeof ref === OBJECT) && !(ref instanceof TypedArray)) { + ref = $(ref); + for (const key in ref) ref[key] = toEntry(ref[key]); + } + return [numeric[OBJECT], ref]; + } + case ARRAY: { + return [numeric[ARRAY], typeof ref === NUMBER ? ref : $(ref).map(toEntry)]; + } + case FUNCTION: { + // own local functions as String(id) + return [numeric[FUNCTION], typeof ref === FUNCTION ? String(hold($(ref))) : ref]; + } + case SYMBOL: return [numeric[SYMBOL], toSymbol(value)]; + default: return [numeric[TYPE], ref]; + } + }; + + const asEntry = (...args) => fromEntry(__main__(...args)); + + const handler = { + [DEFINE_PROPERTY]: (ref, name, descriptor) => asEntry(DEFINE_PROPERTY, ref, toEntry(name), toEntry(descriptor)), + [DELETE_PROPERTY]: (ref, name) => asEntry(DELETE_PROPERTY, ref, toEntry(name)), + [GET]: (ref, name) => asEntry(GET, ref, toEntry(name)), + [GET_PROTOTYPE_OF]: (ref) => asEntry(GET_PROTOTYPE_OF, ref), + [GET_OWN_PROPERTY_DESCRIPTOR]: (ref, name) => { + const descriptor = asEntry(GET_OWN_PROPERTY_DESCRIPTOR, ref, toEntry(name)); + if (descriptor) { + const { get, set, value } = descriptor; + if (get) descriptor.get = fromEntry(get); + if (set) descriptor.set = fromEntry(set); + if (value) descriptor.value = fromEntry(value); + } + return descriptor; + }, + [HAS]: (ref, name) => asEntry(HAS, ref, toEntry(name)), + [IS_EXTENSIBLE]: (ref) => asEntry(IS_EXTENSIBLE, ref), + [OWN_KEYS]: (ref) => asEntry(OWN_KEYS, ref).map(fromEntry), + [PREVENT_EXTENSION]: (ref) => asEntry(PREVENT_EXTENSION, ref), + [SET]: (ref, name, value) => asEntry(SET, ref, toEntry(name), toEntry(value)), + [SET_PROTOTYPE_OF]: (ref, proto) => asEntry(SET_PROTOTYPE_OF, ref, toEntry(proto)), + + [DESTRUCT](ref) { + proxies.delete(ref); + __main__(DESTRUCT, ref); + }, + }; + + const definition = { + object: handler, + array: handler, + function: { + ...handler, + [APPLY]: (ref, ...args) => asEntry(APPLY, ref, ...args.map(toEntry)), + [CONSTRUCT]: (ref, ...args) => asEntry(CONSTRUCT, ref, ...args.map(toEntry)), + }, + }; + + if (DEBUG) { + const augment = handler => { + for (const key in handler) { + const method = handler[key]; + handler[key] = function (...args) { + console.log('Proxy handler before', key, ...args); + const result = method.apply(this, args); + if (key !== DESTRUCT) console.log('Proxy handler after', key, result); + return result; + }; + } + }; + augment(handler); + augment(definition.function); + } + + const { proxy, isProxy, pair } = define(definition); + + // when exports.sync is `false` ... there is a possibility + // to make this read-only by changing the Proxy kind and + // just queue accessors until `await` is performed (a `then` get) + // this feels a bit too much though, let's say for the + // time being I don't care about that possibility 😇 + const window = proxy.object(null); + + // for the time being this is used only to invoke callbacks + // attached as listeners or as references' fields. + exports.proxy[WORKER] = (TRAP, ref, ...args) => { + const id = parseInt(ref); + switch (TRAP) { + case APPLY: { + const [self, params] = args; + return toEntry(apply(get(id), fromEntry(self), params.map(fromEntry))); + } + case DESTRUCT: + drop(id); + } + }; + + if (DEBUG) { + const debug = exports.proxy[WORKER]; + exports.proxy[WORKER] = (TRAP, ...args) => { + const destructing = TRAP === DESTRUCT; + const method = destructing ? console.warn : console.log; + method('Worker before', TRAP, ...args); + const result = debug(TRAP, ...args); + if (!destructing) method('Worker after', TRAP, result); + return result; + }; + } + + return { ...exports, window, isWindowProxy: isProxy }; +}; diff --git a/src/worker.js b/src/worker.js new file mode 100644 index 0000000..cc3d5fa --- /dev/null +++ b/src/worker.js @@ -0,0 +1,113 @@ +// (c) Andrea Giammarchi - MIT + +import { + Atomics, + Int32Array, + SharedArrayBuffer, + addEventListener, + postMessage, + ignore, + polyfill, +} from 'sabayon/worker'; + +import { + ACTION_INIT, + ACTION_WAIT, + ACTION_NOTIFY, + + actionLength, + actionFill, + actionWait, + + createProxy, + + isChannel, + transfer, + withResolvers, +} from './shared.js'; + +const { wait, waitAsync } = Atomics; + +/** + * @typedef {Object} WorkerOptions + * @prop {(text: string, ...args:any) => any} [parse=JSON.parse] + * @prop {(value: any, ...args:any) => string} [stringify=JSON.stringify] + * @prop {(value: any) => any} [transform] + * @prop {{handler: () => void, timeout?: number}} [interrupt] + */ + +/** + * @callback Coincident + * @param {WorkerOptions} [options] + * @returns {Promise<{polyfill: boolean, sync: boolean, transfer: (...args: Transferable[]) => Transferable[], proxy: {}}>} + */ + +export default /** @type {Coincident} */ ({ + parse, + stringify, + transform, + interrupt, +} = JSON) => { + const waitLength = actionLength(stringify, transform); + + const ready = withResolvers(); + const map = new Map; + const results = new Map; + + let CHANNEL = ''; + let waitSync = wait; + if (wait && interrupt) { + const { handler, timeout = 42 } = interrupt; + waitSync = (sb, index, result) => { + while ((result = wait(sb, index, 0, timeout)) === 'timed-out') + handler(); + return result; + }; + } + + addEventListener('message', event => { + if (isChannel(event, CHANNEL)) { + const [_, ACTION, ...rest] = event.data; + switch (ACTION) { + case ACTION_INIT: { + const sync = !!wait; + CHANNEL = _; + ready.resolve({ + polyfill, + sync, + transfer, + proxy: createProxy( + [ + CHANNEL, + bytes => new Int32Array(new SharedArrayBuffer(bytes)), + ignore, + sync, + parse, + polyfill, + postMessage, + transform, + sync ? + (...args) => ({ value: { then: fn => fn(waitSync(...args)) } }) : + waitAsync, + ], + map, + ), + }); + break; + } + case ACTION_WAIT: { + // give the code a chance to finish running (serviceWorker mode) + if (!map.size) setTimeout(actionWait, 0, waitLength, results, map, rest); + else actionWait(waitLength, results, map, rest); + break; + } + case ACTION_NOTIFY: { + actionFill(results, rest); + break; + } + } + } + }); + + return ready.promise; +}; diff --git a/test-results/.last-run.json b/test-results/.last-run.json deleted file mode 100644 index cbcc1fb..0000000 --- a/test-results/.last-run.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "status": "passed", - "failedTests": [] -} \ No newline at end of file diff --git a/test/array.html b/test/array.html deleted file mode 100644 index fe6edbe..0000000 --- a/test/array.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - diff --git a/test/array/index.html b/test/array/index.html new file mode 100644 index 0000000..92dae26 --- /dev/null +++ b/test/array/index.html @@ -0,0 +1,9 @@ + + + + + + array + + + diff --git a/test/array/index.js b/test/array/index.js new file mode 100644 index 0000000..d4ecf70 --- /dev/null +++ b/test/array/index.js @@ -0,0 +1,5 @@ +import coincident from '../../dist/window/main.js'; + +const { Worker } = coincident(); + +new Worker('./worker.js', { serviceWorker: '../sw.js' }); diff --git a/test/array.js b/test/array/worker.js similarity index 82% rename from test/array.js rename to test/array/worker.js index 922f837..4b64c9d 100644 --- a/test/array.js +++ b/test/array/worker.js @@ -1,8 +1,9 @@ -import coincident from './dist/window.js'; +import coincident from '../../dist/window/worker.js'; -const {window} = coincident(self); +const { window } = await coincident(); + +let a = window.Array(1, 2, 3); -const a = window.Array(1, 2); console.assert(!Array.isArray(new window.Number(0))); console.assert(Array.isArray(a)); console.assert(Array.isArray(new window.Array(0))); @@ -21,3 +22,5 @@ console.log([...a]); window.console.log(a); console.log.apply(null, [a]); window.console.log.apply(null, [a]); + +a = null; diff --git a/test/basic/index.html b/test/basic/index.html new file mode 100644 index 0000000..a595154 --- /dev/null +++ b/test/basic/index.html @@ -0,0 +1,9 @@ + + + + + + coincident + + + diff --git a/test/basic/index.js b/test/basic/index.js new file mode 100644 index 0000000..ce542f1 --- /dev/null +++ b/test/basic/index.js @@ -0,0 +1,14 @@ +import coincident from '../../dist/main.js'; + +const { Worker, polyfill } = coincident(); + +console.info('main', { polyfill }); + +const w = new Worker('./worker.js', { serviceWorker: '../sw.js' }); + +w.proxy.alert = (...args) => { + console.info('main', 'alert', args); + return args.join('-'); +}; + +console.log('async', await w.proxy.log(4, 5, 6)); diff --git a/test/basic/worker.js b/test/basic/worker.js new file mode 100644 index 0000000..ce16ebe --- /dev/null +++ b/test/basic/worker.js @@ -0,0 +1,17 @@ +import coincident from '../../dist/worker.js'; + +const { proxy, polyfill, sync } = await coincident(); + +console.table({ polyfill, sync }); + +proxy.log = (...args) => { + console.info('worker', 'log', args); + return args.join('-'); +}; + +const result = proxy.alert(1, 2, 3); + +if (result instanceof Promise) + console.log('async', await result); +else + console.log('sync', result); diff --git a/test/dbmonster/dbmonster.css b/test/dbmonster/dbmonster.css deleted file mode 100644 index a68885c..0000000 --- a/test/dbmonster/dbmonster.css +++ /dev/null @@ -1,147 +0,0 @@ -body { - color: #333; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - line-height: 1.42857143; - margin: 0; -} - -label { - display: inline-block; - font-weight: 700; - margin-bottom: 5px; -} - -#range { -display: flex; -} - -input[type=range] { - display: block; - width: 100%; - margin-bottom: 10px; - margin-top: 5px; -} - -table { - border-collapse: collapse; - border-spacing: 0; -} - -:before, -:after { - box-sizing: border-box; -} - -.table > thead > tr > th, -.table > tbody > tr > th, -.table > tfoot > tr > th, -.table > thead > tr > td, -.table > tbody > tr > td, -.table > tfoot > tr > td { - border-top: 1px solid #ddd; - line-height: 1.42857143; - padding: 8px; - vertical-align: top; -} - -.table { - width: 100%; -} - -.table-striped > tbody > tr:nth-child(odd) > td, -.table-striped > tbody > tr:nth-child(odd) > th { - background: #f9f9f9; -} - -.label { - border-radius: .25em; - color: #fff; - display: inline; - font-size: 75%; - font-weight: 700; - line-height: 1; - padding: .2em .6em .3em; - text-align: center; - vertical-align: baseline; - white-space: nowrap; -} - -.label-success { - background-color: #5cb85c; -} - -.label-warning { - background-color: #f0ad4e; -} - -.popover { - background-color: #fff; - background-clip: padding-box; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, .2); - border-radius: 6px; - box-shadow: 0 5px 10px rgba(0, 0, 0, .2); - display: none; - left: 0; - max-width: 276px; - padding: 1px; - position: absolute; - text-align: left; - top: 0; - white-space: normal; - z-index: 1010; -} - -.popover>.arrow:after { - border-width: 10px; - content: ""; -} - -.popover.left { - margin-left: -10px; -} - -.popover.left > .arrow { - border-right-width: 0; - border-left-color: rgba(0, 0, 0, .25); - margin-top: -11px; - right: -11px; - top: 50%; -} - -.popover.left > .arrow:after { - border-left-color: #fff; - border-right-width: 0; - bottom: -10px; - content: " "; - right: 1px; -} - -.popover > .arrow { - border-width: 11px; -} - -.popover > .arrow, -.popover>.arrow:after { - border-color: transparent; - border-style: solid; - display: block; - height: 0; - position: absolute; - width: 0; -} - -.popover-content { - padding: 9px 14px; -} - -.Query { - position: relative; -} - -.Query:hover .popover { - display: block; - left: -100%; - width: 100%; -} \ No newline at end of file diff --git a/test/dbmonster/dbmonster.js b/test/dbmonster/dbmonster.js deleted file mode 100644 index 37ee177..0000000 --- a/test/dbmonster/dbmonster.js +++ /dev/null @@ -1,274 +0,0 @@ -import coincident from '../../uhtml.js'; -const {uhtml, window} = coincident(self); - -const {render, html} = uhtml; -const {document} = window; - -const target = document.querySelector('#app'); - -const ENV = function () {'use strict'; - var counter = 0; - var data; - var _base; - if (!(_base = String.prototype).lpad) - _base.lpad = function (padding, toLength) { - return padding.repeat((toLength - this.length) / padding.length).concat(this); - }; - - function formatElapsed(value) { - var str = parseFloat(value).toFixed(2); - if (value > 60) { - var minutes = Math.floor(value / 60); - var comps = (value % 60).toFixed(2).split('.'); - var seconds = comps[0].lpad('0', 2); - var ms = comps[1]; - str = minutes + ":" + seconds + "." + ms; - } - return str; - } - - function getElapsedClassName(elapsed) { - var className = 'Query elapsed'; - if (elapsed >= 10.0) { - className += ' warn_long'; - } - else if (elapsed >= 1.0) { - className += ' warn'; - } - else { - className += ' short'; - } - return className; - } - - function countClassName(queries) { - var countClassName = "label"; - if (queries >= 20) { - countClassName += " label-important"; - } - else if (queries >= 10) { - countClassName += " label-warning"; - } - else { - countClassName += " label-success"; - } - return countClassName; - } - - function updateQuery(object) { - if (!object) { - object = {}; - } - var elapsed = Math.random() * 15; - object.elapsed = elapsed; - object.formatElapsed = formatElapsed(elapsed); - object.elapsedClassName = getElapsedClassName(elapsed); - object.query = "SELECT blah FROM something"; - object.waiting = Math.random() < 0.5; - if (Math.random() < 0.2) { - object.query = " in transaction"; - } - if (Math.random() < 0.1) { - object.query = "vacuum"; - } - return object; - } - - function cleanQuery(value) { - if (value) { - value.formatElapsed = ""; - value.elapsedClassName = ""; - value.query = ""; - value.elapsed = null; - value.waiting = null; - } else { - return { - query: "***", - formatElapsed: "", - elapsedClassName: "" - }; - } - } - - function generateRow(object, keepIdentity, counter) { - var nbQueries = Math.floor((Math.random() * 10) + 1); - if (!object) { - object = {}; - } - object.lastMutationId = counter; - object.nbQueries = nbQueries; - if (!object.lastSample) { - object.lastSample = {}; - } - if (!object.lastSample.topFiveQueries) { - object.lastSample.topFiveQueries = []; - } - if (keepIdentity) { - // for Angular optimization - if (!object.lastSample.queries) { - object.lastSample.queries = []; - for (var l = 0; l < 12; l++) { - object.lastSample.queries[l] = cleanQuery(); - } - } - for (var j in object.lastSample.queries) { - var value = object.lastSample.queries[j]; - if (j <= nbQueries) { - updateQuery(value); - } else { - cleanQuery(value); - } - } - } else { - object.lastSample.queries = []; - for (var j = 0; j < 12; j++) { - if (j < nbQueries) { - var value = updateQuery(cleanQuery()); - object.lastSample.queries.push(value); - } else { - object.lastSample.queries.push(cleanQuery()); - } - } - } - for (var i = 0; i < 5; i++) { - var source = object.lastSample.queries[i]; - object.lastSample.topFiveQueries[i] = source; - } - object.lastSample.nbQueries = nbQueries; - object.lastSample.countClassName = countClassName(nbQueries); - return object; - } - - function getData(keepIdentity) { - var oldData = data; - if (!keepIdentity) { // reset for each tick when !keepIdentity - data = []; - for (var i = 1; i <= ENV.rows; i++) { - data.push({ dbname: 'cluster' + i, query: "", formatElapsed: "", elapsedClassName: "" }); - data.push({ dbname: 'cluster' + i + ' slave', query: "", formatElapsed: "", elapsedClassName: "" }); - } - } - if (!data) { // first init when keepIdentity - data = []; - for (var i = 1; i <= ENV.rows; i++) { - data.push({ dbname: 'cluster' + i }); - data.push({ dbname: 'cluster' + i + ' slave' }); - } - oldData = data; - } - for (var i in data) { - var row = data[i]; - if (!keepIdentity && oldData && oldData[i]) { - row.lastSample = oldData[i].lastSample; - } - if (!row.lastSample || Math.random() < ENV.mutations()) { - counter = counter + 1; - if (!keepIdentity) { - row.lastSample = null; - } - generateRow(row, keepIdentity, counter); - } else { - data[i] = oldData[i]; - } - } - return { - toArray: function () { - return data; - } - }; - } - - var mutationsValue = 0.1; - - function mutations(value) { - if (value) { - mutationsValue = value; - return mutationsValue; - } else { - return mutationsValue; - } - } - - var body = document.querySelector('body'); - var theFirstChild = body.firstChild; - - var sliderContainer = document.createElement('div'); - sliderContainer.style.cssText = "display: flex"; - var slider = document.createElement('input'); - var text = document.createElement('label'); - text.innerHTML = 'mutations : ' + (mutationsValue * 100).toFixed(0) + '%'; - text.id = "ratioval"; - slider.setAttribute("type", "range"); - slider.style.cssText = 'margin-bottom: 10px; margin-top: 5px'; - slider.addEventListener('change', function (e) { - ENV.mutations(e.target.value / 100); - document.querySelector('#ratioval').innerHTML = 'mutations : ' + (ENV.mutations() * 100).toFixed(0) + '%'; - }); - sliderContainer.appendChild(text); - sliderContainer.appendChild(slider); - body.insertBefore(sliderContainer, theFirstChild); - - return { - generateData: getData, - rows: 50, - timeout: 0, - mutations: mutations - }; -}(); - -function updateTable(dbs) { - render(target, html` - - ${dbs.map((db, i) => html` - ${[ - html``, - html` - ` - ].concat(db.lastSample.topFiveQueries.map((query, j, a) => - html` - ` - )) - }` - )} -
${db.dbname} - - ${db.lastSample.nbQueries} - - - - ${query.formatElapsed} - -
-
- ${query.query} -
-
-
-
`); -} - -updateTable(ENV.generateData().toArray()); - -const perfMonitor = { - endProfile: function () {}, - initProfiler: function () {}, - startFPSMonitor: function () {}, - startMemMonitor: function () {}, - startProfile: function () {} -}; -perfMonitor.startFPSMonitor(); -perfMonitor.startMemMonitor(); -// perfMonitor.initProfiler('data update'); -perfMonitor.initProfiler('view update'); - -function update() { - // perfMonitor.startProfile('data update'); - var data = ENV.generateData().toArray(); - // perfMonitor.endProfile('data update'); - perfMonitor.startProfile('view update'); - updateTable(data); - perfMonitor.endProfile('view update'); - setTimeout(update, ENV.timeout); -} - -update(); diff --git a/test/dbmonster/index.html b/test/dbmonster/index.html deleted file mode 100644 index 74269a3..0000000 --- a/test/dbmonster/index.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - uhtml dbmonster ... from a Worker! - - - - - - -
-
- - - diff --git a/test/dist/es.js b/test/dist/es.js deleted file mode 100644 index c2be4f7..0000000 --- a/test/dist/es.js +++ /dev/null @@ -1,2 +0,0 @@ -const e="function",t="566fc334-5147-4e86-bb9b-c7d24c13127d",s="get",n="has",a="set",{isArray:o}=Array;let{SharedArrayBuffer:r,window:i}=globalThis,{notify:l,wait:c,waitAsync:f}=Atomics,d=null;f||(f=e=>({value:new Promise((t=>{let s=new Worker("data:application/javascript,onmessage%3D(%7Bdata%3Ab%7D)%3D%3E(Atomics.wait(b%2C0)%2CpostMessage(0))");s.onmessage=t,s.postMessage(e)}))}));try{new r(4)}catch(e){r=ArrayBuffer;const s=new WeakMap;if(i){const e=new Map,{prototype:{postMessage:n}}=Worker,a=s=>{const n=s.data?.[t];if(!o(n)){s.stopImmediatePropagation();const{id:t,sb:a}=n;e.get(t)(a)}};d=function(e,...r){const i=e?.[t];if(o(i)){const[e,t]=i;s.set(t,e),this.addEventListener("message",a)}return n.call(this,e,...r)},f=t=>({value:new Promise((n=>{e.set(s.get(t),n)})).then((n=>{e.delete(s.get(t)),s.delete(t);for(let e=0;e({[t]:{id:e,sb:s}});l=t=>{postMessage(e(s.get(t),t))},addEventListener("message",(e=>{const n=e.data?.[t];if(o(n)){const[e,t]=n;s.set(t,e)}}))}} -/*! (c) Andrea Giammarchi - ISC */const{Int32Array:g,Map:p,Uint16Array:w}=globalThis,{BYTES_PER_ELEMENT:u}=g,{BYTES_PER_ELEMENT:h}=w,y=new WeakSet,m=new WeakMap,E={value:{then:e=>e()}};let b=0;const A=(i,{parse:A=JSON.parse,stringify:M=JSON.stringify,transform:v,interrupt:T}=JSON)=>{if(!m.has(i)){const P=d||i.postMessage,k=(e,...s)=>P.call(i,{[t]:s},{transfer:e}),S=typeof T===e?T:T?.handler,W=T?.delay||42,B=new TextDecoder("utf-16"),L=(e,t)=>e?f(t,0):(S?((e,t,s)=>{for(;"timed-out"===c(e,0,0,t);)s()})(t,W,S):c(t,0),E);let N=!1;m.set(i,new Proxy(new p,{[n]:(e,t)=>"string"==typeof t&&!t.startsWith("_"),[s]:(e,t)=>"then"===t?null:(...e)=>{const s=b++;let n=new g(new r(2*u)),a=[];y.has(e.at(-1)||a)&&y.delete(a=e.pop()),k(a,s,n,t,v?e.map(v):e);const o=i!==globalThis;let l=0;return N&&o&&(l=setTimeout(console.warn,1e3,`💀🔒 - Possible deadlock if proxy.${t}(...args) is awaited`)),L(o,n).value.then((()=>{clearTimeout(l);const e=n[1];if(!e)return;const t=h*e;return n=new g(new r(t+t%u)),k([],s,n),L(o,n).value.then((()=>A(B.decode(new w(n.buffer).slice(0,e)))))}))},[a](s,n,a){const r=typeof a;if(r!==e)throw new Error(`Unable to assign ${n} as ${r}`);if(!s.size){const e=new p;i.addEventListener("message",(async n=>{const a=n.data?.[t];if(o(a)){n.stopImmediatePropagation();const[t,o,...r]=a;let i;if(r.length){const[n,a]=r;if(s.has(n)){N=!0;try{const r=await s.get(n)(...a);if(void 0!==r){const s=M(v?v(r):r);e.set(t,s),o[1]=s.length}}catch(e){i=e}finally{N=!1}}else i=new Error(`Unsupported action: ${n}`);o[0]=1}else{const s=e.get(t);e.delete(t);for(let e=new w(o.buffer),t=0;t(y.add(e),e);export{A as default}; diff --git a/test/dist/mini-coi.js b/test/dist/mini-coi.js deleted file mode 100644 index b7a23bf..0000000 --- a/test/dist/mini-coi.js +++ /dev/null @@ -1,28 +0,0 @@ -/*! coi-serviceworker v0.1.7 - Guido Zuidhof and contributors, licensed under MIT */ -/*! mini-coi - Andrea Giammarchi and contributors, licensed under MIT */ -(({ document: d, navigator: { serviceWorker: s } }) => { - if (d) { - const { currentScript: c } = d; - s.register(c.src, { scope: c.getAttribute('scope') || '.' }).then(r => { - r.addEventListener('updatefound', () => location.reload()); - if (r.active && !s.controller) location.reload(); - }); - } - else { - addEventListener('install', () => skipWaiting()); - addEventListener('activate', e => e.waitUntil(clients.claim())); - addEventListener('fetch', e => { - const { request: r } = e; - if (r.cache === 'only-if-cached' && r.mode !== 'same-origin') return; - e.respondWith(fetch(r).then(r => { - const { body, status, statusText } = r; - if (!status || status > 399) return r; - const h = new Headers(r.headers); - h.set('Cross-Origin-Opener-Policy', 'same-origin'); - h.set('Cross-Origin-Embedder-Policy', 'require-corp'); - h.set('Cross-Origin-Resource-Policy', 'cross-origin'); - return new Response(body, { status, statusText, headers: h }); - })); - }); - } -})(self); diff --git a/test/dist/server.js b/test/dist/server.js deleted file mode 100644 index 20f715d..0000000 --- a/test/dist/server.js +++ /dev/null @@ -1,2 +0,0 @@ -Promise.withResolvers||(Promise.withResolvers=function(){var e,t,n=new this((function(n,r){e=n,t=r}));return{resolve:e,reject:t,promise:n}});const e="566fc334-5147-4e86-bb9b-c7d24c13127d",t="M"+e,n="T"+e,r="apply",s="construct",o="defineProperty",a="deleteProperty",c="get",i="getOwnPropertyDescriptor",l="getPrototypeOf",u="has",f="isExtensible",p="ownKeys",g="preventExtensions",d="set",y="setPrototypeOf",w="delete",h="array",m="function",b="null",v="number",E="object",S="string",M="symbol",P="undefined",{isArray:k}=Array,T=(e,t)=>t,O=e=>typeof e===m?(e=>e())(e):e;function x(){return this}const A=(e,t)=>e===h?[t]:{t:e,v:t},W=(e,t=T)=>{let n=typeof e,r=e;return n===E&&(k(e)?(n=h,r=e.at(0)):({t:n,v:r}=e)),t(n,r)},j=(e,t)=>e===m?t:A(e,t),L=(e,t=j)=>{const n=null===e?b:typeof e;return t(n===E&&k(e)?h:n,e)},{defineProperty:R,deleteProperty:B,getOwnPropertyDescriptor:I,getPrototypeOf:$,isExtensible:D,ownKeys:N,preventExtensions:_,set:J,setPrototypeOf:U}=Reflect,{assign:C,create:z}=Object,F=$(Int8Array),K=(e,t)=>{const{get:n,set:r,value:s}=e;return n&&(e.get=t(n)),r&&(e.set=t(r)),s&&(e.value=t(s)),e},Y=e=>t=>L(t,((t,n)=>{switch(t){case b:return A(b,n);case E:if(n===globalThis)return A(t,null);case h:case m:return e(t,n);case"boolean":case v:case S:case P:case"bigint":return A(t,n);case M:{if(H.has(n))return A(t,H.get(n));let e=Symbol.keyFor(n);if(e)return A(t,`.${e}`)}}throw new TypeError(`Unable to handle this ${t}: ${String(n)}`)})),H=new Map(N(Symbol).filter((e=>typeof Symbol[e]===M)).map((e=>[Symbol[e],e]))),q=e=>{if(e.startsWith("."))return Symbol.for(e.slice(1));for(const[t,n]of H)if(n===e)return t},G=e=>e,Q="object"==typeof self?self:globalThis,V=e=>((e,t)=>{const n=(t,n)=>(e.set(n,t),t),r=s=>{if(e.has(s))return e.get(s);const[o,a]=t[s];switch(o){case 0:case-1:return n(a,s);case 1:{const e=n([],s);for(const t of a)e.push(r(t));return e}case 2:{const e=n({},s);for(const[t,n]of a)e[r(t)]=r(n);return e}case 3:return n(new Date(a),s);case 4:{const{source:e,flags:t}=a;return n(new RegExp(e,t),s)}case 5:{const e=n(new Map,s);for(const[t,n]of a)e.set(r(t),r(n));return e}case 6:{const e=n(new Set,s);for(const t of a)e.add(r(t));return e}case 7:{const{name:e,message:t}=a;return n(new Q[e](t),s)}case 8:return n(BigInt(a),s);case"BigInt":return n(Object(BigInt(a)),s)}return n(new Q[o](a),s)};return r})(new Map,e)(0),X="",{toString:Z}={},{keys:ee}=Object,te=e=>{const t=typeof e;if("object"!==t||!e)return[0,t];const n=Z.call(e).slice(8,-1);switch(n){case"Array":return[1,X];case"Object":return[2,X];case"Date":return[3,X];case"RegExp":return[4,X];case"Map":return[5,X];case"Set":return[6,X]}return n.includes("Array")?[1,n]:n.includes("Error")?[7,n]:[2,n]},ne=([e,t])=>0===e&&("function"===t||"symbol"===t),re=(e,{json:t,lossy:n}={})=>{const r=[];return((e,t,n,r)=>{const s=(e,t)=>{const s=r.push(e)-1;return n.set(t,s),s},o=r=>{if(n.has(r))return n.get(r);let[a,c]=te(r);switch(a){case 0:{let t=r;switch(c){case"bigint":a=8,t=r.toString();break;case"function":case"symbol":if(e)throw new TypeError("unable to serialize "+c);t=null;break;case"undefined":return s([-1],r)}return s([a,t],r)}case 1:{if(c)return s([c,[...r]],r);const e=[],t=s([a,e],r);for(const t of r)e.push(o(t));return t}case 2:{if(c)switch(c){case"BigInt":return s([c,r.toString()],r);case"Boolean":case"Number":case"String":return s([c,r.valueOf()],r)}if(t&&"toJSON"in r)return o(r.toJSON());const n=[],i=s([a,n],r);for(const t of ee(r))!e&&ne(te(r[t]))||n.push([o(t),o(r[t])]);return i}case 3:return s([a,r.toISOString()],r);case 4:{const{source:e,flags:t}=r;return s([a,{source:e,flags:t}],r)}case 5:{const t=[],n=s([a,t],r);for(const[n,s]of r)(e||!ne(te(n))&&!ne(te(s)))&&t.push([o(n),o(s)]);return n}case 6:{const t=[],n=s([a,t],r);for(const n of r)!e&&ne(te(n))||t.push(o(n));return n}}const{message:i}=r;return s([a,{name:c,message:i}],r)};return o})(!(t||n),!!t,new Map,r)(e),r},{parse:se,stringify:oe}=JSON,ae={json:!0,lossy:!0};var ce=Object.freeze({__proto__:null,parse:e=>V(se(e)),stringify:e=>oe(re(e,ae))});const{isArray:ie}=Array;let{SharedArrayBuffer:le,window:ue}=globalThis,{notify:fe,wait:pe,waitAsync:ge}=Atomics,de=null;ge||(ge=e=>({value:new Promise((t=>{let n=new Worker("data:application/javascript,onmessage%3D(%7Bdata%3Ab%7D)%3D%3E(Atomics.wait(b%2C0)%2CpostMessage(0))");n.onmessage=t,n.postMessage(e)}))}));try{new le(4)}catch(t){le=ArrayBuffer;const n=new WeakMap;if(ue){const t=new Map,{prototype:{postMessage:r}}=Worker,s=n=>{const r=n.data?.[e];if(!ie(r)){n.stopImmediatePropagation();const{id:e,sb:s}=r;t.get(e)(s)}};de=function(t,...o){const a=t?.[e];if(ie(a)){const[e,t]=a;n.set(t,e),this.addEventListener("message",s)}return r.call(this,t,...o)},ge=e=>({value:new Promise((r=>{t.set(n.get(e),r)})).then((r=>{t.delete(n.get(e)),n.delete(e);for(let t=0;t({[e]:{id:t,sb:n}});fe=e=>{postMessage(t(n.get(e),e))},addEventListener("message",(t=>{const r=t.data?.[e];if(ie(r)){const[e,t]=r;n.set(t,e)}}))}} -/*! (c) Andrea Giammarchi - ISC */const{Int32Array:ye,Map:we,Uint16Array:he}=globalThis,{BYTES_PER_ELEMENT:me}=ye,{BYTES_PER_ELEMENT:be}=he,ve=new WeakSet,Ee=new WeakMap,Se={value:{then:e=>e()}};let Me=0;const Pe=(t,{parse:n=JSON.parse,stringify:r=JSON.stringify,transform:s,interrupt:o}=JSON)=>{if(!Ee.has(t)){const a=de||t.postMessage,i=(n,...r)=>a.call(t,{[e]:r},{transfer:n}),l=typeof o===m?o:o?.handler,f=o?.delay||42,p=new TextDecoder("utf-16"),g=(e,t)=>e?ge(t,0):(l?((e,t,n)=>{for(;"timed-out"===pe(e,0,0,t);)n()})(t,f,l):pe(t,0),Se);let y=!1;Ee.set(t,new Proxy(new we,{[u]:(e,t)=>"string"==typeof t&&!t.startsWith("_"),[c]:(e,r)=>"then"===r?null:(...e)=>{const o=Me++;let a=new ye(new le(2*me)),c=[];ve.has(e.at(-1)||c)&&ve.delete(c=e.pop()),i(c,o,a,r,s?e.map(s):e);const l=t!==globalThis;let u=0;return y&&l&&(u=setTimeout(console.warn,1e3,`💀🔒 - Possible deadlock if proxy.${r}(...args) is awaited`)),g(l,a).value.then((()=>{clearTimeout(u);const e=a[1];if(!e)return;const t=be*e;return a=new ye(new le(t+t%me)),i([],o,a),g(l,a).value.then((()=>n(p.decode(new he(a.buffer).slice(0,e)))))}))},[d](n,o,a){const c=typeof a;if(c!==m)throw new Error(`Unable to assign ${o} as ${c}`);if(!n.size){const o=new we;t.addEventListener("message",(async t=>{const a=t.data?.[e];if(ie(a)){t.stopImmediatePropagation();const[e,c,...i]=a;let l;if(i.length){const[t,a]=i;if(n.has(t)){y=!0;try{const i=await n.get(t)(...a);if(void 0!==i){const t=r(s?s(i):i);o.set(e,t),c[1]=t.length}}catch(e){l=e}finally{y=!1}}else l=new Error(`Unsupported action: ${t}`);c[0]=1}else{const t=o.get(e);o.delete(e);for(let e=new he(c.buffer),n=0;nPe(e,{...ce,...t});ke.transfer=Pe.transfer=(...e)=>(ve.add(e),e);const Te=new FinalizationRegistry((([e,t,n])=>{n&&console.debug(`Held value ${String(t)} not relevant anymore`),e(t)})),Oe=Object.create(null),xe=(e,t,{debug:n,handler:r,return:s,token:o=e}=Oe)=>{const a=s||new Proxy(e,r||Oe),c=[a,[t,e,!!n]];return!1!==o&&c.push(o),Te.register(...c),a};var Ae=(e,t)=>{const n=t&&new WeakMap;if(t){const{addEventListener:e}=EventTarget.prototype;R(EventTarget.prototype,"addEventListener",{value(t,r,...s){return s.at(0)?.invoke&&(n.has(this)||n.set(this,new Map),n.get(this).set(t,[].concat(s[0].invoke)),delete s[0].invoke),e.call(this,t,r,...s)}})}const b=t&&(e=>{const{currentTarget:t,target:r,type:s}=e;for(const o of n.get(t||r)?.get(s)||[])e[o]()});return function(n,k,T,...O){let x=0,j=this?.transform||G;const L=new Map,H=new Map,{[T]:Q}=n,V=O.length?C(z(globalThis),...O):globalThis,X=Y(((e,t)=>{if(!L.has(t)){let n;for(;H.has(n=x++););L.set(t,n),H.set(n,e===m?t:j(t))}return A(e,L.get(t))})),Z=e=>{Q(w,A(S,e))},ee=(e,n)=>{switch(e){case E:if(null==n)return V;case h:if(typeof n===v)return H.get(n);if(!(n instanceof F))for(const e in n)n[e]=te(n[e]);return n;case m:if(typeof n===S){const e=H.get(n)?.deref();if(e)return e;const s=function(...e){return t&&e.at(0)instanceof Event&&b(...e),Q(r,A(m,n),X(this),e.map(X))};return H.set(n,new WeakRef(s)),xe(n,Z,{return:s,token:!1})}return H.get(n);case M:return q(n)}return n},te=e=>W(e,ee),ne={[r]:(e,t,n)=>X(e.apply(t,n)),[s]:(e,t)=>X(new e(...t)),[o]:(e,t,n)=>X(R(e,t,n)),[a]:(e,t)=>X(B(e,t)),[l]:e=>X($(e)),[c]:(e,t)=>X(e[t]),[i]:(e,t)=>{const n=I(e,t);return n?A(E,K(n,X)):A(P,n)},[u]:(e,t)=>X(t in e),[f]:e=>X(D(e)),[p]:e=>A(h,N(e).map(X)),[g]:e=>X(_(e)),[d]:(e,t,n)=>X(J(e,t,n)),[y]:(e,t)=>X(U(e,t)),[w](e){L.delete(H.get(e)),H.delete(e)}};return n[k]=(e,t,...n)=>{switch(e){case r:n[0]=te(n[0]),n[1]=n[1].map(te);break;case s:n[0]=n[0].map(te);break;case o:{const[e,t]=n;n[0]=te(e);const{get:r,set:s,value:o}=t;r&&(t.get=te(r)),s&&(t.set=te(s)),o&&(t.value=te(o));break}default:n=n.map(te)}return ne[e](te(t),...n)},{proxy:n,[e.toLowerCase()]:V,[`is${e}Proxy`]:()=>!1}}},We=Ae("Window",!0),je=e=>{let t=0;const n=new Map,b=new Map,P=Symbol();return function(k,T,j){const L=this?.transform||G,{[T]:R}=k,B=new Map,I=e=>{B.delete(e),R(w,$(e))},$=Y(((e,r)=>{if(P in r)return O(r[P]);if(e===m){if(r=L(r),!b.has(r)){let e;for(;b.has(e=String(t++)););n.set(r,e),b.set(e,r)}return A(e,n.get(r))}if(!(r instanceof F)){r=L(r);for(const e in r)r[e]=$(r[e])}return A(e,r)})),D=(e,t,n)=>{const r=B.get(n)?.deref();if(r)return r;const s=t===m?(e=>x.bind(e))(e):e,o=new Proxy(s,J);return B.set(n,new WeakRef(o)),xe(n,I,{return:o,token:!1})},N=e=>W(e,((t,n)=>{switch(t){case E:if(null===n)return globalThis;case h:return typeof n===v?D(e,t,n):n;case m:return typeof n===S?b.get(n):D(e,t,n);case M:return q(n)}return n})),_=(e,t,...n)=>N(R(e,O(t),...n)),J={[r]:(e,t,n)=>_(r,e,$(t),n.map($)),[s]:(e,t)=>_(s,e,t.map($)),[o]:(e,t,n)=>{const{get:r,set:s,value:a}=n;return typeof r===m&&(n.get=$(r)),typeof s===m&&(n.set=$(s)),typeof a===m&&(n.value=$(a)),_(o,e,$(t),n)},[a]:(e,t)=>_(a,e,$(t)),[l]:e=>_(l,e),[c]:(e,t)=>t===P?e:_(c,e,$(t)),[i]:(e,t)=>{const n=_(i,e,$(t));return n&&K(n,N)},[u]:(e,t)=>t===P||_(u,e,$(t)),[f]:e=>_(f,e),[p]:e=>_(p,e).map(N),[g]:e=>_(g,e),[d]:(e,t,n)=>_(d,e,$(t),$(n)),[y]:(e,t)=>_(y,e,$(t))};k[j]=(e,t,s,o)=>{switch(e){case r:return N(t).apply(N(s),o.map(N));case w:{const e=N(t);n.delete(b.get(e)),b.delete(e)}}};const U=new Proxy(A(E,null),J);return{[e.toLowerCase()]:U,[`is${e}Proxy`]:e=>typeof e===E&&!!e&&P in e,proxy:k}}},Le=je("Window"),Re=Ae("Server",!1),Be=je("Server"),Ie=typeof Worker===m?Worker:class{};const{notify:$e,wait:De}=Atomics,{parse:Ne,stringify:_e}=ce,Je=!!globalThis.process,Ue=new WeakMap,Ce=e=>{let t;return/^!(-?\d+)?/.test(e)&&(t=RegExp.$1,e=e.slice(1+t.length)),{id:t,result:e?Ne(e):void 0}},ze=Je?(e,t)=>e.on("connection",(e=>{e.once("message",(n=>{let s=0;const[o,a]=Ne(n),c=new Map,{[o]:i}=Re({[a]:async(t,...n)=>{const o=_e([t,...n]);if(t===r){const{promise:t,resolve:n}=Promise.withResolvers(),r=String(s++);return c.set(r,n),e.send("!"+r+o),await t}e.send("!"+o)}},o,a,t).proxy;e.on("close",(()=>{for(const[e,t]of c)t()})).on("message",(t=>{const{id:n,result:r}=Ce(String(t));if(n){const e=c.get(n);c.delete(n),e(r)}else e.send(_e(i(...r)))})).send("")}))})):(e,r,...s)=>{const o=ke(e,...s);if(!Ue.has(o)){const s=e instanceof Ie?Fe:Ke;Ue.set(o,s(e,o,t,n,r))}return Ue.get(o)};Je||(ze.transfer=ke.transfer);const Fe=(e,t,n,r,s)=>(e.addEventListener("message",(({data:[e,n]})=>{const r="M"+e,o="T"+e,{[o]:a}=t;let c;t[r]=(...e)=>new Promise((t=>{c=t,s.send(_e(e))})),s.addEventListener("message",(()=>{s.addEventListener("message",(async({data:e})=>{const{id:t,result:n}=Ce(e);if(null!=t){const e=a(...n);if(t){const n=await e;s.send("!"+t+(void 0===n?"":_e(n)))}}else c&&(c=c(n))})),n[0]=1,$e(n,0)}),{once:!0}),s.send(_e([r,o]))}),{once:!0}),We(t,n,r)),Ke=(e,t,n,r)=>{const s="S"+crypto.randomUUID(),o=new Int32Array(new SharedArrayBuffer(4));return e.postMessage([s,o]),De(o,0),C(Be(t,"M"+s,"T"+s),Le(t,n,r))};export{ze as default}; diff --git a/test/dist/structured.js b/test/dist/structured.js deleted file mode 100644 index d5348c6..0000000 --- a/test/dist/structured.js +++ /dev/null @@ -1,2 +0,0 @@ -const e="object"==typeof self?self:globalThis,t=t=>((t,s)=>{const n=(e,s)=>(t.set(s,e),e),r=o=>{if(t.has(o))return t.get(o);const[a,c]=s[o];switch(a){case 0:case-1:return n(c,o);case 1:{const e=n([],o);for(const t of c)e.push(r(t));return e}case 2:{const e=n({},o);for(const[t,s]of c)e[r(t)]=r(s);return e}case 3:return n(new Date(c),o);case 4:{const{source:e,flags:t}=c;return n(new RegExp(e,t),o)}case 5:{const e=n(new Map,o);for(const[t,s]of c)e.set(r(t),r(s));return e}case 6:{const e=n(new Set,o);for(const t of c)e.add(r(t));return e}case 7:{const{name:t,message:s}=c;return n(new e[t](s),o)}case 8:return n(BigInt(c),o);case"BigInt":return n(Object(BigInt(c)),o)}return n(new e[a](c),o)};return r})(new Map,t)(0),s="",{toString:n}={},{keys:r}=Object,o=e=>{const t=typeof e;if("object"!==t||!e)return[0,t];const r=n.call(e).slice(8,-1);switch(r){case"Array":return[1,s];case"Object":return[2,s];case"Date":return[3,s];case"RegExp":return[4,s];case"Map":return[5,s];case"Set":return[6,s]}return r.includes("Array")?[1,r]:r.includes("Error")?[7,r]:[2,r]},a=([e,t])=>0===e&&("function"===t||"symbol"===t),c=(e,{json:t,lossy:s}={})=>{const n=[];return((e,t,s,n)=>{const c=(e,t)=>{const r=n.push(e)-1;return s.set(t,r),r},i=n=>{if(s.has(n))return s.get(n);let[u,f]=o(n);switch(u){case 0:{let t=n;switch(f){case"bigint":u=8,t=n.toString();break;case"function":case"symbol":if(e)throw new TypeError("unable to serialize "+f);t=null;break;case"undefined":return c([-1],n)}return c([u,t],n)}case 1:{if(f)return c([f,[...n]],n);const e=[],t=c([u,e],n);for(const t of n)e.push(i(t));return t}case 2:{if(f)switch(f){case"BigInt":return c([f,n.toString()],n);case"Boolean":case"Number":case"String":return c([f,n.valueOf()],n)}if(t&&"toJSON"in n)return i(n.toJSON());const s=[],l=c([u,s],n);for(const t of r(n))!e&&a(o(n[t]))||s.push([i(t),i(n[t])]);return l}case 3:return c([u,n.toISOString()],n);case 4:{const{source:e,flags:t}=n;return c([u,{source:e,flags:t}],n)}case 5:{const t=[],s=c([u,t],n);for(const[s,r]of n)(e||!a(o(s))&&!a(o(r)))&&t.push([i(s),i(r)]);return s}case 6:{const t=[],s=c([u,t],n);for(const s of n)!e&&a(o(s))||t.push(i(s));return s}}const{message:l}=n;return c([u,{name:f,message:l}],n)};return i})(!(t||s),!!t,new Map,n)(e),n},{parse:i,stringify:u}=JSON,f={json:!0,lossy:!0};var l=Object.freeze({__proto__:null,parse:e=>t(i(e)),stringify:e=>u(c(e,f))});const g="function",p="566fc334-5147-4e86-bb9b-c7d24c13127d",w="get",d="has",h="set",{isArray:y}=Array;let{SharedArrayBuffer:b,window:m}=globalThis,{notify:E,wait:S,waitAsync:M}=Atomics,A=null;M||(M=e=>({value:new Promise((t=>{let s=new Worker("data:application/javascript,onmessage%3D(%7Bdata%3Ab%7D)%3D%3E(Atomics.wait(b%2C0)%2CpostMessage(0))");s.onmessage=t,s.postMessage(e)}))}));try{new b(4)}catch(e){b=ArrayBuffer;const t=new WeakMap;if(m){const e=new Map,{prototype:{postMessage:s}}=Worker,n=t=>{const s=t.data?.[p];if(!y(s)){t.stopImmediatePropagation();const{id:n,sb:r}=s;e.get(n)(r)}};A=function(e,...r){const o=e?.[p];if(y(o)){const[e,s]=o;t.set(s,e),this.addEventListener("message",n)}return s.call(this,e,...r)},M=s=>({value:new Promise((n=>{e.set(t.get(s),n)})).then((n=>{e.delete(t.get(s)),t.delete(s);for(let e=0;e({[p]:{id:e,sb:t}});E=s=>{postMessage(e(t.get(s),s))},addEventListener("message",(e=>{const s=e.data?.[p];if(y(s)){const[e,n]=s;t.set(n,e)}}))}} -/*! (c) Andrea Giammarchi - ISC */const{Int32Array:v,Map:O,Uint16Array:T}=globalThis,{BYTES_PER_ELEMENT:k}=v,{BYTES_PER_ELEMENT:B}=T,j=new WeakSet,N=new WeakMap,_={value:{then:e=>e()}};let I=0;const P=(e,{parse:t=JSON.parse,stringify:s=JSON.stringify,transform:n,interrupt:r}=JSON)=>{if(!N.has(e)){const o=A||e.postMessage,a=(t,...s)=>o.call(e,{[p]:s},{transfer:t}),c=typeof r===g?r:r?.handler,i=r?.delay||42,u=new TextDecoder("utf-16"),f=(e,t)=>e?M(t,0):(c?((e,t,s)=>{for(;"timed-out"===S(e,0,0,t);)s()})(t,i,c):S(t,0),_);let l=!1;N.set(e,new Proxy(new O,{[d]:(e,t)=>"string"==typeof t&&!t.startsWith("_"),[w]:(s,r)=>"then"===r?null:(...s)=>{const o=I++;let c=new v(new b(2*k)),i=[];j.has(s.at(-1)||i)&&j.delete(i=s.pop()),a(i,o,c,r,n?s.map(n):s);const g=e!==globalThis;let p=0;return l&&g&&(p=setTimeout(console.warn,1e3,`💀🔒 - Possible deadlock if proxy.${r}(...args) is awaited`)),f(g,c).value.then((()=>{clearTimeout(p);const e=c[1];if(!e)return;const s=B*e;return c=new v(new b(s+s%k)),a([],o,c),f(g,c).value.then((()=>t(u.decode(new T(c.buffer).slice(0,e)))))}))},[h](t,r,o){const a=typeof o;if(a!==g)throw new Error(`Unable to assign ${r} as ${a}`);if(!t.size){const r=new O;e.addEventListener("message",(async e=>{const o=e.data?.[p];if(y(o)){e.stopImmediatePropagation();const[a,c,...i]=o;let u;if(i.length){const[e,o]=i;if(t.has(e)){l=!0;try{const i=await t.get(e)(...o);if(void 0!==i){const e=s(n?n(i):i);r.set(a,e),c[1]=e.length}}catch(e){u=e}finally{l=!1}}else u=new Error(`Unsupported action: ${e}`);c[0]=1}else{const e=r.get(a);r.delete(a);for(let t=new T(c.buffer),s=0;sP(e,{...l,...t});x.transfer=P.transfer=(...e)=>(j.add(e),e);export{x as default}; diff --git a/test/dist/uhtml.js b/test/dist/uhtml.js deleted file mode 100644 index 2824660..0000000 --- a/test/dist/uhtml.js +++ /dev/null @@ -1,5 +0,0 @@ -const e="566fc334-5147-4e86-bb9b-c7d24c13127d",t="M"+e,n="T"+e,r="array",s="function",o="null",a="number",i="object",l="string",c="symbol",u="undefined",f="apply",p="construct",h="defineProperty",d="deleteProperty",g="get",y="getOwnPropertyDescriptor",w="getPrototypeOf",m="has",b="isExtensible",v="ownKeys",x="preventExtensions",k="set",C="setPrototypeOf",E="delete",{isArray:M}=Array;let{SharedArrayBuffer:$,window:P}=globalThis,{notify:T,wait:W,waitAsync:A}=Atomics,O=null;A||(A=e=>({value:new Promise((t=>{let n=new Worker("data:application/javascript,onmessage%3D(%7Bdata%3Ab%7D)%3D%3E(Atomics.wait(b%2C0)%2CpostMessage(0))");n.onmessage=t,n.postMessage(e)}))}));try{new $(4)}catch(t){$=ArrayBuffer;const n=new WeakMap;if(P){const t=new Map,{prototype:{postMessage:r}}=Worker,s=n=>{const r=n.data?.[e];if(!M(r)){n.stopImmediatePropagation();const{id:e,sb:s}=r;t.get(e)(s)}};O=function(t,...o){const a=t?.[e];if(M(a)){const[e,t]=a;n.set(t,e),this.addEventListener("message",s)}return r.call(this,t,...o)},A=e=>({value:new Promise((r=>{t.set(n.get(e),r)})).then((r=>{t.delete(n.get(e)),n.delete(e);for(let t=0;t({[e]:{id:t,sb:n}});T=e=>{postMessage(t(n.get(e),e))},addEventListener("message",(t=>{const r=t.data?.[e];if(M(r)){const[e,t]=r;n.set(t,e)}}))}} -/*! (c) Andrea Giammarchi - ISC */const{Int32Array:S,Map:N,Uint16Array:L}=globalThis,{BYTES_PER_ELEMENT:D}=S,{BYTES_PER_ELEMENT:B}=L,j=new WeakSet,R=new WeakMap,F={value:{then:e=>e()}};let _=0;const z=(t,{parse:n=JSON.parse,stringify:r=JSON.stringify,transform:o,interrupt:a}=JSON)=>{if(!R.has(t)){const i=O||t.postMessage,l=(n,...r)=>i.call(t,{[e]:r},{transfer:n}),c=typeof a===s?a:a?.handler,u=a?.delay||42,f=new TextDecoder("utf-16"),p=(e,t)=>e?A(t,0):(c?((e,t,n)=>{for(;"timed-out"===W(e,0,0,t);)n()})(t,u,c):W(t,0),F);let h=!1;R.set(t,new Proxy(new N,{[m]:(e,t)=>"string"==typeof t&&!t.startsWith("_"),[g]:(e,r)=>"then"===r?null:(...e)=>{const s=_++;let a=new S(new $(2*D)),i=[];j.has(e.at(-1)||i)&&j.delete(i=e.pop()),l(i,s,a,r,o?e.map(o):e);const c=t!==globalThis;let u=0;return h&&c&&(u=setTimeout(console.warn,1e3,`💀🔒 - Possible deadlock if proxy.${r}(...args) is awaited`)),p(c,a).value.then((()=>{clearTimeout(u);const e=a[1];if(!e)return;const t=B*e;return a=new S(new $(t+t%D)),l([],s,a),p(c,a).value.then((()=>n(f.decode(new L(a.buffer).slice(0,e)))))}))},[k](n,a,i){const l=typeof i;if(l!==s)throw new Error(`Unable to assign ${a} as ${l}`);if(!n.size){const s=new N;t.addEventListener("message",(async t=>{const a=t.data?.[e];if(M(a)){t.stopImmediatePropagation();const[e,i,...l]=a;let c;if(l.length){const[t,a]=l;if(n.has(t)){h=!0;try{const l=await n.get(t)(...a);if(void 0!==l){const t=r(o?o(l):l);s.set(e,t),i[1]=t.length}}catch(e){c=e}finally{h=!1}}else c=new Error(`Unsupported action: ${t}`);i[0]=1}else{const t=s.get(e);s.delete(e);for(let e=new L(i.buffer),n=0;n(j.add(e),e);const{isArray:I}=Array,U=(e,t)=>t,H=e=>typeof e===s?(e=>e())(e):e;function J(){return this}const K=(e,t)=>e===r?[t]:{t:e,v:t},Y=(e,t=U)=>{let n=typeof e,s=e;return n===i&&(I(e)?(n=r,s=e.at(0)):({t:n,v:s}=e)),t(n,s)},Z=(e,t)=>e===s?t:K(e,t),G=(e,t=Z)=>{const n=null===e?o:typeof e;return t(n===i&&I(e)?r:n,e)},V=new FinalizationRegistry((([e,t,n])=>{n&&console.debug(`Held value ${String(t)} not relevant anymore`),e(t)})),q=Object.create(null),Q=(e,t,{debug:n,handler:r,return:s,token:o=e}=q)=>{const a=s||new Proxy(e,r||q),i=[a,[t,e,!!n]];return!1!==o&&i.push(o),V.register(...i),a},{defineProperty:X,deleteProperty:ee,getOwnPropertyDescriptor:te,getPrototypeOf:ne,isExtensible:re,ownKeys:se,preventExtensions:oe,set:ae,setPrototypeOf:ie}=Reflect,{assign:le,create:ce}=Object,ue=ne(Int8Array),fe=(e,t)=>{const{get:n,set:r,value:s}=e;return n&&(e.get=t(n)),r&&(e.set=t(r)),s&&(e.value=t(s)),e},pe=e=>t=>G(t,((t,n)=>{switch(t){case o:return K(o,n);case i:if(n===globalThis)return K(t,null);case r:case s:return e(t,n);case"boolean":case a:case l:case u:case"bigint":return K(t,n);case c:{if(he.has(n))return K(t,he.get(n));let e=Symbol.keyFor(n);if(e)return K(t,`.${e}`)}}throw new TypeError(`Unable to handle this ${t}: ${String(n)}`)})),he=new Map(se(Symbol).filter((e=>typeof Symbol[e]===c)).map((e=>[Symbol[e],e]))),de=e=>{if(e.startsWith("."))return Symbol.for(e.slice(1));for(const[t,n]of he)if(n===e)return t},ge=e=>e;var ye=(e=>{const t=new WeakMap;{const{addEventListener:e}=EventTarget.prototype;X(EventTarget.prototype,"addEventListener",{value(n,r,...s){return s.at(0)?.invoke&&(t.has(this)||t.set(this,new Map),t.get(this).set(n,[].concat(s[0].invoke)),delete s[0].invoke),e.call(this,n,r,...s)}})}return function(n,o,M,...$){let P=0,T=this?.transform||ge;const W=new Map,A=new Map,{[M]:O}=n,S=$.length?le(ce(globalThis),...$):globalThis,N=pe(((e,t)=>{if(!W.has(t)){let n;for(;A.has(n=P++););W.set(t,n),A.set(n,e===s?t:T(t))}return K(e,W.get(t))})),L=e=>{O(E,K(l,e))},D=(e,n)=>{switch(e){case i:if(null==n)return S;case r:if(typeof n===a)return A.get(n);if(!(n instanceof ue))for(const e in n)n[e]=B(n[e]);return n;case s:if(typeof n===l){const e=A.get(n)?.deref();if(e)return e;const r=function(...e){return e.at(0)instanceof Event&&(e=>{const{currentTarget:n,target:r,type:s}=e;for(const o of t.get(n||r)?.get(s)||[])e[o]()})(...e),O(f,K(s,n),N(this),e.map(N))};return A.set(n,new WeakRef(r)),Q(n,L,{return:r,token:!1})}return A.get(n);case c:return de(n)}return n},B=e=>Y(e,D),j={[f]:(e,t,n)=>N(e.apply(t,n)),[p]:(e,t)=>N(new e(...t)),[h]:(e,t,n)=>N(X(e,t,n)),[d]:(e,t)=>N(ee(e,t)),[w]:e=>N(ne(e)),[g]:(e,t)=>N(e[t]),[y]:(e,t)=>{const n=te(e,t);return n?K(i,fe(n,N)):K(u,n)},[m]:(e,t)=>N(t in e),[b]:e=>N(re(e)),[v]:e=>K(r,se(e).map(N)),[x]:e=>N(oe(e)),[k]:(e,t,n)=>N(ae(e,t,n)),[C]:(e,t)=>N(ie(e,t)),[E](e){W.delete(A.get(e)),A.delete(e)}};return n[o]=(e,t,...n)=>{switch(e){case f:n[0]=B(n[0]),n[1]=n[1].map(B);break;case p:n[0]=n[0].map(B);break;case h:{const[e,t]=n;n[0]=B(e);const{get:r,set:s,value:o}=t;r&&(t.get=B(r)),s&&(t.set=B(s)),o&&(t.value=B(o));break}default:n=n.map(B)}return j[e](B(t),...n)},{proxy:n,[e.toLowerCase()]:S,[`is${e}Proxy`]:()=>!1}}})("Window"),we=(e=>{let t=0;const n=new Map,o=new Map,u=Symbol();return function(M,$,P){const T=this?.transform||ge,{[$]:W}=M,A=new Map,O=e=>{A.delete(e),W(E,S(e))},S=pe(((e,r)=>{if(u in r)return H(r[u]);if(e===s){if(r=T(r),!o.has(r)){let e;for(;o.has(e=String(t++)););n.set(r,e),o.set(e,r)}return K(e,n.get(r))}if(!(r instanceof ue)){r=T(r);for(const e in r)r[e]=S(r[e])}return K(e,r)})),N=(e,t,n)=>{const r=A.get(n)?.deref();if(r)return r;const o=t===s?(e=>J.bind(e))(e):e,a=new Proxy(o,B);return A.set(n,new WeakRef(a)),Q(n,O,{return:a,token:!1})},L=e=>Y(e,((t,n)=>{switch(t){case i:if(null===n)return globalThis;case r:return typeof n===a?N(e,t,n):n;case s:return typeof n===l?o.get(n):N(e,t,n);case c:return de(n)}return n})),D=(e,t,...n)=>L(W(e,H(t),...n)),B={[f]:(e,t,n)=>D(f,e,S(t),n.map(S)),[p]:(e,t)=>D(p,e,t.map(S)),[h]:(e,t,n)=>{const{get:r,set:o,value:a}=n;return typeof r===s&&(n.get=S(r)),typeof o===s&&(n.set=S(o)),typeof a===s&&(n.value=S(a)),D(h,e,S(t),n)},[d]:(e,t)=>D(d,e,S(t)),[w]:e=>D(w,e),[g]:(e,t)=>t===u?e:D(g,e,S(t)),[y]:(e,t)=>{const n=D(y,e,S(t));return n&&fe(n,L)},[m]:(e,t)=>t===u||D(m,e,S(t)),[b]:e=>D(b,e),[v]:e=>D(v,e).map(L),[x]:e=>D(x,e),[k]:(e,t,n)=>D(k,e,S(t),S(n)),[C]:(e,t)=>D(C,e,S(t))};M[P]=(e,t,r,s)=>{switch(e){case f:return L(t).apply(L(r),s.map(L));case E:{const e=L(t);n.delete(o.get(e)),o.delete(e)}}};const j=new Proxy(K(i,null),B);return{[e.toLowerCase()]:j,[`is${e}Proxy`]:e=>typeof e===i&&!!e&&u in e,proxy:M}}})("Window"),me=typeof Worker===s?Worker:class{};const be=new WeakMap,ve=(e,...r)=>{const s=z(e,...r);if(!be.has(s)){const o=e instanceof me?ye:we;be.set(s,o.call(r.at(0),s,t,n))}return be.get(s)};var xe=e=>function(){const{constructor:t}=e.createDocumentFragment();const{isArray:n}=Array,{getPrototypeOf:r,getOwnPropertyDescriptor:s}=Object,o=[],a=()=>e.createRange(),i=(e,t,n)=>(e.set(t,n),n),l=(e,t)=>t.reduceRight(c,e),c=(e,t)=>e.childNodes[t],{setPrototypeOf:u}=Object;let f;var p=(e,t,n)=>(f||(f=a()),n?f.setStartAfter(e):f.setStartBefore(e),f.setEndAfter(t),f.deleteContents(),e);const h=({firstChild:e,lastChild:t},n)=>p(e,t,n);let d=!1;const g=(e,t)=>d&&11===e.nodeType?1/t<0?t?h(e,!0):e.lastChild:t?e.valueOf():e.firstChild:e,y=t=>e.createComment(t);class w extends((e=>{function t(e){return u(e,new.target.prototype)}return t.prototype=e.prototype,t})(t)){#e=y("<>");#t=y("");#n=o;constructor(e){super(e),this.replaceChildren(this.#e,...e.childNodes,this.#t),d=!0}get firstChild(){return this.#e}get lastChild(){return this.#t}get parentNode(){return this.#e.parentNode}remove(){h(this,!1)}replaceWith(e){h(this,!0).replaceWith(e)}valueOf(){const{parentNode:e}=this;if(e===this)this.#n===o&&(this.#n=[...this.childNodes]);else{if(e){let{firstChild:e,lastChild:t}=this;for(this.#n=[e];e!==t;)this.#n.push(e=e.nextSibling)}this.replaceChildren(...this.#n)}return this}}const m=(e,t,n)=>e.setAttribute(t,n),b=(e,t)=>e.removeAttribute(t);let v;const x=(e,t,r)=>{r=r.slice(1),v||(v=new WeakMap);const s=v.get(e)||i(v,e,{});let o=s[r];return o&&o[0]&&e.removeEventListener(r,...o),o=n(t)?t:[t,!1],s[r]=o,o[0]&&e.addEventListener(r,...o),t},k=(e,t)=>{const{t:n,n:r}=e;let s=!1;switch(typeof t){case"object":if(null!==t){(r||n).replaceWith(e.n=t.valueOf());break}case"undefined":s=!0;default:n.data=s?"":t,r&&(e.n=null,r.replaceWith(n))}return t},C=(e,t,n)=>e[n]=t,E=(e,t,n)=>C(e,t,n.slice(1)),M=(e,t,n)=>null==t?(b(e,n),t):C(e,t,n),$=(e,t)=>("function"==typeof t?t(e):t.current=e,t),P=(e,t,n)=>(null==t?b(e,n):m(e,n,t),t),T=(e,t,n)=>(e.toggleAttribute(n.slice(1),t),t),W=(e,t,n)=>{const{length:r}=t;if(e.data=`[${r}]`,r)return((e,t,n,r,s)=>{const o=n.length;let a=t.length,i=o,l=0,c=0,u=null;for(;ls-c){const o=r(t[l],0);for(;c{for(const n in t){const r=t[n],s="role"===n?n:`aria-${n}`;null==r?b(e,s):m(e,s,r)}return t}],["class",(e,t)=>M(e,t,null==t?"class":"className")],["data",(e,t)=>{const{dataset:n}=e;for(const e in t)null==t[e]?delete n[e]:n[e]=t[e];return t}],["ref",$],["style",(e,t)=>null==t?M(e,t,"style"):C(e.style,t,"cssText")]]),O=(e,t,n)=>{switch(t[0]){case".":return E;case"?":return T;case"@":return x;default:return n||"ownerSVGElement"in e?"ref"===t?$:P:A.get(t)||(t in e?t.startsWith("on")?C:((e,t)=>{let n;do{n=s(e,t)}while(!n&&(e=r(e)));return n})(e,t)?.set?M:P:P)}},S=(e,t)=>(e.textContent=null==t?"":t,t),N=(e,t,n)=>({a:e,b:t,c:n}),L=()=>N(null,null,o);var D=t=>(n,r)=>{const{a:s,b:a,c:i}=t(n,r),c=e.importNode(s,!0);let u=o;if(a!==o){u=[];for(let e,t,n=0;n({b:e,c:t}))(i?c.firstChild:new w(c),u)};const B=/^(?:plaintext|script|style|textarea|title|xmp)$/i,j=/^(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)$/i,R=/<([a-zA-Z0-9]+[a-zA-Z0-9:._-]*)([^>]*?)(\/?)>/g,F=/([^\s\\>"'=]+)\s*=\s*(['"]?)\x01/g,_=/[\x01\x02]/g;let z,I,U=e.createElement("template");var H=(t,n)=>{if(n)return z||(z=e.createElementNS("http://www.w3.org/2000/svg","svg"),I=a(),I.selectNodeContents(z)),I.createContextualFragment(t);U.innerHTML=t;const{content:r}=U;return U=U.cloneNode(!1),r};const J=e=>{const t=[];let n;for(;n=e.parentNode;)t.push(t.indexOf.call(n.childNodes,e)),e=n;return t},K=()=>e.createTextNode(""),Y=(t,r,s)=>{const a=H(((e,t,n)=>{let r=0;return e.join("").trim().replace(R,((e,t,r,s)=>`<${t}${r.replace(F,"=$2$1").trimEnd()}${s?n||j.test(t)?" /":`>`)).replace(_,(e=>""===e?`\x3c!--${t+r++}--\x3e`:t+r++))})(t,G,s),s),{length:l}=t;let c=o;if(l>1){const t=[],o=e.createTreeWalker(a,129);let i=0,u=`${G}${i++}`;for(c=[];i(t,n)=>Z.get(t)||Y(t,n,e);const q=D(V(!1)),Q=D(V(!0)),X=(e,{s:t,t:n,v:r})=>{if(e.a!==n){const{b:s,c:o}=(t?Q:q)(n,r);e.a=n,e.b=s,e.c=o}for(let{c:t}=e,n=0;n{let n=0,{length:r}=t;for(r(t,...n)=>new te(e,t,n),re=ne(!1),se=ne(!0),oe=new WeakMap; -/*! (c) Andrea Giammarchi - MIT */ -const ae=new WeakMap,ie=e=>(t,n)=>{const r=ae.get(t)||i(ae,t,new Map);return r.get(n)||i(r,n,function(t,...n){return new te(e,t,n).toDOM(this)}.bind(L()))},le=ie(!1),ce=ie(!0);return{Hole:te,attr:A,html:re,htmlFor:le,render:(e,t)=>((e,t)=>{const n=oe.get(e)||i(oe,e,L()),{b:r}=n,s="function"==typeof t?t():t,o=s instanceof te?s.toDOM(n):s;return r!==o&&e.replaceChildren((n.b=o).valueOf()),e})(e,t),svg:se,svgFor:ce}}();const ke=(e,...t)=>{const n=ve(e,...t);return n.uhtml||(n.uhtml=xe(n.window.document)),n};ke.transfer=ve.transfer=z.transfer;export{ke as default}; diff --git a/test/dist/window.js b/test/dist/window.js deleted file mode 100644 index f6a13d0..0000000 --- a/test/dist/window.js +++ /dev/null @@ -1,2 +0,0 @@ -const e="566fc334-5147-4e86-bb9b-c7d24c13127d",t="M"+e,n="T"+e,r="array",s="function",o="null",a="number",i="object",c="string",l="symbol",f="undefined",u="apply",p="construct",g="defineProperty",y="deleteProperty",d="get",w="getOwnPropertyDescriptor",h="getPrototypeOf",b="has",m="isExtensible",v="ownKeys",E="preventExtensions",k="set",P="setPrototypeOf",M="delete",{isArray:T}=Array;let{SharedArrayBuffer:S,window:x}=globalThis,{notify:W,wait:A,waitAsync:O}=Atomics,$=null;O||(O=e=>({value:new Promise((t=>{let n=new Worker("data:application/javascript,onmessage%3D(%7Bdata%3Ab%7D)%3D%3E(Atomics.wait(b%2C0)%2CpostMessage(0))");n.onmessage=t,n.postMessage(e)}))}));try{new S(4)}catch(t){S=ArrayBuffer;const n=new WeakMap;if(x){const t=new Map,{prototype:{postMessage:r}}=Worker,s=n=>{const r=n.data?.[e];if(!T(r)){n.stopImmediatePropagation();const{id:e,sb:s}=r;t.get(e)(s)}};$=function(t,...o){const a=t?.[e];if(T(a)){const[e,t]=a;n.set(t,e),this.addEventListener("message",s)}return r.call(this,t,...o)},O=e=>({value:new Promise((r=>{t.set(n.get(e),r)})).then((r=>{t.delete(n.get(e)),n.delete(e);for(let t=0;t({[e]:{id:t,sb:n}});W=e=>{postMessage(t(n.get(e),e))},addEventListener("message",(t=>{const r=t.data?.[e];if(T(r)){const[e,t]=r;n.set(t,e)}}))}} -/*! (c) Andrea Giammarchi - ISC */const{Int32Array:L,Map:D,Uint16Array:R}=globalThis,{BYTES_PER_ELEMENT:B}=L,{BYTES_PER_ELEMENT:C}=R,N=new WeakSet,_=new WeakMap,j={value:{then:e=>e()}};let I=0;const U=(t,{parse:n=JSON.parse,stringify:r=JSON.stringify,transform:o,interrupt:a}=JSON)=>{if(!_.has(t)){const i=$||t.postMessage,c=(n,...r)=>i.call(t,{[e]:r},{transfer:n}),l=typeof a===s?a:a?.handler,f=a?.delay||42,u=new TextDecoder("utf-16"),p=(e,t)=>e?O(t,0):(l?((e,t,n)=>{for(;"timed-out"===A(e,0,0,t);)n()})(t,f,l):A(t,0),j);let g=!1;_.set(t,new Proxy(new D,{[b]:(e,t)=>"string"==typeof t&&!t.startsWith("_"),[d]:(e,r)=>"then"===r?null:(...e)=>{const s=I++;let a=new L(new S(2*B)),i=[];N.has(e.at(-1)||i)&&N.delete(i=e.pop()),c(i,s,a,r,o?e.map(o):e);const l=t!==globalThis;let f=0;return g&&l&&(f=setTimeout(console.warn,1e3,`💀🔒 - Possible deadlock if proxy.${r}(...args) is awaited`)),p(l,a).value.then((()=>{clearTimeout(f);const e=a[1];if(!e)return;const t=C*e;return a=new L(new S(t+t%B)),c([],s,a),p(l,a).value.then((()=>n(u.decode(new R(a.buffer).slice(0,e)))))}))},[k](n,a,i){const c=typeof i;if(c!==s)throw new Error(`Unable to assign ${a} as ${c}`);if(!n.size){const s=new D;t.addEventListener("message",(async t=>{const a=t.data?.[e];if(T(a)){t.stopImmediatePropagation();const[e,i,...c]=a;let l;if(c.length){const[t,a]=c;if(n.has(t)){g=!0;try{const c=await n.get(t)(...a);if(void 0!==c){const t=r(o?o(c):c);s.set(e,t),i[1]=t.length}}catch(e){l=e}finally{g=!1}}else l=new Error(`Unsupported action: ${t}`);i[0]=1}else{const t=s.get(e);s.delete(e);for(let e=new R(i.buffer),n=0;n(N.add(e),e);const{isArray:J}=Array,z=(e,t)=>t,F=e=>typeof e===s?(e=>e())(e):e;function K(){return this}const Y=(e,t)=>e===r?[t]:{t:e,v:t},H=(e,t=z)=>{let n=typeof e,s=e;return n===i&&(J(e)?(n=r,s=e.at(0)):({t:n,v:s}=e)),t(n,s)},q=(e,t)=>e===s?t:Y(e,t),G=(e,t=q)=>{const n=null===e?o:typeof e;return t(n===i&&J(e)?r:n,e)},Q=new FinalizationRegistry((([e,t,n])=>{n&&console.debug(`Held value ${String(t)} not relevant anymore`),e(t)})),V=Object.create(null),X=(e,t,{debug:n,handler:r,return:s,token:o=e}=V)=>{const a=s||new Proxy(e,r||V),i=[a,[t,e,!!n]];return!1!==o&&i.push(o),Q.register(...i),a},{defineProperty:Z,deleteProperty:ee,getOwnPropertyDescriptor:te,getPrototypeOf:ne,isExtensible:re,ownKeys:se,preventExtensions:oe,set:ae,setPrototypeOf:ie}=Reflect,{assign:ce,create:le}=Object,fe=ne(Int8Array),ue=(e,t)=>{const{get:n,set:r,value:s}=e;return n&&(e.get=t(n)),r&&(e.set=t(r)),s&&(e.value=t(s)),e},pe=e=>t=>G(t,((t,n)=>{switch(t){case o:return Y(o,n);case i:if(n===globalThis)return Y(t,null);case r:case s:return e(t,n);case"boolean":case a:case c:case f:case"bigint":return Y(t,n);case l:{if(ge.has(n))return Y(t,ge.get(n));let e=Symbol.keyFor(n);if(e)return Y(t,`.${e}`)}}throw new TypeError(`Unable to handle this ${t}: ${String(n)}`)})),ge=new Map(se(Symbol).filter((e=>typeof Symbol[e]===l)).map((e=>[Symbol[e],e]))),ye=e=>{if(e.startsWith("."))return Symbol.for(e.slice(1));for(const[t,n]of ge)if(n===e)return t},de=e=>e;var we=(e=>{const t=new WeakMap;{const{addEventListener:e}=EventTarget.prototype;Z(EventTarget.prototype,"addEventListener",{value(n,r,...s){return s.at(0)?.invoke&&(t.has(this)||t.set(this,new Map),t.get(this).set(n,[].concat(s[0].invoke)),delete s[0].invoke),e.call(this,n,r,...s)}})}return function(n,o,T,...S){let x=0,W=this?.transform||de;const A=new Map,O=new Map,{[T]:$}=n,L=S.length?ce(le(globalThis),...S):globalThis,D=pe(((e,t)=>{if(!A.has(t)){let n;for(;O.has(n=x++););A.set(t,n),O.set(n,e===s?t:W(t))}return Y(e,A.get(t))})),R=e=>{$(M,Y(c,e))},B=(e,n)=>{switch(e){case i:if(null==n)return L;case r:if(typeof n===a)return O.get(n);if(!(n instanceof fe))for(const e in n)n[e]=C(n[e]);return n;case s:if(typeof n===c){const e=O.get(n)?.deref();if(e)return e;const r=function(...e){return e.at(0)instanceof Event&&(e=>{const{currentTarget:n,target:r,type:s}=e;for(const o of t.get(n||r)?.get(s)||[])e[o]()})(...e),$(u,Y(s,n),D(this),e.map(D))};return O.set(n,new WeakRef(r)),X(n,R,{return:r,token:!1})}return O.get(n);case l:return ye(n)}return n},C=e=>H(e,B),N={[u]:(e,t,n)=>D(e.apply(t,n)),[p]:(e,t)=>D(new e(...t)),[g]:(e,t,n)=>D(Z(e,t,n)),[y]:(e,t)=>D(ee(e,t)),[h]:e=>D(ne(e)),[d]:(e,t)=>D(e[t]),[w]:(e,t)=>{const n=te(e,t);return n?Y(i,ue(n,D)):Y(f,n)},[b]:(e,t)=>D(t in e),[m]:e=>D(re(e)),[v]:e=>Y(r,se(e).map(D)),[E]:e=>D(oe(e)),[k]:(e,t,n)=>D(ae(e,t,n)),[P]:(e,t)=>D(ie(e,t)),[M](e){A.delete(O.get(e)),O.delete(e)}};return n[o]=(e,t,...n)=>{switch(e){case u:n[0]=C(n[0]),n[1]=n[1].map(C);break;case p:n[0]=n[0].map(C);break;case g:{const[e,t]=n;n[0]=C(e);const{get:r,set:s,value:o}=t;r&&(t.get=C(r)),s&&(t.set=C(s)),o&&(t.value=C(o));break}default:n=n.map(C)}return N[e](C(t),...n)},{proxy:n,[e.toLowerCase()]:L,[`is${e}Proxy`]:()=>!1}}})("Window"),he=(e=>{let t=0;const n=new Map,o=new Map,f=Symbol();return function(T,S,x){const W=this?.transform||de,{[S]:A}=T,O=new Map,$=e=>{O.delete(e),A(M,L(e))},L=pe(((e,r)=>{if(f in r)return F(r[f]);if(e===s){if(r=W(r),!o.has(r)){let e;for(;o.has(e=String(t++)););n.set(r,e),o.set(e,r)}return Y(e,n.get(r))}if(!(r instanceof fe)){r=W(r);for(const e in r)r[e]=L(r[e])}return Y(e,r)})),D=(e,t,n)=>{const r=O.get(n)?.deref();if(r)return r;const o=t===s?(e=>K.bind(e))(e):e,a=new Proxy(o,C);return O.set(n,new WeakRef(a)),X(n,$,{return:a,token:!1})},R=e=>H(e,((t,n)=>{switch(t){case i:if(null===n)return globalThis;case r:return typeof n===a?D(e,t,n):n;case s:return typeof n===c?o.get(n):D(e,t,n);case l:return ye(n)}return n})),B=(e,t,...n)=>R(A(e,F(t),...n)),C={[u]:(e,t,n)=>B(u,e,L(t),n.map(L)),[p]:(e,t)=>B(p,e,t.map(L)),[g]:(e,t,n)=>{const{get:r,set:o,value:a}=n;return typeof r===s&&(n.get=L(r)),typeof o===s&&(n.set=L(o)),typeof a===s&&(n.value=L(a)),B(g,e,L(t),n)},[y]:(e,t)=>B(y,e,L(t)),[h]:e=>B(h,e),[d]:(e,t)=>t===f?e:B(d,e,L(t)),[w]:(e,t)=>{const n=B(w,e,L(t));return n&&ue(n,R)},[b]:(e,t)=>t===f||B(b,e,L(t)),[m]:e=>B(m,e),[v]:e=>B(v,e).map(R),[E]:e=>B(E,e),[k]:(e,t,n)=>B(k,e,L(t),L(n)),[P]:(e,t)=>B(P,e,L(t))};T[x]=(e,t,r,s)=>{switch(e){case u:return R(t).apply(R(r),s.map(R));case M:{const e=R(t);n.delete(o.get(e)),o.delete(e)}}};const N=new Proxy(Y(i,null),C);return{[e.toLowerCase()]:N,[`is${e}Proxy`]:e=>typeof e===i&&!!e&&f in e,proxy:T}}})("Window"),be=typeof Worker===s?Worker:class{};const me=new WeakMap,ve=(e,...r)=>{const s=U(e,...r);if(!me.has(s)){const o=e instanceof be?we:he;me.set(s,o.call(r.at(0),s,t,n))}return me.get(s)};ve.transfer=U.transfer;export{ve as default}; diff --git a/test/dom/index.html b/test/dom/index.html new file mode 100644 index 0000000..0cdd7f2 --- /dev/null +++ b/test/dom/index.html @@ -0,0 +1,9 @@ + + + + + + DOM + + + diff --git a/test/dom/index.js b/test/dom/index.js new file mode 100644 index 0000000..d4ecf70 --- /dev/null +++ b/test/dom/index.js @@ -0,0 +1,5 @@ +import coincident from '../../dist/window/main.js'; + +const { Worker } = coincident(); + +new Worker('./worker.js', { serviceWorker: '../sw.js' }); diff --git a/test/dom/worker.js b/test/dom/worker.js new file mode 100644 index 0000000..f2a9f79 --- /dev/null +++ b/test/dom/worker.js @@ -0,0 +1,16 @@ +import coincident from '../../dist/window/worker.js'; + +const { window } = await coincident(); +const { document } = window; + +document.body.textContent = 'Testing ...'; + +document.addEventListener( + 'click', + event => { + document.body.textContent = event.type; + }, + { once: true } +); + +document.body.click(); diff --git a/test/global.html b/test/global.html deleted file mode 100644 index e7a3d8f..0000000 --- a/test/global.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - diff --git a/test/global.js b/test/global.js deleted file mode 100644 index b815292..0000000 --- a/test/global.js +++ /dev/null @@ -1,5 +0,0 @@ -import coincident from './dist/window.js'; - -const { window } = coincident(self); - -console.assert(self === window.global.call(self, window), 'self should be globalThis'); diff --git a/test/harakiri.html b/test/harakiri.html deleted file mode 100644 index 3481fd9..0000000 --- a/test/harakiri.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - diff --git a/test/harakiri.js b/test/harakiri.js deleted file mode 100644 index 5ecb0ab..0000000 --- a/test/harakiri.js +++ /dev/null @@ -1,8 +0,0 @@ -import coincident from './dist/window.js'; - -const { proxy } = coincident(self); - -proxy.worker = () => '🔥 this is fine 🔥'; - -// here the 💀🔒 -proxy.main(); diff --git a/test/harakiri/index.html b/test/harakiri/index.html new file mode 100644 index 0000000..0fd7711 --- /dev/null +++ b/test/harakiri/index.html @@ -0,0 +1,26 @@ + + + + + + + + + diff --git a/test/harakiri/worker.js b/test/harakiri/worker.js new file mode 100644 index 0000000..3ee1243 --- /dev/null +++ b/test/harakiri/worker.js @@ -0,0 +1,7 @@ +import coincident from '../../dist/window/worker.js'; +const { proxy } = await coincident(); + +proxy.worker = () => '🔥 this is fine 🔥'; + +// here the 💀🔒 +proxy.main(); diff --git a/test/hyperhtml.html b/test/hyperhtml.html deleted file mode 100644 index 0016ecb..0000000 --- a/test/hyperhtml.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - diff --git a/test/hyperhtml.js b/test/hyperhtml.js deleted file mode 100644 index b38f446..0000000 --- a/test/hyperhtml.js +++ /dev/null @@ -1,21 +0,0 @@ -import coincident from './dist/window.js'; - -const {window} = coincident(self); - -// neededd as global in hyperHTML module -globalThis.document = window.document; - -import('./hyperhtml.mjs').then(({bind}) => { - const html = bind(document.body); - tick(html); - setInterval(tick, 1000, html); -}); - -function tick(html) { - html` -
-

Hello, world!

-

It is ${new Date().toLocaleTimeString()}.

-
- `; -} diff --git a/test/hyperhtml.mjs b/test/hyperhtml.mjs deleted file mode 100644 index 1ded632..0000000 --- a/test/hyperhtml.mjs +++ /dev/null @@ -1,3 +0,0 @@ -/*! (c) Andrea Giammarchi (ISC) */var hyperHTML=function(N){"use strict";var t={};try{t.WeakMap=WeakMap}catch(e){t.WeakMap=function(t,e){var n=e.defineProperty,r=e.hasOwnProperty,i=a.prototype;return i.delete=function(e){return this.has(e)&&delete e[this._]},i.get=function(e){return this.has(e)?e[this._]:void 0},i.has=function(e){return r.call(e,this._)},i.set=function(e,t){return n(e,this._,{configurable:!0,value:t}),this},a;function a(e){n(this,"_",{value:"_@ungap/weakmap"+t++}),e&&e.forEach(o,this)}function o(e){this.set(e[0],e[1])}}(Math.random(),Object)}var s=t.WeakMap,i={};try{i.WeakSet=WeakSet}catch(e){!function(e,t){var n=r.prototype;function r(){t(this,"_",{value:"_@ungap/weakmap"+e++})}n.add=function(e){return this.has(e)||t(e,this._,{value:!0,configurable:!0}),this},n.has=function(e){return this.hasOwnProperty.call(e,this._)},n.delete=function(e){return this.has(e)&&delete e[this._]},i.WeakSet=r}(Math.random(),Object.defineProperty)}function m(e,t,n,r,i,a){for(var o=("selectedIndex"in t),u=o;ro;)--c;l=u+r-c;var m=Array(l),y=s[c];for(--n;y;){for(var b=y.newi,w=y.oldi;b>>0;n"+e+"",r.querySelectorAll(t)):(r.innerHTML=e,r.childNodes)),n},function(e,t){return("svg"===t?function(e){var t=H(O),n=H("div");return n.innerHTML=''+e+"",F(t,n.firstChild.childNodes),t}:M)(e)});function F(e,t){for(var n=t.length;n--;)e.appendChild(t[0])}function H(e){return e===O?S.createDocumentFragment():S.createElementNS("http://www.w3.org/1999/xhtml",e)}var I,z,V,Z,G,q,B,J,K,Q,U=(z="appendChild",V="cloneNode",Z="createTextNode",q=(G="importNode")in(I=N),(B=I.createDocumentFragment())[z](I[Z]("g")),B[z](I[Z]("")),(q?I[G](B,!0):B[V](!0)).childNodes.length<2?function e(t,n){for(var r=t[V](),i=t.childNodes||[],a=i.length,o=0;n&&o

',J[K].childNodes[0].getAttribute(Q)==Y)||(Y="_dt: "+Y.slice(1,-1)+";",ee=!0)}catch(e){}var te="\x3c!--"+Y+"--\x3e",ne=8,re=1,ie=3,ae=/^(?:style|textarea)$/i,oe=/^(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)$/i;var ue=" \\f\\n\\r\\t",ce="[^"+ue+"\\/>\"'=]+",le="["+ue+"]+"+ce,se="<([A-Za-z]+[A-Za-z0-9:._-]*)((?:",fe="(?:\\s*=\\s*(?:'[^']*?'|\"[^\"]*?\"|<[^>]*?>|"+ce.replace("\\/","")+"))?)",he=new RegExp(se+le+fe+"+)(["+ue+"]*/?>)","g"),de=new RegExp(se+le+fe+"*)(["+ue+"]*/>)","g"),ve=new RegExp("("+le+"\\s*=\\s*)(['\"]?)"+te+"\\2","gi");function pe(e,t,n,r){return"<"+t+n.replace(ve,ge)+r}function ge(e,t,n){return t+(n||'"')+Y+(n||'"')}function me(e,t,n){return oe.test(t)?e:"<"+t+n+">"}var ye=ee?function(e,t){var n=t.join(" ");return t.slice.call(e,0).sort(function(e,t){return n.indexOf(e.name)<=n.indexOf(t.name)?-1:1})}:function(e,t){return t.slice.call(e,0)};function be(e,t,n,r){for(var i=e.childNodes,a=i.length,o=0;o \ No newline at end of file diff --git a/test/iframe/index.html b/test/iframe/index.html index 2b316c3..8418d05 100644 --- a/test/iframe/index.html +++ b/test/iframe/index.html @@ -3,7 +3,6 @@ - - - - - - - + + + + Coincident Tests + + + + + diff --git a/test/index.js b/test/index.js deleted file mode 100644 index 4797eea..0000000 --- a/test/index.js +++ /dev/null @@ -1,4 +0,0 @@ -const coincident = require('../cjs'); - -console.log('Until Node.js supports Web Workers out of the box:'); -console.log('`npm run server` and then reach http://localhost:8080/test/'); diff --git a/test/input.html b/test/input.html deleted file mode 100644 index 30cd80b..0000000 --- a/test/input.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - diff --git a/test/input.js b/test/input.js deleted file mode 100644 index d620748..0000000 --- a/test/input.js +++ /dev/null @@ -1,24 +0,0 @@ -import coincident from '../uhtml.js'; - -const {window, uhtml} = coincident(self); -const {render, html} = uhtml; -const {document} = window; - -input('', handler); - -function input(value, handler) { - render(document.body, html` -
- - - -
${value}
-
- `); -} - -function handler(event) { - const {value} = event.target; - console.log(value); - input(value, handler); -} diff --git a/test/input/index.html b/test/input/index.html new file mode 100644 index 0000000..ff79a11 --- /dev/null +++ b/test/input/index.html @@ -0,0 +1,15 @@ + + + + + + non-blocking input + + + + + + diff --git a/test/input/index.js b/test/input/index.js new file mode 100644 index 0000000..08382eb --- /dev/null +++ b/test/input/index.js @@ -0,0 +1,20 @@ +import coincident from '../../dist/window/main.js'; + +const { Worker } = coincident(); + +const { proxy } = new Worker('./worker.js', { serviceWorker: '../sw.js' }); + +// sync way VS promise based (more Webbish) +// add a slash in front of the next line to see the form +//**/proxy.input = value => prompt(value);/* +proxy.input = placeholder => new Promise(resolve => { + const [user, submit] = document.querySelectorAll('input'); + submit.addEventListener('click', event => { + event.preventDefault(); + resolve(user.value.trim()); + }, {once: true}); + question.removeAttribute('hidden'); + user.placeholder = placeholder; + user.focus(); +}); +//*/ \ No newline at end of file diff --git a/test/worker.js b/test/input/worker.js similarity index 50% rename from test/worker.js rename to test/input/worker.js index 4856277..9b3ae29 100644 --- a/test/worker.js +++ b/test/input/worker.js @@ -1,8 +1,8 @@ -import coincident from './dist/window.js'; +import coincident from '../../dist/window/worker.js'; -const until = coincident(self).proxy; +const { proxy } = await coincident(); console.log('asking for an input'); // pauses in a non blocking way the worker until the answer has been received -console.log('input', until.input('what is 1 + 3 ?')); +console.log('input', proxy.input('what is 1 + 3 ?')); console.log('input received'); diff --git a/test/integration.spec.js b/test/integration.spec.js deleted file mode 100644 index 600ec96..0000000 --- a/test/integration.spec.js +++ /dev/null @@ -1,57 +0,0 @@ -require('@ungap/with-resolvers'); -const { join } = require('node:path'); -const { scripts } = require(join(__dirname, '..', 'package.json')); -const { test, expect } = require('@playwright/test'); - -// amount of ms to be sure the server is running -const WORKER_DELAY = 50; - -const pages = new WeakMap; -const server = { - ...Promise.withResolvers(), - process: null -}; - -test.beforeAll(() => { - const [command, ...args] = scripts.server.split(/\s+/); - server.process = require('child_process').spawn(command, args, { - cwd: join(__dirname, '..'), - }); - server.process.stdout.on('data', server.resolve); - // this is to ignore dangling server around - // (tests will fail if not pointing at the right localhost) - server.process.stderr.on('data', server.resolve); -}); - -test.afterAll(() => { - server.process.kill(); -}); - -test.beforeEach(async ({ page }) => { - const {resolve, promise} = Promise.withResolvers(); - page.once('worker', worker => { - // give the worker enough time to be parsed and do stuff - setTimeout(resolve, WORKER_DELAY); - }); - pages.set(page, promise); - await server.promise; - // no worker case (wait twice to be sure) - setTimeout(resolve, WORKER_DELAY * 2); -}); - -test('has title', async ({ page }) => { - await page.goto('http://localhost:8080/test/integration/'); - await expect(page).toHaveTitle(/coincident/); -}); - -test('has worker working', async ({ page }) => { - await page.goto('http://localhost:8080/test/integration/'); - await page.waitForSelector('html.ready'); - const result = await page.evaluate(() => document.body.textContent); - await expect(result.trim()).toBe('Greetingstrue'); -}); - -test('worker can set classes', async ({ page }) => { - await page.goto('http://localhost:8080/test/integration/'); - await page.waitForSelector('html.ready'); -}); diff --git a/test/integration/index.html b/test/integration/index.html deleted file mode 100644 index af86821..0000000 --- a/test/integration/index.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - coincident - - - diff --git a/test/integration/index.js b/test/integration/index.js deleted file mode 100644 index d98fcd7..0000000 --- a/test/integration/index.js +++ /dev/null @@ -1,9 +0,0 @@ -import coincident from '../dist/window.js'; - -const {proxy, window, isWindowProxy} = coincident(self); - -window.dispatchEvent(new window.Event('ready')); - -proxy.greetings(isWindowProxy(window.document.body)); - -window.document.documentElement.classList.add('ready'); diff --git a/test/issue-26/index.html b/test/issue-26/index.html index a711cc8..0cb902e 100644 --- a/test/issue-26/index.html +++ b/test/issue-26/index.html @@ -5,8 +5,12 @@ - \ No newline at end of file + diff --git a/test/issue-26/worker.js b/test/issue-26/worker.js index 7c37e69..bf135f0 100644 --- a/test/issue-26/worker.js +++ b/test/issue-26/worker.js @@ -1,9 +1,11 @@ console.log('worker.js'); -import coincident from '../../es.js'; -const proxy = coincident(self); +import coincident from '../../dist/window/worker.js'; +const { proxy } = await coincident(); -for (let i = 0; i < 100000; i++) +console.time('loop'); +for (let i = 0; i < 10000; i++) proxy.func(); +console.timeEnd('loop'); console.log('DONE'); diff --git a/test/issue-34/index.html b/test/issue-34/index.html index 756a67b..bda5aea 100644 --- a/test/issue-34/index.html +++ b/test/issue-34/index.html @@ -5,12 +5,14 @@ - \ No newline at end of file + diff --git a/test/issue-34/worker.js b/test/issue-34/worker.js index aad5698..e395a4f 100644 --- a/test/issue-34/worker.js +++ b/test/issue-34/worker.js @@ -1,5 +1,5 @@ -import coincident from '../dist/window.js'; -const { window } = coincident(self); +import coincident from '../../dist/window/worker.js'; +const { window } = await coincident(); const { array, object } = window; diff --git a/test/micropython.html b/test/micropython.html deleted file mode 100644 index e38da02..0000000 --- a/test/micropython.html +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - MicroPython Terminal - - - - - - - diff --git a/test/no-sab-or-sw/index.html b/test/no-sab-or-sw/index.html new file mode 100644 index 0000000..caffc53 --- /dev/null +++ b/test/no-sab-or-sw/index.html @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/test/no-sab-or-sw/worker.js b/test/no-sab-or-sw/worker.js new file mode 100644 index 0000000..9ff50c8 --- /dev/null +++ b/test/no-sab-or-sw/worker.js @@ -0,0 +1,8 @@ +import coincident from '../../dist/window/worker.js'; +const { proxy, polyfill, sync } = await coincident(); + +console.table({ polyfill, sync }); + +proxy.sum = (...args) => args.reduce((p, c) => (p + c), 0); + +console.log('worker invoking main', await proxy.href()); diff --git a/test/no-sab/index.html b/test/no-sab/index.html deleted file mode 100644 index 3ef2dd6..0000000 --- a/test/no-sab/index.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - diff --git a/test/no-sab/worker.js b/test/no-sab/worker.js deleted file mode 100644 index 4a88e39..0000000 --- a/test/no-sab/worker.js +++ /dev/null @@ -1,3 +0,0 @@ -import coincident from '../dist/es.js'; - -coincident(self).getValue = () => Math.random(); diff --git a/test/package.json b/test/package.json deleted file mode 100644 index 0292b99..0000000 --- a/test/package.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"commonjs"} \ No newline at end of file diff --git a/test/ping-pong.html b/test/ping-pong.html deleted file mode 100644 index 7d7b14c..0000000 --- a/test/ping-pong.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - diff --git a/test/ping-pong.js b/test/ping-pong.js deleted file mode 100644 index 692d3be..0000000 --- a/test/ping-pong.js +++ /dev/null @@ -1,7 +0,0 @@ -import coincident from '../es.js'; - -const wrap = coincident(self); - -// define a method that can be awaited from the main -// asking for a question in main while returning -wrap.sum = num => (num + parseInt(wrap.ask(`${num} + ... ?`), 10)); diff --git a/test/pyterminal/index.html b/test/pyterminal/index.html deleted file mode 100644 index ea8521e..0000000 --- a/test/pyterminal/index.html +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - PyScript Terminal - - - - - - - diff --git a/test/reflect/index.html b/test/reflect/index.html new file mode 100644 index 0000000..666bb1a --- /dev/null +++ b/test/reflect/index.html @@ -0,0 +1,9 @@ + + + + + + Reflect Own Keys + + + diff --git a/test/reflect/index.js b/test/reflect/index.js new file mode 100644 index 0000000..dd8ae27 --- /dev/null +++ b/test/reflect/index.js @@ -0,0 +1,10 @@ +import coincident from '../../dist/window/main.js'; + +const { Worker } = coincident(); + +new Worker('./worker.js', { serviceWorker: '../sw.js' }); + +globalThis.test = { + a: 1, + b: 2, +}; diff --git a/test/reflect/worker.js b/test/reflect/worker.js new file mode 100644 index 0000000..f160d87 --- /dev/null +++ b/test/reflect/worker.js @@ -0,0 +1,18 @@ +import coincident from '../../dist/window/worker.js'; + +const { window } = await coincident(); +const { document, test } = window; + +console.assert(Reflect.ownKeys(test).join(',') === 'a,b'); + +Object.defineProperty(test, 'value', { + configurable: true, + value() { + return this; + } +}); + +console.assert(Object.getOwnPropertyDescriptor(test, 'value').configurable); +console.assert(await test.value() === test); + +document.body.textContent = 'OK'; diff --git a/test/server/bun.js b/test/server/bun.js deleted file mode 100644 index 3999aa9..0000000 --- a/test/server/bun.js +++ /dev/null @@ -1,30 +0,0 @@ -import { serve, file } from 'bun'; -import { EventEmitter } from 'events'; -import coincidentWS from '../../esm/bun.js'; - -const port = 8080; -const headers = { - 'Cross-Origin-Opener-Policy': 'same-origin', - 'Cross-Origin-Embedder-Policy': 'require-corp', - 'Cross-Origin-Resource-Policy': 'same-origin' -}; - -serve({ - port, - fetch(req, server) { - if (server.upgrade(req)) return; - let path = '.' + new URL(req.url).pathname; - if (path.endsWith('/')) path += 'index.html'; - return new Response(file(path), {headers}); - }, - websocket: coincidentWS({ - import: name => import(name), - emitter: () => { - const emitter = new EventEmitter; - setTimeout(() => { emitter.emit('event', 'emitter', Math.random()); }, 1000); - return emitter; - } - }), -}); - -console.log(`http://localhost:${port}/test/server/`); diff --git a/test/server/index.html b/test/server/index.html deleted file mode 100644 index 3ade79a..0000000 --- a/test/server/index.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - diff --git a/test/server/main.cjs b/test/server/main.cjs deleted file mode 100644 index 16b06cf..0000000 --- a/test/server/main.cjs +++ /dev/null @@ -1,24 +0,0 @@ -const {createServer} = require('http'); -const {join} = require('path'); -const {WebSocketServer} = require('ws'); -const {EventEmitter} = require('node:events'); -const staticHandler = require('static-handler'); -const coincident = require('../../cjs/server.js'); -const handler = staticHandler(join(__dirname, '..', '..'), { - 'Cross-Origin-Opener-Policy': 'same-origin', - 'Cross-Origin-Embedder-Policy': 'require-corp', - 'Cross-Origin-Resource-Policy': 'same-origin' -}); -const server = createServer(handler); -coincident(new WebSocketServer({server}), { - require, - import: name => import(name), - emitter: () => { - const emitter = new EventEmitter; - setTimeout(() => { emitter.emit('event', 'emitter', Math.random()); }, 1000); - return emitter; - } -}); -server.listen(8080, () => { - console.log(`http://localhost:8080/test/server/`); -}); diff --git a/test/server/worker.js b/test/server/worker.js deleted file mode 100644 index 0a92214..0000000 --- a/test/server/worker.js +++ /dev/null @@ -1,36 +0,0 @@ -import coincident from '../../server.js'; - -console.time('Bootstrap'); -const { - proxy, // the main thread (UI/DOM) proxy - window, // the window reference - isWindowProxy, // the window introspection helper - server, // the server reference - isServerProxy, // the server introspection helper -} = coincident(self); -console.timeEnd('Bootstrap'); - -const os = await server.import('os'); - -console.time('Server'); -const html = ` -

coincident/server

-

Platform Info

-
    -
  • Platform: ${os.platform()}
  • -
  • Arch: ${os.arch()}
  • -
  • CPUS: ${os.cpus().length}
  • -
  • RAM: ${os.totalmem()}
  • -
  • Free: ${os.freemem()}
  • -
-`; -console.timeEnd('Server'); - -console.time('Main'); -window.document.body.innerHTML = html; -console.timeEnd('Main'); - -server.setTimeout(() => { console.log('OK'); }, 1000); - -const test = server.emitter(); -test.on('event', (...args) => console.log(...args)); diff --git a/test/sqlite/bun.js b/test/sqlite/bun.js deleted file mode 100644 index 6e12211..0000000 --- a/test/sqlite/bun.js +++ /dev/null @@ -1,22 +0,0 @@ -import { serve, file } from 'bun'; -import coincidentWS from '../../esm/bun.js'; - -const port = 8080; -const headers = { - 'Cross-Origin-Opener-Policy': 'same-origin', - 'Cross-Origin-Embedder-Policy': 'require-corp', - 'Cross-Origin-Resource-Policy': 'same-origin' -}; - -serve({ - port, - fetch(req, server) { - if (server.upgrade(req)) return; - let path = '.' + new URL(req.url).pathname; - if (path.endsWith('/')) path += 'index.html'; - return new Response(file(path), {headers}); - }, - websocket: coincidentWS({import: name => import(name)}), -}); - -console.log(`http://localhost:${port}/test/sqlite/`); diff --git a/test/sqlite/index.html b/test/sqlite/index.html deleted file mode 100644 index a00b3c2..0000000 --- a/test/sqlite/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - diff --git a/test/sqlite/worker.js b/test/sqlite/worker.js deleted file mode 100644 index 522ec2a..0000000 --- a/test/sqlite/worker.js +++ /dev/null @@ -1,24 +0,0 @@ -import coincident from '../../server.js'; - -const {window, server} = coincident(self); - -const os = await server.import('os'); -const {Database} = await server.import('bun:sqlite'); - -const db = new Database(":memory:"); - -console.time('query'); -const {message} = db.query("select 'Hello world' as message;").get(); -console.timeEnd('query'); - -const html = ` -

coincident/bun

-

SQLite Message

-

- ${message} -

-`; - -console.time('html'); -window.document.body.innerHTML = html; -console.timeEnd('html'); diff --git a/test/structured.html b/test/structured.html deleted file mode 100644 index eb798a8..0000000 --- a/test/structured.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - diff --git a/test/structured.js b/test/structured.js deleted file mode 100644 index cd401f3..0000000 --- a/test/structured.js +++ /dev/null @@ -1,8 +0,0 @@ -import coincident from '../structured.js'; - -const until = coincident(self); - -const result = until.input('what is 1 + 3 ?'); -console.log('result', result); - -console.assert(typeof result.bigInt === 'bigint'); diff --git a/test/sw.js b/test/sw.js new file mode 100644 index 0000000..0a7c67a --- /dev/null +++ b/test/sw.js @@ -0,0 +1 @@ +const{isArray:e}=Array,t=new Map,s=e=>{e.stopImmediatePropagation(),e.preventDefault()};var n=Object.freeze({__proto__:null,activate:e=>e.waitUntil(clients.claim()),fetch:e=>{const{request:n}=e;"POST"===n.method&&n.url===`${location.href}?sabayon`&&(s(e),e.respondWith(n.json().then((async e=>{const{promise:s,resolve:o}=Promise.withResolvers(),a=e.join(",");t.set(a,o);for(const t of await clients.matchAll())t.postMessage(e);return s.then((e=>new Response(`[${e.join(",")}]`,n.headers)))}))))},message:n=>{const{data:o}=n;if(e(o)&&4===o.length){const[e,a,r,i]=o,c=[e,a,r].join(",");t.has(c)&&(s(n),t.get(c)(i),t.delete(c))}}});for(const e in n)addEventListener(e,n[e]); diff --git a/test/too-big/index.html b/test/too-big/index.html index 4f5b174..a477c35 100644 --- a/test/too-big/index.html +++ b/test/too-big/index.html @@ -4,12 +4,15 @@ - \ No newline at end of file + diff --git a/test/too-big/worker.js b/test/too-big/worker.js index d553c53..6e66c63 100644 --- a/test/too-big/worker.js +++ b/test/too-big/worker.js @@ -1,5 +1,5 @@ -import coincident from '../../es.js'; -const proxy = coincident(self); +import coincident from '../../dist/window/worker.js'; +const { proxy } = await coincident(); let x = proxy.func(); console.log("len: ", Object.keys(x).length); diff --git a/test/transfer.html b/test/transfer.html deleted file mode 100644 index 1892812..0000000 --- a/test/transfer.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - diff --git a/test/transfer.js b/test/transfer.js deleted file mode 100644 index 94be1ce..0000000 --- a/test/transfer.js +++ /dev/null @@ -1,10 +0,0 @@ -import coincident from '../es.js'; - -const until = coincident(self); -const {transfer} = coincident; - -const uInt8Array = new Uint8Array(1024 * 1024 * 8).map((v, i) => i); -console.assert(uInt8Array.byteLength === 8388608, 'expected original length'); -until.transfer([1, 2], {array: uInt8Array}, transfer(uInt8Array.buffer)); -console.assert(uInt8Array.byteLength === 0, 'expected transfered length'); -console.log('OK'); diff --git a/test/uhtml.html b/test/uhtml.html deleted file mode 100644 index d2c89d0..0000000 --- a/test/uhtml.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - diff --git a/test/uhtml.js b/test/uhtml.js deleted file mode 100644 index 18f09c3..0000000 --- a/test/uhtml.js +++ /dev/null @@ -1,22 +0,0 @@ -// import * as JSON from '../node_modules/@ungap/structured-clone/esm/json.js'; -import coincident from '../uhtml.js'; - -const {window, uhtml} = coincident(self, JSON); -const {render, html} = uhtml; -const {document} = window; - -const log = event => { - console.log(event.type, 'hello there'); -}; - -tick(uhtml); -setInterval(tick, 1000, uhtml); - -function tick() { - render(document.body, html` -
console.log(type)}> -

Hello, world!

-

It is ${new Date().toLocaleTimeString()}.

-
- `); -} diff --git a/test/undefined.html b/test/undefined.html deleted file mode 100644 index b4e03b7..0000000 --- a/test/undefined.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - diff --git a/test/undefined.js b/test/undefined.js deleted file mode 100644 index 67a60a9..0000000 --- a/test/undefined.js +++ /dev/null @@ -1,4 +0,0 @@ -import coincident from '../es.js'; - -console.log(coincident(self).undefined()); -console.log(coincident(self).null()); diff --git a/test/unknown.html b/test/unknown.html deleted file mode 100644 index 6bc6cfb..0000000 --- a/test/unknown.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - diff --git a/test/unknown.js b/test/unknown.js deleted file mode 100644 index 5cb1b1f..0000000 --- a/test/unknown.js +++ /dev/null @@ -1,5 +0,0 @@ -import coincident from './dist/window.js'; - -const {proxy} = coincident(self); - -proxy.greetings(); diff --git a/test/virtual-dom/index.html b/test/virtual-dom/index.html index eaff9b7..420e302 100644 --- a/test/virtual-dom/index.html +++ b/test/virtual-dom/index.html @@ -3,7 +3,6 @@ - - - - diff --git a/test/window/index.html b/test/window/index.html new file mode 100644 index 0000000..483fb04 --- /dev/null +++ b/test/window/index.html @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/test/window.js b/test/window/worker.js similarity index 93% rename from test/window.js rename to test/window/worker.js index 271dd7b..1f42095 100644 --- a/test/window.js +++ b/test/window/worker.js @@ -1,6 +1,5 @@ -import coincident from './dist/window.js'; - -const {proxy, window, isWindowProxy} = coincident(self); +import coincident from '../../dist/window/worker.js'; +const { proxy, window, isWindowProxy } = await coincident(); console.log(window[Symbol.for('coincident')]); @@ -36,6 +35,7 @@ document.body.appendChild(document.createElement('div')).textContent = '🥳'; const remote = new window.Object; console.assert(isWindowProxy(remote)); +console.assert(!isWindowProxy({})); console.log(JSON.stringify( window.Object.getOwnPropertyDescriptor(window.Int32Array, 'BYTES_PER_ELEMENT') diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index 6e11ea1..0000000 --- a/tsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "compilerOptions": { - "module": "NodeNext", - "target": "esnext", - "moduleResolution": "nodenext", - "allowJs": true, - "declaration": true, - "emitDeclarationOnly": true, - "strictNullChecks": true, - "checkJs": false, - "declarationDir": "types" - }, - "include": [ - "esm/index.js", - "esm/json.js", - "esm/bun.js", - "esm/server.js", - "esm/structured.js", - "esm/window.js" - ] -} \ No newline at end of file diff --git a/types/bridge.d.ts b/types/bridge.d.ts deleted file mode 100644 index 7f2c625..0000000 --- a/types/bridge.d.ts +++ /dev/null @@ -1,27 +0,0 @@ -export let SharedArrayBuffer: SharedArrayBufferConstructor; -export const isArray: (arg: any) => arg is any[]; -export let notify: { - (typedArray: Int32Array, index: number, count?: number): number; - (typedArray: BigInt64Array, index: number, count?: number): number; -}; -export let postPatched: any; -export let wait: { - (typedArray: Int32Array, index: number, value: number, timeout?: number): "ok" | "not-equal" | "timed-out"; - (typedArray: BigInt64Array, index: number, value: bigint, timeout?: number): "ok" | "not-equal" | "timed-out"; -}; -export let waitAsync: { - (typedArray: Int32Array, index: number, value: number, timeout?: number): { - async: false; - value: "not-equal" | "timed-out"; - } | { - async: true; - value: Promise<"ok" | "timed-out">; - }; - (typedArray: BigInt64Array, index: number, value: bigint, timeout?: number): { - async: false; - value: "not-equal" | "timed-out"; - } | { - async: true; - value: Promise<"ok" | "timed-out">; - }; -}; diff --git a/types/bun.d.ts b/types/bun.d.ts deleted file mode 100644 index 48d38f2..0000000 --- a/types/bun.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -declare function _default(globals: object): { - /** - * @param {WebSocket} ws - * @param {string} message - */ - message(ws: WebSocket, message: string): void; - /** - * @param {WebSocket} ws - */ - open(ws: WebSocket): void; - /** - * @param {WebSocket} ws - */ - close(ws: WebSocket): void; -}; -export default _default; diff --git a/types/channel.d.ts b/types/channel.d.ts deleted file mode 100644 index 346a904..0000000 --- a/types/channel.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const CHANNEL: "566fc334-5147-4e86-bb9b-c7d24c13127d"; -export const MAIN: string; -export const THREAD: string; diff --git a/types/fallback.d.ts b/types/fallback.d.ts deleted file mode 100644 index 6259402..0000000 --- a/types/fallback.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare function _default(buffer: any): { - value: Promise; -}; -export default _default; diff --git a/types/index.d.ts b/types/index.d.ts deleted file mode 100644 index a75a7ec..0000000 --- a/types/index.d.ts +++ /dev/null @@ -1,34 +0,0 @@ -export default coincident; -/** - * used to sanity-check interrupts while waiting synchronously. - */ -export type Interrupt = { - /** - * a callback invoked every `delay` milliseconds. - */ - handler?: Function | undefined; - /** - * define `handler` invokes in terms of milliseconds. - */ - delay?: number | undefined; -}; -/** - * @typedef {Object} Interrupt used to sanity-check interrupts while waiting synchronously. - * @prop {function} [handler] a callback invoked every `delay` milliseconds. - * @prop {number} [delay=42] define `handler` invokes in terms of milliseconds. - */ -/** - * Create once a `Proxy` able to orchestrate synchronous `postMessage` out of the box. - * @param {globalThis | Worker} self the context in which code should run - * @param {{parse: (serialized: string) => any, stringify: (serializable: any) => string, transform?: (value:any) => any, interrupt?: () => void | Interrupt}} [JSON] an optional `JSON` like interface to `parse` or `stringify` content with extra `transform` ability. - * @returns {ProxyHandler | ProxyHandler} - */ -declare function coincident(self: typeof globalThis | Worker, { parse, stringify, transform, interrupt }?: { - parse: (serialized: string) => any; - stringify: (serializable: any) => string; - transform?: (value: any) => any; - interrupt?: () => void | Interrupt; -} | undefined): ProxyHandler | ProxyHandler; -declare namespace coincident { - function transfer(...args: any[]): any[]; -} diff --git a/types/json.d.ts b/types/json.d.ts deleted file mode 100644 index 270b51e..0000000 --- a/types/json.d.ts +++ /dev/null @@ -1 +0,0 @@ -export default JSON; diff --git a/types/server.d.ts b/types/server.d.ts deleted file mode 100644 index 5b6a4fb..0000000 --- a/types/server.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -export default coincident; -export type Coincident = { - proxy: ProxyHandler; - window: ProxyHandler; - isWindowProxy: (value: any) => boolean; -}; -export type CoincidentWorker = object & Coincident; -export type CoincidentServer = (wss: WebSocketServer, globals?: object) => WebSocketServer; -export type CoincidentWeb = (self: typeof globalThis | Worker, ws?: WebSocket | undefined) => Coincident | CoincidentWorker; -/** @type {CoincidentServer} */ -declare function coincident(wss: WebSocketServer, globals: any): WebSocketServer; diff --git a/types/server/main.d.ts b/types/server/main.d.ts deleted file mode 100644 index 2bdd17d..0000000 --- a/types/server/main.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -declare const _default: (thread: any, MAIN: any, THREAD: any, ...args: any[]) => { - [x: string]: any; - [x: number]: any; - proxy: any; -}; -export default _default; diff --git a/types/server/thread.d.ts b/types/server/thread.d.ts deleted file mode 100644 index 8a3d220..0000000 --- a/types/server/thread.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -declare const _default: (main: any, MAIN: any, THREAD: any) => { - [x: string]: any; - [x: number]: any; - proxy: any; -}; -export default _default; diff --git a/types/shared/main.d.ts b/types/shared/main.d.ts deleted file mode 100644 index 52784fc..0000000 --- a/types/shared/main.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -declare function _default(name: any, patch: any): (thread: any, MAIN: any, THREAD: any, ...args: any[]) => { - [x: string]: any; - [x: number]: any; - proxy: any; -}; -export default _default; diff --git a/types/shared/thread.d.ts b/types/shared/thread.d.ts deleted file mode 100644 index 4712820..0000000 --- a/types/shared/thread.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -declare function _default(name: any): (main: any, MAIN: any, THREAD: any) => { - [x: string]: any; - [x: number]: any; - proxy: any; -}; -export default _default; diff --git a/types/shared/traps.d.ts b/types/shared/traps.d.ts deleted file mode 100644 index 3151f23..0000000 --- a/types/shared/traps.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "proxy-target/traps"; -export const DELETE: "delete"; diff --git a/types/shared/utils.d.ts b/types/shared/utils.d.ts deleted file mode 100644 index 8b2659f..0000000 --- a/types/shared/utils.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -export const TypedArray: object | null; -export function augment(descriptor: any, how: any): any; -export function asEntry(transform: any): (value: any) => any; -export function symbol(value: any): any; -export function transform(o: any): any; -export const assign: { - (target: T, source: U): T & U; - (target: T, source1: U, source2: V): T & U & V; - (target: T, source1: U, source2: V, source3: W): T & U & V & W; - (target: object, ...sources: any[]): any; -}; -export const create: { - (o: object | null): any; - (o: object | null, properties: PropertyDescriptorMap & ThisType): any; -}; -export const defineProperty: typeof Reflect.defineProperty; -export const deleteProperty: typeof Reflect.deleteProperty; -export const getOwnPropertyDescriptor: typeof Reflect.getOwnPropertyDescriptor; -export const getPrototypeOf: typeof Reflect.getPrototypeOf; -export const isExtensible: typeof Reflect.isExtensible; -export const ownKeys: typeof Reflect.ownKeys; -export const preventExtensions: typeof Reflect.preventExtensions; -export const set: typeof Reflect.set; -export const setPrototypeOf: typeof Reflect.setPrototypeOf; diff --git a/types/shared/worker.d.ts b/types/shared/worker.d.ts deleted file mode 100644 index 63e15ae..0000000 --- a/types/shared/worker.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -declare const _default: { - new (scriptURL: string | URL, options?: WorkerOptions): Worker; - prototype: Worker; -} | { - new (): {}; -}; -export default _default; diff --git a/types/structured.d.ts b/types/structured.d.ts deleted file mode 100644 index b31366e..0000000 --- a/types/structured.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -export default coincident; -/** - * Create once a `Proxy` able to orchestrate synchronous `postMessage` out of the box. - * @param {globalThis | Worker} self the context in which code should run - * @returns {ProxyHandler | ProxyHandler} - */ -declare function coincident(self: typeof globalThis | Worker, options: any): ProxyHandler | ProxyHandler; -declare namespace coincident { - let transfer: (...args: any[]) => any[]; -} diff --git a/types/window.d.ts b/types/window.d.ts deleted file mode 100644 index ae4fe88..0000000 --- a/types/window.d.ts +++ /dev/null @@ -1,22 +0,0 @@ -export default coincident; -export type Coincident = { - proxy: ProxyHandler; - window: ProxyHandler; - isWindowProxy: (value: any) => boolean; -}; -/** - * @typedef {object} Coincident - * @property {ProxyHandler} proxy - * @property {ProxyHandler} window - * @property {(value: any) => boolean} isWindowProxy - */ -/** - * Create once a `Proxy` able to orchestrate synchronous `postMessage` out of the box. - * In workers, returns a `{proxy, window, isWindowProxy}` namespace to reach main globals synchronously. - * @param {Worker | globalThis} self the context in which code should run - * @returns {ProxyHandler | Coincident} - */ -declare function coincident(self: Worker | typeof globalThis, ...args: any[]): ProxyHandler | Coincident; -declare namespace coincident { - let transfer: (...args: any[]) => any[]; -} diff --git a/types/window/main.d.ts b/types/window/main.d.ts deleted file mode 100644 index 2bdd17d..0000000 --- a/types/window/main.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -declare const _default: (thread: any, MAIN: any, THREAD: any, ...args: any[]) => { - [x: string]: any; - [x: number]: any; - proxy: any; -}; -export default _default; diff --git a/types/window/thread.d.ts b/types/window/thread.d.ts deleted file mode 100644 index 8a3d220..0000000 --- a/types/window/thread.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -declare const _default: (main: any, MAIN: any, THREAD: any) => { - [x: string]: any; - [x: number]: any; - proxy: any; -}; -export default _default; diff --git a/uhtml.js b/uhtml.js deleted file mode 100644 index 2824660..0000000 --- a/uhtml.js +++ /dev/null @@ -1,5 +0,0 @@ -const e="566fc334-5147-4e86-bb9b-c7d24c13127d",t="M"+e,n="T"+e,r="array",s="function",o="null",a="number",i="object",l="string",c="symbol",u="undefined",f="apply",p="construct",h="defineProperty",d="deleteProperty",g="get",y="getOwnPropertyDescriptor",w="getPrototypeOf",m="has",b="isExtensible",v="ownKeys",x="preventExtensions",k="set",C="setPrototypeOf",E="delete",{isArray:M}=Array;let{SharedArrayBuffer:$,window:P}=globalThis,{notify:T,wait:W,waitAsync:A}=Atomics,O=null;A||(A=e=>({value:new Promise((t=>{let n=new Worker("data:application/javascript,onmessage%3D(%7Bdata%3Ab%7D)%3D%3E(Atomics.wait(b%2C0)%2CpostMessage(0))");n.onmessage=t,n.postMessage(e)}))}));try{new $(4)}catch(t){$=ArrayBuffer;const n=new WeakMap;if(P){const t=new Map,{prototype:{postMessage:r}}=Worker,s=n=>{const r=n.data?.[e];if(!M(r)){n.stopImmediatePropagation();const{id:e,sb:s}=r;t.get(e)(s)}};O=function(t,...o){const a=t?.[e];if(M(a)){const[e,t]=a;n.set(t,e),this.addEventListener("message",s)}return r.call(this,t,...o)},A=e=>({value:new Promise((r=>{t.set(n.get(e),r)})).then((r=>{t.delete(n.get(e)),n.delete(e);for(let t=0;t({[e]:{id:t,sb:n}});T=e=>{postMessage(t(n.get(e),e))},addEventListener("message",(t=>{const r=t.data?.[e];if(M(r)){const[e,t]=r;n.set(t,e)}}))}} -/*! (c) Andrea Giammarchi - ISC */const{Int32Array:S,Map:N,Uint16Array:L}=globalThis,{BYTES_PER_ELEMENT:D}=S,{BYTES_PER_ELEMENT:B}=L,j=new WeakSet,R=new WeakMap,F={value:{then:e=>e()}};let _=0;const z=(t,{parse:n=JSON.parse,stringify:r=JSON.stringify,transform:o,interrupt:a}=JSON)=>{if(!R.has(t)){const i=O||t.postMessage,l=(n,...r)=>i.call(t,{[e]:r},{transfer:n}),c=typeof a===s?a:a?.handler,u=a?.delay||42,f=new TextDecoder("utf-16"),p=(e,t)=>e?A(t,0):(c?((e,t,n)=>{for(;"timed-out"===W(e,0,0,t);)n()})(t,u,c):W(t,0),F);let h=!1;R.set(t,new Proxy(new N,{[m]:(e,t)=>"string"==typeof t&&!t.startsWith("_"),[g]:(e,r)=>"then"===r?null:(...e)=>{const s=_++;let a=new S(new $(2*D)),i=[];j.has(e.at(-1)||i)&&j.delete(i=e.pop()),l(i,s,a,r,o?e.map(o):e);const c=t!==globalThis;let u=0;return h&&c&&(u=setTimeout(console.warn,1e3,`💀🔒 - Possible deadlock if proxy.${r}(...args) is awaited`)),p(c,a).value.then((()=>{clearTimeout(u);const e=a[1];if(!e)return;const t=B*e;return a=new S(new $(t+t%D)),l([],s,a),p(c,a).value.then((()=>n(f.decode(new L(a.buffer).slice(0,e)))))}))},[k](n,a,i){const l=typeof i;if(l!==s)throw new Error(`Unable to assign ${a} as ${l}`);if(!n.size){const s=new N;t.addEventListener("message",(async t=>{const a=t.data?.[e];if(M(a)){t.stopImmediatePropagation();const[e,i,...l]=a;let c;if(l.length){const[t,a]=l;if(n.has(t)){h=!0;try{const l=await n.get(t)(...a);if(void 0!==l){const t=r(o?o(l):l);s.set(e,t),i[1]=t.length}}catch(e){c=e}finally{h=!1}}else c=new Error(`Unsupported action: ${t}`);i[0]=1}else{const t=s.get(e);s.delete(e);for(let e=new L(i.buffer),n=0;n(j.add(e),e);const{isArray:I}=Array,U=(e,t)=>t,H=e=>typeof e===s?(e=>e())(e):e;function J(){return this}const K=(e,t)=>e===r?[t]:{t:e,v:t},Y=(e,t=U)=>{let n=typeof e,s=e;return n===i&&(I(e)?(n=r,s=e.at(0)):({t:n,v:s}=e)),t(n,s)},Z=(e,t)=>e===s?t:K(e,t),G=(e,t=Z)=>{const n=null===e?o:typeof e;return t(n===i&&I(e)?r:n,e)},V=new FinalizationRegistry((([e,t,n])=>{n&&console.debug(`Held value ${String(t)} not relevant anymore`),e(t)})),q=Object.create(null),Q=(e,t,{debug:n,handler:r,return:s,token:o=e}=q)=>{const a=s||new Proxy(e,r||q),i=[a,[t,e,!!n]];return!1!==o&&i.push(o),V.register(...i),a},{defineProperty:X,deleteProperty:ee,getOwnPropertyDescriptor:te,getPrototypeOf:ne,isExtensible:re,ownKeys:se,preventExtensions:oe,set:ae,setPrototypeOf:ie}=Reflect,{assign:le,create:ce}=Object,ue=ne(Int8Array),fe=(e,t)=>{const{get:n,set:r,value:s}=e;return n&&(e.get=t(n)),r&&(e.set=t(r)),s&&(e.value=t(s)),e},pe=e=>t=>G(t,((t,n)=>{switch(t){case o:return K(o,n);case i:if(n===globalThis)return K(t,null);case r:case s:return e(t,n);case"boolean":case a:case l:case u:case"bigint":return K(t,n);case c:{if(he.has(n))return K(t,he.get(n));let e=Symbol.keyFor(n);if(e)return K(t,`.${e}`)}}throw new TypeError(`Unable to handle this ${t}: ${String(n)}`)})),he=new Map(se(Symbol).filter((e=>typeof Symbol[e]===c)).map((e=>[Symbol[e],e]))),de=e=>{if(e.startsWith("."))return Symbol.for(e.slice(1));for(const[t,n]of he)if(n===e)return t},ge=e=>e;var ye=(e=>{const t=new WeakMap;{const{addEventListener:e}=EventTarget.prototype;X(EventTarget.prototype,"addEventListener",{value(n,r,...s){return s.at(0)?.invoke&&(t.has(this)||t.set(this,new Map),t.get(this).set(n,[].concat(s[0].invoke)),delete s[0].invoke),e.call(this,n,r,...s)}})}return function(n,o,M,...$){let P=0,T=this?.transform||ge;const W=new Map,A=new Map,{[M]:O}=n,S=$.length?le(ce(globalThis),...$):globalThis,N=pe(((e,t)=>{if(!W.has(t)){let n;for(;A.has(n=P++););W.set(t,n),A.set(n,e===s?t:T(t))}return K(e,W.get(t))})),L=e=>{O(E,K(l,e))},D=(e,n)=>{switch(e){case i:if(null==n)return S;case r:if(typeof n===a)return A.get(n);if(!(n instanceof ue))for(const e in n)n[e]=B(n[e]);return n;case s:if(typeof n===l){const e=A.get(n)?.deref();if(e)return e;const r=function(...e){return e.at(0)instanceof Event&&(e=>{const{currentTarget:n,target:r,type:s}=e;for(const o of t.get(n||r)?.get(s)||[])e[o]()})(...e),O(f,K(s,n),N(this),e.map(N))};return A.set(n,new WeakRef(r)),Q(n,L,{return:r,token:!1})}return A.get(n);case c:return de(n)}return n},B=e=>Y(e,D),j={[f]:(e,t,n)=>N(e.apply(t,n)),[p]:(e,t)=>N(new e(...t)),[h]:(e,t,n)=>N(X(e,t,n)),[d]:(e,t)=>N(ee(e,t)),[w]:e=>N(ne(e)),[g]:(e,t)=>N(e[t]),[y]:(e,t)=>{const n=te(e,t);return n?K(i,fe(n,N)):K(u,n)},[m]:(e,t)=>N(t in e),[b]:e=>N(re(e)),[v]:e=>K(r,se(e).map(N)),[x]:e=>N(oe(e)),[k]:(e,t,n)=>N(ae(e,t,n)),[C]:(e,t)=>N(ie(e,t)),[E](e){W.delete(A.get(e)),A.delete(e)}};return n[o]=(e,t,...n)=>{switch(e){case f:n[0]=B(n[0]),n[1]=n[1].map(B);break;case p:n[0]=n[0].map(B);break;case h:{const[e,t]=n;n[0]=B(e);const{get:r,set:s,value:o}=t;r&&(t.get=B(r)),s&&(t.set=B(s)),o&&(t.value=B(o));break}default:n=n.map(B)}return j[e](B(t),...n)},{proxy:n,[e.toLowerCase()]:S,[`is${e}Proxy`]:()=>!1}}})("Window"),we=(e=>{let t=0;const n=new Map,o=new Map,u=Symbol();return function(M,$,P){const T=this?.transform||ge,{[$]:W}=M,A=new Map,O=e=>{A.delete(e),W(E,S(e))},S=pe(((e,r)=>{if(u in r)return H(r[u]);if(e===s){if(r=T(r),!o.has(r)){let e;for(;o.has(e=String(t++)););n.set(r,e),o.set(e,r)}return K(e,n.get(r))}if(!(r instanceof ue)){r=T(r);for(const e in r)r[e]=S(r[e])}return K(e,r)})),N=(e,t,n)=>{const r=A.get(n)?.deref();if(r)return r;const o=t===s?(e=>J.bind(e))(e):e,a=new Proxy(o,B);return A.set(n,new WeakRef(a)),Q(n,O,{return:a,token:!1})},L=e=>Y(e,((t,n)=>{switch(t){case i:if(null===n)return globalThis;case r:return typeof n===a?N(e,t,n):n;case s:return typeof n===l?o.get(n):N(e,t,n);case c:return de(n)}return n})),D=(e,t,...n)=>L(W(e,H(t),...n)),B={[f]:(e,t,n)=>D(f,e,S(t),n.map(S)),[p]:(e,t)=>D(p,e,t.map(S)),[h]:(e,t,n)=>{const{get:r,set:o,value:a}=n;return typeof r===s&&(n.get=S(r)),typeof o===s&&(n.set=S(o)),typeof a===s&&(n.value=S(a)),D(h,e,S(t),n)},[d]:(e,t)=>D(d,e,S(t)),[w]:e=>D(w,e),[g]:(e,t)=>t===u?e:D(g,e,S(t)),[y]:(e,t)=>{const n=D(y,e,S(t));return n&&fe(n,L)},[m]:(e,t)=>t===u||D(m,e,S(t)),[b]:e=>D(b,e),[v]:e=>D(v,e).map(L),[x]:e=>D(x,e),[k]:(e,t,n)=>D(k,e,S(t),S(n)),[C]:(e,t)=>D(C,e,S(t))};M[P]=(e,t,r,s)=>{switch(e){case f:return L(t).apply(L(r),s.map(L));case E:{const e=L(t);n.delete(o.get(e)),o.delete(e)}}};const j=new Proxy(K(i,null),B);return{[e.toLowerCase()]:j,[`is${e}Proxy`]:e=>typeof e===i&&!!e&&u in e,proxy:M}}})("Window"),me=typeof Worker===s?Worker:class{};const be=new WeakMap,ve=(e,...r)=>{const s=z(e,...r);if(!be.has(s)){const o=e instanceof me?ye:we;be.set(s,o.call(r.at(0),s,t,n))}return be.get(s)};var xe=e=>function(){const{constructor:t}=e.createDocumentFragment();const{isArray:n}=Array,{getPrototypeOf:r,getOwnPropertyDescriptor:s}=Object,o=[],a=()=>e.createRange(),i=(e,t,n)=>(e.set(t,n),n),l=(e,t)=>t.reduceRight(c,e),c=(e,t)=>e.childNodes[t],{setPrototypeOf:u}=Object;let f;var p=(e,t,n)=>(f||(f=a()),n?f.setStartAfter(e):f.setStartBefore(e),f.setEndAfter(t),f.deleteContents(),e);const h=({firstChild:e,lastChild:t},n)=>p(e,t,n);let d=!1;const g=(e,t)=>d&&11===e.nodeType?1/t<0?t?h(e,!0):e.lastChild:t?e.valueOf():e.firstChild:e,y=t=>e.createComment(t);class w extends((e=>{function t(e){return u(e,new.target.prototype)}return t.prototype=e.prototype,t})(t)){#e=y("<>");#t=y("");#n=o;constructor(e){super(e),this.replaceChildren(this.#e,...e.childNodes,this.#t),d=!0}get firstChild(){return this.#e}get lastChild(){return this.#t}get parentNode(){return this.#e.parentNode}remove(){h(this,!1)}replaceWith(e){h(this,!0).replaceWith(e)}valueOf(){const{parentNode:e}=this;if(e===this)this.#n===o&&(this.#n=[...this.childNodes]);else{if(e){let{firstChild:e,lastChild:t}=this;for(this.#n=[e];e!==t;)this.#n.push(e=e.nextSibling)}this.replaceChildren(...this.#n)}return this}}const m=(e,t,n)=>e.setAttribute(t,n),b=(e,t)=>e.removeAttribute(t);let v;const x=(e,t,r)=>{r=r.slice(1),v||(v=new WeakMap);const s=v.get(e)||i(v,e,{});let o=s[r];return o&&o[0]&&e.removeEventListener(r,...o),o=n(t)?t:[t,!1],s[r]=o,o[0]&&e.addEventListener(r,...o),t},k=(e,t)=>{const{t:n,n:r}=e;let s=!1;switch(typeof t){case"object":if(null!==t){(r||n).replaceWith(e.n=t.valueOf());break}case"undefined":s=!0;default:n.data=s?"":t,r&&(e.n=null,r.replaceWith(n))}return t},C=(e,t,n)=>e[n]=t,E=(e,t,n)=>C(e,t,n.slice(1)),M=(e,t,n)=>null==t?(b(e,n),t):C(e,t,n),$=(e,t)=>("function"==typeof t?t(e):t.current=e,t),P=(e,t,n)=>(null==t?b(e,n):m(e,n,t),t),T=(e,t,n)=>(e.toggleAttribute(n.slice(1),t),t),W=(e,t,n)=>{const{length:r}=t;if(e.data=`[${r}]`,r)return((e,t,n,r,s)=>{const o=n.length;let a=t.length,i=o,l=0,c=0,u=null;for(;ls-c){const o=r(t[l],0);for(;c{for(const n in t){const r=t[n],s="role"===n?n:`aria-${n}`;null==r?b(e,s):m(e,s,r)}return t}],["class",(e,t)=>M(e,t,null==t?"class":"className")],["data",(e,t)=>{const{dataset:n}=e;for(const e in t)null==t[e]?delete n[e]:n[e]=t[e];return t}],["ref",$],["style",(e,t)=>null==t?M(e,t,"style"):C(e.style,t,"cssText")]]),O=(e,t,n)=>{switch(t[0]){case".":return E;case"?":return T;case"@":return x;default:return n||"ownerSVGElement"in e?"ref"===t?$:P:A.get(t)||(t in e?t.startsWith("on")?C:((e,t)=>{let n;do{n=s(e,t)}while(!n&&(e=r(e)));return n})(e,t)?.set?M:P:P)}},S=(e,t)=>(e.textContent=null==t?"":t,t),N=(e,t,n)=>({a:e,b:t,c:n}),L=()=>N(null,null,o);var D=t=>(n,r)=>{const{a:s,b:a,c:i}=t(n,r),c=e.importNode(s,!0);let u=o;if(a!==o){u=[];for(let e,t,n=0;n({b:e,c:t}))(i?c.firstChild:new w(c),u)};const B=/^(?:plaintext|script|style|textarea|title|xmp)$/i,j=/^(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)$/i,R=/<([a-zA-Z0-9]+[a-zA-Z0-9:._-]*)([^>]*?)(\/?)>/g,F=/([^\s\\>"'=]+)\s*=\s*(['"]?)\x01/g,_=/[\x01\x02]/g;let z,I,U=e.createElement("template");var H=(t,n)=>{if(n)return z||(z=e.createElementNS("http://www.w3.org/2000/svg","svg"),I=a(),I.selectNodeContents(z)),I.createContextualFragment(t);U.innerHTML=t;const{content:r}=U;return U=U.cloneNode(!1),r};const J=e=>{const t=[];let n;for(;n=e.parentNode;)t.push(t.indexOf.call(n.childNodes,e)),e=n;return t},K=()=>e.createTextNode(""),Y=(t,r,s)=>{const a=H(((e,t,n)=>{let r=0;return e.join("").trim().replace(R,((e,t,r,s)=>`<${t}${r.replace(F,"=$2$1").trimEnd()}${s?n||j.test(t)?" /":`>`)).replace(_,(e=>""===e?`\x3c!--${t+r++}--\x3e`:t+r++))})(t,G,s),s),{length:l}=t;let c=o;if(l>1){const t=[],o=e.createTreeWalker(a,129);let i=0,u=`${G}${i++}`;for(c=[];i(t,n)=>Z.get(t)||Y(t,n,e);const q=D(V(!1)),Q=D(V(!0)),X=(e,{s:t,t:n,v:r})=>{if(e.a!==n){const{b:s,c:o}=(t?Q:q)(n,r);e.a=n,e.b=s,e.c=o}for(let{c:t}=e,n=0;n{let n=0,{length:r}=t;for(r(t,...n)=>new te(e,t,n),re=ne(!1),se=ne(!0),oe=new WeakMap; -/*! (c) Andrea Giammarchi - MIT */ -const ae=new WeakMap,ie=e=>(t,n)=>{const r=ae.get(t)||i(ae,t,new Map);return r.get(n)||i(r,n,function(t,...n){return new te(e,t,n).toDOM(this)}.bind(L()))},le=ie(!1),ce=ie(!0);return{Hole:te,attr:A,html:re,htmlFor:le,render:(e,t)=>((e,t)=>{const n=oe.get(e)||i(oe,e,L()),{b:r}=n,s="function"==typeof t?t():t,o=s instanceof te?s.toDOM(n):s;return r!==o&&e.replaceChildren((n.b=o).valueOf()),e})(e,t),svg:se,svgFor:ce}}();const ke=(e,...t)=>{const n=ve(e,...t);return n.uhtml||(n.uhtml=xe(n.window.document)),n};ke.transfer=ve.transfer=z.transfer;export{ke as default};