From 81cd6a19f6b3b9b77842c3532f4e16571834369c Mon Sep 17 00:00:00 2001 From: webreflection Date: Mon, 22 Jul 2024 14:50:43 +0200 Subject: [PATCH 1/3] =?UTF-8?q?v2=20-=20Coincident=20meets=20js-proxy=20&?= =?UTF-8?q?=20sabayon=20=F0=9F=8D=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/node.js.yml | 26 - .gitignore | 17 +- .npmignore | 6 +- .npmrc | 2 +- LICENSE | 30 +- README.md | 397 ++--- build/constants.cjs | 18 + build/dist.js | 39 + build/index.cjs | 43 + cjs/package.json | 1 - dist/main.js | 1 + dist/window/main.js | 1 + dist/window/worker.js | 1 + dist/worker.js | 1 + esm/bridge.js | 87 -- esm/bun.js | 68 - esm/channel.js | 5 - esm/index.js | 199 --- esm/json.js | 3 - esm/server.js | 168 --- esm/server/main.js | 3 - esm/server/thread.js | 3 - esm/shared/main.js | 197 --- esm/shared/thread.js | 155 -- esm/shared/traps.js | 2 - esm/shared/utils.js | 98 -- esm/shared/worker.js | 2 - esm/structured.js | 13 - esm/uhtml.js | 18 - esm/window.js | 33 - esm/window/main.js | 3 - esm/window/thread.js | 3 - favicon.ico | Bin 16201 -> 0 bytes index.html | 39 +- mini-coi.js | 28 - package-lock.json | 2062 -------------------------- package.json | 86 +- rollup/channel.cjs | 13 - rollup/es.config.js | 11 - rollup/server.config.js | 11 - rollup/structured.config.js | 11 - rollup/uhtml.config.js | 11 - rollup/window.config.js | 11 - src/debug.js | 1 + src/main.js | 92 ++ src/shared.js | 127 ++ src/ts.js | 7 + src/window/constants.js | 3 + src/window/events.js | 20 + src/window/main.js | 151 ++ src/window/symbol.js | 24 + src/window/types.js | 34 + src/window/worker.js | 182 +++ src/worker.js | 111 ++ test-results/.last-run.json | 4 - test/array.html | 12 - test/array/index.html | 9 + test/array/index.js | 5 + test/{array.js => array/worker.js} | 9 +- test/basic/index.html | 9 + test/basic/index.js | 14 + test/basic/worker.js | 17 + test/dbmonster/dbmonster.css | 147 -- test/dbmonster/dbmonster.js | 274 ---- test/dbmonster/index.html | 21 - test/dist/es.js | 2 - test/dist/mini-coi.js | 28 - test/dist/server.js | 2 - test/dist/structured.js | 2 - test/dist/uhtml.js | 5 - test/dist/window.js | 2 - test/dom/index.html | 9 + test/dom/index.js | 5 + test/dom/worker.js | 16 + test/global.html | 17 - test/global.js | 5 - test/harakiri.html | 23 - test/harakiri.js | 8 - test/harakiri/index.html | 26 + test/harakiri/worker.js | 7 + test/hyperhtml.html | 12 - test/hyperhtml.js | 21 - test/hyperhtml.mjs | 3 - test/iframe/iframe.html | 6 +- test/iframe/index.html | 1 - test/iframe/worker.js | 4 +- test/index.html | 54 +- test/index.js | 4 - test/input.html | 12 - test/input.js | 24 - test/input/index.html | 15 + test/input/index.js | 20 + test/{ => input}/worker.js | 6 +- test/integration.spec.js | 57 - test/integration/index.html | 17 - test/integration/index.js | 9 - test/issue-26/index.html | 10 +- test/issue-26/worker.js | 8 +- test/issue-34/index.html | 8 +- test/issue-34/worker.js | 4 +- test/micropython.html | 69 - test/no-sab/index.html | 19 - test/no-sab/worker.js | 3 - test/package.json | 1 - test/ping-pong.html | 20 - test/ping-pong.js | 7 - test/pyterminal/index.html | 56 - test/reflect/index.html | 9 + test/reflect/index.js | 10 + test/reflect/worker.js | 18 + test/server/bun.js | 30 - test/server/index.html | 15 - test/server/main.cjs | 24 - test/server/worker.js | 36 - test/sqlite/bun.js | 22 - test/sqlite/index.html | 14 - test/sqlite/worker.js | 24 - test/structured.html | 24 - test/structured.js | 8 - test/sw.js | 1 + test/too-big/index.html | 9 +- test/too-big/worker.js | 4 +- test/transfer.html | 19 - test/transfer.js | 10 - test/uhtml.html | 13 - test/uhtml.js | 22 - test/undefined.html | 21 - test/undefined.js | 4 - test/unknown.html | 12 - test/unknown.js | 5 - test/virtual-dom/index.html | 6 +- test/virtual-dom/worker-utils.js | 6 +- test/window.html | 16 - test/window/index.html | 17 + test/{window.js => window/worker.js} | 5 +- tsconfig.json | 21 - types/bridge.d.ts | 27 - types/bun.d.ts | 16 - types/channel.d.ts | 3 - types/fallback.d.ts | 4 - types/index.d.ts | 34 - types/json.d.ts | 1 - types/server.d.ts | 11 - types/server/main.d.ts | 6 - types/server/thread.d.ts | 6 - types/shared/main.d.ts | 6 - types/shared/thread.d.ts | 6 - types/shared/traps.d.ts | 2 - types/shared/utils.d.ts | 24 - types/shared/worker.d.ts | 7 - types/structured.d.ts | 10 - types/window.d.ts | 22 - types/window/main.d.ts | 6 - types/window/thread.d.ts | 6 - uhtml.js | 5 - 155 files changed, 1281 insertions(+), 5172 deletions(-) delete mode 100644 .github/workflows/node.js.yml create mode 100644 build/constants.cjs create mode 100644 build/dist.js create mode 100644 build/index.cjs delete mode 100644 cjs/package.json create mode 100644 dist/main.js create mode 100644 dist/window/main.js create mode 100644 dist/window/worker.js create mode 100644 dist/worker.js delete mode 100644 esm/bridge.js delete mode 100644 esm/bun.js delete mode 100644 esm/channel.js delete mode 100644 esm/index.js delete mode 100644 esm/json.js delete mode 100644 esm/server.js delete mode 100644 esm/server/main.js delete mode 100644 esm/server/thread.js delete mode 100644 esm/shared/main.js delete mode 100644 esm/shared/thread.js delete mode 100644 esm/shared/traps.js delete mode 100644 esm/shared/utils.js delete mode 100644 esm/shared/worker.js delete mode 100644 esm/structured.js delete mode 100644 esm/uhtml.js delete mode 100644 esm/window.js delete mode 100644 esm/window/main.js delete mode 100644 esm/window/thread.js delete mode 100644 favicon.ico delete mode 100644 mini-coi.js delete mode 100644 package-lock.json delete mode 100644 rollup/channel.cjs delete mode 100644 rollup/es.config.js delete mode 100644 rollup/server.config.js delete mode 100644 rollup/structured.config.js delete mode 100644 rollup/uhtml.config.js delete mode 100644 rollup/window.config.js create mode 100644 src/debug.js create mode 100644 src/main.js create mode 100644 src/shared.js create mode 100644 src/ts.js create mode 100644 src/window/constants.js create mode 100644 src/window/events.js create mode 100644 src/window/main.js create mode 100644 src/window/symbol.js create mode 100644 src/window/types.js create mode 100644 src/window/worker.js create mode 100644 src/worker.js delete mode 100644 test-results/.last-run.json delete mode 100644 test/array.html create mode 100644 test/array/index.html create mode 100644 test/array/index.js rename test/{array.js => array/worker.js} (82%) create mode 100644 test/basic/index.html create mode 100644 test/basic/index.js create mode 100644 test/basic/worker.js delete mode 100644 test/dbmonster/dbmonster.css delete mode 100644 test/dbmonster/dbmonster.js delete mode 100644 test/dbmonster/index.html delete mode 100644 test/dist/es.js delete mode 100644 test/dist/mini-coi.js delete mode 100644 test/dist/server.js delete mode 100644 test/dist/structured.js delete mode 100644 test/dist/uhtml.js delete mode 100644 test/dist/window.js create mode 100644 test/dom/index.html create mode 100644 test/dom/index.js create mode 100644 test/dom/worker.js delete mode 100644 test/global.html delete mode 100644 test/global.js delete mode 100644 test/harakiri.html delete mode 100644 test/harakiri.js create mode 100644 test/harakiri/index.html create mode 100644 test/harakiri/worker.js delete mode 100644 test/hyperhtml.html delete mode 100644 test/hyperhtml.js delete mode 100644 test/hyperhtml.mjs delete mode 100644 test/index.js delete mode 100644 test/input.html delete mode 100644 test/input.js create mode 100644 test/input/index.html create mode 100644 test/input/index.js rename test/{ => input}/worker.js (50%) delete mode 100644 test/integration.spec.js delete mode 100644 test/integration/index.html delete mode 100644 test/integration/index.js delete mode 100644 test/micropython.html delete mode 100644 test/no-sab/index.html delete mode 100644 test/no-sab/worker.js delete mode 100644 test/package.json delete mode 100644 test/ping-pong.html delete mode 100644 test/ping-pong.js delete mode 100644 test/pyterminal/index.html create mode 100644 test/reflect/index.html create mode 100644 test/reflect/index.js create mode 100644 test/reflect/worker.js delete mode 100644 test/server/bun.js delete mode 100644 test/server/index.html delete mode 100644 test/server/main.cjs delete mode 100644 test/server/worker.js delete mode 100644 test/sqlite/bun.js delete mode 100644 test/sqlite/index.html delete mode 100644 test/sqlite/worker.js delete mode 100644 test/structured.html delete mode 100644 test/structured.js create mode 100644 test/sw.js delete mode 100644 test/transfer.html delete mode 100644 test/transfer.js delete mode 100644 test/uhtml.html delete mode 100644 test/uhtml.js delete mode 100644 test/undefined.html delete mode 100644 test/undefined.js delete mode 100644 test/unknown.html delete mode 100644 test/unknown.js delete mode 100644 test/window.html create mode 100644 test/window/index.html rename test/{window.js => window/worker.js} (95%) delete mode 100644 tsconfig.json delete mode 100644 types/bridge.d.ts delete mode 100644 types/bun.d.ts delete mode 100644 types/channel.d.ts delete mode 100644 types/fallback.d.ts delete mode 100644 types/index.d.ts delete mode 100644 types/json.d.ts delete mode 100644 types/server.d.ts delete mode 100644 types/server/main.d.ts delete mode 100644 types/server/thread.d.ts delete mode 100644 types/shared/main.d.ts delete mode 100644 types/shared/thread.d.ts delete mode 100644 types/shared/traps.d.ts delete mode 100644 types/shared/utils.d.ts delete mode 100644 types/shared/worker.d.ts delete mode 100644 types/structured.d.ts delete mode 100644 types/window.d.ts delete mode 100644 types/window/main.d.ts delete mode 100644 types/window/thread.d.ts delete mode 100644 uhtml.js 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..6c46e52 100644 --- a/.gitignore +++ b/.gitignore @@ -1,20 +1,5 @@ .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 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..efbed5c 100644 --- a/README.md +++ b/README.md @@ -1,362 +1,141 @@ # 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). - -**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. - -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 - -``` - -```js -// worker.js -import coincident from 'coincident'; - -// expose a specific function to the main thread -coincident(self).compute = (a, b) => (a + b); -``` - - -### 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*. - -Please keep in mind not all complex types are supported by the polyfill but also any other export could use this version with ease: - -```js -import * as JSON from '@ungap/structured-clone/json'; -import coincident from 'coincident/uhtml'; - -// bootstrap in both main / workers like this -const {proxy, window, isWindowProxy} = coincident(self, JSON); - -// that's it: structured-clone enabled for responses! -``` - - -### 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. +Following the description of all different imports to use either on the *main* or the *worker* 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. +### coincident/main - -```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 -// 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 - -// ... but here is the fun part ... -const {document} = window; -document.body.innerHTML = '

Hello World!

