diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..08a52c7
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,27 @@
+name: CI
+
+on:
+ push:
+ pull_request:
+
+jobs:
+ node_tests:
+ name: Node tests
+ runs-on: ubuntu-24.04
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup Node
+ uses: actions/setup-node@v4
+ with:
+ node-version: "20"
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Build
+ run: npm run build
+
+ - name: Test
+ run: npm run test:run
diff --git a/.gitignore b/.gitignore
index a3d090e..bdc2f8e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,4 +4,3 @@
lib/
node_modules/
-package-lock.json
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..1381b98
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2021 Pau Marfany
+Copyright (c) 2026 Xe Iaso
+
+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 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 bc759b7..664fac1 100644
--- a/README.md
+++ b/README.md
@@ -1,46 +1,92 @@
# worker-polyfill
-A simple script that emulates web worker threads in non compatible browsers.
-The code will still be slow (single threaded) but you can keep you code consistent.
+A small polyfill that emulates the Dedicated [Web Worker API](https://developer.mozilla.org/en-US/docs/Web/API/Worker)
+in browsers that don't support it (Internet Explorer and other old browsers).
+The code is still single-threaded, but it lets you keep one consistent code
+path. Messages are structured-cloned and delivered asynchronously, matching
+the spec's observable behaviour.
-Usage:
-```js
-// You must check for compatibility before loading the polyfill
-if ( !Worker ) { require('worker-loader'); }
+## Install
+
+The polyfill installs itself as the global `Worker` **only if the browser has
+no native implementation**, so it is safe to include unconditionally:
+
+```html
+
```
-Workers can be loaded and used as usual:
+## Usage
+
+Workers are created and used as usual:
+
```js
-var worker = new Worker("your_script.js");
+var worker = new Worker("your_script.js");
-worker.onmessage = function(event) {
- alert("Got: " + event.data);
-};
+worker.onmessage = function (event) {
+ alert("Got: " + event.data);
+};
-worker.onerror = function(error) {
- alert("Worker error: " + error);
+worker.onerror = function (event) {
+ alert("Worker error: " + event.message);
};
-worker.postMessage("Hello World");
+worker.postMessage("Hello World");
```
-'addEventListener' methods are also supported:
+`addEventListener` is supported with full multi-listener semantics:
```js
-var worker = new Worker("your_script.js");
-
-worker.addEventListener("message", function(event) {
- alert("Got: " + event.data);
+worker.addEventListener("message", function (event) {
+ alert("Got: " + event.data);
});
-
-worker.addEventListener("error", function(error) {
- alert("Worker error: " + error);
+worker.addEventListener("error", function (event) {
+ alert("Worker error: " + event.message);
});
+```
-worker.postMessage("Hello World");
+Inside the worker script, the usual idioms work because the script runs in its
+own scope:
+
+```js
+// your_script.js
+self.onmessage = function (event) {
+ self.postMessage("echo: " + event.data);
+};
+// importScripts() is supported and runs synchronously
+// close() stops the worker
```
-- For more info on worker threads see
-https://developer.mozilla.org/En/Using_web_workers
+## Supported
+
+`postMessage` (structured-cloned, ordered), `terminate`, `close`,
+`addEventListener`/`removeEventListener`/`dispatchEvent`, `message`/`error`
+events, `importScripts` (synchronous), `self`/`name`.
+
+## Not supported
+
+Module workers (`type: "module"`), transferable objects, `blob:`/`data:` URLs,
+`credentials`, and real OS-thread parallelism. Pass plain, cloneable data.
+
+## Limitations
+
+`importScripts()` is synchronous and executes imported scripts immediately,
+but top-level `var`/`function` declarations in an imported script are NOT
+visible to the main worker script (or vice versa). Use `self.X = ...`
+assignments (which land on the worker scope) to share values across scripts
+loaded via `importScripts()`.
+
+The bare identifier `arguments` (and the internal parameter names
+`__worker_scope__` and `__worker_src__`) are shadowed inside top-level
+worker code due to the Function constructor wrapper—avoid using `arguments`
+as an identifier in worker scripts.
+
+## Development
+
+```bash
+npm install
+npm test # vitest + jsdom conformance suite
+npm run build # webpack UMD bundle into lib/
+```
+- For more on workers see https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
- Originally exported from Google Code (https://code.google.com/p/ie-web-worker/).
diff --git a/docs/superpowers/plans/2026-06-28-worker-polyfill-spec-conformance.md b/docs/superpowers/plans/2026-06-28-worker-polyfill-spec-conformance.md
new file mode 100644
index 0000000..40e8d4c
--- /dev/null
+++ b/docs/superpowers/plans/2026-06-28-worker-polyfill-spec-conformance.md
@@ -0,0 +1,1354 @@
+# Worker Polyfill Spec-Conformance Implementation Plan
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** Fix the wiring bugs in the Worker polyfill and bring its core surface up to the WHATWG/MDN Dedicated Worker spec (real EventTarget semantics, real message/error events, structured-clone messages, ordered delivery, a proper worker-side `self`/`close`/`name`, and synchronous `importScripts`), backed by a Vitest + jsdom conformance suite.
+
+**Architecture:** The polyfill keeps its core approach — fetch the worker script with synchronous `XHR` and `eval` it in-process (single-threaded fake worker). We split responsibilities into small modules: a deep-clone shim, event-object factories, a reusable `EventTarget` mixin used by *both* the `Worker` object and the worker scope, and a dedicated worker-scope builder. The worker script is evaluated inside its **own** scope object (so `self`, `postMessage`, `onmessage`, etc. resolve to the worker globals, not the `Worker` instance) via a sloppy-mode `Function`-constructor evaluator that uses `with`. Messages flow through FIFO queues drained on `setTimeout`, so ordering and async semantics match the spec.
+
+**Tech Stack:** TypeScript (target ES5), webpack 5 (UMD bundle), Vitest + jsdom for tests. Zero runtime dependencies.
+
+## Global Constraints
+
+- **No runtime dependencies.** The shipped bundle must stay dependency-free (testing deps are `devDependencies` only).
+- **IE / old-browser safe at runtime.** Source may use modern TS syntax (compiled to ES5), but must not call runtime APIs missing in IE11: no `Promise`, `Map`/`WeakMap`, `Array.from`, `structuredClone`, `MessageEvent`/`ErrorEvent` constructors, `Object.assign`, or arrow-function-only features at runtime. Use `for` loops, `indexOf`, `splice`, array-based bookkeeping.
+- **TypeScript:** `typescript@^6` (matches `package.json`). `tsconfig.json` stays `target: es5`, `module: commonjs`, `lib: ["es2015","dom","scripthost"]`, `strict: false`.
+- **Scope:** Dedicated Workers only. Out of scope: module workers (`type:"module"`), transferables, `blob:`/`data:` URLs, `credentials`. These must be accepted-but-ignored without throwing where the constructor signature allows them.
+- **The script evaluator must not assume strict mode is off in the surrounding module.** Use `new Function(...)` (sloppy-mode body) for any `with`-based evaluation.
+- **Author/license unchanged.** MIT, existing author field preserved.
+
+---
+
+## File Structure
+
+| File | Responsibility | Action |
+|---|---|---|
+| `src/utils.ts` | `isFunction`, `getHTTPObject`, `getGlobal`, `fetchScriptSync` | Modify |
+| `src/clone.ts` | `structuredCloneShim` — deep copy with cycle support | Create |
+| `src/events.ts` | `createMessageEvent`, `createErrorEvent`, `createMessageErrorEvent` + `PolyfillEvent` type | Create |
+| `src/event-target.ts` | `installEventTarget` mixin (multi-listener add/remove/dispatch + `on*` handlers) | Create |
+| `src/worker-scope.ts` | `createWorkerScope` — the DedicatedWorkerGlobalScope-like object + sloppy-mode evaluator | Create |
+| `src/worker-polyfill.ts` | `WorkerPolyfill` constructor (queues, terminate, error dispatch) + guarded global install | Rewrite |
+| `test/helpers/mockXHR.ts` | Fake synchronous `XMLHttpRequest` serving canned scripts | Create |
+| `test/*.test.ts` | Unit + integration conformance tests | Create |
+| `vitest.config.ts` | Vitest config (jsdom env) | Create |
+| `tsconfig.json` | Ensure `test/**` excluded from build | Modify |
+| `webpack.config.js` | Rename UMD global to `WorkerPolyfill` so it doesn't clobber the side-effect install | Modify |
+| `package.json` | Add `test`/`test:run` scripts + dev deps | Modify |
+| `README.md` | Document new behaviour | Modify |
+
+---
+
+## Task 1: Test harness (Vitest + jsdom + mock XHR)
+
+**Files:**
+- Create: `vitest.config.ts`
+- Create: `test/helpers/mockXHR.ts`
+- Create: `test/harness.test.ts`
+- Modify: `package.json`
+- Modify: `tsconfig.json:13` (exclude `test`)
+
+**Interfaces:**
+- Produces:
+ - `installMockXHR(): void` — replaces `globalThis.XMLHttpRequest` with the mock.
+ - `setScript(url: string, code: string): void` — register a script body for a URL.
+ - `failScript(url: string): void` — make a URL return HTTP 404.
+ - `resetScripts(): void` — clear registry.
+
+- [ ] **Step 1: Add dev dependencies**
+
+Run:
+```bash
+npm install --save-dev vitest@^3 jsdom@^25
+```
+Expected: `vitest` and `jsdom` appear under `devDependencies` in `package.json`.
+
+- [ ] **Step 2: Add test scripts to `package.json`**
+
+In `package.json`, add to the `"scripts"` object (keep existing `prebuild`/`build`):
+```json
+"test": "vitest",
+"test:run": "vitest run"
+```
+
+- [ ] **Step 3: Create `vitest.config.ts`**
+
+```ts
+import { defineConfig } from "vitest/config";
+
+export default defineConfig({
+ test: {
+ environment: "jsdom",
+ include: ["test/**/*.test.ts"],
+ },
+});
+```
+
+- [ ] **Step 4: Exclude `test` from the TS build**
+
+In `tsconfig.json`, change the `exclude` array (line 14) to:
+```json
+"exclude": ["node_modules", "lib", "test"]
+```
+
+- [ ] **Step 5: Create the mock XHR helper `test/helpers/mockXHR.ts`**
+
+```ts
+// A minimal synchronous XMLHttpRequest stand-in. The polyfill fetches
+// worker scripts with sync XHR; jsdom can't fetch arbitrary URLs, so tests
+// register script bodies here and the mock serves them.
+type ScriptMap = { [url: string]: string };
+
+let scripts: ScriptMap = {};
+let failUrls: string[] = [];
+
+class MockXHR {
+ status = 0;
+ readyState = 0;
+ responseText = "";
+ private url = "";
+
+ open(_method: string, url: string, _async?: boolean) {
+ this.url = url;
+ }
+
+ send(_body?: any) {
+ this.readyState = 4;
+ if (failUrls.indexOf(this.url) !== -1) {
+ this.status = 404;
+ this.responseText = "";
+ return;
+ }
+ if (Object.prototype.hasOwnProperty.call(scripts, this.url)) {
+ this.status = 200;
+ this.responseText = scripts[this.url];
+ } else {
+ this.status = 404;
+ this.responseText = "";
+ }
+ }
+}
+
+export function setScript(url: string, code: string): void {
+ scripts[url] = code;
+}
+
+export function failScript(url: string): void {
+ failUrls.push(url);
+}
+
+export function resetScripts(): void {
+ scripts = {};
+ failUrls = [];
+}
+
+export function installMockXHR(): void {
+ (globalThis as any).XMLHttpRequest = MockXHR as any;
+}
+```
+
+- [ ] **Step 6: Write a harness smoke test `test/harness.test.ts`**
+
+```ts
+import { describe, it, expect, beforeEach } from "vitest";
+import { installMockXHR, setScript, resetScripts } from "./helpers/mockXHR";
+
+describe("test harness", () => {
+ beforeEach(() => {
+ resetScripts();
+ installMockXHR();
+ });
+
+ it("serves a registered script over sync XHR", () => {
+ setScript("hello.js", "var x = 1;");
+ const xhr: any = new (globalThis as any).XMLHttpRequest();
+ xhr.open("GET", "hello.js", false);
+ xhr.send(null);
+ expect(xhr.readyState).toBe(4);
+ expect(xhr.status).toBe(200);
+ expect(xhr.responseText).toBe("var x = 1;");
+ });
+});
+```
+
+- [ ] **Step 7: Run the harness test**
+
+Run: `npx vitest run test/harness.test.ts`
+Expected: PASS (1 test).
+
+- [ ] **Step 8: Commit**
+
+```bash
+git add package.json package-lock.json vitest.config.ts tsconfig.json test/helpers/mockXHR.ts test/harness.test.ts
+git commit -m "test: add vitest + jsdom harness with mock XHR"
+```
+
+---
+
+## Task 2: `structuredCloneShim` (deep clone)
+
+**Files:**
+- Create: `src/clone.ts`
+- Create: `test/clone.test.ts`
+
+**Interfaces:**
+- Produces: `structuredCloneShim(value: any): any` — returns a deep copy of plain data (primitives, arrays, plain objects, `Date`, `RegExp`), preserving internal cyclic references. Functions/DOM nodes are copied by reference inside the object graph (best-effort; the polyfill's contract is plain data).
+
+- [ ] **Step 1: Write the failing test `test/clone.test.ts`**
+
+```ts
+import { describe, it, expect } from "vitest";
+import { structuredCloneShim } from "../src/clone";
+
+describe("structuredCloneShim", () => {
+ it("returns primitives unchanged", () => {
+ expect(structuredCloneShim(5)).toBe(5);
+ expect(structuredCloneShim("a")).toBe("a");
+ expect(structuredCloneShim(null)).toBe(null);
+ });
+
+ it("deep-copies objects so mutations do not leak", () => {
+ const src = { a: 1, nested: { b: 2 } };
+ const copy = structuredCloneShim(src);
+ copy.nested.b = 99;
+ expect(src.nested.b).toBe(2);
+ expect(copy.nested.b).toBe(99);
+ });
+
+ it("deep-copies arrays", () => {
+ const src = [1, [2, 3]];
+ const copy = structuredCloneShim(src);
+ copy[1][0] = 9;
+ expect(src[1][0]).toBe(2);
+ });
+
+ it("preserves cyclic references", () => {
+ const src: any = { name: "x" };
+ src.me = src;
+ const copy = structuredCloneShim(src);
+ expect(copy.me).toBe(copy);
+ expect(copy).not.toBe(src);
+ });
+
+ it("clones Date and RegExp", () => {
+ const d = structuredCloneShim(new Date(1000));
+ expect(d instanceof Date).toBe(true);
+ expect(d.getTime()).toBe(1000);
+ });
+});
+```
+
+- [ ] **Step 2: Run test to verify it fails**
+
+Run: `npx vitest run test/clone.test.ts`
+Expected: FAIL — cannot resolve `../src/clone`.
+
+- [ ] **Step 3: Implement `src/clone.ts`**
+
+```ts
+// Minimal structured-clone approximation for the Worker polyfill.
+// Handles primitives, arrays, plain objects, Date, RegExp, and cyclic
+// references using paired arrays (no Map/WeakMap, for IE compatibility).
+// Non-cloneable values (functions, DOM nodes) are kept by reference.
+const structuredCloneShim = (value: any, seen?: any[], copies?: any[]): any => {
+ if (value === null || typeof value !== "object") {
+ return value;
+ }
+
+ seen = seen || [];
+ copies = copies || [];
+
+ for (let i = 0; i < seen.length; i++) {
+ if (seen[i] === value) {
+ return copies[i];
+ }
+ }
+
+ if (value instanceof Date) {
+ return new Date(value.getTime());
+ }
+ if (value instanceof RegExp) {
+ return new RegExp(value.source, value.flags);
+ }
+
+ const out: any = Array.isArray(value) ? [] : {};
+ seen.push(value);
+ copies.push(out);
+
+ for (const key in value) {
+ if (Object.prototype.hasOwnProperty.call(value, key)) {
+ out[key] = structuredCloneShim(value[key], seen, copies);
+ }
+ }
+
+ return out;
+};
+
+export { structuredCloneShim };
+```
+
+- [ ] **Step 4: Run test to verify it passes**
+
+Run: `npx vitest run test/clone.test.ts`
+Expected: PASS (5 tests).
+
+- [ ] **Step 5: Commit**
+
+```bash
+git add src/clone.ts test/clone.test.ts
+git commit -m "feat: add structured-clone shim for postMessage"
+```
+
+---
+
+## Task 3: Event factories
+
+**Files:**
+- Create: `src/events.ts`
+- Create: `test/events.test.ts`
+
+**Interfaces:**
+- Produces:
+ - `PolyfillEvent` — interface: `{ type: string; target: any; currentTarget: any; [k: string]: any }`.
+ - `createMessageEvent(data: any, target: any): PolyfillEvent` — `type:"message"`, `.data`, `.origin:""`, `.lastEventId:""`, `.source:null`, `.ports:[]`.
+ - `createErrorEvent(error: any, target: any): PolyfillEvent` — `type:"error"`, `.message`, `.filename:""`, `.lineno:0`, `.colno:0`, `.error`.
+ - `createMessageErrorEvent(target: any): PolyfillEvent` — `type:"messageerror"`, `.data:null`.
+
+- [ ] **Step 1: Write the failing test `test/events.test.ts`**
+
+```ts
+import { describe, it, expect } from "vitest";
+import {
+ createMessageEvent,
+ createErrorEvent,
+ createMessageErrorEvent,
+} from "../src/events";
+
+describe("event factories", () => {
+ it("builds a message event with spec-shaped fields", () => {
+ const t = {};
+ const e = createMessageEvent({ hi: 1 }, t);
+ expect(e.type).toBe("message");
+ expect(e.data).toEqual({ hi: 1 });
+ expect(e.target).toBe(t);
+ expect(e.ports).toEqual([]);
+ expect(e.origin).toBe("");
+ });
+
+ it("builds an error event from an Error", () => {
+ const t = {};
+ const err = new Error("boom");
+ const e = createErrorEvent(err, t);
+ expect(e.type).toBe("error");
+ expect(e.message).toBe("boom");
+ expect(e.error).toBe(err);
+ expect(e.lineno).toBe(0);
+ });
+
+ it("builds an error event from a non-Error value", () => {
+ const e = createErrorEvent("plain", {});
+ expect(e.message).toBe("plain");
+ });
+
+ it("builds a messageerror event", () => {
+ const e = createMessageErrorEvent({});
+ expect(e.type).toBe("messageerror");
+ expect(e.data).toBe(null);
+ });
+});
+```
+
+- [ ] **Step 2: Run test to verify it fails**
+
+Run: `npx vitest run test/events.test.ts`
+Expected: FAIL — cannot resolve `../src/events`.
+
+- [ ] **Step 3: Implement `src/events.ts`**
+
+```ts
+// Lightweight event objects. Old browsers may lack the MessageEvent /
+// ErrorEvent constructors, so we build plain objects carrying the fields the
+// Worker API exposes.
+interface PolyfillEvent {
+ type: string;
+ target: any;
+ currentTarget: any;
+ [key: string]: any;
+}
+
+const createMessageEvent = (data: any, target: any): PolyfillEvent => {
+ return {
+ type: "message",
+ data: data,
+ target: target,
+ currentTarget: target,
+ origin: "",
+ lastEventId: "",
+ source: null,
+ ports: [],
+ };
+};
+
+const createErrorEvent = (error: any, target: any): PolyfillEvent => {
+ const message = error && error.message ? error.message : String(error);
+ return {
+ type: "error",
+ target: target,
+ currentTarget: target,
+ message: message,
+ filename: "",
+ lineno: 0,
+ colno: 0,
+ error: error,
+ };
+};
+
+const createMessageErrorEvent = (target: any): PolyfillEvent => {
+ return {
+ type: "messageerror",
+ target: target,
+ currentTarget: target,
+ data: null,
+ };
+};
+
+export {
+ PolyfillEvent,
+ createMessageEvent,
+ createErrorEvent,
+ createMessageErrorEvent,
+};
+```
+
+- [ ] **Step 4: Run test to verify it passes**
+
+Run: `npx vitest run test/events.test.ts`
+Expected: PASS (4 tests).
+
+- [ ] **Step 5: Commit**
+
+```bash
+git add src/events.ts test/events.test.ts
+git commit -m "feat: add message/error event factories"
+```
+
+---
+
+## Task 4: `installEventTarget` mixin
+
+**Files:**
+- Create: `src/event-target.ts`
+- Create: `test/event-target.test.ts`
+
+**Interfaces:**
+- Consumes: `isFunction` from `./utils`; `PolyfillEvent` from `./events`.
+- Produces:
+ - `EventTargetLike` — interface: `{ addEventListener(type,cb): void; removeEventListener(type,cb): void; dispatchEvent(event): boolean }`.
+ - `installEventTarget(host: any): EventTargetLike` — attaches `addEventListener`/`removeEventListener`/`dispatchEvent` to `host`; `dispatchEvent` invokes both the `host["on"+type]` handler (if a function) and every registered listener, each called with `host` as `this`.
+
+- [ ] **Step 1: Write the failing test `test/event-target.test.ts`**
+
+```ts
+import { describe, it, expect } from "vitest";
+import { installEventTarget } from "../src/event-target";
+
+describe("installEventTarget", () => {
+ it("dispatches to multiple listeners", () => {
+ const host: any = {};
+ installEventTarget(host);
+ const calls: string[] = [];
+ host.addEventListener("message", () => calls.push("a"));
+ host.addEventListener("message", () => calls.push("b"));
+ host.dispatchEvent({ type: "message", target: null, currentTarget: null });
+ expect(calls).toEqual(["a", "b"]);
+ });
+
+ it("also invokes the on handler property", () => {
+ const host: any = {};
+ installEventTarget(host);
+ let got = "";
+ host.onmessage = () => (got = "handler");
+ host.dispatchEvent({ type: "message", target: null, currentTarget: null });
+ expect(got).toBe("handler");
+ });
+
+ it("removeEventListener stops a listener", () => {
+ const host: any = {};
+ installEventTarget(host);
+ const calls: string[] = [];
+ const fn = () => calls.push("x");
+ host.addEventListener("message", fn);
+ host.removeEventListener("message", fn);
+ host.dispatchEvent({ type: "message", target: null, currentTarget: null });
+ expect(calls).toEqual([]);
+ });
+
+ it("does not register the same listener twice", () => {
+ const host: any = {};
+ installEventTarget(host);
+ let n = 0;
+ const fn = () => n++;
+ host.addEventListener("message", fn);
+ host.addEventListener("message", fn);
+ host.dispatchEvent({ type: "message", target: null, currentTarget: null });
+ expect(n).toBe(1);
+ });
+
+ it("sets target/currentTarget on the event", () => {
+ const host: any = {};
+ installEventTarget(host);
+ let seen: any = null;
+ host.addEventListener("message", (e: any) => (seen = e));
+ host.dispatchEvent({ type: "message", target: null, currentTarget: null });
+ expect(seen.currentTarget).toBe(host);
+ expect(seen.target).toBe(host);
+ });
+});
+```
+
+- [ ] **Step 2: Run test to verify it fails**
+
+Run: `npx vitest run test/event-target.test.ts`
+Expected: FAIL — cannot resolve `../src/event-target`.
+
+- [ ] **Step 3: Implement `src/event-target.ts`**
+
+```ts
+import { isFunction } from "./utils";
+import { PolyfillEvent } from "./events";
+
+// A minimal EventTarget that also supports legacy `on` handler
+// properties. Both the Worker (parent) object and the worker global scope
+// use this, giving them spec-style multi-listener behaviour.
+interface EventTargetLike {
+ addEventListener: (type: string, callback: any) => void;
+ removeEventListener: (type: string, callback: any) => void;
+ dispatchEvent: (event: PolyfillEvent) => boolean;
+}
+
+const installEventTarget = (host: any): EventTargetLike => {
+ const listeners: { [type: string]: any[] } = {};
+
+ host.addEventListener = function (type: string, callback: any) {
+ if (!isFunction(callback)) {
+ return;
+ }
+ if (!listeners[type]) {
+ listeners[type] = [];
+ }
+ if (listeners[type].indexOf(callback) === -1) {
+ listeners[type].push(callback);
+ }
+ };
+
+ host.removeEventListener = function (type: string, callback: any) {
+ const list = listeners[type];
+ if (!list) {
+ return;
+ }
+ const idx = list.indexOf(callback);
+ if (idx !== -1) {
+ list.splice(idx, 1);
+ }
+ };
+
+ host.dispatchEvent = function (event: PolyfillEvent) {
+ event.target = event.target || host;
+ event.currentTarget = host;
+
+ const handler = host["on" + event.type];
+ if (isFunction(handler)) {
+ handler.call(host, event);
+ }
+
+ const list = listeners[event.type];
+ if (list) {
+ // Snapshot so a listener removing another mid-dispatch is safe.
+ const snapshot = list.slice();
+ for (let i = 0; i < snapshot.length; i++) {
+ snapshot[i].call(host, event);
+ }
+ }
+ return true;
+ };
+
+ return host as EventTargetLike;
+};
+
+export { EventTargetLike, installEventTarget };
+```
+
+- [ ] **Step 4: Run test to verify it passes**
+
+Run: `npx vitest run test/event-target.test.ts`
+Expected: PASS (5 tests).
+
+- [ ] **Step 5: Commit**
+
+```bash
+git add src/event-target.ts test/event-target.test.ts
+git commit -m "feat: add EventTarget mixin with multi-listener + on* support"
+```
+
+---
+
+## Task 5: `utils.ts` — global accessor + synchronous fetch
+
+**Files:**
+- Modify: `src/utils.ts`
+- Create: `test/utils.test.ts`
+
+**Interfaces:**
+- Consumes: nothing new.
+- Produces (additions; keep existing `isFunction`, `getHTTPObject`):
+ - `getGlobal(): any` — returns the global object (`globalThis` / `self` / `window`), IE-safe.
+ - `fetchScriptSync(url: string): string` — synchronous GET; returns `responseText` on success, throws `Error` on load failure (no object, non-`200`-ish status, or 404/500).
+
+- [ ] **Step 1: Write the failing test `test/utils.test.ts`**
+
+```ts
+import { describe, it, expect, beforeEach } from "vitest";
+import { fetchScriptSync, getGlobal } from "../src/utils";
+import { installMockXHR, setScript, failScript, resetScripts } from "./helpers/mockXHR";
+
+describe("utils", () => {
+ beforeEach(() => {
+ resetScripts();
+ installMockXHR();
+ });
+
+ it("getGlobal returns an object with setTimeout", () => {
+ const g = getGlobal();
+ expect(typeof g.setTimeout).toBe("function");
+ });
+
+ it("fetchScriptSync returns the script body", () => {
+ setScript("a.js", "var a = 1;");
+ expect(fetchScriptSync("a.js")).toBe("var a = 1;");
+ });
+
+ it("fetchScriptSync throws on a failed load", () => {
+ failScript("missing.js");
+ expect(() => fetchScriptSync("missing.js")).toThrow();
+ });
+});
+```
+
+- [ ] **Step 2: Run test to verify it fails**
+
+Run: `npx vitest run test/utils.test.ts`
+Expected: FAIL — `fetchScriptSync`/`getGlobal` are not exported.
+
+- [ ] **Step 3: Rewrite `src/utils.ts`**
+
+```ts
+const isFunction = (f: any) => {
+ return typeof f === "function";
+};
+
+/* HTTP Request */
+const getHTTPObject = (): any => {
+ let xmlhttp: any;
+ try {
+ xmlhttp = new XMLHttpRequest();
+ } catch (e) {
+ try {
+ // @ts-ignore - ActiveXObject only exists in old IE
+ xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
+ } catch (e2) {
+ xmlhttp = false;
+ }
+ }
+ return xmlhttp;
+};
+
+// Resolve the global object across environments (browser, worker, Node, IE).
+const getGlobal = (): any => {
+ if (typeof globalThis !== "undefined") {
+ return globalThis;
+ }
+ if (typeof self !== "undefined") {
+ return self;
+ }
+ // @ts-ignore - window exists in browsers
+ if (typeof window !== "undefined") {
+ // @ts-ignore
+ return window;
+ }
+ return {};
+};
+
+// Fetch a script synchronously and return its source text. Throws on failure
+// so callers can surface an `error` event.
+const fetchScriptSync = (url: string): string => {
+ const http = getHTTPObject();
+ if (!http) {
+ throw new Error("No XMLHttpRequest available to load: " + url);
+ }
+ http.open("GET", url, false);
+ http.send(null);
+
+ const ok =
+ http.readyState === 4 &&
+ http.status !== 404 &&
+ http.status !== 500;
+
+ if (!ok) {
+ throw new Error(
+ "Failed to load worker script: " + url + " (status " + http.status + ")",
+ );
+ }
+ return http.responseText;
+};
+
+export { isFunction, getHTTPObject, getGlobal, fetchScriptSync };
+```
+
+- [ ] **Step 4: Run test to verify it passes**
+
+Run: `npx vitest run test/utils.test.ts`
+Expected: PASS (3 tests).
+
+- [ ] **Step 5: Commit**
+
+```bash
+git add src/utils.ts test/utils.test.ts
+git commit -m "feat: add getGlobal and fetchScriptSync helpers"
+```
+
+---
+
+## Task 6: `createWorkerScope` (worker-side global)
+
+**Files:**
+- Create: `src/worker-scope.ts`
+- Create: `test/worker-scope.test.ts`
+
+**Interfaces:**
+- Consumes: `fetchScriptSync` from `./utils`; `installEventTarget` from `./event-target`; `createMessageEvent` from `./events`; `structuredCloneShim` from `./clone`.
+- Produces:
+ - `WorkerScope` — interface with `self`, `name`, `onmessage`, `onmessageerror`, `onerror`, `postMessage(data)`, `importScripts(...urls)`, `close()`, `addEventListener`, `removeEventListener`, `dispatchEvent`, `__deliver(data)`, `__evalScript(code)`.
+ - `createWorkerScope(name: string, toParent: (data:any)=>void, onClose: ()=>void): WorkerScope` — builds the scope. `postMessage` clones then calls `toParent`. `__deliver` dispatches a `message` event into the scope. `__evalScript` runs code with the scope as the variable environment (bare `self`/`postMessage`/`onmessage` resolve to scope members).
+
+- [ ] **Step 1: Write the failing test `test/worker-scope.test.ts`**
+
+```ts
+import { describe, it, expect } from "vitest";
+import { createWorkerScope } from "../src/worker-scope";
+
+describe("createWorkerScope", () => {
+ it("self refers to the scope itself", () => {
+ const scope = createWorkerScope("", () => {}, () => {});
+ expect(scope.self).toBe(scope);
+ });
+
+ it("evaluated code can set self.onmessage and receive __deliver", () => {
+ const out: any[] = [];
+ const scope = createWorkerScope("", (d) => out.push(d), () => {});
+ scope.__evalScript("self.onmessage = function(e){ self.postMessage(e.data); };");
+ scope.__deliver("ping");
+ expect(out).toEqual(["ping"]);
+ });
+
+ it("bare onmessage/postMessage identifiers resolve to the scope", () => {
+ const out: any[] = [];
+ const scope = createWorkerScope("", (d) => out.push(d), () => {});
+ scope.__evalScript("onmessage = function(e){ postMessage(e.data + '!'); };");
+ scope.__deliver("hey");
+ expect(out).toEqual(["hey!"]);
+ });
+
+ it("postMessage clones the payload", () => {
+ const out: any[] = [];
+ const scope = createWorkerScope("", (d) => out.push(d), () => {});
+ const obj = { n: 1 };
+ scope.postMessage(obj);
+ obj.n = 2;
+ expect(out[0].n).toBe(1);
+ });
+
+ it("close() invokes the onClose callback", () => {
+ let closed = false;
+ const scope = createWorkerScope("", () => {}, () => (closed = true));
+ scope.__evalScript("close();");
+ expect(closed).toBe(true);
+ });
+
+ it("exposes the worker name", () => {
+ const scope = createWorkerScope("worker-1", () => {}, () => {});
+ expect(scope.name).toBe("worker-1");
+ });
+});
+```
+
+- [ ] **Step 2: Run test to verify it fails**
+
+Run: `npx vitest run test/worker-scope.test.ts`
+Expected: FAIL — cannot resolve `../src/worker-scope`.
+
+- [ ] **Step 3: Implement `src/worker-scope.ts`**
+
+```ts
+import { fetchScriptSync } from "./utils";
+import { installEventTarget } from "./event-target";
+import { createMessageEvent } from "./events";
+import { structuredCloneShim } from "./clone";
+
+interface WorkerScope {
+ self: WorkerScope;
+ name: string;
+ onmessage: any;
+ onmessageerror: any;
+ onerror: any;
+ postMessage: (data: any) => void;
+ importScripts: (...urls: string[]) => void;
+ close: () => void;
+ addEventListener: (type: string, cb: any) => void;
+ removeEventListener: (type: string, cb: any) => void;
+ dispatchEvent: (event: any) => boolean;
+ __deliver: (data: any) => void;
+ __evalScript: (code: string) => void;
+}
+
+// Evaluate worker code with `scope` as its variable environment. `with` is
+// illegal in strict mode, but a Function-constructor body is sloppy mode
+// regardless of how the surrounding module is compiled, so bare identifiers
+// (self, postMessage, onmessage, importScripts, close, ...) resolve to the
+// scope object. Direct `eval` runs in this augmented environment.
+// NOTE: the parameter names below leak into worker code as identifiers; they
+// are deliberately obscure to avoid collisions.
+const runWithScope: (scope: any, __worker_src__: string) => void = new Function(
+ "__worker_scope__",
+ "__worker_src__",
+ "with (__worker_scope__) { eval(__worker_src__); }",
+) as any;
+
+// Builds the worker-side global scope (a DedicatedWorkerGlobalScope-like
+// object). `toParent` is called when the worker posts a message out; `onClose`
+// is called when the worker calls close().
+const createWorkerScope = (
+ name: string,
+ toParent: (data: any) => void,
+ onClose: () => void,
+): WorkerScope => {
+ const scope = {} as WorkerScope;
+ installEventTarget(scope);
+
+ scope.self = scope;
+ scope.name = name || "";
+ scope.onmessage = null;
+ scope.onmessageerror = null;
+ scope.onerror = null;
+
+ scope.postMessage = function (data: any) {
+ toParent(structuredCloneShim(data));
+ };
+
+ scope.importScripts = function () {
+ const urls = Array.prototype.slice.call(arguments);
+ for (let i = 0; i < urls.length; i++) {
+ scope.__evalScript(fetchScriptSync(urls[i]));
+ }
+ };
+
+ scope.close = function () {
+ onClose();
+ };
+
+ // Deliver a parent->worker message as a `message` event inside the scope.
+ scope.__deliver = function (data: any) {
+ scope.dispatchEvent(createMessageEvent(data, scope));
+ };
+
+ scope.__evalScript = function (code: string) {
+ runWithScope(scope, code);
+ };
+
+ return scope;
+};
+
+export { WorkerScope, createWorkerScope };
+```
+
+- [ ] **Step 4: Run test to verify it passes**
+
+Run: `npx vitest run test/worker-scope.test.ts`
+Expected: PASS (6 tests).
+
+- [ ] **Step 5: Commit**
+
+```bash
+git add src/worker-scope.ts test/worker-scope.test.ts
+git commit -m "feat: add worker scope with isolated self and sync importScripts"
+```
+
+---
+
+## Task 7: `WorkerPolyfill` constructor (rewrite)
+
+**Files:**
+- Rewrite: `src/worker-polyfill.ts`
+- Create: `test/worker-polyfill.test.ts`
+
+**Interfaces:**
+- Consumes: `fetchScriptSync`, `getGlobal` from `./utils`; `installEventTarget` from `./event-target`; `createMessageEvent`, `createErrorEvent` from `./events`; `structuredCloneShim` from `./clone`; `createWorkerScope`, `WorkerScope` from `./worker-scope`.
+- Produces:
+ - `WorkerPolyfill` — constructor `new WorkerPolyfill(scriptFile: string, options?: { type?; name?; credentials? })`. Instance is an `EventTarget` with `postMessage(data)`, `terminate()`, and `on(message|error|messageerror)`. Parent→worker delivery is FIFO and async (`setTimeout`); worker→parent delivery is async. `terminate()` and worker-side `close()` stop all further delivery. Load/eval failures dispatch an async `error` event.
+ - Side effect on import: installs `WorkerPolyfill` as the global `Worker` **only if no native `Worker` exists**.
+
+- [ ] **Step 1: Write the failing test `test/worker-polyfill.test.ts`**
+
+```ts
+import { describe, it, expect, beforeEach, vi } from "vitest";
+import { installMockXHR, setScript, failScript, resetScripts } from "./helpers/mockXHR";
+import { WorkerPolyfill } from "../src/worker-polyfill";
+
+const makeWorker = (file: string, opts?: any) =>
+ new (WorkerPolyfill as any)(file, opts);
+
+describe("WorkerPolyfill", () => {
+ beforeEach(() => {
+ resetScripts();
+ installMockXHR();
+ vi.useFakeTimers();
+ });
+
+ it("echoes a message using the self.* idiom", () => {
+ setScript("echo.js", "self.onmessage = function(e){ self.postMessage(e.data); };");
+ const w = makeWorker("echo.js");
+ const got: any[] = [];
+ w.onmessage = (e: any) => got.push(e.data);
+ w.postMessage("hi");
+ vi.runAllTimers();
+ expect(got).toEqual(["hi"]);
+ });
+
+ it("delivers a message event object, not a bare value", () => {
+ setScript("echo.js", "onmessage = function(e){ postMessage(e.data); };");
+ const w = makeWorker("echo.js");
+ let evt: any = null;
+ w.addEventListener("message", (e: any) => (evt = e));
+ w.postMessage("x");
+ vi.runAllTimers();
+ expect(evt.type).toBe("message");
+ expect(evt.data).toBe("x");
+ expect(evt.target).toBe(w);
+ });
+
+ it("preserves message order for rapid posts", () => {
+ setScript("echo.js", "onmessage = function(e){ postMessage(e.data); };");
+ const w = makeWorker("echo.js");
+ const got: any[] = [];
+ w.onmessage = (e: any) => got.push(e.data);
+ w.postMessage(1);
+ w.postMessage(2);
+ w.postMessage(3);
+ vi.runAllTimers();
+ expect(got).toEqual([1, 2, 3]);
+ });
+
+ it("structured-clones outgoing messages", () => {
+ setScript("echo.js", "onmessage = function(e){ postMessage(e.data); };");
+ const w = makeWorker("echo.js");
+ let received: any = null;
+ w.onmessage = (e: any) => (received = e.data);
+ const payload = { n: 1 };
+ w.postMessage(payload);
+ payload.n = 2;
+ vi.runAllTimers();
+ expect(received.n).toBe(1);
+ });
+
+ it("supports multiple message listeners", () => {
+ setScript("echo.js", "onmessage = function(e){ postMessage(e.data); };");
+ const w = makeWorker("echo.js");
+ const calls: string[] = [];
+ w.addEventListener("message", () => calls.push("a"));
+ w.addEventListener("message", () => calls.push("b"));
+ w.postMessage("x");
+ vi.runAllTimers();
+ expect(calls).toEqual(["a", "b"]);
+ });
+
+ it("fires the error event when a handler throws", () => {
+ setScript("bad.js", "onmessage = function(){ throw new Error('boom'); };");
+ const w = makeWorker("bad.js");
+ let err: any = null;
+ w.onerror = (e: any) => (err = e);
+ w.postMessage("go");
+ vi.runAllTimers();
+ expect(err).not.toBe(null);
+ expect(err.type).toBe("error");
+ expect(err.message).toBe("boom");
+ });
+
+ it("fires the error event when the script fails to load", () => {
+ failScript("missing.js");
+ const w = makeWorker("missing.js");
+ let err: any = null;
+ w.onerror = (e: any) => (err = e);
+ vi.runAllTimers();
+ expect(err).not.toBe(null);
+ expect(err.type).toBe("error");
+ });
+
+ it("fires the error event when top-level worker code throws", () => {
+ setScript("throws.js", "throw new Error('top-level');");
+ const w = makeWorker("throws.js");
+ let err: any = null;
+ w.onerror = (e: any) => (err = e);
+ vi.runAllTimers();
+ expect(err.message).toBe("top-level");
+ });
+
+ it("terminate() stops further delivery", () => {
+ setScript("echo.js", "onmessage = function(e){ postMessage(e.data); };");
+ const w = makeWorker("echo.js");
+ const got: any[] = [];
+ w.onmessage = (e: any) => got.push(e.data);
+ w.postMessage("a");
+ w.terminate();
+ w.postMessage("b");
+ vi.runAllTimers();
+ expect(got).toEqual([]);
+ });
+
+ it("worker close() stops further delivery", () => {
+ setScript("closer.js", "onmessage = function(){ close(); postMessage('after'); };");
+ const w = makeWorker("closer.js");
+ const got: any[] = [];
+ w.onmessage = (e: any) => got.push(e.data);
+ w.postMessage("go");
+ vi.runAllTimers();
+ expect(got).toEqual([]);
+ });
+
+ it("supports importScripts synchronously", () => {
+ setScript("dep.js", "var DEP_VALUE = 42;");
+ setScript("main.js", "importScripts('dep.js'); onmessage = function(){ postMessage(DEP_VALUE); };");
+ const w = makeWorker("main.js");
+ let got: any = null;
+ w.onmessage = (e: any) => (got = e.data);
+ w.postMessage("go");
+ vi.runAllTimers();
+ expect(got).toBe(42);
+ });
+});
+```
+
+- [ ] **Step 2: Run test to verify it fails**
+
+Run: `npx vitest run test/worker-polyfill.test.ts`
+Expected: FAIL — `WorkerPolyfill` not exported / behaviour mismatch.
+
+- [ ] **Step 3: Rewrite `src/worker-polyfill.ts`**
+
+```ts
+/*
+ A single-threaded Worker polyfill for IE and other old browsers.
+ Dedicated Workers only. The worker script is fetched with synchronous XHR
+ and eval'd in-process, inside its own scope object so that `self`,
+ `postMessage`, `onmessage`, etc. behave like a real worker global.
+ Remember: messages are structured-cloned, but this is NOT a real thread and
+ provides none of the native security isolation.
+*/
+import { fetchScriptSync, getGlobal } from "./utils";
+import { installEventTarget } from "./event-target";
+import { createMessageEvent, createErrorEvent } from "./events";
+import { structuredCloneShim } from "./clone";
+import { createWorkerScope, WorkerScope } from "./worker-scope";
+
+interface PolyfillWorkerOptions {
+ type?: string;
+ name?: string;
+ credentials?: string;
+}
+
+const WorkerPolyfill = function (
+ this: any,
+ scriptFile: string,
+ options?: PolyfillWorkerOptions,
+) {
+ const self = this;
+ const opts = options || {};
+ const glob = getGlobal();
+
+ installEventTarget(self);
+ self.onmessage = null;
+ self.onerror = null;
+ self.onmessageerror = null;
+
+ let terminated = false;
+ const inbox: any[] = [];
+ let scope: WorkerScope | null = null;
+
+ // worker -> parent
+ const toParent = function (data: any) {
+ if (terminated) {
+ return;
+ }
+ glob.setTimeout(function () {
+ if (terminated) {
+ return;
+ }
+ self.dispatchEvent(createMessageEvent(data, self));
+ }, 0);
+ };
+
+ const stop = function () {
+ terminated = true;
+ inbox.length = 0;
+ };
+
+ // Drain queued parent->worker messages one at a time, asynchronously, so
+ // ordering is preserved and delivery never blocks the caller.
+ const drain = function () {
+ if (terminated || !scope || inbox.length === 0) {
+ return;
+ }
+ const data = inbox.shift();
+ try {
+ scope.__deliver(data);
+ } catch (e) {
+ self.dispatchEvent(createErrorEvent(e, self));
+ }
+ if (!terminated && inbox.length > 0) {
+ glob.setTimeout(drain, 0);
+ }
+ };
+
+ // parent -> worker
+ self.postMessage = function (data: any) {
+ if (terminated) {
+ return;
+ }
+ inbox.push(structuredCloneShim(data));
+ glob.setTimeout(drain, 0);
+ };
+
+ self.terminate = function () {
+ stop();
+ };
+
+ // Load and start the worker. Failures (load or top-level eval) dispatch an
+ // async error event so handlers attached right after construction still fire.
+ try {
+ const code = fetchScriptSync(scriptFile);
+ scope = createWorkerScope(opts.name || "", toParent, stop);
+ scope.__evalScript(code);
+ } catch (e) {
+ glob.setTimeout(function () {
+ self.dispatchEvent(createErrorEvent(e, self));
+ }, 0);
+ }
+};
+
+// Install as the global Worker only when there is no native implementation.
+const glob = getGlobal();
+if (typeof glob.Worker === "undefined") {
+ glob.Worker = WorkerPolyfill;
+}
+
+export { WorkerPolyfill };
+```
+
+- [ ] **Step 4: Run test to verify it passes**
+
+Run: `npx vitest run test/worker-polyfill.test.ts`
+Expected: PASS (11 tests).
+
+- [ ] **Step 5: Run the full suite**
+
+Run: `npm run test:run`
+Expected: PASS — all test files green.
+
+- [ ] **Step 6: Commit**
+
+```bash
+git add src/worker-polyfill.ts test/worker-polyfill.test.ts
+git commit -m "feat: rewrite Worker constructor with queues, error events, terminate"
+```
+
+---
+
+## Task 8: Build config + bundle verification
+
+**Files:**
+- Modify: `webpack.config.js:26` (UMD library name)
+- Verify: `lib/` build output
+
+**Interfaces:**
+- Consumes: all `src` modules.
+- Produces: `lib/worker-polyfill.js` (+ `.min.js`) UMD bundle that installs the global `Worker` as a side effect and exposes `WorkerPolyfill` as the named UMD export.
+
+**Rationale:** The current UMD `library: 'Worker'` makes webpack assign `window.Worker = factory()`. Since the module now has a real export, that would set `window.Worker` to the exports object and clobber the guarded side-effect install. Renaming the UMD global to `WorkerPolyfill` lets the in-module guarded install own `window.Worker`.
+
+- [ ] **Step 1: Update the UMD library name in `webpack.config.js`**
+
+Change line 26 from:
+```js
+ library: 'Worker',
+```
+to:
+```js
+ library: 'WorkerPolyfill',
+```
+
+- [ ] **Step 2: Build the bundle**
+
+Run: `npm run build`
+Expected: webpack completes with no TypeScript errors; `lib/worker-polyfill.js` and `lib/worker-polyfill.min.js` are regenerated.
+
+- [ ] **Step 3: Smoke-check the built bundle installs a global Worker**
+
+Run:
+```bash
+node -e "var XHR=function(){};XHR.prototype.open=function(){};XHR.prototype.send=function(){this.readyState=4;this.status=200;this.responseText='';};global.XMLHttpRequest=XHR;global.window=global;require('./lib/worker-polyfill.js');console.log(typeof global.Worker);"
+```
+Expected output: `function`
+
+- [ ] **Step 4: Commit**
+
+```bash
+git add webpack.config.js lib
+git commit -m "build: expose WorkerPolyfill UMD export without clobbering global Worker"
+```
+
+---
+
+## Task 9: README update
+
+**Files:**
+- Modify: `README.md`
+
+**Interfaces:** none (docs only).
+
+- [ ] **Step 1: Update `README.md` to reflect the new behaviour**
+
+Replace the body of `README.md` with:
+
+````markdown
+# worker-polyfill
+
+A small polyfill that emulates the Dedicated [Web Worker API](https://developer.mozilla.org/en-US/docs/Web/API/Worker)
+in browsers that don't support it (Internet Explorer and other old browsers).
+The code is still single-threaded, but it lets you keep one consistent code
+path. Messages are structured-cloned and delivered asynchronously, matching
+the spec's observable behaviour.
+
+## Install
+
+The polyfill installs itself as the global `Worker` **only if the browser has
+no native implementation**, so it is safe to include unconditionally:
+
+```html
+
+```
+
+## Usage
+
+Workers are created and used as usual:
+
+```js
+var worker = new Worker("your_script.js");
+
+worker.onmessage = function (event) {
+ alert("Got: " + event.data);
+};
+
+worker.onerror = function (event) {
+ alert("Worker error: " + event.message);
+};
+
+worker.postMessage("Hello World");
+```
+
+`addEventListener` is supported with full multi-listener semantics:
+
+```js
+worker.addEventListener("message", function (event) {
+ alert("Got: " + event.data);
+});
+worker.addEventListener("error", function (event) {
+ alert("Worker error: " + event.message);
+});
+```
+
+Inside the worker script, the usual idioms work because the script runs in its
+own scope:
+
+```js
+// your_script.js
+self.onmessage = function (event) {
+ self.postMessage("echo: " + event.data);
+};
+// importScripts() is supported and runs synchronously
+// close() stops the worker
+```
+
+## Supported
+
+`postMessage` (structured-cloned, ordered), `terminate`, `close`,
+`addEventListener`/`removeEventListener`/`dispatchEvent`, `message`/`error`
+events, `importScripts` (synchronous), `self`/`name`.
+
+## Not supported
+
+Module workers (`type: "module"`), transferable objects, `blob:`/`data:` URLs,
+`credentials`, and real OS-thread parallelism. Pass plain, cloneable data.
+
+## Development
+
+```bash
+npm install
+npm test # vitest + jsdom conformance suite
+npm run build # webpack UMD bundle into lib/
+```
+
+- For more on workers see https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
+- Originally exported from Google Code (https://code.google.com/p/ie-web-worker/).
+````
+
+- [ ] **Step 2: Commit**
+
+```bash
+git add README.md
+git commit -m "docs: document spec-conformant behaviour and limitations"
+```
+
+---
+
+## Testing Process (summary)
+
+The suite is **test-first per task** (TDD) and layered:
+
+1. **Unit tests** for each pure module — `clone`, `events`, `event-target`, `utils` — verify behaviour in isolation against the spec's field shapes and semantics.
+2. **Worker-scope tests** verify the hardest fix (the `self` collision) directly: that `self.*` and bare identifiers both resolve to the worker scope, that `postMessage` clones, and that `close()` works.
+3. **Integration tests** (`worker-polyfill.test.ts`) drive the public `Worker` API end-to-end through the mock XHR, with **fake timers** (`vi.useFakeTimers()` + `vi.runAllTimers()`) to deterministically flush the async `setTimeout` delivery queues. These cover every bug from the audit:
+ - error event fires on handler throw / load failure / top-level throw (audit #1, #2)
+ - message ordering for rapid posts (audit #3)
+ - multiple `addEventListener` listeners (audit #4)
+ - `self.*` idiom works (audit #5)
+ - synchronous `importScripts` (audit #6)
+ - structured clone, real event objects, `terminate`, worker `close`.
+4. **Build verification** (`npm run build`) confirms the TS compiles to ES5 and the UMD bundle installs the global without clobbering a native `Worker`.
+
+Run everything with `npm run test:run`; run the production build with `npm run build`.
+
+---
+
+## Self-Review
+
+**Spec coverage** (audit findings → task):
+- #1 error event never fires → Task 7 (handler-throw + drain catch dispatch `error`). ✅
+- #2 silent construction failure → Task 5 (`fetchScriptSync` throws) + Task 7 (catch → async `error`). ✅
+- #3 message loss/duplication → Task 7 (FIFO `inbox` queue). ✅
+- #4 single addEventListener listener → Task 4 (`installEventTarget` multi-listener). ✅
+- #5 `self` collision → Task 6 (isolated scope + sloppy-mode `with` evaluator). ✅
+- #6 async importScripts + page pollution → Task 6 (sync XHR eval into scope). ✅
+- Missing surface (real MessageEvent/ErrorEvent → Task 3; structured clone → Task 2; terminate halts → Task 7; messageerror factory → Task 3; close/name/self → Task 6; remove/dispatchEvent → Task 4; feature-detection guard → Task 7). ✅
+- Out-of-scope (module workers, transferables, blob:/data:, credentials) documented as accepted-but-ignored / unsupported in README (Task 9) and Global Constraints. ✅
+
+**Placeholder scan:** No `TBD`/`TODO`/"add error handling"/"similar to" — every code and test step contains complete content. ✅
+
+**Type consistency:** `WorkerScope` members (`__deliver`, `__evalScript`, `postMessage`, `close`, `name`) are defined in Task 6 and consumed identically in Task 7. `installEventTarget`/`PolyfillEvent`/event factory signatures are consistent across Tasks 3, 4, 6, 7. `fetchScriptSync`/`getGlobal` defined in Task 5 and used in Tasks 6, 7. ✅
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..4edeb09
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,3979 @@
+{
+ "name": "@techaro/worker-polyfill",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "@techaro/worker-polyfill",
+ "version": "1.0.0",
+ "license": "MIT",
+ "devDependencies": {
+ "jsdom": "^25.0.1",
+ "rimraf": "^6.0.1",
+ "ts-loader": "^9.5.4",
+ "typescript": "^6.0.3",
+ "vitest": "^3.2.6",
+ "webpack": "^5.108.1",
+ "webpack-cli": "^7.1.0"
+ }
+ },
+ "node_modules/@asamuzakjp/css-color": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz",
+ "integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@csstools/css-calc": "^2.1.3",
+ "@csstools/css-color-parser": "^3.0.9",
+ "@csstools/css-parser-algorithms": "^3.0.4",
+ "@csstools/css-tokenizer": "^3.0.3",
+ "lru-cache": "^10.4.3"
+ }
+ },
+ "node_modules/@asamuzakjp/css-color/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/@csstools/color-helpers": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz",
+ "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT-0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@csstools/css-calc": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz",
+ "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@csstools/css-parser-algorithms": "^3.0.5",
+ "@csstools/css-tokenizer": "^3.0.4"
+ }
+ },
+ "node_modules/@csstools/css-color-parser": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz",
+ "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@csstools/color-helpers": "^5.1.0",
+ "@csstools/css-calc": "^2.1.4"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@csstools/css-parser-algorithms": "^3.0.5",
+ "@csstools/css-tokenizer": "^3.0.4"
+ }
+ },
+ "node_modules/@csstools/css-parser-algorithms": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz",
+ "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@csstools/css-tokenizer": "^3.0.4"
+ }
+ },
+ "node_modules/@csstools/css-tokenizer": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz",
+ "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@discoveryjs/json-ext": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-1.1.0.tgz",
+ "integrity": "sha512-Xc3VhU02wqZ1HvHRJUwL09HkZSTvidqY5Ya0NXBSYOxAp+Ln9dcJr9fySI+CkONzP3PekQo9WdzCv0PGER/mOA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.17.0"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz",
+ "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz",
+ "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz",
+ "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz",
+ "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz",
+ "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz",
+ "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz",
+ "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz",
+ "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz",
+ "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz",
+ "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz",
+ "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz",
+ "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz",
+ "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz",
+ "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz",
+ "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz",
+ "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz",
+ "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz",
+ "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz",
+ "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz",
+ "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz",
+ "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz",
+ "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz",
+ "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz",
+ "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz",
+ "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz",
+ "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.13",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "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/source-map": {
+ "version": "0.3.11",
+ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz",
+ "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==",
+ "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.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.31",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.2.tgz",
+ "integrity": "sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.2.tgz",
+ "integrity": "sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.2.tgz",
+ "integrity": "sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.2.tgz",
+ "integrity": "sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.2.tgz",
+ "integrity": "sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.2.tgz",
+ "integrity": "sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.2.tgz",
+ "integrity": "sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.2.tgz",
+ "integrity": "sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.2.tgz",
+ "integrity": "sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.2.tgz",
+ "integrity": "sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.2.tgz",
+ "integrity": "sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-musl": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.2.tgz",
+ "integrity": "sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.2.tgz",
+ "integrity": "sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-musl": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.2.tgz",
+ "integrity": "sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.2.tgz",
+ "integrity": "sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.2.tgz",
+ "integrity": "sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.2.tgz",
+ "integrity": "sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.2.tgz",
+ "integrity": "sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.2.tgz",
+ "integrity": "sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-openbsd-x64": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.2.tgz",
+ "integrity": "sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-openharmony-arm64": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.2.tgz",
+ "integrity": "sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.2.tgz",
+ "integrity": "sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.2.tgz",
+ "integrity": "sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.2.tgz",
+ "integrity": "sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.2.tgz",
+ "integrity": "sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@types/chai": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz",
+ "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/deep-eql": "*",
+ "assertion-error": "^2.0.1"
+ }
+ },
+ "node_modules/@types/deep-eql": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz",
+ "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
+ "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "26.0.1",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-26.0.1.tgz",
+ "integrity": "sha512-fc3KiUoBt6kie0N9bIW3E47vZsuaMf0PM2AaUpLCLT0s/LvX1nxAim6Fc049cNxODPpGm6qRAuUOB86SkRuPQw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~8.3.0"
+ }
+ },
+ "node_modules/@vitest/expect": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.6.tgz",
+ "integrity": "sha512-1+7q9BtaKzEmO+fmNT3kYvoNn5Y71XWAx2Q5HRim4tTVRQVRv4uJFAQ5FbK0OPUeNP/WmVCpxYxoJdvuHVjzBQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/chai": "^5.2.2",
+ "@vitest/spy": "3.2.6",
+ "@vitest/utils": "3.2.6",
+ "chai": "^5.2.0",
+ "tinyrainbow": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/mocker": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.6.tgz",
+ "integrity": "sha512-EZOrpDbkKotFAP7wPAQV1UIyoGOk4oX7ynWhBhLB7v+meMHbQhU16oPpIYGTTe4oFlhpryGpgpcZP/sin3hYuw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/spy": "3.2.6",
+ "estree-walker": "^3.0.3",
+ "magic-string": "^0.30.17"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "msw": "^2.4.9",
+ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0"
+ },
+ "peerDependenciesMeta": {
+ "msw": {
+ "optional": true
+ },
+ "vite": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@vitest/pretty-format": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.6.tgz",
+ "integrity": "sha512-lb7XXXzmm2h2ASzFnRvQpDo6onT1NmMJA3tkGTWiBFtRJ9lxGY3d3mm/Apt36gej2bkkOVLL/yTOtufDaFa/jA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tinyrainbow": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/runner": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.6.tgz",
+ "integrity": "sha512-HYcoSj1w5tcgUnzoF0HcyaAQjpA1gj9ftUJ7iSJSuipc02jW9gKkigwZbjFldAfYHA1fa8UZVRftdMY5msWM9Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/utils": "3.2.6",
+ "pathe": "^2.0.3",
+ "strip-literal": "^3.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/snapshot": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.6.tgz",
+ "integrity": "sha512-H+ZjNTWGpObenh0YnlBctAPnJSI20P81PL8BPzWpx54YXLLTm8hEsWawtcYLMrwvpK48hGxLLbCS+1KRXhsKhw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/pretty-format": "3.2.6",
+ "magic-string": "^0.30.17",
+ "pathe": "^2.0.3"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/spy": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.6.tgz",
+ "integrity": "sha512-oq6BbH68WzcWmwtBrU9nqLeaXTR4XwJF7FSLkKEZo4i6eoXcrxjcwSuTvWBIRUTC6VC72nXYunzqgZA+IKdtxg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tinyspy": "^4.0.3"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/utils": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.6.tgz",
+ "integrity": "sha512-lI23nIs4bnT3T8NIoh+vFaz5s2/DdP0Jgt2jxwgWljvwn82cLJtyi/If+fjFyoLMGIOz0U/fKvWE0d4jsNQEfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/pretty-format": "3.2.6",
+ "loupe": "^3.1.4",
+ "tinyrainbow": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@webassemblyjs/ast": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz",
+ "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@webassemblyjs/helper-numbers": "1.13.2",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2"
+ }
+ },
+ "node_modules/@webassemblyjs/floating-point-hex-parser": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz",
+ "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@webassemblyjs/helper-api-error": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz",
+ "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@webassemblyjs/helper-buffer": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz",
+ "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@webassemblyjs/helper-numbers": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz",
+ "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@webassemblyjs/floating-point-hex-parser": "1.13.2",
+ "@webassemblyjs/helper-api-error": "1.13.2",
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "node_modules/@webassemblyjs/helper-wasm-bytecode": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz",
+ "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@webassemblyjs/helper-wasm-section": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz",
+ "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-buffer": "1.14.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/wasm-gen": "1.14.1"
+ }
+ },
+ "node_modules/@webassemblyjs/ieee754": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz",
+ "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@xtuc/ieee754": "^1.2.0"
+ }
+ },
+ "node_modules/@webassemblyjs/leb128": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz",
+ "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "node_modules/@webassemblyjs/utf8": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz",
+ "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@webassemblyjs/wasm-edit": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz",
+ "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-buffer": "1.14.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/helper-wasm-section": "1.14.1",
+ "@webassemblyjs/wasm-gen": "1.14.1",
+ "@webassemblyjs/wasm-opt": "1.14.1",
+ "@webassemblyjs/wasm-parser": "1.14.1",
+ "@webassemblyjs/wast-printer": "1.14.1"
+ }
+ },
+ "node_modules/@webassemblyjs/wasm-gen": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz",
+ "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/ieee754": "1.13.2",
+ "@webassemblyjs/leb128": "1.13.2",
+ "@webassemblyjs/utf8": "1.13.2"
+ }
+ },
+ "node_modules/@webassemblyjs/wasm-opt": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz",
+ "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-buffer": "1.14.1",
+ "@webassemblyjs/wasm-gen": "1.14.1",
+ "@webassemblyjs/wasm-parser": "1.14.1"
+ }
+ },
+ "node_modules/@webassemblyjs/wasm-parser": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz",
+ "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-api-error": "1.13.2",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/ieee754": "1.13.2",
+ "@webassemblyjs/leb128": "1.13.2",
+ "@webassemblyjs/utf8": "1.13.2"
+ }
+ },
+ "node_modules/@webassemblyjs/wast-printer": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz",
+ "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@webassemblyjs/ast": "1.14.1",
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "node_modules/@xtuc/ieee754": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
+ "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@xtuc/long": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
+ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/acorn": {
+ "version": "8.17.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz",
+ "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-import-phases": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz",
+ "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "peerDependencies": {
+ "acorn": "^8.14.0"
+ }
+ },
+ "node_modules/agent-base": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
+ "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "8.20.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
+ "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ajv-formats": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
+ "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "ajv": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ajv-keywords": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
+ "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3"
+ },
+ "peerDependencies": {
+ "ajv": "^8.8.2"
+ }
+ },
+ "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/assertion-error": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
+ "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/balanced-match": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
+ "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.10.40",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.40.tgz",
+ "integrity": "sha512-BSSLZ9/Cjjv7Gtj5B68ZzXcXUg8iOf3fme+FCuh8rC/Go+Kmh8cox7M3A8dolou16s64QjLPOSdngh7GxXvkSw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.cjs"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "5.0.6",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
+ "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^4.0.2"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.28.4",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.4.tgz",
+ "integrity": "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "baseline-browser-mapping": "^2.10.38",
+ "caniuse-lite": "^1.0.30001799",
+ "electron-to-chromium": "^1.5.376",
+ "node-releases": "^2.0.48",
+ "update-browserslist-db": "^1.2.3"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "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/cac": {
+ "version": "6.7.14",
+ "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
+ "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001799",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz",
+ "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/chai": {
+ "version": "5.3.3",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz",
+ "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "assertion-error": "^2.0.1",
+ "check-error": "^2.1.1",
+ "deep-eql": "^5.0.1",
+ "loupe": "^3.1.0",
+ "pathval": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/check-error": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz",
+ "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 16"
+ }
+ },
+ "node_modules/chrome-trace-event": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz",
+ "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0"
+ }
+ },
+ "node_modules/clone-deep": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
+ "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-plain-object": "^2.0.4",
+ "kind-of": "^6.0.2",
+ "shallow-clone": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "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/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "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/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/cssstyle": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz",
+ "integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@asamuzakjp/css-color": "^3.2.0",
+ "rrweb-cssom": "^0.8.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/cssstyle/node_modules/rrweb-cssom": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz",
+ "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/data-urls": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz",
+ "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "whatwg-mimetype": "^4.0.0",
+ "whatwg-url": "^14.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decimal.js": {
+ "version": "10.6.0",
+ "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz",
+ "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/deep-eql": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz",
+ "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.380",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.380.tgz",
+ "integrity": "sha512-W6d5AbuEoRayO447cqrg6lKJIlscgRnnxOZl/08kfV71BQDoEBC7Wwis68z87LjyK6f4kWyTaubuDbhHKrZkbA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/enhanced-resolve": {
+ "version": "5.24.1",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.1.tgz",
+ "integrity": "sha512-7DdUaTjmNwMcH2gLr1qycesKII3BK4RLy/mdAb7x10Lq7bR4aNKHt1BR1ZALSv0rPM/hF5wYF0PhGop/rJm8vw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.4",
+ "tapable": "^2.3.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/entities": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
+ "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/envinfo": {
+ "version": "7.21.0",
+ "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.21.0.tgz",
+ "integrity": "sha512-Lw7I8Zp5YKHFCXL7+Dz95g4CcbMEpgvqZNNq3AmlT5XAV6CgAAk6gyAMqn2zjw08K9BHfcNuKrMiCPLByGafow==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "envinfo": "dist/cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-module-lexer": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz",
+ "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz",
+ "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz",
+ "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.28.1",
+ "@esbuild/android-arm": "0.28.1",
+ "@esbuild/android-arm64": "0.28.1",
+ "@esbuild/android-x64": "0.28.1",
+ "@esbuild/darwin-arm64": "0.28.1",
+ "@esbuild/darwin-x64": "0.28.1",
+ "@esbuild/freebsd-arm64": "0.28.1",
+ "@esbuild/freebsd-x64": "0.28.1",
+ "@esbuild/linux-arm": "0.28.1",
+ "@esbuild/linux-arm64": "0.28.1",
+ "@esbuild/linux-ia32": "0.28.1",
+ "@esbuild/linux-loong64": "0.28.1",
+ "@esbuild/linux-mips64el": "0.28.1",
+ "@esbuild/linux-ppc64": "0.28.1",
+ "@esbuild/linux-riscv64": "0.28.1",
+ "@esbuild/linux-s390x": "0.28.1",
+ "@esbuild/linux-x64": "0.28.1",
+ "@esbuild/netbsd-arm64": "0.28.1",
+ "@esbuild/netbsd-x64": "0.28.1",
+ "@esbuild/openbsd-arm64": "0.28.1",
+ "@esbuild/openbsd-x64": "0.28.1",
+ "@esbuild/openharmony-arm64": "0.28.1",
+ "@esbuild/sunos-x64": "0.28.1",
+ "@esbuild/win32-arm64": "0.28.1",
+ "@esbuild/win32-ia32": "0.28.1",
+ "@esbuild/win32-x64": "0.28.1"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estree-walker": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
+ "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0"
+ }
+ },
+ "node_modules/events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.x"
+ }
+ },
+ "node_modules/expect-type": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz",
+ "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz",
+ "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/flat": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "bin": {
+ "flat": "cli.js"
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz",
+ "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.4",
+ "mime-types": "^2.1.35"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "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/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/glob": {
+ "version": "13.0.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz",
+ "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "minimatch": "^10.2.2",
+ "minipass": "^7.1.3",
+ "path-scurry": "^2.0.2"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "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/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
+ "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/html-encoding-sniffer": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz",
+ "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "whatwg-encoding": "^3.1.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/http-proxy-agent": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
+ "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
+ "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/import-local": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz",
+ "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "pkg-dir": "^4.2.0",
+ "resolve-cwd": "^3.0.0"
+ },
+ "bin": {
+ "import-local-fixture": "fixtures/cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/interpret": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz",
+ "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.16.2",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz",
+ "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-plain-object": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "isobject": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-potential-custom-element-name": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
+ "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
+ "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/isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/jest-worker": {
+ "version": "27.5.1",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
+ "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ }
+ },
+ "node_modules/jest-worker/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz",
+ "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/jsdom": {
+ "version": "25.0.1",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz",
+ "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cssstyle": "^4.1.0",
+ "data-urls": "^5.0.0",
+ "decimal.js": "^10.4.3",
+ "form-data": "^4.0.0",
+ "html-encoding-sniffer": "^4.0.0",
+ "http-proxy-agent": "^7.0.2",
+ "https-proxy-agent": "^7.0.5",
+ "is-potential-custom-element-name": "^1.0.1",
+ "nwsapi": "^2.2.12",
+ "parse5": "^7.1.2",
+ "rrweb-cssom": "^0.7.1",
+ "saxes": "^6.0.0",
+ "symbol-tree": "^3.2.4",
+ "tough-cookie": "^5.0.0",
+ "w3c-xmlserializer": "^5.0.0",
+ "webidl-conversions": "^7.0.0",
+ "whatwg-encoding": "^3.1.1",
+ "whatwg-mimetype": "^4.0.0",
+ "whatwg-url": "^14.0.0",
+ "ws": "^8.18.0",
+ "xml-name-validator": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "canvas": "^2.11.2"
+ },
+ "peerDependenciesMeta": {
+ "canvas": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/loader-runner": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz",
+ "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.11.5"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/loupe": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz",
+ "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lru-cache": {
+ "version": "11.5.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz",
+ "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.21",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.5"
+ }
+ },
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/mime-db": {
+ "version": "1.54.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
+ "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
+ "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/mime-types/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/minimatch": {
+ "version": "10.2.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
+ "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "brace-expansion": "^5.0.5"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/minimizer-webpack-plugin": {
+ "version": "5.6.1",
+ "resolved": "https://registry.npmjs.org/minimizer-webpack-plugin/-/minimizer-webpack-plugin-5.6.1.tgz",
+ "integrity": "sha512-DoeAZz8Q1C1znwsUzej1fdoi4jCf7/+Em27ouLqfK/+3m8G+D7yDhUwrc3CNhjSzGUN1kn7Iv4sWmjflQHenpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "jest-worker": "^27.4.5",
+ "schema-utils": "^4.3.0",
+ "terser": "^5.31.1"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^5.1.0"
+ },
+ "peerDependenciesMeta": {
+ "@minify-html/node": {
+ "optional": true
+ },
+ "@swc/core": {
+ "optional": true
+ },
+ "@swc/css": {
+ "optional": true
+ },
+ "@swc/html": {
+ "optional": true
+ },
+ "clean-css": {
+ "optional": true
+ },
+ "cssnano": {
+ "optional": true
+ },
+ "csso": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ },
+ "html-minifier-terser": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "postcss": {
+ "optional": true
+ },
+ "uglify-js": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/minipass": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz",
+ "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.15",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz",
+ "integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/neo-async": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.50",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.50.tgz",
+ "integrity": "sha512-J6l92tKHX6w8Jy5nO1Vuc01NoIiRGi/d6qBKVxh+IQ8Cr3b6HbVNfKiF8ZpFKufTwpwxMmce2W3iQZ861ZRyTg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/nwsapi": {
+ "version": "2.2.24",
+ "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.24.tgz",
+ "integrity": "sha512-7YRhZ3jS45LwmSCT4b2sVFHt/WuovaktDU07QrtOBY2PXskss5a9jfmR9jptyumwXST+rFjrmppMY1KT/yn35A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/package-json-from-dist": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0"
+ },
+ "node_modules/parse5": {
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
+ "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "entities": "^6.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "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": "2.0.2",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz",
+ "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^11.0.0",
+ "minipass": "^7.1.2"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/pathe": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
+ "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/pathval": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz",
+ "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14.16"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "find-up": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.16",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.16.tgz",
+ "integrity": "sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.12",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/rechoir": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz",
+ "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "resolve": "^1.20.0"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ }
+ },
+ "node_modules/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.12",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz",
+ "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "is-core-module": "^2.16.1",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-cwd": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "6.1.3",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz",
+ "integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "glob": "^13.0.3",
+ "package-json-from-dist": "^1.0.1"
+ },
+ "bin": {
+ "rimraf": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.2.tgz",
+ "integrity": "sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "1.0.9"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.62.2",
+ "@rollup/rollup-android-arm64": "4.62.2",
+ "@rollup/rollup-darwin-arm64": "4.62.2",
+ "@rollup/rollup-darwin-x64": "4.62.2",
+ "@rollup/rollup-freebsd-arm64": "4.62.2",
+ "@rollup/rollup-freebsd-x64": "4.62.2",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.62.2",
+ "@rollup/rollup-linux-arm-musleabihf": "4.62.2",
+ "@rollup/rollup-linux-arm64-gnu": "4.62.2",
+ "@rollup/rollup-linux-arm64-musl": "4.62.2",
+ "@rollup/rollup-linux-loong64-gnu": "4.62.2",
+ "@rollup/rollup-linux-loong64-musl": "4.62.2",
+ "@rollup/rollup-linux-ppc64-gnu": "4.62.2",
+ "@rollup/rollup-linux-ppc64-musl": "4.62.2",
+ "@rollup/rollup-linux-riscv64-gnu": "4.62.2",
+ "@rollup/rollup-linux-riscv64-musl": "4.62.2",
+ "@rollup/rollup-linux-s390x-gnu": "4.62.2",
+ "@rollup/rollup-linux-x64-gnu": "4.62.2",
+ "@rollup/rollup-linux-x64-musl": "4.62.2",
+ "@rollup/rollup-openbsd-x64": "4.62.2",
+ "@rollup/rollup-openharmony-arm64": "4.62.2",
+ "@rollup/rollup-win32-arm64-msvc": "4.62.2",
+ "@rollup/rollup-win32-ia32-msvc": "4.62.2",
+ "@rollup/rollup-win32-x64-gnu": "4.62.2",
+ "@rollup/rollup-win32-x64-msvc": "4.62.2",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/rrweb-cssom": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz",
+ "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/saxes": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
+ "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "xmlchars": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=v12.22.7"
+ }
+ },
+ "node_modules/schema-utils": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz",
+ "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/json-schema": "^7.0.9",
+ "ajv": "^8.9.0",
+ "ajv-formats": "^2.1.1",
+ "ajv-keywords": "^5.1.0"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/shallow-clone": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
+ "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "kind-of": "^6.0.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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/siginfo": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
+ "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/source-map": {
+ "version": "0.7.6",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz",
+ "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "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/source-map-support/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/stackback": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
+ "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/std-env": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz",
+ "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/strip-literal": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz",
+ "integrity": "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "js-tokens": "^9.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "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/symbol-tree": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
+ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/tapable": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz",
+ "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/terser": {
+ "version": "5.48.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.48.0.tgz",
+ "integrity": "sha512-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@jridgewell/source-map": "^0.3.3",
+ "acorn": "^8.15.0",
+ "commander": "^2.20.0",
+ "source-map-support": "~0.5.20"
+ },
+ "bin": {
+ "terser": "bin/terser"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/tinybench": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
+ "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/tinyexec": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz",
+ "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.17",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
+ "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/tinypool": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz",
+ "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ }
+ },
+ "node_modules/tinyrainbow": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz",
+ "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/tinyspy": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.4.tgz",
+ "integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/tldts": {
+ "version": "6.1.86",
+ "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz",
+ "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tldts-core": "^6.1.86"
+ },
+ "bin": {
+ "tldts": "bin/cli.js"
+ }
+ },
+ "node_modules/tldts-core": {
+ "version": "6.1.86",
+ "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz",
+ "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/tough-cookie": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz",
+ "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "tldts": "^6.1.32"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/tr46": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz",
+ "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "punycode": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/ts-loader": {
+ "version": "9.6.2",
+ "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.6.2.tgz",
+ "integrity": "sha512-R4iuczmtgxvtuI556s+hTZ6/7Ee03VCAk/l/M8LY1OAsUgB7YydsCxkgq9D9pKRaD7GJqUi2u8fp9zZP/ufjKA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "picomatch": "^4.0.0",
+ "source-map": "^0.7.4"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "loader-utils": "*",
+ "typescript": "*",
+ "webpack": "^4.0.0 || ^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "loader-utils": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/typescript": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz",
+ "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz",
+ "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
+ "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/vite": {
+ "version": "7.3.6",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.6.tgz",
+ "integrity": "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "^0.27.0 || ^0.28.0",
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.3",
+ "postcss": "^8.5.6",
+ "rollup": "^4.43.0",
+ "tinyglobby": "^0.2.15"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^20.19.0 || >=22.12.0",
+ "jiti": ">=1.21.0",
+ "less": "^4.0.0",
+ "lightningcss": "^1.21.0",
+ "sass": "^1.70.0",
+ "sass-embedded": "^1.70.0",
+ "stylus": ">=0.54.8",
+ "sugarss": "^5.0.0",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vite-node": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz",
+ "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cac": "^6.7.14",
+ "debug": "^4.4.1",
+ "es-module-lexer": "^1.7.0",
+ "pathe": "^2.0.3",
+ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0"
+ },
+ "bin": {
+ "vite-node": "vite-node.mjs"
+ },
+ "engines": {
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/vite-node/node_modules/es-module-lexer": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
+ "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/vitest": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.6.tgz",
+ "integrity": "sha512-xejya+bT/j/+R/AGa1XOfRxLmNUlLtlwjRsFUILF+xHfzElmGcmFydy2gqqIrd62ptIEfwVMofd19uNWD9L7Nw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/chai": "^5.2.2",
+ "@vitest/expect": "3.2.6",
+ "@vitest/mocker": "3.2.6",
+ "@vitest/pretty-format": "^3.2.6",
+ "@vitest/runner": "3.2.6",
+ "@vitest/snapshot": "3.2.6",
+ "@vitest/spy": "3.2.6",
+ "@vitest/utils": "3.2.6",
+ "chai": "^5.2.0",
+ "debug": "^4.4.1",
+ "expect-type": "^1.2.1",
+ "magic-string": "^0.30.17",
+ "pathe": "^2.0.3",
+ "picomatch": "^4.0.2",
+ "std-env": "^3.9.0",
+ "tinybench": "^2.9.0",
+ "tinyexec": "^0.3.2",
+ "tinyglobby": "^0.2.14",
+ "tinypool": "^1.1.1",
+ "tinyrainbow": "^2.0.0",
+ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0",
+ "vite-node": "3.2.4",
+ "why-is-node-running": "^2.3.0"
+ },
+ "bin": {
+ "vitest": "vitest.mjs"
+ },
+ "engines": {
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "@edge-runtime/vm": "*",
+ "@types/debug": "^4.1.12",
+ "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
+ "@vitest/browser": "3.2.6",
+ "@vitest/ui": "3.2.6",
+ "happy-dom": "*",
+ "jsdom": "*"
+ },
+ "peerDependenciesMeta": {
+ "@edge-runtime/vm": {
+ "optional": true
+ },
+ "@types/debug": {
+ "optional": true
+ },
+ "@types/node": {
+ "optional": true
+ },
+ "@vitest/browser": {
+ "optional": true
+ },
+ "@vitest/ui": {
+ "optional": true
+ },
+ "happy-dom": {
+ "optional": true
+ },
+ "jsdom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/w3c-xmlserializer": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz",
+ "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "xml-name-validator": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/watchpack": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.2.tgz",
+ "integrity": "sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.1.2"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/webidl-conversions": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
+ "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/webpack": {
+ "version": "5.108.1",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.108.1.tgz",
+ "integrity": "sha512-UUCihHQK3O7483Woa0SulNLDeAiOhHI2PN2PAPU4fVWJqbzhv04EJ8FaWtB9WWh3i8fRt28543U7VfuJTOrpgQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.8",
+ "@types/json-schema": "^7.0.15",
+ "@webassemblyjs/ast": "^1.14.1",
+ "@webassemblyjs/wasm-edit": "^1.14.1",
+ "@webassemblyjs/wasm-parser": "^1.14.1",
+ "acorn": "^8.16.0",
+ "acorn-import-phases": "^1.0.3",
+ "browserslist": "^4.28.1",
+ "chrome-trace-event": "^1.0.2",
+ "enhanced-resolve": "^5.22.2",
+ "es-module-lexer": "^2.1.0",
+ "eslint-scope": "5.1.1",
+ "events": "^3.2.0",
+ "graceful-fs": "^4.2.11",
+ "loader-runner": "^4.3.2",
+ "mime-db": "^1.54.0",
+ "minimizer-webpack-plugin": "^5.6.1",
+ "neo-async": "^2.6.2",
+ "schema-utils": "^4.3.3",
+ "tapable": "^2.3.0",
+ "watchpack": "^2.5.2",
+ "webpack-sources": "^3.5.0"
+ },
+ "bin": {
+ "webpack": "bin/webpack.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependenciesMeta": {
+ "webpack-cli": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/webpack-cli": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-7.1.0.tgz",
+ "integrity": "sha512-pSJ5p5PkXRD88sfCq5Wo+coc42QykwRu5Md0DyESj0rT6PPPA2wTNabpHPKgqH8EMkfTDo3IWx3iiNXMu8XDBQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@discoveryjs/json-ext": "^1.1.0",
+ "commander": "^14.0.3",
+ "cross-spawn": "^7.0.6",
+ "envinfo": "^7.21.0",
+ "import-local": "^3.2.0",
+ "interpret": "^3.1.1",
+ "rechoir": "^0.8.0",
+ "webpack-merge": "^6.0.1"
+ },
+ "bin": {
+ "webpack-cli": "bin/cli.js"
+ },
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "js-yaml": "^4.0.0 || ^5.0.0",
+ "json5": "^2.2.3",
+ "toml": "^3.0.0 || ^4.0.0",
+ "webpack": "^5.101.0",
+ "webpack-bundle-analyzer": "^4.0.0 || ^5.0.0",
+ "webpack-dev-server": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "js-yaml": {
+ "optional": true
+ },
+ "json5": {
+ "optional": true
+ },
+ "toml": {
+ "optional": true
+ },
+ "webpack-bundle-analyzer": {
+ "optional": true
+ },
+ "webpack-dev-server": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/webpack-cli/node_modules/commander": {
+ "version": "14.0.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz",
+ "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/webpack-merge": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz",
+ "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "clone-deep": "^4.0.1",
+ "flat": "^5.0.2",
+ "wildcard": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/webpack-sources": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.5.0.tgz",
+ "integrity": "sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/whatwg-encoding": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
+ "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
+ "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "iconv-lite": "0.6.3"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/whatwg-mimetype": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
+ "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/whatwg-url": {
+ "version": "14.2.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz",
+ "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tr46": "^5.1.0",
+ "webidl-conversions": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "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/why-is-node-running": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
+ "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "siginfo": "^2.0.0",
+ "stackback": "0.0.2"
+ },
+ "bin": {
+ "why-is-node-running": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wildcard": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz",
+ "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/ws": {
+ "version": "8.21.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz",
+ "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==",
+ "dev": true,
+ "license": "MIT",
+ "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/xml-name-validator": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz",
+ "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/xmlchars": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
+ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
+ "dev": true,
+ "license": "MIT"
+ }
+ }
+}
diff --git a/package.json b/package.json
index 67e844d..af8184f 100644
--- a/package.json
+++ b/package.json
@@ -1,15 +1,18 @@
{
- "name": "worker-polyfill",
+ "name": "@techaro/worker-polyfill",
"version": "1.0.0",
"description": "Polyfill for the Web Worker API that works in Internet Explorer and other old browsers that don't support this API",
"main": "lib/worker-polyfill.js",
"scripts": {
"prebuild": "rimraf lib",
- "build": "webpack --mode=production"
+ "build": "webpack --mode=production",
+ "test": "vitest",
+ "test:run": "vitest run",
+ "ci": "act -P ubuntu-24.04=ghcr.io/catthehacker/ubuntu:act-24.04 -j node_tests"
},
"repository": {
"type": "git",
- "url": "git+https://github.com/pmarfany/worker-polyfill.git"
+ "url": "git+https://github.com/TecharoHQ/worker-polyfill.git"
},
"keywords": [
"worker",
@@ -19,14 +22,16 @@
"author": "Pau Marfany",
"license": "MIT",
"bugs": {
- "url": "https://github.com/pmarfany/worker-polyfill/issues"
+ "url": "https://github.com/TecharoHQ/worker-polyfill/issues"
},
- "homepage": "https://github.com/pmarfany/worker-polyfill#readme",
+ "homepage": "https://github.com/TecharoHQ/worker-polyfill#readme",
"devDependencies": {
- "awesome-typescript-loader": "^5.2.1",
- "rimraf": "^2.6.3",
- "typescript": "^3.4.1",
- "webpack": "^4.29.6",
- "webpack-cli": "^3.3.0"
+ "jsdom": "^25.0.1",
+ "rimraf": "^6.0.1",
+ "ts-loader": "^9.5.4",
+ "typescript": "^6.0.3",
+ "vitest": "^3.2.6",
+ "webpack": "^5.108.1",
+ "webpack-cli": "^7.1.0"
}
}
diff --git a/src/clone.ts b/src/clone.ts
new file mode 100644
index 0000000..1c7d4cb
--- /dev/null
+++ b/src/clone.ts
@@ -0,0 +1,39 @@
+// Minimal structured-clone approximation for the Worker polyfill.
+// Handles primitives, arrays, plain objects, Date, RegExp, and cyclic
+// references using paired arrays (no Map/WeakMap, for IE compatibility).
+// Non-cloneable values (functions, DOM nodes) are kept by reference.
+const structuredCloneShim = (value: any, seen?: any[], copies?: any[]): any => {
+ if (value === null || typeof value !== "object") {
+ return value;
+ }
+
+ seen = seen || [];
+ copies = copies || [];
+
+ for (let i = 0; i < seen.length; i++) {
+ if (seen[i] === value) {
+ return copies[i];
+ }
+ }
+
+ if (value instanceof Date) {
+ return new Date(value.getTime());
+ }
+ if (value instanceof RegExp) {
+ return new RegExp(value.source, value.flags);
+ }
+
+ const out: any = Array.isArray(value) ? [] : {};
+ seen.push(value);
+ copies.push(out);
+
+ for (const key in value) {
+ if (Object.prototype.hasOwnProperty.call(value, key)) {
+ out[key] = structuredCloneShim(value[key], seen, copies);
+ }
+ }
+
+ return out;
+};
+
+export { structuredCloneShim };
diff --git a/src/event-target.ts b/src/event-target.ts
new file mode 100644
index 0000000..d263328
--- /dev/null
+++ b/src/event-target.ts
@@ -0,0 +1,82 @@
+import { isFunction, getGlobal } from "./utils";
+import { PolyfillEvent, createErrorEvent } from "./events";
+
+// A minimal EventTarget that also supports legacy `on` handler
+// properties. Both the Worker (parent) object and the worker global scope
+// use this, giving them spec-style multi-listener behaviour.
+interface EventTargetLike {
+ addEventListener: (type: string, callback: any) => void;
+ removeEventListener: (type: string, callback: any) => void;
+ dispatchEvent: (event: PolyfillEvent) => boolean;
+}
+
+const installEventTarget = (host: any, options?: { catchErrors: boolean }): EventTargetLike => {
+ const listeners: { [type: string]: any[] } = {};
+ const catchErrors = options?.catchErrors !== false; // default to true
+ let inErrorDispatch = false;
+
+ host.addEventListener = function (type: string, callback: any) {
+ if (!isFunction(callback)) {
+ return;
+ }
+ if (!listeners[type]) {
+ listeners[type] = [];
+ }
+ if (listeners[type].indexOf(callback) === -1) {
+ listeners[type].push(callback);
+ }
+ };
+
+ host.removeEventListener = function (type: string, callback: any) {
+ const list = listeners[type];
+ if (!list) {
+ return;
+ }
+ const idx = list.indexOf(callback);
+ if (idx !== -1) {
+ list.splice(idx, 1);
+ }
+ };
+
+ host.dispatchEvent = function (event: PolyfillEvent) {
+ event.target = event.target || host;
+ event.currentTarget = host;
+
+ const handler = host["on" + event.type];
+ if (isFunction(handler)) {
+ if (catchErrors) {
+ try {
+ handler.call(host, event);
+ } catch (e) {
+ // Swallow handler errors to prevent queue stranding and spec violations.
+ // Listener errors are intentionally not re-thrown to maintain fire-and-forget semantics.
+ }
+ } else {
+ handler.call(host, event);
+ }
+ }
+
+ const list = listeners[event.type];
+ if (list) {
+ // Snapshot so a listener removing another mid-dispatch is safe.
+ const snapshot = list.slice();
+ for (let i = 0; i < snapshot.length; i++) {
+ if (catchErrors) {
+ try {
+ snapshot[i].call(host, event);
+ } catch (e) {
+ // Swallow listener errors to prevent queue stranding and spec violations.
+ // Listener errors are intentionally not re-thrown to maintain fire-and-forget semantics.
+ }
+ } else {
+ snapshot[i].call(host, event);
+ }
+ }
+ }
+ return true;
+ };
+
+ return host as EventTargetLike;
+};
+
+export { EventTargetLike, installEventTarget };
diff --git a/src/events.ts b/src/events.ts
new file mode 100644
index 0000000..66ea1ec
--- /dev/null
+++ b/src/events.ts
@@ -0,0 +1,52 @@
+// Lightweight event objects. Old browsers may lack the MessageEvent /
+// ErrorEvent constructors, so we build plain objects carrying the fields the
+// Worker API exposes.
+interface PolyfillEvent {
+ type: string;
+ target: any;
+ currentTarget: any;
+ [key: string]: any;
+}
+
+const createMessageEvent = (data: any, target: any): PolyfillEvent => {
+ return {
+ type: "message",
+ data: data,
+ target: target,
+ currentTarget: target,
+ origin: "",
+ lastEventId: "",
+ source: null,
+ ports: [],
+ };
+};
+
+const createErrorEvent = (error: any, target: any): PolyfillEvent => {
+ const message = error && error.message ? error.message : String(error);
+ return {
+ type: "error",
+ target: target,
+ currentTarget: target,
+ message: message,
+ filename: "",
+ lineno: 0,
+ colno: 0,
+ error: error,
+ };
+};
+
+const createMessageErrorEvent = (target: any): PolyfillEvent => {
+ return {
+ type: "messageerror",
+ target: target,
+ currentTarget: target,
+ data: null,
+ };
+};
+
+export {
+ PolyfillEvent,
+ createMessageEvent,
+ createErrorEvent,
+ createMessageErrorEvent,
+};
diff --git a/src/utils.ts b/src/utils.ts
index 2b0e27c..0d2bfbe 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -1,20 +1,59 @@
-const isFunction = (f: () => any) => {
- return typeof f === 'function';
+const isFunction = (f: any) => {
+ return typeof f === "function";
};
-/* HTTP Request*/
-const getHTTPObject = () => {
- let xmlhttp;
+/* HTTP Request */
+const getHTTPObject = (): any => {
+ let xmlhttp: any;
try {
xmlhttp = new XMLHttpRequest();
} catch (e) {
try {
+ // @ts-ignore - ActiveXObject only exists in old IE
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
- } catch (e) {
+ } catch (e2) {
xmlhttp = false;
}
}
return xmlhttp;
};
-export { isFunction, getHTTPObject };
+// Resolve the global object across environments (browser, worker, Node, IE).
+const getGlobal = (): any => {
+ if (typeof globalThis !== "undefined") {
+ return globalThis;
+ }
+ if (typeof self !== "undefined") {
+ return self;
+ }
+ // @ts-ignore - window exists in browsers
+ if (typeof window !== "undefined") {
+ // @ts-ignore
+ return window;
+ }
+ return {};
+};
+
+// Fetch a script synchronously and return its source text. Throws on failure
+// so callers can surface an `error` event.
+const fetchScriptSync = (url: string): string => {
+ const http = getHTTPObject();
+ if (!http) {
+ throw new Error("No XMLHttpRequest available to load: " + url);
+ }
+ http.open("GET", url, false);
+ http.send(null);
+
+ const ok =
+ http.readyState === 4 &&
+ (http.status === 0 || (http.status >= 200 && http.status < 300));
+
+ if (!ok) {
+ throw new Error(
+ "Failed to load worker script: " + url + " (status " + http.status + ")",
+ );
+ }
+ return http.responseText;
+};
+
+export { isFunction, getHTTPObject, getGlobal, fetchScriptSync };
diff --git a/src/worker-polyfill.ts b/src/worker-polyfill.ts
index 3fd56a4..a219db5 100644
--- a/src/worker-polyfill.ts
+++ b/src/worker-polyfill.ts
@@ -1,114 +1,106 @@
/*
- Create a fake worker thread of IE and other browsers
- Remember: Only pass in primitives, and there is none of the native security happening
- Only Supports Dedicated Web Workers
+ A single-threaded Worker polyfill for IE and other old browsers.
+ Dedicated Workers only. The worker script is fetched with synchronous XHR
+ and eval'd in-process, inside its own scope object so that `self`,
+ `postMessage`, `onmessage`, etc. behave like a real worker global.
+ Remember: messages are structured-cloned, but this is NOT a real thread and
+ provides none of the native security isolation.
*/
-import {getHTTPObject, isFunction} from "./utils";
-
-// @ts-ignore
-Worker = function (scriptFile: any) {
- let self = this;
- let __timer: number = null;
- let __text: any = null;
- let __fileContent: any = null;
-
- // External methods (worker.METHOD)
+import { fetchScriptSync, getGlobal } from "./utils";
+import { installEventTarget } from "./event-target";
+import { createMessageEvent, createErrorEvent } from "./events";
+import { structuredCloneShim } from "./clone";
+import { createWorkerScope, WorkerScope } from "./worker-scope";
+
+interface PolyfillWorkerOptions {
+ type?: string;
+ name?: string;
+ credentials?: string;
+}
+
+const WorkerPolyfill = function (
+ this: any,
+ scriptFile: string,
+ options?: PolyfillWorkerOptions,
+) {
+ const self = this;
+ const opts = options || {};
+ const glob = getGlobal();
+
+ installEventTarget(self);
self.onmessage = null;
self.onerror = null;
+ self.onmessageerror = null;
- // Child methods
- let onmessage;
- let onerror;
+ let terminated = false;
+ const inbox: any[] = [];
+ let scope: WorkerScope | null = null;
- // Child runs this itself and calls for it's parent to be notified
- const postMessage = function (data: any) {
- if ( isFunction(self.onmessage) ) {
- return self.onmessage({ data });
+ // worker -> parent
+ const toParent = function (data: any) {
+ if (terminated) {
+ return;
}
- return false;
- };
-
- // Method that starts the threading
- self.postMessage = function (text: any) {
- __text = text;
- __iterate();
- return true;
+ glob.setTimeout(function () {
+ if (terminated) {
+ return;
+ }
+ self.dispatchEvent(createMessageEvent(data, self));
+ }, 0);
};
- // Child can call this method instead of assigning methods directly
- const addEventListener = function (type, callback) {
- switch(type) {
- case 'message':
- onmessage = callback;
- break;
- case 'error':
- onerror = callback;
- break;
- }
+ const stop = function () {
+ terminated = true;
+ inbox.length = 0;
};
- // Parent can call this method instead of assigning methods directly
- self.addEventListener = function (type, callback) {
- switch(type) {
- case 'message':
- self.onmessage = callback;
- break;
- case 'error':
- self.onerror = callback;
- break;
+ // Drain queued parent->worker messages one at a time, asynchronously, so
+ // ordering is preserved and delivery never blocks the caller.
+ const drain = function () {
+ if (terminated || !scope || inbox.length === 0) {
+ return;
}
- };
-
- const __iterate = function () {
- // Execute on a timer so we don't block (well as good as we can get in a single thread)
- __timer = setTimeout(__onIterate, 1);
- return true;
- };
-
- const __onIterate = function () {
+ const data = inbox.shift();
try {
- if ( isFunction(onmessage) ) {
- onmessage({ data: __text });
- }
- return true;
+ scope.__deliver(data);
} catch (e) {
- if ( isFunction(onerror) ) {
- return onerror(e);
- }
+ self.dispatchEvent(createErrorEvent(e, self));
+ }
+ if (!terminated && inbox.length > 0) {
+ glob.setTimeout(drain, 0);
}
- return false;
- };
-
- self.terminate = function () {
- clearTimeout(__timer);
- return true;
};
- const importScripts = function () {
- // Turn arguments from pseudo-array in to array in order to iterate it
- const params = Array.prototype.slice.call(arguments);
-
- for (let i = 0, j = params.length; i < j; i++) {
- const script = document.createElement('script');
- script.src = params[i];
- script.setAttribute('type', 'text/javascript');
- document.getElementsByTagName('head')[0].appendChild(script)
+ // parent -> worker
+ self.postMessage = function (data: any) {
+ if (terminated) {
+ return;
}
+ inbox.push(structuredCloneShim(data));
+ glob.setTimeout(drain, 0);
};
- const http = getHTTPObject();
- http.open("GET", scriptFile, false);
- http.send(null);
-
- if (http.readyState == 4) {
- const strResponse = http.responseText;
+ self.terminate = function () {
+ stop();
+ };
- if (http.status !== 404 && http.status !== 500) {
- __fileContent = strResponse;
- // IE functions will become delagates of the instance of Worker
- eval(__fileContent);
- }
+ // Load and start the worker. Failures (load or top-level eval) dispatch an
+ // async error event so handlers attached right after construction still fire.
+ try {
+ const code = fetchScriptSync(scriptFile);
+ scope = createWorkerScope(opts.name || "", toParent, stop);
+ scope.__evalScript(code);
+ } catch (e) {
+ glob.setTimeout(function () {
+ self.dispatchEvent(createErrorEvent(e, self));
+ }, 0);
}
-
- return true;
};
+
+// Install as the global Worker only when there is no native implementation.
+const glob = getGlobal();
+if (typeof glob.Worker === "undefined") {
+ glob.Worker = WorkerPolyfill;
+}
+
+export { WorkerPolyfill };
diff --git a/src/worker-scope.ts b/src/worker-scope.ts
new file mode 100644
index 0000000..5ef8d33
--- /dev/null
+++ b/src/worker-scope.ts
@@ -0,0 +1,79 @@
+import { fetchScriptSync } from "./utils";
+import { installEventTarget } from "./event-target";
+import { createMessageEvent } from "./events";
+import { structuredCloneShim } from "./clone";
+
+interface WorkerScope {
+ self: WorkerScope;
+ name: string;
+ onmessage: any;
+ onmessageerror: any;
+ onerror: any;
+ postMessage: (data: any) => void;
+ importScripts: (...urls: string[]) => void;
+ close: () => void;
+ addEventListener: (type: string, cb: any) => void;
+ removeEventListener: (type: string, cb: any) => void;
+ dispatchEvent: (event: any) => boolean;
+ __deliver: (data: any) => void;
+ __evalScript: (code: string) => void;
+}
+
+// Evaluate worker code with `scope` as its variable environment. `with` is
+// illegal in strict mode, but a Function-constructor body is sloppy mode
+// regardless of how the surrounding module is compiled, so bare identifiers
+// (self, postMessage, onmessage, importScripts, close, ...) resolve to the
+// scope object. Direct `eval` runs in this augmented environment.
+// NOTE: the parameter names below leak into worker code as identifiers; they
+// are deliberately obscure to avoid collisions.
+const runWithScope: (scope: any, __worker_src__: string) => void = new Function(
+ "__worker_scope__",
+ "__worker_src__",
+ "with (__worker_scope__) { eval(__worker_src__); }",
+) as any;
+
+// Builds the worker-side global scope (a DedicatedWorkerGlobalScope-like
+// object). `toParent` is called when the worker posts a message out; `onClose`
+// is called when the worker calls close().
+const createWorkerScope = (
+ name: string,
+ toParent: (data: any) => void,
+ onClose: () => void,
+): WorkerScope => {
+ const scope = {} as WorkerScope;
+ installEventTarget(scope, { catchErrors: false });
+
+ scope.self = scope;
+ scope.name = name || "";
+ scope.onmessage = null;
+ scope.onmessageerror = null;
+ scope.onerror = null;
+
+ scope.postMessage = function (data: any) {
+ toParent(structuredCloneShim(data));
+ };
+
+ scope.importScripts = function () {
+ const urls = Array.prototype.slice.call(arguments);
+ for (let i = 0; i < urls.length; i++) {
+ scope.__evalScript(fetchScriptSync(urls[i]));
+ }
+ };
+
+ scope.close = function () {
+ onClose();
+ };
+
+ // Deliver a parent->worker message as a `message` event inside the scope.
+ scope.__deliver = function (data: any) {
+ scope.dispatchEvent(createMessageEvent(data, scope));
+ };
+
+ scope.__evalScript = function (code: string) {
+ runWithScope(scope, code);
+ };
+
+ return scope;
+};
+
+export { WorkerScope, createWorkerScope };
diff --git a/test/clone.test.ts b/test/clone.test.ts
new file mode 100644
index 0000000..abdb612
--- /dev/null
+++ b/test/clone.test.ts
@@ -0,0 +1,44 @@
+import { describe, it, expect } from "vitest";
+import { structuredCloneShim } from "../src/clone";
+
+describe("structuredCloneShim", () => {
+ it("returns primitives unchanged", () => {
+ expect(structuredCloneShim(5)).toBe(5);
+ expect(structuredCloneShim("a")).toBe("a");
+ expect(structuredCloneShim(null)).toBe(null);
+ });
+
+ it("deep-copies objects so mutations do not leak", () => {
+ const src = { a: 1, nested: { b: 2 } };
+ const copy = structuredCloneShim(src);
+ copy.nested.b = 99;
+ expect(src.nested.b).toBe(2);
+ expect(copy.nested.b).toBe(99);
+ });
+
+ it("deep-copies arrays", () => {
+ const src = [1, [2, 3]];
+ const copy = structuredCloneShim(src);
+ copy[1][0] = 9;
+ expect(src[1][0]).toBe(2);
+ });
+
+ it("preserves cyclic references", () => {
+ const src: any = { name: "x" };
+ src.me = src;
+ const copy = structuredCloneShim(src);
+ expect(copy.me).toBe(copy);
+ expect(copy).not.toBe(src);
+ });
+
+ it("clones Date and RegExp", () => {
+ const d = structuredCloneShim(new Date(1000));
+ expect(d instanceof Date).toBe(true);
+ expect(d.getTime()).toBe(1000);
+
+ const re = structuredCloneShim(/foo/gi);
+ expect(re instanceof RegExp).toBe(true);
+ expect(re.source).toBe("foo");
+ expect(re.flags).toBe("gi");
+ });
+});
diff --git a/test/event-target.test.ts b/test/event-target.test.ts
new file mode 100644
index 0000000..1136f6f
--- /dev/null
+++ b/test/event-target.test.ts
@@ -0,0 +1,68 @@
+import { describe, it, expect } from "vitest";
+import { installEventTarget } from "../src/event-target";
+
+describe("installEventTarget", () => {
+ it("dispatches to multiple listeners", () => {
+ const host: any = {};
+ installEventTarget(host);
+ const calls: string[] = [];
+ host.addEventListener("message", () => calls.push("a"));
+ host.addEventListener("message", () => calls.push("b"));
+ host.dispatchEvent({ type: "message", target: null, currentTarget: null });
+ expect(calls).toEqual(["a", "b"]);
+ });
+
+ it("also invokes the on handler property", () => {
+ const host: any = {};
+ installEventTarget(host);
+ let got = "";
+ host.onmessage = () => (got = "handler");
+ host.dispatchEvent({ type: "message", target: null, currentTarget: null });
+ expect(got).toBe("handler");
+ });
+
+ it("removeEventListener stops a listener", () => {
+ const host: any = {};
+ installEventTarget(host);
+ const calls: string[] = [];
+ const fn = () => calls.push("x");
+ host.addEventListener("message", fn);
+ host.removeEventListener("message", fn);
+ host.dispatchEvent({ type: "message", target: null, currentTarget: null });
+ expect(calls).toEqual([]);
+ });
+
+ it("does not register the same listener twice", () => {
+ const host: any = {};
+ installEventTarget(host);
+ let n = 0;
+ const fn = () => n++;
+ host.addEventListener("message", fn);
+ host.addEventListener("message", fn);
+ host.dispatchEvent({ type: "message", target: null, currentTarget: null });
+ expect(n).toBe(1);
+ });
+
+ it("sets target/currentTarget on the event", () => {
+ const host: any = {};
+ installEventTarget(host);
+ let seen: any = null;
+ host.addEventListener("message", (e: any) => (seen = e));
+ host.dispatchEvent({ type: "message", target: null, currentTarget: null });
+ expect(seen.currentTarget).toBe(host);
+ expect(seen.target).toBe(host);
+ });
+
+ it("continues dispatching after a listener throws", () => {
+ const host: any = {};
+ installEventTarget(host);
+ const calls: string[] = [];
+ host.addEventListener("message", () => {
+ calls.push("first");
+ throw new Error("boom");
+ });
+ host.addEventListener("message", () => calls.push("second"));
+ host.dispatchEvent({ type: "message", target: null, currentTarget: null });
+ expect(calls).toEqual(["first", "second"]);
+ });
+});
diff --git a/test/events.test.ts b/test/events.test.ts
new file mode 100644
index 0000000..ad5e976
--- /dev/null
+++ b/test/events.test.ts
@@ -0,0 +1,39 @@
+import { describe, it, expect } from "vitest";
+import {
+ createMessageEvent,
+ createErrorEvent,
+ createMessageErrorEvent,
+} from "../src/events";
+
+describe("event factories", () => {
+ it("builds a message event with spec-shaped fields", () => {
+ const t = {};
+ const e = createMessageEvent({ hi: 1 }, t);
+ expect(e.type).toBe("message");
+ expect(e.data).toEqual({ hi: 1 });
+ expect(e.target).toBe(t);
+ expect(e.ports).toEqual([]);
+ expect(e.origin).toBe("");
+ });
+
+ it("builds an error event from an Error", () => {
+ const t = {};
+ const err = new Error("boom");
+ const e = createErrorEvent(err, t);
+ expect(e.type).toBe("error");
+ expect(e.message).toBe("boom");
+ expect(e.error).toBe(err);
+ expect(e.lineno).toBe(0);
+ });
+
+ it("builds an error event from a non-Error value", () => {
+ const e = createErrorEvent("plain", {});
+ expect(e.message).toBe("plain");
+ });
+
+ it("builds a messageerror event", () => {
+ const e = createMessageErrorEvent({});
+ expect(e.type).toBe("messageerror");
+ expect(e.data).toBe(null);
+ });
+});
diff --git a/test/harness.test.ts b/test/harness.test.ts
new file mode 100644
index 0000000..91fabdb
--- /dev/null
+++ b/test/harness.test.ts
@@ -0,0 +1,19 @@
+import { describe, it, expect, beforeEach } from "vitest";
+import { installMockXHR, setScript, resetScripts } from "./helpers/mockXHR";
+
+describe("test harness", () => {
+ beforeEach(() => {
+ resetScripts();
+ installMockXHR();
+ });
+
+ it("serves a registered script over sync XHR", () => {
+ setScript("hello.js", "var x = 1;");
+ const xhr: any = new (globalThis as any).XMLHttpRequest();
+ xhr.open("GET", "hello.js", false);
+ xhr.send(null);
+ expect(xhr.readyState).toBe(4);
+ expect(xhr.status).toBe(200);
+ expect(xhr.responseText).toBe("var x = 1;");
+ });
+});
diff --git a/test/helpers/mockXHR.ts b/test/helpers/mockXHR.ts
new file mode 100644
index 0000000..235865c
--- /dev/null
+++ b/test/helpers/mockXHR.ts
@@ -0,0 +1,62 @@
+// A minimal synchronous XMLHttpRequest stand-in. The polyfill fetches
+// worker scripts with sync XHR; jsdom can't fetch arbitrary URLs, so tests
+// register script bodies here and the mock serves them.
+type ScriptMap = { [url: string]: string };
+type ScriptWithStatusMap = { [url: string]: { code: string; status: number } };
+
+let scripts: ScriptMap = {};
+let scriptsWithStatus: ScriptWithStatusMap = {};
+let failUrls: string[] = [];
+
+class MockXHR {
+ status = 0;
+ readyState = 0;
+ responseText = "";
+ private url = "";
+
+ open(_method: string, url: string, _async?: boolean) {
+ this.url = url;
+ }
+
+ send(_body?: any) {
+ this.readyState = 4;
+ if (failUrls.indexOf(this.url) !== -1) {
+ this.status = 404;
+ this.responseText = "";
+ return;
+ }
+ if (Object.prototype.hasOwnProperty.call(scriptsWithStatus, this.url)) {
+ const entry = scriptsWithStatus[this.url];
+ this.status = entry.status;
+ this.responseText = entry.code;
+ } else if (Object.prototype.hasOwnProperty.call(scripts, this.url)) {
+ this.status = 200;
+ this.responseText = scripts[this.url];
+ } else {
+ this.status = 404;
+ this.responseText = "";
+ }
+ }
+}
+
+export function setScript(url: string, code: string): void {
+ scripts[url] = code;
+}
+
+export function setScriptWithStatus(url: string, code: string, status: number): void {
+ scriptsWithStatus[url] = { code, status };
+}
+
+export function failScript(url: string): void {
+ failUrls.push(url);
+}
+
+export function resetScripts(): void {
+ scripts = {};
+ scriptsWithStatus = {};
+ failUrls = [];
+}
+
+export function installMockXHR(): void {
+ (globalThis as any).XMLHttpRequest = MockXHR as any;
+}
diff --git a/test/utils.test.ts b/test/utils.test.ts
new file mode 100644
index 0000000..07e7899
--- /dev/null
+++ b/test/utils.test.ts
@@ -0,0 +1,30 @@
+import { describe, it, expect, beforeEach } from "vitest";
+import { fetchScriptSync, getGlobal } from "../src/utils";
+import { installMockXHR, setScript, failScript, resetScripts, setScriptWithStatus } from "./helpers/mockXHR";
+
+describe("utils", () => {
+ beforeEach(() => {
+ resetScripts();
+ installMockXHR();
+ });
+
+ it("getGlobal returns an object with setTimeout", () => {
+ const g = getGlobal();
+ expect(typeof g.setTimeout).toBe("function");
+ });
+
+ it("fetchScriptSync returns the script body", () => {
+ setScript("a.js", "var a = 1;");
+ expect(fetchScriptSync("a.js")).toBe("var a = 1;");
+ });
+
+ it("fetchScriptSync throws on a failed load", () => {
+ failScript("missing.js");
+ expect(() => fetchScriptSync("missing.js")).toThrow();
+ });
+
+ it("fetchScriptSync throws on non-2xx status", () => {
+ setScriptWithStatus("bad.js", "var a = 1;", 502);
+ expect(() => fetchScriptSync("bad.js")).toThrow("Failed to load worker script: bad.js (status 502)");
+ });
+});
diff --git a/test/worker-polyfill.test.ts b/test/worker-polyfill.test.ts
new file mode 100644
index 0000000..d6986b5
--- /dev/null
+++ b/test/worker-polyfill.test.ts
@@ -0,0 +1,158 @@
+import { describe, it, expect, beforeEach, vi } from "vitest";
+import { installMockXHR, setScript, failScript, resetScripts } from "./helpers/mockXHR";
+import { WorkerPolyfill } from "../src/worker-polyfill";
+
+const makeWorker = (file: string, opts?: any) =>
+ new (WorkerPolyfill as any)(file, opts);
+
+describe("WorkerPolyfill", () => {
+ beforeEach(() => {
+ resetScripts();
+ installMockXHR();
+ vi.useFakeTimers();
+ });
+
+ it("echoes a message using the self.* idiom", () => {
+ setScript("echo.js", "self.onmessage = function(e){ self.postMessage(e.data); };");
+ const w = makeWorker("echo.js");
+ const got: any[] = [];
+ w.onmessage = (e: any) => got.push(e.data);
+ w.postMessage("hi");
+ vi.runAllTimers();
+ expect(got).toEqual(["hi"]);
+ });
+
+ it("delivers a message event object, not a bare value", () => {
+ setScript("echo.js", "onmessage = function(e){ postMessage(e.data); };");
+ const w = makeWorker("echo.js");
+ let evt: any = null;
+ w.addEventListener("message", (e: any) => (evt = e));
+ w.postMessage("x");
+ vi.runAllTimers();
+ expect(evt.type).toBe("message");
+ expect(evt.data).toBe("x");
+ expect(evt.target).toBe(w);
+ });
+
+ it("preserves message order for rapid posts", () => {
+ setScript("echo.js", "onmessage = function(e){ postMessage(e.data); };");
+ const w = makeWorker("echo.js");
+ const got: any[] = [];
+ w.onmessage = (e: any) => got.push(e.data);
+ w.postMessage(1);
+ w.postMessage(2);
+ w.postMessage(3);
+ vi.runAllTimers();
+ expect(got).toEqual([1, 2, 3]);
+ });
+
+ it("structured-clones outgoing messages", () => {
+ setScript("echo.js", "onmessage = function(e){ postMessage(e.data); };");
+ const w = makeWorker("echo.js");
+ let received: any = null;
+ w.onmessage = (e: any) => (received = e.data);
+ const payload = { n: 1 };
+ w.postMessage(payload);
+ payload.n = 2;
+ vi.runAllTimers();
+ expect(received.n).toBe(1);
+ });
+
+ it("supports multiple message listeners", () => {
+ setScript("echo.js", "onmessage = function(e){ postMessage(e.data); };");
+ const w = makeWorker("echo.js");
+ const calls: string[] = [];
+ w.addEventListener("message", () => calls.push("a"));
+ w.addEventListener("message", () => calls.push("b"));
+ w.postMessage("x");
+ vi.runAllTimers();
+ expect(calls).toEqual(["a", "b"]);
+ });
+
+ it("fires the error event when a handler throws", () => {
+ setScript("bad.js", "onmessage = function(){ throw new Error('boom'); };");
+ const w = makeWorker("bad.js");
+ let err: any = null;
+ w.onerror = (e: any) => (err = e);
+ w.postMessage("go");
+ vi.runAllTimers();
+ expect(err).not.toBe(null);
+ expect(err.type).toBe("error");
+ expect(err.message).toBe("boom");
+ // Verify the error event was dispatched even though we swallow listener throws
+ expect(err.error).toBeDefined();
+ });
+
+ it("fires the error event when the script fails to load", () => {
+ failScript("missing.js");
+ const w = makeWorker("missing.js");
+ let err: any = null;
+ w.onerror = (e: any) => (err = e);
+ vi.runAllTimers();
+ expect(err).not.toBe(null);
+ expect(err.type).toBe("error");
+ });
+
+ it("fires the error event when top-level worker code throws", () => {
+ setScript("throws.js", "throw new Error('top-level');");
+ const w = makeWorker("throws.js");
+ let err: any = null;
+ w.onerror = (e: any) => (err = e);
+ vi.runAllTimers();
+ expect(err.message).toBe("top-level");
+ });
+
+ it("terminate() stops further delivery", () => {
+ setScript("echo.js", "onmessage = function(e){ postMessage(e.data); };");
+ const w = makeWorker("echo.js");
+ const got: any[] = [];
+ w.onmessage = (e: any) => got.push(e.data);
+ w.postMessage("a");
+ w.terminate();
+ w.postMessage("b");
+ vi.runAllTimers();
+ expect(got).toEqual([]);
+ });
+
+ it("worker close() stops further delivery", () => {
+ setScript("closer.js", "onmessage = function(){ close(); postMessage('after'); };");
+ const w = makeWorker("closer.js");
+ const got: any[] = [];
+ w.onmessage = (e: any) => got.push(e.data);
+ w.postMessage("go");
+ vi.runAllTimers();
+ expect(got).toEqual([]);
+ });
+
+ it("supports importScripts synchronously", () => {
+ setScript("dep.js", "self.DEP_VALUE = 42;");
+ setScript("main.js", "importScripts('dep.js'); onmessage = function(){ postMessage(DEP_VALUE); };");
+ const w = makeWorker("main.js");
+ let got: any = null;
+ w.onmessage = (e: any) => (got = e.data);
+ w.postMessage("go");
+ vi.runAllTimers();
+ expect(got).toBe(42);
+ });
+
+ it("does not strand messages when both onmessage and onerror throw", () => {
+ setScript("thrower.js", "onmessage = function(){ throw new Error('worker boom'); };");
+ const w = makeWorker("thrower.js");
+ const errors: any[] = [];
+ const messages: any[] = [];
+ w.onerror = (e: any) => {
+ errors.push(e.message);
+ throw new Error("parent boom");
+ };
+ w.onmessage = (e: any) => messages.push(e.data);
+ w.postMessage("first");
+ w.postMessage("second");
+ vi.runAllTimers();
+ // First message should trigger error path (swallowed, no propagation)
+ expect(errors.length).toBeGreaterThanOrEqual(1);
+ expect(errors[0]).toBe("worker boom");
+ // Second message should also be processed (not stranded)
+ expect(errors.length).toBeGreaterThanOrEqual(2);
+ expect(errors[1]).toBe("worker boom");
+ });
+});
diff --git a/test/worker-scope.test.ts b/test/worker-scope.test.ts
new file mode 100644
index 0000000..304ebd9
--- /dev/null
+++ b/test/worker-scope.test.ts
@@ -0,0 +1,46 @@
+import { describe, it, expect } from "vitest";
+import { createWorkerScope } from "../src/worker-scope";
+
+describe("createWorkerScope", () => {
+ it("self refers to the scope itself", () => {
+ const scope = createWorkerScope("", () => {}, () => {});
+ expect(scope.self).toBe(scope);
+ });
+
+ it("evaluated code can set self.onmessage and receive __deliver", () => {
+ const out: any[] = [];
+ const scope = createWorkerScope("", (d) => out.push(d), () => {});
+ scope.__evalScript("self.onmessage = function(e){ self.postMessage(e.data); };");
+ scope.__deliver("ping");
+ expect(out).toEqual(["ping"]);
+ });
+
+ it("bare onmessage/postMessage identifiers resolve to the scope", () => {
+ const out: any[] = [];
+ const scope = createWorkerScope("", (d) => out.push(d), () => {});
+ scope.__evalScript("onmessage = function(e){ postMessage(e.data + '!'); };");
+ scope.__deliver("hey");
+ expect(out).toEqual(["hey!"]);
+ });
+
+ it("postMessage clones the payload", () => {
+ const out: any[] = [];
+ const scope = createWorkerScope("", (d) => out.push(d), () => {});
+ const obj = { n: 1 };
+ scope.postMessage(obj);
+ obj.n = 2;
+ expect(out[0].n).toBe(1);
+ });
+
+ it("close() invokes the onClose callback", () => {
+ let closed = false;
+ const scope = createWorkerScope("", () => {}, () => (closed = true));
+ scope.__evalScript("close();");
+ expect(closed).toBe(true);
+ });
+
+ it("exposes the worker name", () => {
+ const scope = createWorkerScope("worker-1", () => {}, () => {});
+ expect(scope.name).toBe("worker-1");
+ });
+});
diff --git a/tsconfig.json b/tsconfig.json
index 6e88eb3..a498011 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,13 +1,15 @@
{
"compilerOptions": {
"target": "es5",
+ "ignoreDeprecations": "6.0",
"module": "commonjs",
"lib": ["es2015", "dom", "scripthost"],
+ "rootDir": "src",
"outDir": "lib",
"strict": false,
"declaration": false,
"sourceMap": true
},
"include": ["src/**/*"],
- "exclude": ["node_modules", "lib"]
+ "exclude": ["node_modules", "lib", "test"]
}
diff --git a/vitest.config.ts b/vitest.config.ts
new file mode 100644
index 0000000..5517232
--- /dev/null
+++ b/vitest.config.ts
@@ -0,0 +1,8 @@
+import { defineConfig } from "vitest/config";
+
+export default defineConfig({
+ test: {
+ environment: "jsdom",
+ include: ["test/**/*.test.ts"],
+ },
+});
diff --git a/webpack.config.js b/webpack.config.js
index d0cb07f..e75d771 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -23,7 +23,7 @@ const config = {
path: PATHS.bundles,
filename: '[name].js',
libraryTarget: 'umd',
- library: 'Worker',
+ library: 'WorkerPolyfill',
umdNamedDefine: true
},
@@ -38,7 +38,7 @@ const config = {
{
test: /\.ts?$/,
exclude: /node_modules/,
- use: 'awesome-typescript-loader',
+ use: 'ts-loader',
},
]
},