'; - -document.body.appendChild( - document.createElement('div') -).textContent = '😱'; +import coincident from 'coincident/main'; -const scoped = true; -document.body.addEventListener('click', event => { - console.log(event.type, 'running in a worker', scoped); +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, }); ``` -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. - -#### 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*). - -```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. - - -### coincident/uhtml - -This export includes [uhtml](https://github.com/WebReflection/uhtml#readme) to fully drive reactive UI from a Worker. +#### coincident/main - Worker class -The `uhtml` field is added to the returned object after `coincident(self)` call. +The `Worker` class returned by `coincident()` has these features: -```html - - -``` + * 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 -// The worker.js !!! -import coincident from 'coincident/window'; - -const {proxy, window, uhtml} = coincident(self); - -// uhtml directly from the thread -const {render, html} = uhtml; +const { proxy } = new Worker('./worker.js'); -const {document} = window; +// can be invoked from the worker +proxy.location = () => location.href; -render(document.body, html` -

Hello uhtml!

-`); +// exposed via worker code +await proxy.compute(); ``` -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`. - - -### coincident/server +### coincident/worker -⚠️ **WARNING - THIS EXPORT SHOULD NOT BE PUBLICLY AVAILABLE** +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. -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 - - - - - - - - - -``` - -**Worker example** - see [test/server/worker.js](./test/server/worker.js) ```js -import coincident from 'coincident/server'; +import coincident from 'coincident/worker'; 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

- -`; - -``` - -**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' + // the counter-part of the main worker.proxy reference + proxy, + // a boolean indicating if sabayon is being used + polyfill, + // 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 }, }); -const server = createServer(handler); +// exposed to the main thread +proxy.compute = async () => { + // super expensive task ... + return 'result'; +}; -// require the coincident export -const coincident = require('coincident/server'); +// consumed from the main thread +// synchronous if COI is enabled or +// the Service Worker was passed +console.log(proxy.location()); +``` -// 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}); +- - - -// bootstrap the server and that's it! -server.listen(8080, () => { - console.log(`http://localhost:8080/test/server/`); -}); -``` +### About 💀🔒 Deadlock Message -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. +This module allows different worlds to expose utilities that can be invoked elsewhere and there are two ways this can work: -That being said, in Apps where no foreign code is allowed, this export unlocks an infinite amount of potentials for any sort of project. + * `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! -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. +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. -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. +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. -### Local Only +### About SharedArrayBuffer -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. +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. -```js -{ - 'Cross-Origin-Opener-Policy': 'same-origin', - 'Cross-Origin-Embedder-Policy': 'require-corp', - 'Cross-Origin-Resource-Policy': 'same-origin' -} -``` +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. -### coincident/bun +#### Enable both sync & async SharedArrayBuffer features -Same as *coincident/server* except it's 100% based on *Bun* primitives (*websocket*): +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: -```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' -}; + * 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) -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)}), -}); +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. -console.log(`http://localhost:${port}/test/server/`); -``` +#### Enable only async SharedArrayBuffer features -### A quick way to test SharedArrayBuffer +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. -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: +This scenario is **ideal** when: -```sh -npx mini-coi . + * 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* -# or even ... -bunx mini-coi . -``` +As long as these enabled use cases are clear, here the caveats: -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. + * 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 -To copy the **script** that must be used on the page locally as Service Worker, you can also use *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. -```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..d7987e2 --- /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,g=(e,t)=>class extends e{constructor(e,...s){super(e,...s),e instanceof t&&f.set(this,[p++,0,l()])}},u=new WeakSet,d=e=>(u.add(e),e),w=(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},y=e=>null!==e&&"object"==typeof e&&!u.has(e),h=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))y(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)h.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(w(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=>h.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=g(A,k),E=g(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(w(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 y(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="";const L=new Map;let R=0;const _=([e,t,s,r,n,a,o,c,i,l],p)=>(...f)=>{let g=""!==B,u=0;g&&(u=((e,t)=>setTimeout(console.warn,1e3,`💀🔒 - proxy.${e}() in proxy.${t}()`))(p,B));const d=R++,w=[];P.has(f.at(-1)||w)&&P.delete(w=f.pop());const y=r(i?f.map(i):f);let h=new t(new s(2*U));return c([e,2,p,d,h,y,n],{transfer:w}),l(h,0).value.then((()=>{g&&clearTimeout(u);const r=h[1];if(!r)return;const n=W*r;return h=new t(new s(n+n%U)),c([e,1,d,h]),l(h,0).value.then((()=>{const e=new Uint16Array(h.buffer),t=o?e.subarray(0,r):e.slice(0,r);return a(D.decode(t))}))}))};var N=({parse:e,stringify:t,transform:s}=JSON)=>{const r=((e,t)=>async(s,[r,n,a,o,c])=>{c&&(B=r);try{const r=await s(...o);if(void 0!==r){const s=e(t?t(r):r);L.set(n,s),a[1]=s.length}}finally{c&&(B=""),a[0]=1,S(a,0)}})(t,s),n=crypto.randomUUID();return{Worker:class extends x{constructor(t,a){const o=new Map;super(t,a),this.proxy=((e,t)=>new Proxy(t,{get:(t,s)=>t.get(s)||t.set(s,_(e,s)).get(s),set:(e,t,s)=>!!e.set(t,s)}))([n,E,k,T,!1,e,b,(...e)=>this.postMessage(...e),s,i.waitAsync],o),this.postMessage(T([n,0,a])),this.addEventListener("message",(e=>{if(w(e,n)){const[t,s,...n]=e.data;switch(s){case 2:((e,t,s)=>{const[r]=s,n=t.get(r);if(!n)throw new Error(`Unknown proxy.${r}()`);e(n,s)})(r,o,n);break;case 1:((e,t)=>{const s=L.get(e);L.delete(e);for(let e=new Uint16Array(t.buffer),r=0,{length:n}=s;ru.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:w}=Array,{create:h,getPrototypeOf:v,values:m}=Object,b=v(Int32Array),M=h(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=w(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="";const q=new Map;let G=0;const Q=([e,t,r,s,n,a,o,c,i,l],u)=>(...f)=>{let p=""!==K,g=0;p&&(g=((e,t)=>setTimeout(console.warn,1e3,`💀🔒 - proxy.${e}() in proxy.${t}()`))(u,K));const d=G++,y=[];H.has(f.at(-1)||y)&&H.delete(y=f.pop());const w=s(i?f.map(i):f);let h=new t(new r(2*z));return c([e,2,u,d,h,w,n],{transfer:y}),l(h,0).value.then((()=>{p&&clearTimeout(g);const s=h[1];if(!s)return;const n=F*s;return h=new t(new r(n+n%z)),c([e,1,d,h]),l(h,0).value.then((()=>{const e=new Uint16Array(h.buffer),t=o?e.subarray(0,s):e.slice(0,s);return a(C.decode(t))}))}))};var V=({parse:e,stringify:t,transform:r}=JSON)=>{const s=((e,t)=>async(r,[s,n,a,o,c])=>{c&&(K=s);try{const s=await r(...o);if(void 0!==s){const r=e(t?t(s):s);q.set(n,r),a[1]=r.length}}finally{c&&(K=""),a[0]=1,Y(a,0)}})(t,r),n=crypto.randomUUID();return{Worker:class extends B{constructor(t,a){const o=new Map;super(t,a),this.proxy=((e,t)=>new Proxy(t,{get:(t,r)=>t.get(r)||t.set(r,Q(e,r)).get(r),set:(e,t,r)=>!!e.set(t,r)}))([n,L,O,$,!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)=>{const[s]=r,n=t.get(s);if(!n)throw new Error(`Unknown proxy.${s}()`);e(n,r)})(s,o,n);break;case 1:((e,t)=>{const r=q.get(e);q.delete(e);for(let e=new Uint16Array(t.buffer),s=0,{length:n}=r;s[e,t])));const Z="ownKeys",ee="destruct",{[Z]:te}=Reflect,re=new Map(te(Symbol).filter((e=>typeof Symbol[e]===o)).map((e=>[Symbol[e],e]))),se=e=>re.get(e)||`.${Symbol.keyFor(e)||""}`,ne="029d89be-c1c3-4993-a5e4-1b211947c69e",ae="M"+ne,oe="W"+ne,ce=new FinalizationRegistry((([e,t,r])=>{r&&console.debug(`Held value ${String(t)} not relevant anymore`),e(t)})),ie=Object.create(null),{addEventListener:le}=EventTarget.prototype,ue=new WeakMap;Reflect.defineProperty(EventTarget.prototype,"addEventListener",{value(e,t,...r){const s=r.at(0)?.invoke;if(s){let t=ue.get(this);t||ue.set(this,t=new Map),t.set(e,[].concat(s)),delete r[0].invoke}return le.call(this,e,t,...r)}});const{isArray:fe}=Array;var pe=i=>{const g=V(i),{Worker:d}=g,y=s=>{const a=typeof s;switch(a){case n:return null===s?[X[r],s]:s===globalThis?[X[n],null]:fe(s)?[X[e],p(s)]:[X[n],s instanceof b?s:p(s)];case t:return[X[t],p(s)];case o:return[X[o],se(s)];default:return[X[a],s]}};return{...g,Worker:class extends d{constructor(r,i){const{proxy:p}=super(r,i),{[oe]:g}=p,d=new Map,w=e=>{d.delete(e),g(ee,e)},h=([r,c])=>{switch(r){case X[n]:if(null===c)return globalThis;if(typeof c===s)return f(c);if(!(c instanceof b))for(const e in c)c[e]=h(c[e]);return c;case X[e]:return typeof c===s?f(c):c.map(h);case X[t]:switch(typeof c){case s:return f(c);case a:{let e=d.get(c)?.deref();return e||(e=((e,t,{debug:r,handler:s,return:n,token:a=e}=ie)=>{const o=n||new Proxy(e,s||ie),c=[o,[t,e,!!r]];return!1!==a&&c.push(a),ce.register(...c),o})(c,w,{token:!1,return:function(...e){return e.at(0)instanceof Event&&(e=>{const{currentTarget:t,target:r,type:s}=e,n=ue.get(t||r)?.get(s);if(n)for(const t of n)e[t]()})(...e),g("apply",c,y(this),e.map(y)).then(h)}}),d.set(c,new WeakRef(e))),e}}case X[o]:return(e=>{if(e.startsWith("."))return Symbol.for(e.slice(1));for(const[t,r]of re)if(r===e)return t})(c);default:return c}},v=(e,t)=>{const{get:r,set:s,value:n}=e;return r&&(e.get=t(r)),s&&(e.set=t(s)),n&&(e.value=t(n)),e};p[ae]=(t,r,...a)=>{if(t===ee)(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(h);return y(s(o,e,t))}case"getOwnPropertyDescriptor":{const e=s(o,...a.map(h));return[X[e?n:c],e&&v(e,y)]}case Z:return[X[e],s(o).map(y)];default:return((e,t,r)=>y(e(t,...r.map(h))))(s,o,a)}}}}}}};export{pe as default}; diff --git a/dist/window/worker.js b/dist/window/worker.js new file mode 100644 index 0000000..9bbc023 --- /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",w="has",d="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:w,IS_EXTENSIBLE:d,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:we,addEventListener:de,postMessage:ge}=globalThis,he=!0,be=e=>e,Ee=!1;const ve=ee();try{new we(4),Q.waitAsync||(Q.waitAsync=ue),ve.resolve()}catch(e){const t=ge,r=de,n=[];let s="",a="";we=class extends z{},pe=ne(pe,we),ye=ne(ye,we),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])}})),de=(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=new Map,xe=(e,t,r)=>{const[n]=r,s=t.get(n);if(!s)throw new Error(`Unknown proxy.${n}()`);e(s,r)};let _e=0;const Me=([e,t,r,n,s,a,o,c,l,i],u)=>(...f)=>{let p=""!==Ae,y=0;p&&(y=((e,t)=>setTimeout(console.warn,1e3,`💀🔒 - proxy.${e}() in proxy.${t}()`))(u,Ae));const w=_e++,d=[];ke.has(f.at(-1)||d)&&ke.delete(d=f.pop());const g=n(l?f.map(l):f);let h=new t(new r(2*Te));return c([e,2,u,w,h,g,s],{transfer:d}),i(h,0).value.then((()=>{p&&clearTimeout(y);const n=h[1];if(!n)return;const s=me*n;return h=new t(new r(s+s%Te)),c([e,1,w,h]),i(h,0).value.then((()=>{const e=new Uint16Array(h.buffer),t=o?e.subarray(0,n):e.slice(0,n);return a(Pe.decode(t))}))}))},Ie=(e,t)=>new Proxy(t,{get:(t,r)=>t.get(r)||t.set(r,Me(e,r)).get(r),set:(e,t,r)=>!!e.set(t,r)}),{wait:je,waitAsync:We}=Q;var $e=({parse:e,stringify:t,transform:r,interrupt:n}=JSON)=>{const s=((e,t)=>async(r,[n,s,a,o,c])=>{c&&(Ae=n);try{const n=await r(...o);if(void 0!==n){const r=e(t?t(n):n);Re.set(s,r),a[1]=r.length}}finally{c&&(Ae=""),a[0]=1,Oe(a,0)}})(t,r),a=ee(),o=new Map;let c="",l=je;if(je&&n){const{handler:e,timeout:t=42}=n;l=(r,n,s)=>{for(;"timed-out"===(s=je(r,n,0,t));)e();return s}}return de("message",(t=>{if(oe(t,c)){const[n,i,...u]=t.data;switch(i){case 0:c=n,a.resolve({polyfill:Ee,transfer:Se,proxy:Ie([c,ye,we,be,!!je,e,Ee,ge,r,je?(...e)=>({value:{then:t=>t(l(...e))}}):We],o)});break;case 2:o.size?xe(s,o,u):setTimeout(xe,0,s,o,u);break;case 1:((e,t)=>{const r=Re.get(e);Re.delete(e);for(let e=new Uint16Array(t.buffer),n=0,{length:s}=r;n[e,t])));const Ye="destruct",{[g]:De}=Reflect,Le=new Map(De(Symbol).filter((e=>typeof Symbol[e]===a)).map((e=>[Symbol[e],e]))),Be=e=>Le.get(e)||`.${Symbol.keyFor(e)||""}`,Ce="029d89be-c1c3-4993-a5e4-1b211947c69e",Fe="M"+Ce,Ue="W"+Ce,{[c]:ze}=Reflect;var He=async r=>{const o=await $e(r),v=r?.transform||(e=>e),{[Fe]: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 Ne[s]:return null==o?globalThis:typeof o===n?O(o,x.object):o;case Ne[e]:return typeof o===n?O(o,x.array):o;case Ne[t]:return typeof o===n?O(o,x.function):F(parseInt(o));case Ne[a]:return(e=>{if(e.startsWith("."))return Symbol.for(e.slice(1));for(const[t,r]of Le)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[Ne[s],c];case e:return[Ne[e],typeof c===n?c:v(c).map(k)];case t:return[Ne[t],typeof c===t?String(U(v(c))):c];case a:return[Ne[a],Be(r)];default:return[Ne[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},[w]:(e,t)=>S(w,e,k(t)),[d]:e=>S(d,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)),[Ye](e){m.delete(e),T(Ye,e)}};let 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))}};const{proxy:x,isProxy:_,pair:M}=D(R),I=x.object(null);return o.proxy[Ue]=(e,t,...r)=>{const s=parseInt(t);switch(e){case c:{const[e,t]=r;return k(ze(F(s),P(e),t.map(P)))}case Ye:(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{He as default}; diff --git a/dist/worker.js b/dist/worker.js new file mode 100644 index 0000000..a76b344 --- /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 f=0;const u=new Map,d=(e,t)=>class extends e{constructor(e,...s){super(e,...s),e instanceof t&&u.set(this,[f++,0,p()])}},w=new WeakSet,y=e=>(w.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&&!w.has(e),v=new WeakMap,m=(t,s,r)=>{if(u.has(t))s.set(t,u.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=u.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=y,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;u.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 u)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=new Map,_=(e,t,s)=>{const[r]=s,n=t.get(r);if(!n)throw new Error(`Unknown proxy.${r}()`);e(n,s)};let N=0;const q=([e,t,s,r,n,a,o,c,i,l],p)=>(...f)=>{let u=""!==O,d=0;u&&(d=((e,t)=>setTimeout(console.warn,1e3,`💀🔒 - proxy.${e}() in proxy.${t}()`))(p,O));const w=N++,y=[];D.has(f.at(-1)||y)&&D.delete(y=f.pop());const g=r(i?f.map(i):f);let h=new t(new s(2*j));return c([e,2,p,w,h,g,n],{transfer:y}),l(h,0).value.then((()=>{u&&clearTimeout(d);const r=h[1];if(!r)return;const n=B*r;return h=new t(new s(n+n%j)),c([e,1,w,h]),l(h,0).value.then((()=>{const e=new Uint16Array(h.buffer),t=o?e.subarray(0,r):e.slice(0,r);return a(W.decode(t))}))}))},z=(e,t)=>new Proxy(t,{get:(t,s)=>t.get(s)||t.set(s,q(e,s)).get(s),set:(e,t,s)=>!!e.set(t,s)}),{wait:C,waitAsync:H}=i;var Y=({parse:e,stringify:t,transform:s,interrupt:r}=JSON)=>{const n=((e,t)=>async(s,[r,n,a,o,c])=>{c&&(O=r);try{const r=await s(...o);if(void 0!==r){const s=e(t?t(r):r);U.set(n,s),a[1]=s.length}}finally{c&&(O=""),a[0]=1,R(a,0)}})(t,s),a=p(),o=new Map;let c="",i=C;if(C&&r){const{handler:e,timeout:t=42}=r;i=(s,r,n)=>{for(;"timed-out"===(n=C(s,r,0,t));)e();return n}}return M("message",(t=>{if(g(t,c)){const[r,l,...p]=t.data;switch(l){case 0:c=r,a.resolve({polyfill:P,transfer:L,proxy:z([c,k,b,S,!!C,e,P,x,s,C?(...e)=>({value:{then:t=>t(i(...e))}}):H],o)});break;case 2:o.size?_(n,o,p):setTimeout(_,0,n,o,p);break;case 1:((e,t)=>{const s=U.get(e);U.delete(e);for(let e=new Uint16Array(t.buffer),r=0,{length:n}=s;r 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 d9800d59b3e804c350ec076efcd789f539a095b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16201 zcmai5gQXXRyO5uHq^{}IV&`oBGH22nIqt5~f}j&p;;l30y;#0qz92 z9Tw#;X4-TJ{}H^NQ|c|BtfTKUNqbh9m-g>s5|k5p<<--Eqqo? z8lVu)VkZhg87ZNR|1nLooOd6(WNB%6(hWwLnW0qbEx>+smaY3By9XH>9_|C<5EfW> zh0(d)j01j@Xkf$*eE7su{WJe7?ivC{ACbrPa}D_H7k2i};B*kj1{H%`#Ph?4LcmEO z5$M36;pK;fVm?O)8OxW5MKjTXHjkJwQFHd^3M4XDNJ*tX!OAms!y{voTZQtaEBky# zpUX&2CJwjlM}csX9(3NTZ5o?Gf5K{BR0BpGN!0Aim3!KDWTy!1=o_$VhlFBImR@%n z%Wmq|;FyyVf*57o7%F<{xj0IHL*aVC(G%DN?Wm5sRvcVhI#GdSK*v593=_vH4V2Pi zVUdfFJbY*e;kzZCGCzdtd^&D_C5OVKV^UTYO(+lrdfb%(!|X$+I>Q+NMwuT$2@PHhxCrfARjOfDj!O5%Q!`0z9FPjf{jRTsKC{*E zI@J`!_P>Do0n_b~tOp(KzySgc_DJahMMYHq=a1FD@^%%95OzP^2#H9T)lsz>4qN_nz48wbNOBpS9LGf9CSOt~|;lq8{Y_!*Z)=1+e ztiCyZdFMKN0sB?w8+<2bu#CHrk4^Y1vB=vj^+x|7D#w}HEG_5cBp zU`>AdZ$5pc&ksBRywZ)Ey6(WEkuKa|B=x=GE{CCB|G=tcAS?fI%FGh&?}!+VV?uo`jKA{6c!&K@aqj#bdwTYl9SUgxpo*qS;E`3skqnxAezZ`^4Ng z;gLVKeb!%{O(V@)V?&sMT)#;MI*EA(qkj@&=oL>gtu<3#(B^Wo=OuuPC7=g(;2o>C zMrqXO&(s|dKNB9?t*!&tk((k8QX9EH9bKcXsWT{)j!wbVH90I@3oQuW$})yYUbF|T zlB^O_0D-1Y<{-$YB%1?MuE)6X_1#!g=hQcLY|nqb4B#Jbeu$?v1bt}3Fu?k)9hP-Z zkwT+)k<`~@X3xrqo|vjy_g>K{*?!EZ9W)Y=iS6~|*gql)c3l5;s#+lDwDK!_GCJ*f zW~*e(5e<^G2LCt^20-k0xcg#cJT>cHN88IV`beHkx?Q~6u>kN^^(m2_i zFk9dWv_#X1=jQ`88?5*4a^Lr}_0)n%?f@?$zU4#QOWp3`9l6xk9W26`1pY6P2Qx10 z!_UNO?ctUwSOZL8)`zU7w9;8B?Q1=j1oxYZr7w}rJd$Wg;606J8%HUrzEH#hnDM4% zd$Cfa~L5vgYCcZTNT+h$x)O+HIumDcN)v`Fdo4K;)wfN}K=_{C|O zUi5FVkCo&XZK))?zaGR>xA?V4e@{ORzE=YOia{x`by`zwy2Z&M^!>DwZzJo?!Y~#l z>5lj^){FT)+;fFa;5WtGtNGf5DxxL(LA}PLq_$v62Y6%3dcSBqgR8yY=h7*vhjV>$ zEH$aL;wtaj`q%JaCr~_`ly7pqTmvzrH2hnB(8W4=E>ET*QP(UarLLCj50dCgwG}d0 zgTPlC6-ayuq0S2rSS1Nb%%v)1179X0gej;49lrEYu4Ak%py}&BNBEn z-zT;I;$1zPoYyDafmAE>^!w)U&lfc3hm3UC;tzig{O+wDm`Vzl#65SA`wS&egGaBo z7<_e{r?d;*r~GY%N;GN>#ND-{6ojv6S7!NSzhMge2F&EWA&+U7t#?6Y*_*^qQZA|G z6A5@pJ?x}`m@Cx;U$&8^!FCcPDegT~=F_L6zlB+D;o(hxhW=81a4Dgh!o>KOdg~GQ zxfKb2`{yCw093DWH(&c;CMDO!I7e0!-rX)7-#MaP&ui)(SI~j5NIF>Id8+>}$v%bu z3-;Faj!^8cpYE}Vk7E@+nn(sIAuoe*+84%Sia68SVP9TnejhYye`L~p@XouV|Ezr- zc!qYD(un+W+qK~R>_)##_84^Wnu4?ReGgsvJX^7D2i0{+540#?pzER_PUK^4b02A; zo$ANc04(3(6LtQ)o!9Z5pJ!72d@J|HPXphJETacF;SaVRrM~&7wP34(q!j=(wB%9e zJ%5jow?}?unbvqFq4TsMT}v3JPq`i{pk&u)#^gIY@nr z85dVKdAJ3gpeAwWyStJ@ zV4e1Ct|04y0WEP!+JKUDJ=^AWhqd+A-%-k6ofp{j54WY#4bP}L;y}6($th=@p|{*f zyvw}>sNYfdiO$D7d7?F8TD7}L>{Zg%tN}}2gW!D$a1GuuJ?<>EFON7R z)b^dp<@R)fS~)B!@r%z#_H!63VUFjVEOH-@N2+}ITkj%|qquM7iMT{)6`G5(2;Gaej~rp%^zjqecR?<)j$x}pti=_P zS0akvY*W5=TTjFxvQ=89uD)GUK8lkav+<`FZju<`{#+Z{zGO3JrTo0H`k{GVvY6|Y z>ETWK<`^u~TtN4`=}2&o5MdsTEnMnz7Bt~6p6u|zkMh@&{>!6%x;FpX^VeOkQ+))o ztgg_B9o|67%Kort-&V4>W6(*8Ag+}4elV6sEPYxX#=OdONmdo151Y(9JTnSi;!D3H zap~|cT1W3mUgO|nEA1&c9K`T9AAiJKc*|?toM47FK?R?6Llm;I!XH6#h$AuYQ;WfM z97S89I?EKsH?}VUjZeSL%8)reLSLWinBo*jM_c(6@KRV8+XWFcGRJ*r4}#uk?QBuU zO7uwC`qfPjt;;^H`%PfnQ2XI7HRVU_jqx_pRAy&q^Tbk%s9)c@CBFe*fqnjXx{GGJ zydYB_B$0f>$6oAnFM-g_l~=yW?!T2$G5_|Hs8VD?<PTgbK)srSNq-Zco37-bRfIF{;dO5IFBUBPiwOc4d%+vAg zY5;GjT%1tFW4ilZJW>3pRcLH*g2;g5$CByh(YF`W?%@>PBP8uKVoaQ#8>-6t1PM5jV7B7_x}a0QEH zR>c9W?9a*X3i&?i@YyoA4;44xrLVA!n$iuIf}r9oN#75mOu&lEZSmcH;(@mU5J}ZG zWpnvO8qG^d7hUN~%Z8^FQ&OZg=_G4Bh<$?;4gw$N$>7q zLw{E3EUQmuNto%ZPkx_p))&3OQ%t*1Ya{hy=eHiCc@;U1b~hczPXlD(?nGm285ooq zgT8<|F&)(EwYyi4b2c+aKu(+F*-K8VfK9`k)|0{d9q`)^HI+)T6qXvs;Oe+%MR zuAc2WU#(_hsDW>^VqwxGH}+a-f@0>LxsN zU^!lka9tGTWL#~Kic|h6>;9n=tMrktqnde6zrXc%^>-Nof`jpkN=A7ji~B#vd0UEt za+ZNLh_;bXlVBCL!1XpU)lQ;Ac|Orw4Ty*kbK>2dU*D%D;DIto+fRcL#ukQ?2poHI zN(R-wAK2IzgtcQ~0+Cb*>Mtc)+!v}ErM5p^c&MAz+w>FBIz)+epzSIYWP#Jdtdp|?`=>S3ViRLkr` z&*A-~)gUmnx5eE4CEULuwUs`~TpOQbe-}wS_gWi1Y~WBfdBe#wf#lHHql%`*=`vwdtYSI#yA_1>w-G z9$shRvoSiHF_<=I7FH)$?~m(i8z20Y(+WXn9sju_>&;n^IQbc4P!+i=D=mtH)0$t~2ZDP--BXb716JI$_gT-7UN=+-l zl26Us9ouaDxwkb^OdCorTpd+Ymv0zp9Q}D3OG7W7s!8Ek^Z=Z9l0AM zPw=p6e>@p|Y_qvY;9_UjBys(i(&MqJDYVRjyq6%ggJZsBFehEZfg~foba!{ZxKpP< zi|o#!rhPY+cyE4MdLql*JtVR3lvu8LwbZ$OFF*G#90=Co@c&*I+JcXnXKgK3sac0+ zwRiurSMyJbjrbG2-}E^TytYN`xtiqpM6fm)aEhMSm!RyB(bvGuivk!xER(fxUeiOo zGc!MxQ56?HNh+Ko|CIQB1mLw_rTOlBep}wwJLrfV@<{UJM3`}0XCY$|i2mdfmOTFQBiCaFil)TzvL;eb{OhuDD zd~C^p37#y|M*UVhJS9$+L2T3OiDFt5gXFXtBN5_YOfrV7yp`7@|ChN*mk~_TfZ>FM zp9WNY6-pT}4Os~r&zUkb1OBz3F_L92XLY>ow775|+iUnb4+_WAAgspxI6fNv6#U|O zZ@AWGnU7wbk6od89GdTORQm)?ypGr{A77Xn)cJ!*@j=0^Sx|mYaB%R8A)2-YxRPv> zdIldOUUGhcxqDdM_EO&6Nw(T}qt{-s^r6Ye=@7mY?y31&IiOyqEnZ^Kx52%{8=RIr z^sR)5qp-T?muaOqs7z;7$Ni>rdKCNINwv1`gIF^W0~QThnE(MO?^QCfqlY<{uj7Y^ z>l=-!WeM!trCdekzcRMe`b1*THC&SLjO?qNQDPd0eL3o47AM!Ow^|XlT~3@mEKH=z zBfDc$ojlg-A#H@#T3VEAj>>%eV63I2)Kt<^<4Pts@$Jxzg4<_DEU{Yf3iD5;fvzMB zyuCK$2QOp9d*jgHYD8wZwUtMkNQRVv{dLSsD%BHYvDVDdT4($7-l7eUn{O%-hn+pgy?V~N$%SsbP7cV?CS{6D%p}IzM|uERSPc- zw0oiGjxGk|Qp2H++WK-~%y^!V0&5CiyizROdY_*C>w)dazZkMd{)!1#Fo?}gu-fth4s#yOE`=+#plJTZ*KzCl^`iL60385e8} zf3{9fT}+wbxH`pNn72)I(QrhIACdA4PFByXt+2G*Yo z$;VucR&GST)O$M?7)UW7TKx4}tWHIHlFd4;=|w`nxi~JFH~)yO)a-nh%tzx#Ww}x* zM#ECiK!G)$r@XLbaiIo@fmV$_GiMKczLFbCImxx|xkT#d(QqGp-G}en9a3=|&@*$2 z%>ktAHbc;p>d1UUkg_bk=5#kEI=oHgN%Y%nU2{{vGKmA13MWx_$f?`}X$cnHp0i{w z!$<-1QUXOOEAPeb#`&x;FYpcSTn!rf>4`{8@u41D@d~km#-V`~!&YY?mrB8ERTOIZ zkupu6)~&VS5ZSL~_~o^~$woHLR5*k#GT1-rd>R$)V8K|&nU30h`hoA%9omWW8L8ds z#A{D*phvON1M4eAr{(yoOB_}4)`Ou$EIgAO?$2Tas2vd`yDmh{9uMdN)G-K8Ym=D4u9L}}CX&392y%JvLB*@nS(ZuOPzFVKtn=0rQ|#>IN~=3`}(v-~1wY|{U&aGt2g^W$UxDqViea_|)>H1Rj)@lSZGsj_Ql$w7-XlRe{#md7q_ zhEa_ENQ|1Ac14rYj$h@=MLj>&W_}wG+g+B%+w|OmV+PaYaA72m$I1~dp?9g-OiX9A z>Wk8GO;;#3Ha1a;;6Y8HR*n&j)&%EnFy$FdME8M|xcw!d-q;%Ae{wZ0cE!WtxfzhZ zL(7WAQJCl7R{aG+cBEQ|+3imB5TC?Tg`Vv6x5l0K7{mXZ6@AOhzc*LQ{iYQ1A(Y62 zOOie5=|%vEB8jf<(ESjj?uIHgs8JEhE5DQ6-OtRmc2#Ut`Ii#y1uoajECY!+4O2~P z>Uw;}?D+6gdaM(W`PHlxz}lrGg~^P2H@1zdoXyi>|GeAxcL5{cQSNingp?*ghc&`*xR(P6y^rI{QdCVEkNbbybLkL1Q~; zmRe@?AY`foU+ToJ;Fcf(DBB$n(pBan(WIXPkC#|mW346lho@Fv3HNEeDrbNn61CnY z_#A4|A@0K^+N7S@+VSlTX_P)X!;&>cP1fHZ_)^%)!3f}SeRcUtjPO22Nq~1{n`YQ7 zP85_t>>T<$wYM+Ic+6vsUlhw8f|Ey11e2E!V*sWIV0{7Z4<78_vh`2;thqnrN^jm# zqj~i>E8_=xq-j`OE6|{r$Hs`w5vfc|-nNKMZi8-@?d-u*t84^z$%s`|oy$z;a~eiJ z>P1od6GRPD47 z@AKP|_K~eB4CHQO&P(Br?q81HIhM}?;j!Y|R>D??@6;)lIQh~nopYyl4?@Pdl1?^) zfpayWkFnvh9~v`N*n+HReWa*Rm~A3L?8Zjr`fq5beO&IzJNC^OU4&tNZ}&hx?pV{1 zwyv!@S{JIfB$29Tsk4}4G9l1QrzWv?rb^=(fMh}#nLBi^EOu&g(#Vhds+fg%6FMFZ`` z0l|36yZ_j)e6$8xWHkf>k2cgNz7fT+fd-hr42}LccG{DnI}sN z?46WvCR#H%Hw*?wNU(d20Z#(4s^4J~-#Iv=bPZVsgXG`jho7QVAGb$xUy@tdxk zw}@syG1i8MlhLu}XyWKQ;n0NKTwY8Bi#{BcZq1sSMR#O^hg57DlDel5_UbE~ zl(<-|Mc3Bv{8>#Y%7!X}o*iF@PVvbRz;mz=)H}4@3Gu9zYzc2;yEmqG<3DaX_~-=) z-cGu%J{_udA$uptc$Fb=9zg4b?(9{R8XOF`DFA-Go(i-kSDKYuHtbT4S>^EYbBZn3 z)U^6_ay<_X9hEk`uRdSi(2IIJ**Km`X3pVY$An1*&-ne4#Yn*X?OucAov*m_cgWsp zPLp!Ht^23S{e@a9|0L^3mh^+C&xq@&X znV;l3>)sHDeT~ZkbUg!Uitme`sXZ!9&970@9T`n^lFn7`&F#DzKKCOFN^6!M zmZ)A&p`b0AL?;qhN`NT9Gy0_Wr2X%91a)8xiVkYIrPs)@Smx+-z0*b6`TcUhjYyA) z#%s8vKWMJz0z9%Kw~v?H3I$P!ki5V+RuhX3l)$CNy1l9ty?+80ub%xx|D?-(f4P&C zi{b3c?O#>tdwJ-Gpt-5UC07?0RJRO()oo(n9&Cw}{d5)JAAj}inN<((Qc>=d85T~} zV%Mql$ZS0+{M%v`g3Hv@G=~9z5W`Hx(4-Bpyol(@O=l=P=HgT675wgXs!0RJJ|@qt zrE2U%14tpn_&%DODc1xhMc6o1t0)$jj|tR#%{Td7KI#umP$9B=mBf@69vlpQdgqzr zsNfgmvPtVrllA>^nti#+br$}X{B`#>_ix{@HF`2`0|rb4f()K2&)xX_c#g}Q>A`qB zGa%ycxd!B5=HHe(S@-=T4V}+a>M1eEe7AP&9*FtU5`*`Y8wHA7C?94`eYVHinBw81 z+l^VtzVNC!D8|SwG$1RGrzc3{{?*Ys46P|GEv?^u8m3DCm&5|LA>zyZ-GBU=64$xg z_Ri_CZ6LDx3Xq}$Ek(%V>{*D+6r znl(E!vcb!BN|`{$)}Mq|na4YnnxF|kwqB)4{j(_)#GQwZOXf@bhdY5TA9&F>zbapM zYMjp5y$k%BuovE`H@DPflWYcn^|xQuXwLg*=AaQ_W&AFD&{O1Hs^d7yOP<+MZxWi- z)HHpsJr0E6qnB6>Fe|6ZGh{_=& zLi?Tr6Y(Mr;aYaBSy1S+OFv(QzjtbQu2f3oHFpD}Yw$BLkh zaE%k2WyeFLIrPTcIK;u&FxPOTfdwK&j4*a^6?QQm{Lrs`y=&F7nYgm~6YiV6DMKC@ z1Xb`de9h-wqBRihfMHkTG+YU<0nSx`zJ{MX^~kfdunX@B}q@iq+zHvC2crG;iiJW73w^)R2K`=b8%a9l$# z^w+9bK5v&RcRHLDuJh^lV|47xJr?FKj~~R*DDu<^$)I^=H~>!Yihb>l8N{loX(!z* zpe5@Q(%r4FZB?-U=}RZ@3^b&I~`1 z-!WmSry z=vRT%3G)jDmFj_FLJ@)kVLZ>?8d`r{bG`kse*WmbWBI1TGnUq=XrxoKhB_h2xBvAN z1qaCQ8752xCr=cPzqyhY3VZFz(6U+ZzAHZI2)9}VB$a7h|AT^kt#Vi7-cpSHZ@h^r zpb`J_rr~T|^pu{ML#pupBP9`R?@K2Zcp~#jMS#i)#LI~LMx7xX#6wQI-95Q01ts8{ zx4JKzGkh_-<)GT@_>#p%>xs$2h_Ahbmr~qE+l~2%me1X z_hf^l2#%`%@VuLHSIGTi)`&7je-^|5LM%(s(QWx8JB$HKS_%cHZ!`BtGU*b(I&!C0 zC3C0ZHVZQY)WDH~^hqa%IL-@x2OU}br!xy%b_prc)N&2c9BGaP?jGNU4V|rm832DG z#N;%Zf#G@PwEKUKMsXYzDa^Xkq#@0wH=N^9{^n9?_stc;oq++@ZFXRawRZ*U0)E8w z;v_eC>cN6xM*5P|zL75F;Bf7zyD~*4+R#lSBgW>@L|5C${zB+CCU}A#q-s-Jp1!`D z`|$V8FGLU|b*ht1ymwLcI|n^*+@1P5(+G?;cOnW{iGJDJe&%ad=Y3yZBRK##rlpD! z0By1@#Pm7>GoHJ9$C#vgu@I(Rr&10T+4Q3nyvO0zZ<6>8&ThP2VkA^*j0 z7Wg<6WTOFuHcZ6$K(a>nfkSV-FE3q7>KID_$>)<{cY*L)p6J&`si~?ix<`rJ;va|b zUrTE$w?ryv-WW&(kz|VS5orP}S~854+{n)s$azyTPnh9*j$*57i;J12+t(-sSrq96 zj%m}EXy<6Dq2|kcSO#T!Fz^Eo$d{vkT9df&y7QfhsO|yqKOdY|!>5Gvzu^fxC{^F) zCb2wTJ3C#SHOd|dTI#xRb;&=*vIGTw|Fhb<-{Zp?^$MI@Ic*?8CdvW`+m~;XH>0DB zNC|pU@(j_uW~LPnaEOV$nU8P;rw1oI{#auu=$|=az3?r=&^mx@8nW!rQZz?mahCRz2j-eDF*|!s4>wK;bga!kG zL~bsio0DgVPBmyZ9Y}fQktsQ}Nb_@lzKdGc3$3Q{S9-2NgVOi|f}o$0ocUjkA`16# z8Q}WQC2uKskRaH?aWv;7bmqiuHR42}bjsVn&VT=$RZ&w8I*=Li2^BKc!yH$*p1y7m z34n{)cGZf&Es?vkfBIW7ohK}wR+M@O_AB!iRJ7Mvwhm6+^K5X2uN11QVE3!Ya(L70>LM9w@s$oF`jCaX;8cA!+OkGU;1D<3KDUWAHWqvwg4Rz8ez-pllR|>D?w5pTr zCC;OR4A?7J=0ljTWJSz~Exfvq6sCBN%5G_#s+X<|$3AZRYyEY3_#gvDh9qVMIv~L` z{T?IossI{lo-BZqW}Urvz4_17MM<|b4gNRpm5cw3b2H~WM3In?FnB*jcs5J*W3Ca4 z5x`9d;2wA-`RNXcVcf0EY))GzN12+}lrIGps6GR_5|nA!U;-kc^=zAdwKU`6%~CQ_ z@<(%-O@#x1g^J^DRvT6Nm=1tfzl#LEuE2uyrolFz74UZkib@$uwYUWFdLHtm#TvjX zemn~I%kBx44;gBxln44}{qNh32@8%+o{xIX?vFn0RiGO0T@`shys9K^;q$u1ZdPC& zI&C8`85zvc89>bS$O|VvZl#(BYche3mnI0kd_`t;{3x~3*qeX~6dG8HSh77=ysZvS zRu|fC%H{Du71j1~OSA5Od;+BJ86At$EN_8FoQqZb)-q0GdPE=^NY3z>r6@MVZtm7% z2dTOH@ZRmSr2h|@l~Rv017SC^POt%(0yhINz(c-i9aS+_7xo)Omj;$Oys(*2Ji$cD zSH6~0W>ZK}W)Q%t_JNL$UxzIbp8J#jqd4Ac4i1j4mBgoV=#MuhzYB)@!pxdEz+lX+ z=##a{&fECnv1ThaxDNs*Kmgyn2|J^d{5?q(h~xD{OaVgJJE`|H(kN43i}F%hf7d|x zZyxj?cU|unCr@0$;y~qYn8)iCpoI$%0N}gA8^*6mHwi_Q8wp znB$Y>vpUu5magAM`A_ADInV_f{Fz2AIwi;3F1wOq_P=|IcSmo%aH%C;9Xk;Q8rJ zeb9oYHP5)`vd#`RtY=zsdZYn$YQvtiC9(*X|2h&&it!Y#cc&@PZ6cm;iWH;4pvMiSB=kMLEoWmE zpJyc_cs9Fn&l>*#OYLKN#{9G^0}wCLHMDc#;reOg%DEI0s9o>Q+ z1mM6VQw<*y2WsD{_>a_n)So8Ftr_34qew!n|2d>O8R!;ULawDKC(Ps^-EFr$TqWHd z#D&n~uUfvK@3KH-ipL`EKF8`A4jb*De2zPD#x8GSIekpY>3h(`^A~UDjcVUG^noe= zo*gR6$gltg;#qwA(OR4OUxLns-jbLrG%cMCv(-(qnGE%~W_N5q;z{56zsUBnUFbJ& z8>LP7>L~TN^5Q9$PW}lgBMWqs4aYpmyJT4YlMx>!zDV?Z*$|{`|Ceuo634K_jbNJh zg~W)dA+>{RE^%c0yQ}Km%A5tk<4H4Lyw*9cSka3Q`9BkX-d&%Of_Ln42J5nil&S4m zap2u8PHyuOfj71G$XBT&wd3UpjR0~f6fZ&3RX1kP^~>=-(|%83W~p>PWO1Co%0B^>FI!w# zBeTNto@mF)6Gzdi&*2LzB|S@i^@FbYb3YdzOR_OYS+MnYev6rK9Eu!Dz%@N#*Vj}d zp@;VdL;ui7=_y@m{jpa5L&u}YFfu{!aTD4nnz-M6^KafjH_U5Q$WU?ApX}}xA z3Wh#P7OxtV)*nO3%n5me{XJG5oFVK$<(N=ePFbQEKuKL+U;nf)9a`xFHYIMXSwV8x zPjA>6ER2qGzI~x~cpdV1%$DYVM-eKwD-2QN(;6c*889O>Ufj9uDRj#8#65Y;`G!r9U5X3!{Xw|7mI! zPeLX;xAhO-f7V~=>mM;0iBeW(7P^v+J>)L^Wngnl{7~SNj-+oSV!@JcbPzUSg38Y|mjCaR#V#B4~HcUtcS{iw0a= zTvB-HRQw-gDA7+@Nx|PBSztvWEYK5Hwxb^1m3!OD5EGH4}Ty*(FPZ+LF z{BPmDvy!8!Xzk!(j_sZSF@{#-xxM>5oGAAG7tiTG7)`D1BGn51W}o38~ClM9B1h9#I6?{rl4qD8J-ySaMg z^7GRk3N@OMb8pj;mqk_HTG9L_*E#sV<+g;b>X+V+nO7y%Rq0{d49R$!nJ_?%X1_K7EJ)3wh=b&%7ieWi~|dvN)SMm-+UFyz;{fVjQ0oRX((# zjCuoNE_VN@SzfMAwh3Zq=o%K{N=xJ-^?bQ8(3*LyB~^ha)q4_>dRLe>^BhAss&w$&eCV8QtC)8a||1(tT7RZ%1I~iQ6 zo*Q*V=ko+yF@Id=&~qNc+DN{^1W4fb>Nd^RG_f|qJxXR80)Mv(Z1Jm4K1|U)OzniML~{KqYaTjTCcFFE1IPGim*V}uPA#=ece!u2Z+ z4A~l{$5|b$()H!&z;*NLvv?P7bTS)K*E1L&@|-XaC5L&bf!_86`HE{3qfPYu^cz08 zx;PVNl+)j+U#TTSxUgbP8Ca3HybndEwkuwYS#Hq5*CLk<&+Zm9uSP;ydW+iII~wz? zkW&#BxVAb}9E^M|+xJMJ39=CQumI!8FJd6CR3-->7NfJsbMg67Cso*-G+9`jnXG+W)!+#(BTIXmA<##3-`h zyWlaMZ*{st#|xRghNpMulu*-61bH=%?rWe5ICt&e_U&56^LYjYUN4tt)$f$`t$fF!TQgJ?5!>MWnPq~Hij-40YRO}eNlR`Rdh_`YmGy_knT?ISEeki$2Ii=P%Gr2VIMPd2^hcBj3yM zzVC@UnjRTNiXA&g7Tw0BO(?h4&A-aC!wc5eFV+ExwFb3NH7Uei+8`pTw7Q8<^{9$D zMDVCGX+~#ORUQWAIQ9WCl;v+cV$b2cfT-Vtj87_IC(A))0V2iE!#4!rv$|22;tGw_ zKF;#Ix<7|Bp?p>&6cSIada2H(z+{LXHSH#gUjl`!vj?f@j?0u7)Q>g@SvWOF08T)I z=cLnC5K~4lcxYt1`+>DseqKhgdXD!cY?nazx>x`3nimN8rFp%I_7!;I(Y$$N8+tXX zJ>4U&I~!7HqkJ~7+!k&o7cNKyXB-OEQ<8eIbhhkh)PP@(u}p##59cUt@4oaQkFHL$ z9)Ic!k${1of&HZ4R{J1m;g68NAkcYzf;&R(y=q%|@MG1f=jr`^ae!xAcc9a{+R=I? zu`~G^7cS`|&ckwBQ1{=xtHiq^5;FoxmAv8KCjKupd3#oLe;oXimjan8jdhI+IIqF{ zos8YSYr4M~ccePJ#=9VQXnrP#x3^cS=I)#cw>CmE!A$g4YaDzGMtaD}HD7(j-c zATkk6iPm(F?IDN5`9o`ad4ju#_jkQb!==2Y(rHuWUsE?86<6QmWu3QQTVDwue`0$2 zb(Z$lYoj-EkH{)!a9fA!min8pz$BUP`u&s}ecbE5Q4}Y!+l{;ra5>lnZ={G3`)J^1 z7B^Ya^Jc$NVHlmt$g6`I=@eA|6m7B z@;k9*RK@*yM+fF{RR3-(2+?vJ5OQ$7vb3s2JKe{O;3^c2iMXfa(|r=yktRxg|0~q@ zPT8asv#?;&b}_!6*}bnoP_wc;f2T`7{8W|LgZWIdy-u1jh*wOLvriPsb&Y3LATW7o zcQASI^X#UWnz^N#5odA1C7Ct)^Oku9?eW`RZ47>s5qP)tcd?~yIg6G7yGB#M2L!6`~_m2(H zu26E_Cpe>Q$JAWh)+Ua3@l_$7?uX!g@}OP0Uc2DsQ0Egeb3WF+vevx}lV-}Jtu1eS z<)(YiZo!54pULsh?_R>0K}~j9O@Rq@(CztU@h=R-MtX>vaar4?{5nzE=|wFSCNKO; z-~6gNNGfrLa}IhWiPy$$ts%JXTT)Ktr}K9O$()LNY5qyLvM!EK9)%dNjH%G7?>ym7 zs4y(=4kGX2$PK>6EkjZYNjHe9o)}MmYu}xb9&|Dy48q4-qWkd@saqO|ZmIpMo`n1e zsozaLsyRnC?DSqpDmNK;g`r)smk3R>%?e(m^y}pUF9&^{Ui{!~(Y3Kc>~d2@$OGQg zWXe`7{_Xj|E{5}*_bn3<{MoOW)WOnYAAgb_X0;cpL;_f(9@)>|qvMZaCVpu>FsRr+ zISdFLQ(Swq2jY7^*dv>fWVswLSl7Y9nuD8!SnCSO^oP3fnJO&@6cp26fduUBMqMX@SjJ{E?UHv_Prq|4JDf;@>3f$4dCx&{J^e2NtgNig{FMb)cHq#8 z;JT-4Cs#!QzN>D@r=3A8(A>VNzqC*0kADbaR&m!pOVRpyC1_N09F<%%E5}%WY>QkD z|8qny^g;J3`$2Gx>6hQ`qxO*Fb9Uc0qmw?Gi#W7DTd#*wn_BMMVb@iYF9KGH=H_Q1 zKWn`&hp(Y+<{a#FamqD3bceQjR*Z-4Y?j0F6=E-RtqC7ikVvGX>)i#KIK?^x^q^h@ zi>x^O$3V{dB7=J^YLh@<<@6bvkJet*ZG2DC}-^UQR{~9%bg5UCso-Q=Gu7p)W}HoTfxcl z0Y2~aB1BX#KNNQdW{98N?JEksv9n0J5OLe^|^I1g|xH)JJioClT}$Xal!&{B}XF%`zE`>@%S zydAKUUFj|c3tRupKMN6m<(zw_8nTVl29utq7s3h0&m<*VpmXaz1-WbNUpsnsUlz?d zaNKL?Dn-n|*%rhfg63S_JY&OCBr_{CFpfpz0Zo$^H=*CXjQg^$>#6y!lPpDw?whNc zTxv?PTFjKuYWo0aYF+k<1W%II0CFfls6Eqrv=@ml_%=OT6>;Jwgus(pEZ?LcgDm%E z`<@<;^;nb^m??i-8mCUd+|8*B`tTinZ(5hL@$oxubgMyf1iWGm!*@%+VPj3Uw2ui^ zurM8;Dnr|j<8jhB4b@8oo2E=bxIFZwQY&a2F%H%8Rbv60?y2=5*|Mqo@X_b;q zb;Xzj|JG(Uo*q@0ekrWQ2#7Anm-wPvJ;e5Kv<%VGOC|hVBxfqJlN-#?b0g0FcWi{+ z9KQDx+i7_ojZe%d!6r~Jw&r^p@o zqaTj9^#H?`C@d)4`wRU#K`blq-$vbrtT1jo+y7^OIUy6v_rH&jrVBzy_a~gUsLk+z N(kpejDjD - - - - - 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..b0f4176 100644 --- a/package.json +++ b/package.json @@ -1,92 +1,38 @@ { "name": "coincident", - "version": "1.2.3", + "version": "2.0.0-rc1", "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.4.5" } } 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..1a9c36d --- /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; + super(url, options); + this.proxy = createProxy( + [ + CHANNEL, + Int32Array, + SharedArrayBuffer, + 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, map, rest); + break; + } + case ACTION_NOTIFY: { + actionFill(...rest); + break; + } + } + } + }); + } + } + + return { + Worker, + polyfill, + transfer, + }; +}; diff --git a/src/shared.js b/src/shared.js new file mode 100644 index 0000000..767ec43 --- /dev/null +++ b/src/shared.js @@ -0,0 +1,127 @@ +// (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; + +/** + * @param {...Transferable} args + */ +const transfer = (...args) => (buffers.add(args), args); + +let seppuku = ''; +const results = new Map; +const actionLength = (stringify, transform) => async (callback, [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 = (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, map, rest) => { + const [name] = rest; + const callback = map.get(name); + if (!callback) throw new Error(`Unknown proxy.${name}()`); + waitLength(callback, rest); +}; + +const warn = (name, seppuku) => setTimeout( + console.warn, + 1000, + `💀🔒 - proxy.${name}() in proxy.${seppuku}()` +); + +let uid = 0; +const invoke = ( + [ + CHANNEL, + Int32Array, + SharedArrayBuffer, + 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 = new Int32Array(new SharedArrayBuffer(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 = new Int32Array(new SharedArrayBuffer(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) => ( + map.get(name) || + map.set(name, invoke(details, name)).get(name) + ), + set: (map, name, callback) => !!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..2c4c8ef --- /dev/null +++ b/src/ts.js @@ -0,0 +1,7 @@ +// this is here just to please TS ( it disappears once built ) +export class CoincidentWorker extends Worker { + constructor(url, options) { + super(url, { ...options, type: 'module' }); + this.proxy = {}; + } +} diff --git a/src/window/constants.js b/src/window/constants.js new file mode 100644 index 0000000..798bf4e --- /dev/null +++ b/src/window/constants.js @@ -0,0 +1,3 @@ +const CHANNEL = '029d89be-c1c3-4993-a5e4-1b211947c69e'; +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..ec5e098 --- /dev/null +++ b/src/window/events.js @@ -0,0 +1,20 @@ +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) eventsHandler.set(this, (map = new 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..38751ae --- /dev/null +++ b/src/window/main.js @@ -0,0 +1,151 @@ +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 { Worker: $Worker } = exports; + + 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 $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.at(0) instanceof Event) handleEvent(...args); + 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))); + + const asDescriptor = (descriptor, asEntry) => { + const { get, set, value } = descriptor; + if (get) descriptor.get = asEntry(get); + if (set) descriptor.set = asEntry(set); + if (value) descriptor.value = asEntry(value); + return descriptor; + }; + + 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 value = method(target, ...args.map(fromEntry)); + return [numeric[value ? OBJECT : UNDEFINED], value && asDescriptor(value, toEntry)]; + } + 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..0a1fb8a --- /dev/null +++ b/src/window/worker.js @@ -0,0 +1,182 @@ +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, 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); + }, + }; + + let 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); + + 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..4fd6e79 --- /dev/null +++ b/src/worker.js @@ -0,0 +1,111 @@ +// (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, 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; + + 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: { + CHANNEL = _; + ready.resolve({ + polyfill, + transfer, + proxy: createProxy( + [ + CHANNEL, + Int32Array, + SharedArrayBuffer, + ignore, + !!wait, + parse, + polyfill, + postMessage, + transform, + wait ? + (...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, map, rest); + else actionWait(waitLength, map, rest); + break; + } + case ACTION_NOTIFY: { + actionFill(...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..1ca5c4e --- /dev/null +++ b/test/basic/worker.js @@ -0,0 +1,17 @@ +import coincident from '../../dist/worker.js'; + +const { proxy, polyfill } = await coincident(); + +console.info('worker', { polyfill }); + +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/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 95% rename from test/window.js rename to test/window/worker.js index 271dd7b..b770f95 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')]); 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}; From 3a8ab56e72a25ccc50e2053c3bb7deb12a7e480e Mon Sep 17 00:00:00 2001 From: webreflection Date: Tue, 23 Jul 2024 12:37:18 +0200 Subject: [PATCH 2/3] rc2 --- .gitignore | 1 + README.md | 64 +++++++++++++++++++++++++++++++++++- dist/main.js | 2 +- dist/window/main.js | 2 +- dist/window/worker.js | 2 +- dist/worker.js | 2 +- index.html | 1 + package.json | 4 +-- src/main.js | 8 ++--- src/shared.js | 39 +++++++++++++--------- src/ts.js | 6 +++- src/window/constants.js | 3 +- src/window/events.js | 9 +++-- src/window/main.js | 25 +++++++------- src/window/worker.js | 11 +++++-- src/worker.js | 18 +++++----- test/basic/worker.js | 4 +-- test/index.html | 1 + test/no-sab-or-sw/index.html | 18 ++++++++++ test/no-sab-or-sw/worker.js | 8 +++++ test/window/worker.js | 1 + 21 files changed, 170 insertions(+), 59 deletions(-) create mode 100644 test/no-sab-or-sw/index.html create mode 100644 test/no-sab-or-sw/worker.js diff --git a/.gitignore b/.gitignore index 6c46e52..f099858 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ v8.log coverage/ node_modules/ +coincident-* diff --git a/README.md b/README.md index efbed5c..ffe2bee 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ const { The `Worker` class returned by `coincident()` has these features: - * it always starts a *Worker* as `{ type: "module" }` ( mostly because the worker needs to `await coincident()` on bootstrap ) + * 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 @@ -63,6 +63,8 @@ const { 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, @@ -89,6 +91,66 @@ proxy.compute = async () => { console.log(proxy.location()); ``` +### coincident/window/main + +When the *worker* code expects the *main* `window` reference, this import is needed to allow just that. + +```js +import coincident from 'coincident/window/main'; +// ^^^^^^ + +const { Worker, polyfill, transfer } = coincident(); +``` + +The signature, on the *main* thread, is identical. + +### coincident/window/worker + +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 +import coincident from 'coincident/window/worker'; +// ^^^^^^ + +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(); + +// direct synchronous access to the main `window` +console.log(window.location.href); + +window.document.body.textContent = 'Hello World 👋'; +``` + +#### 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. + +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). + +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. + +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: + +```js +const { window } = await coincident(); + +const { document } = window; +const { head, body } = document; + +// any time we need to change the content +body.textContent = 'Hello World 👋'; +``` + +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. + - - - ### About 💀🔒 Deadlock Message diff --git a/dist/main.js b/dist/main.js index d7987e2..11dd116 100644 --- a/dist/main.js +++ b/dist/main.js @@ -1 +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,g=(e,t)=>class extends e{constructor(e,...s){super(e,...s),e instanceof t&&f.set(this,[p++,0,l()])}},u=new WeakSet,d=e=>(u.add(e),e),w=(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},y=e=>null!==e&&"object"==typeof e&&!u.has(e),h=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))y(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)h.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(w(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=>h.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=g(A,k),E=g(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(w(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 y(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="";const L=new Map;let R=0;const _=([e,t,s,r,n,a,o,c,i,l],p)=>(...f)=>{let g=""!==B,u=0;g&&(u=((e,t)=>setTimeout(console.warn,1e3,`💀🔒 - proxy.${e}() in proxy.${t}()`))(p,B));const d=R++,w=[];P.has(f.at(-1)||w)&&P.delete(w=f.pop());const y=r(i?f.map(i):f);let h=new t(new s(2*U));return c([e,2,p,d,h,y,n],{transfer:w}),l(h,0).value.then((()=>{g&&clearTimeout(u);const r=h[1];if(!r)return;const n=W*r;return h=new t(new s(n+n%U)),c([e,1,d,h]),l(h,0).value.then((()=>{const e=new Uint16Array(h.buffer),t=o?e.subarray(0,r):e.slice(0,r);return a(D.decode(t))}))}))};var N=({parse:e,stringify:t,transform:s}=JSON)=>{const r=((e,t)=>async(s,[r,n,a,o,c])=>{c&&(B=r);try{const r=await s(...o);if(void 0!==r){const s=e(t?t(r):r);L.set(n,s),a[1]=s.length}}finally{c&&(B=""),a[0]=1,S(a,0)}})(t,s),n=crypto.randomUUID();return{Worker:class extends x{constructor(t,a){const o=new Map;super(t,a),this.proxy=((e,t)=>new Proxy(t,{get:(t,s)=>t.get(s)||t.set(s,_(e,s)).get(s),set:(e,t,s)=>!!e.set(t,s)}))([n,E,k,T,!1,e,b,(...e)=>this.postMessage(...e),s,i.waitAsync],o),this.postMessage(T([n,0,a])),this.addEventListener("message",(e=>{if(w(e,n)){const[t,s,...n]=e.data;switch(s){case 2:((e,t,s)=>{const[r]=s,n=t.get(r);if(!n)throw new Error(`Unknown proxy.${r}()`);e(n,s)})(r,o,n);break;case 1:((e,t)=>{const s=L.get(e);L.delete(e);for(let e=new Uint16Array(t.buffer),r=0,{length:n}=s;rs.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:w}=Array,{create:h,getPrototypeOf:v,values:m}=Object,b=v(Int32Array),M=h(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=w(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="";const q=new Map;let G=0;const Q=([e,t,r,s,n,a,o,c,i,l],u)=>(...f)=>{let p=""!==K,g=0;p&&(g=((e,t)=>setTimeout(console.warn,1e3,`💀🔒 - proxy.${e}() in proxy.${t}()`))(u,K));const d=G++,y=[];H.has(f.at(-1)||y)&&H.delete(y=f.pop());const w=s(i?f.map(i):f);let h=new t(new r(2*z));return c([e,2,u,d,h,w,n],{transfer:y}),l(h,0).value.then((()=>{p&&clearTimeout(g);const s=h[1];if(!s)return;const n=F*s;return h=new t(new r(n+n%z)),c([e,1,d,h]),l(h,0).value.then((()=>{const e=new Uint16Array(h.buffer),t=o?e.subarray(0,s):e.slice(0,s);return a(C.decode(t))}))}))};var V=({parse:e,stringify:t,transform:r}=JSON)=>{const s=((e,t)=>async(r,[s,n,a,o,c])=>{c&&(K=s);try{const s=await r(...o);if(void 0!==s){const r=e(t?t(s):s);q.set(n,r),a[1]=r.length}}finally{c&&(K=""),a[0]=1,Y(a,0)}})(t,r),n=crypto.randomUUID();return{Worker:class extends B{constructor(t,a){const o=new Map;super(t,a),this.proxy=((e,t)=>new Proxy(t,{get:(t,r)=>t.get(r)||t.set(r,Q(e,r)).get(r),set:(e,t,r)=>!!e.set(t,r)}))([n,L,O,$,!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)=>{const[s]=r,n=t.get(s);if(!n)throw new Error(`Unknown proxy.${s}()`);e(n,r)})(s,o,n);break;case 1:((e,t)=>{const r=q.get(e);q.delete(e);for(let e=new Uint16Array(t.buffer),s=0,{length:n}=r;s[e,t])));const Z="ownKeys",ee="destruct",{[Z]:te}=Reflect,re=new Map(te(Symbol).filter((e=>typeof Symbol[e]===o)).map((e=>[Symbol[e],e]))),se=e=>re.get(e)||`.${Symbol.keyFor(e)||""}`,ne="029d89be-c1c3-4993-a5e4-1b211947c69e",ae="M"+ne,oe="W"+ne,ce=new FinalizationRegistry((([e,t,r])=>{r&&console.debug(`Held value ${String(t)} not relevant anymore`),e(t)})),ie=Object.create(null),{addEventListener:le}=EventTarget.prototype,ue=new WeakMap;Reflect.defineProperty(EventTarget.prototype,"addEventListener",{value(e,t,...r){const s=r.at(0)?.invoke;if(s){let t=ue.get(this);t||ue.set(this,t=new Map),t.set(e,[].concat(s)),delete r[0].invoke}return le.call(this,e,t,...r)}});const{isArray:fe}=Array;var pe=i=>{const g=V(i),{Worker:d}=g,y=s=>{const a=typeof s;switch(a){case n:return null===s?[X[r],s]:s===globalThis?[X[n],null]:fe(s)?[X[e],p(s)]:[X[n],s instanceof b?s:p(s)];case t:return[X[t],p(s)];case o:return[X[o],se(s)];default:return[X[a],s]}};return{...g,Worker:class extends d{constructor(r,i){const{proxy:p}=super(r,i),{[oe]:g}=p,d=new Map,w=e=>{d.delete(e),g(ee,e)},h=([r,c])=>{switch(r){case X[n]:if(null===c)return globalThis;if(typeof c===s)return f(c);if(!(c instanceof b))for(const e in c)c[e]=h(c[e]);return c;case X[e]:return typeof c===s?f(c):c.map(h);case X[t]:switch(typeof c){case s:return f(c);case a:{let e=d.get(c)?.deref();return e||(e=((e,t,{debug:r,handler:s,return:n,token:a=e}=ie)=>{const o=n||new Proxy(e,s||ie),c=[o,[t,e,!!r]];return!1!==a&&c.push(a),ce.register(...c),o})(c,w,{token:!1,return:function(...e){return e.at(0)instanceof Event&&(e=>{const{currentTarget:t,target:r,type:s}=e,n=ue.get(t||r)?.get(s);if(n)for(const t of n)e[t]()})(...e),g("apply",c,y(this),e.map(y)).then(h)}}),d.set(c,new WeakRef(e))),e}}case X[o]:return(e=>{if(e.startsWith("."))return Symbol.for(e.slice(1));for(const[t,r]of re)if(r===e)return t})(c);default:return c}},v=(e,t)=>{const{get:r,set:s,value:n}=e;return r&&(e.get=t(r)),s&&(e.set=t(s)),n&&(e.value=t(n)),e};p[ae]=(t,r,...a)=>{if(t===ee)(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(h);return y(s(o,e,t))}case"getOwnPropertyDescriptor":{const e=s(o,...a.map(h));return[X[e?n:c],e&&v(e,y)]}case Z:return[X[e],s(o).map(y)];default:return((e,t,r)=>y(e(t,...r.map(h))))(s,o,a)}}}}}}};export{pe as default}; +const e="array",t="function",r="null",s="number",n="object",a="string",o="symbol",c="undefined";let i=0;const l=new Map,u=new Map,f=e=>u.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 index 9bbc023..6ea14f7 100644 --- a/dist/window/worker.js +++ b/dist/window/worker.js @@ -1 +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",w="has",d="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:w,IS_EXTENSIBLE:d,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:we,addEventListener:de,postMessage:ge}=globalThis,he=!0,be=e=>e,Ee=!1;const ve=ee();try{new we(4),Q.waitAsync||(Q.waitAsync=ue),ve.resolve()}catch(e){const t=ge,r=de,n=[];let s="",a="";we=class extends z{},pe=ne(pe,we),ye=ne(ye,we),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])}})),de=(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=new Map,xe=(e,t,r)=>{const[n]=r,s=t.get(n);if(!s)throw new Error(`Unknown proxy.${n}()`);e(s,r)};let _e=0;const Me=([e,t,r,n,s,a,o,c,l,i],u)=>(...f)=>{let p=""!==Ae,y=0;p&&(y=((e,t)=>setTimeout(console.warn,1e3,`💀🔒 - proxy.${e}() in proxy.${t}()`))(u,Ae));const w=_e++,d=[];ke.has(f.at(-1)||d)&&ke.delete(d=f.pop());const g=n(l?f.map(l):f);let h=new t(new r(2*Te));return c([e,2,u,w,h,g,s],{transfer:d}),i(h,0).value.then((()=>{p&&clearTimeout(y);const n=h[1];if(!n)return;const s=me*n;return h=new t(new r(s+s%Te)),c([e,1,w,h]),i(h,0).value.then((()=>{const e=new Uint16Array(h.buffer),t=o?e.subarray(0,n):e.slice(0,n);return a(Pe.decode(t))}))}))},Ie=(e,t)=>new Proxy(t,{get:(t,r)=>t.get(r)||t.set(r,Me(e,r)).get(r),set:(e,t,r)=>!!e.set(t,r)}),{wait:je,waitAsync:We}=Q;var $e=({parse:e,stringify:t,transform:r,interrupt:n}=JSON)=>{const s=((e,t)=>async(r,[n,s,a,o,c])=>{c&&(Ae=n);try{const n=await r(...o);if(void 0!==n){const r=e(t?t(n):n);Re.set(s,r),a[1]=r.length}}finally{c&&(Ae=""),a[0]=1,Oe(a,0)}})(t,r),a=ee(),o=new Map;let c="",l=je;if(je&&n){const{handler:e,timeout:t=42}=n;l=(r,n,s)=>{for(;"timed-out"===(s=je(r,n,0,t));)e();return s}}return de("message",(t=>{if(oe(t,c)){const[n,i,...u]=t.data;switch(i){case 0:c=n,a.resolve({polyfill:Ee,transfer:Se,proxy:Ie([c,ye,we,be,!!je,e,Ee,ge,r,je?(...e)=>({value:{then:t=>t(l(...e))}}):We],o)});break;case 2:o.size?xe(s,o,u):setTimeout(xe,0,s,o,u);break;case 1:((e,t)=>{const r=Re.get(e);Re.delete(e);for(let e=new Uint16Array(t.buffer),n=0,{length:s}=r;n[e,t])));const Ye="destruct",{[g]:De}=Reflect,Le=new Map(De(Symbol).filter((e=>typeof Symbol[e]===a)).map((e=>[Symbol[e],e]))),Be=e=>Le.get(e)||`.${Symbol.keyFor(e)||""}`,Ce="029d89be-c1c3-4993-a5e4-1b211947c69e",Fe="M"+Ce,Ue="W"+Ce,{[c]:ze}=Reflect;var He=async r=>{const o=await $e(r),v=r?.transform||(e=>e),{[Fe]: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 Ne[s]:return null==o?globalThis:typeof o===n?O(o,x.object):o;case Ne[e]:return typeof o===n?O(o,x.array):o;case Ne[t]:return typeof o===n?O(o,x.function):F(parseInt(o));case Ne[a]:return(e=>{if(e.startsWith("."))return Symbol.for(e.slice(1));for(const[t,r]of Le)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[Ne[s],c];case e:return[Ne[e],typeof c===n?c:v(c).map(k)];case t:return[Ne[t],typeof c===t?String(U(v(c))):c];case a:return[Ne[a],Be(r)];default:return[Ne[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},[w]:(e,t)=>S(w,e,k(t)),[d]:e=>S(d,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)),[Ye](e){m.delete(e),T(Ye,e)}};let 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))}};const{proxy:x,isProxy:_,pair:M}=D(R),I=x.object(null);return o.proxy[Ue]=(e,t,...r)=>{const s=parseInt(t);switch(e){case c:{const[e,t]=r;return k(ze(F(s),P(e),t.map(P)))}case Ye:(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{He as default}; +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 index a76b344..6990d56 100644 --- a/dist/worker.js +++ b/dist/worker.js @@ -1 +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 f=0;const u=new Map,d=(e,t)=>class extends e{constructor(e,...s){super(e,...s),e instanceof t&&u.set(this,[f++,0,p()])}},w=new WeakSet,y=e=>(w.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&&!w.has(e),v=new WeakMap,m=(t,s,r)=>{if(u.has(t))s.set(t,u.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=u.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=y,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;u.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 u)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=new Map,_=(e,t,s)=>{const[r]=s,n=t.get(r);if(!n)throw new Error(`Unknown proxy.${r}()`);e(n,s)};let N=0;const q=([e,t,s,r,n,a,o,c,i,l],p)=>(...f)=>{let u=""!==O,d=0;u&&(d=((e,t)=>setTimeout(console.warn,1e3,`💀🔒 - proxy.${e}() in proxy.${t}()`))(p,O));const w=N++,y=[];D.has(f.at(-1)||y)&&D.delete(y=f.pop());const g=r(i?f.map(i):f);let h=new t(new s(2*j));return c([e,2,p,w,h,g,n],{transfer:y}),l(h,0).value.then((()=>{u&&clearTimeout(d);const r=h[1];if(!r)return;const n=B*r;return h=new t(new s(n+n%j)),c([e,1,w,h]),l(h,0).value.then((()=>{const e=new Uint16Array(h.buffer),t=o?e.subarray(0,r):e.slice(0,r);return a(W.decode(t))}))}))},z=(e,t)=>new Proxy(t,{get:(t,s)=>t.get(s)||t.set(s,q(e,s)).get(s),set:(e,t,s)=>!!e.set(t,s)}),{wait:C,waitAsync:H}=i;var Y=({parse:e,stringify:t,transform:s,interrupt:r}=JSON)=>{const n=((e,t)=>async(s,[r,n,a,o,c])=>{c&&(O=r);try{const r=await s(...o);if(void 0!==r){const s=e(t?t(r):r);U.set(n,s),a[1]=s.length}}finally{c&&(O=""),a[0]=1,R(a,0)}})(t,s),a=p(),o=new Map;let c="",i=C;if(C&&r){const{handler:e,timeout:t=42}=r;i=(s,r,n)=>{for(;"timed-out"===(n=C(s,r,0,t));)e();return n}}return M("message",(t=>{if(g(t,c)){const[r,l,...p]=t.data;switch(l){case 0:c=r,a.resolve({polyfill:P,transfer:L,proxy:z([c,k,b,S,!!C,e,P,x,s,C?(...e)=>({value:{then:t=>t(i(...e))}}):H],o)});break;case 2:o.size?_(n,o,p):setTimeout(_,0,n,o,p);break;case 1:((e,t)=>{const s=U.get(e);U.delete(e);for(let e=new Uint16Array(t.buffer),r=0,{length:n}=s;re.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;tinput
  • issue-26
  • issue-34
  • +
  • no-sab-or-sw
  • reflect
  • too-big
  • virtual-dom
  • diff --git a/package.json b/package.json index b0f4176..182c749 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "coincident", - "version": "2.0.0-rc1", + "version": "1.2.3", "description": "An Atomics based Proxy to simplify, and synchronize, Worker related tasks", "scripts": { "build": "node build/index.cjs && node build/constants.cjs && rollup --config build/dist.js && sabayon ./test/sw.js && npm run size", @@ -33,6 +33,6 @@ "dependencies": { "gc-hook": "^0.3.1", "js-proxy": "^0.4.3", - "sabayon": "^0.4.5" + "sabayon": "^0.5.0" } } diff --git a/src/main.js b/src/main.js index 1a9c36d..5aee217 100644 --- a/src/main.js +++ b/src/main.js @@ -49,12 +49,12 @@ export default /** @type {Coincident} */ ({ class Worker extends $Worker { constructor(url, options) { const map = new Map; + const results = new Map; super(url, options); this.proxy = createProxy( [ CHANNEL, - Int32Array, - SharedArrayBuffer, + bytes => new Int32Array(new SharedArrayBuffer(bytes)), ignore, false, parse, @@ -71,11 +71,11 @@ export default /** @type {Coincident} */ ({ const [_, ACTION, ...rest] = event.data; switch (ACTION) { case ACTION_WAIT: { - actionWait(waitLength, map, rest); + actionWait(waitLength, results, map, rest); break; } case ACTION_NOTIFY: { - actionFill(...rest); + actionFill(results, rest); break; } } diff --git a/src/shared.js b/src/shared.js index 767ec43..4f48892 100644 --- a/src/shared.js +++ b/src/shared.js @@ -18,14 +18,10 @@ const decoder = new TextDecoder('utf-16'); const buffers = new WeakSet; -/** - * @param {...Transferable} args - */ const transfer = (...args) => (buffers.add(args), args); let seppuku = ''; -const results = new Map; -const actionLength = (stringify, transform) => async (callback, [name, id, sb, args, isSync]) => { +const actionLength = (stringify, transform) => async (callback, results, [name, id, sb, args, isSync]) => { if (isSync) seppuku = name; try { const result = await callback(...args); @@ -41,18 +37,18 @@ const actionLength = (stringify, transform) => async (callback, [name, id, sb, a notify(sb, 0); } }; -const actionFill = (id, sb) => { +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, map, rest) => { +const actionWait = (waitLength, results, map, rest) => { const [name] = rest; const callback = map.get(name); if (!callback) throw new Error(`Unknown proxy.${name}()`); - waitLength(callback, rest); + waitLength(callback, results, rest); }; const warn = (name, seppuku) => setTimeout( @@ -65,8 +61,7 @@ let uid = 0; const invoke = ( [ CHANNEL, - Int32Array, - SharedArrayBuffer, + i32View, ignore, isSync, parse, @@ -84,14 +79,14 @@ const invoke = ( if (buffers.has(args.at(-1) || transfer)) buffers.delete(transfer = args.pop()); const data = ignore(transform ? args.map(transform) : args); - let sb = new Int32Array(new SharedArrayBuffer(I32_BYTES * 2)); + 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 = new Int32Array(new SharedArrayBuffer(bytes + (bytes % I32_BYTES))); + sb = i32View(bytes + (bytes % I32_BYTES)); postMessage([CHANNEL, ACTION_NOTIFY, id, sb]); return waitAsync(sb, 0).value.then(() =>{ const ui16a = new Uint16Array(sb.buffer); @@ -102,11 +97,23 @@ const invoke = ( }; const createProxy = (details, map) => new Proxy(map, { - get: (map, name) => ( - map.get(name) || - map.set(name, invoke(details, name)).get(name) + 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) ), - set: (map, name, callback) => !!map.set(name, callback), }); export { diff --git a/src/ts.js b/src/ts.js index 2c4c8ef..ed18819 100644 --- a/src/ts.js +++ b/src/ts.js @@ -1,7 +1,11 @@ -// this is here just to please TS ( it disappears once built ) +// 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 index 798bf4e..f9a99ca 100644 --- a/src/window/constants.js +++ b/src/window/constants.js @@ -1,3 +1,4 @@ -const CHANNEL = '029d89be-c1c3-4993-a5e4-1b211947c69e'; +// ⚠️ 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 index ec5e098..bbf5a8c 100644 --- a/src/window/events.js +++ b/src/window/events.js @@ -1,11 +1,14 @@ const { addEventListener } = EventTarget.prototype; -const eventsHandler = new WeakMap(); -Reflect.defineProperty(EventTarget.prototype, "addEventListener", { +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) eventsHandler.set(this, (map = new Map())); + if (!map) { + map = new Map; + eventsHandler.set(this, map); + } map.set(type, [].concat(invoke)); delete options[0].invoke; } diff --git a/src/window/main.js b/src/window/main.js index 38751ae..34a37dd 100644 --- a/src/window/main.js +++ b/src/window/main.js @@ -36,7 +36,6 @@ const { isArray } = Array; export default /** @type {import('../main.js').Coincident} */ options => { const exports = coincident(options); - const { Worker: $Worker } = exports; const toEntry = value => { const TYPE = typeof value; @@ -53,12 +52,12 @@ export default /** @type {import('../main.js').Coincident} */ options => { } }; - class Worker extends $Worker { + class Worker extends exports.Worker { constructor(url, options) { const { proxy } = super(url, options); const { [WORKER]: __worker__ } = proxy; - const proxies = new Map(); + const proxies = new Map; const onGC = ref => { proxies.delete(ref); __worker__(DESTRUCT, ref); @@ -88,7 +87,7 @@ export default /** @type {import('../main.js').Coincident} */ options => { fn = create(value, onGC, { token: false, return: function (...args) { - if (args.at(0) instanceof Event) handleEvent(...args); + if (args.length && args[0] instanceof Event) handleEvent(args[0]); return __worker__(APPLY, value, toEntry(this), args.map(toEntry)).then(fromEntry); } }); @@ -105,14 +104,6 @@ export default /** @type {import('../main.js').Coincident} */ options => { const asEntry = (method, target, args) => toEntry(method(target, ...args.map(fromEntry))); - const asDescriptor = (descriptor, asEntry) => { - const { get, set, value } = descriptor; - if (get) descriptor.get = asEntry(get); - if (set) descriptor.set = asEntry(set); - if (value) descriptor.value = asEntry(value); - return descriptor; - }; - proxy[MAIN] = (TRAP, ref, ...args) => { if (TRAP === DESTRUCT) drop(ref); else { @@ -124,8 +115,14 @@ export default /** @type {import('../main.js').Coincident} */ options => { return toEntry(method(target, name, descriptor)); } case GET_OWN_PROPERTY_DESCRIPTOR: { - const value = method(target, ...args.map(fromEntry)); - return [numeric[value ? OBJECT : UNDEFINED], value && asDescriptor(value, toEntry)]; + 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); diff --git a/src/window/worker.js b/src/window/worker.js index 0a1fb8a..0ff8597 100644 --- a/src/window/worker.js +++ b/src/window/worker.js @@ -34,7 +34,7 @@ const { [APPLY]: apply } = Reflect; /** * @callback Coincident * @param {import('../worker.js').WorkerOptions} [options] - * @returns {Promise<{polyfill: boolean, transfer: (...args: Transferable[]) => Transferable[], proxy: {}, window: Window, isWindowProxy: (value: any) => boolean}>} + * @returns {Promise<{polyfill: boolean, sync: boolean, transfer: (...args: Transferable[]) => Transferable[], proxy: {}, window: Window, isWindowProxy: (value: any) => boolean}>} */ export default /** @type {Coincident} */ async options => { @@ -42,7 +42,7 @@ export default /** @type {Coincident} */ async options => { const $ = options?.transform || ((o) => o); const { [MAIN]: __main__ } = exports.proxy; - const proxies = new Map(); + const proxies = new Map; const proxied = (value, proxy) => { let ref = proxies.get(value)?.deref(); if (!ref) proxies.set(value, new WeakRef((ref = proxy(value)))); @@ -122,7 +122,7 @@ export default /** @type {Coincident} */ async options => { }, }; - let definition = { + const definition = { object: handler, array: handler, function: { @@ -150,6 +150,11 @@ export default /** @type {Coincident} */ async options => { 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 diff --git a/src/worker.js b/src/worker.js index 4fd6e79..cc3d5fa 100644 --- a/src/worker.js +++ b/src/worker.js @@ -39,7 +39,7 @@ const { wait, waitAsync } = Atomics; /** * @callback Coincident * @param {WorkerOptions} [options] - * @returns {Promise<{polyfill: boolean, transfer: (...args: Transferable[]) => Transferable[], proxy: {}}>} + * @returns {Promise<{polyfill: boolean, sync: boolean, transfer: (...args: Transferable[]) => Transferable[], proxy: {}}>} */ export default /** @type {Coincident} */ ({ @@ -52,6 +52,7 @@ export default /** @type {Coincident} */ ({ const ready = withResolvers(); const map = new Map; + const results = new Map; let CHANNEL = ''; let waitSync = wait; @@ -69,22 +70,23 @@ export default /** @type {Coincident} */ ({ const [_, ACTION, ...rest] = event.data; switch (ACTION) { case ACTION_INIT: { + const sync = !!wait; CHANNEL = _; ready.resolve({ polyfill, + sync, transfer, proxy: createProxy( [ CHANNEL, - Int32Array, - SharedArrayBuffer, + bytes => new Int32Array(new SharedArrayBuffer(bytes)), ignore, - !!wait, + sync, parse, polyfill, postMessage, transform, - wait ? + sync ? (...args) => ({ value: { then: fn => fn(waitSync(...args)) } }) : waitAsync, ], @@ -95,12 +97,12 @@ export default /** @type {Coincident} */ ({ } case ACTION_WAIT: { // give the code a chance to finish running (serviceWorker mode) - if (!map.size) setTimeout(actionWait, 0, waitLength, map, rest); - else actionWait(waitLength, map, rest); + if (!map.size) setTimeout(actionWait, 0, waitLength, results, map, rest); + else actionWait(waitLength, results, map, rest); break; } case ACTION_NOTIFY: { - actionFill(...rest); + actionFill(results, rest); break; } } diff --git a/test/basic/worker.js b/test/basic/worker.js index 1ca5c4e..ce16ebe 100644 --- a/test/basic/worker.js +++ b/test/basic/worker.js @@ -1,8 +1,8 @@ import coincident from '../../dist/worker.js'; -const { proxy, polyfill } = await coincident(); +const { proxy, polyfill, sync } = await coincident(); -console.info('worker', { polyfill }); +console.table({ polyfill, sync }); proxy.log = (...args) => { console.info('worker', 'log', args); diff --git a/test/index.html b/test/index.html index 3275eb2..06ad220 100644 --- a/test/index.html +++ b/test/index.html @@ -13,6 +13,7 @@
  • input
  • issue-26
  • issue-34
  • +
  • no-sab-or-sw
  • reflect
  • too-big
  • virtual-dom
  • 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/window/worker.js b/test/window/worker.js index b770f95..1f42095 100644 --- a/test/window/worker.js +++ b/test/window/worker.js @@ -35,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') From dd499f94b4ff6d6162f629661c0463b2ff4b690e Mon Sep 17 00:00:00 2001 From: webreflection Date: Thu, 25 Jul 2024 13:38:24 +0200 Subject: [PATCH 3/3] 2.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 182c749..650dd28 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "coincident", - "version": "1.2.3", + "version": "2.0.0", "description": "An Atomics based Proxy to simplify, and synchronize, Worker related tasks", "scripts": { "build": "node build/index.cjs && node build/constants.cjs && rollup --config build/dist.js && sabayon ./test/sw.js && npm run size",