@atolljs/islands 0.1.12 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.d.ts +57 -0
- package/dist/callbackProps.d.ts +35 -0
- package/dist/chunk-TX4FAHRB.js +1187 -0
- package/dist/contract.d.ts +96 -0
- package/dist/devtoolsCommands.d.ts +21 -0
- package/dist/devtoolsPreview.d.ts +8 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +30 -0
- package/dist/island.d.ts +175 -0
- package/dist/memory.d.ts +34 -0
- package/dist/metrics.d.ts +38 -0
- package/dist/ops.d.ts +339 -0
- package/dist/worker/defineWorkers.d.ts +207 -0
- package/dist/worker/dom/css.d.ts +24 -0
- package/dist/worker/dom/document.d.ts +274 -0
- package/dist/worker/dom/element.d.ts +199 -0
- package/dist/worker/dom/html.d.ts +7 -0
- package/dist/worker/dom/node.d.ts +172 -0
- package/dist/worker/dom/resizeObserver.d.ts +29 -0
- package/dist/worker/dom/selectors.d.ts +17 -0
- package/dist/worker/dom/window.d.ts +80 -0
- package/dist/worker/index.d.ts +33 -0
- package/dist/worker/index.js +3159 -0
- package/dist/worker/instance.d.ts +187 -0
- package/dist/worker/proxyDom.d.ts +10 -0
- package/dist/worker/subIsland.d.ts +11 -0
- package/package.json +15 -5
- package/src/index.ts +1 -1
- package/src/island.ts +13 -3
- package/src/worker/subIsland.ts +5 -4
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Island contracts — the framework-free seam between a micro-frontend's
|
|
3
|
+
* worker and any shell.
|
|
4
|
+
*
|
|
5
|
+
* The contract module is the one file BOTH sides import: it names the
|
|
6
|
+
* registry app, declares the props/events wire shape as `Schema`s (the
|
|
7
|
+
* vendored `z` from `@atolljs/core`, consumer-supplied zod, or any
|
|
8
|
+
* `{ parse }` validator), and can carry the worker factory so
|
|
9
|
+
* `lazyIsland(() => import('./x.contract.js'))` is a self-contained split
|
|
10
|
+
* point. No framework types cross it — a React shell mounting an Angular
|
|
11
|
+
* app needs only this file.
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* // checkout.contract.ts — published by the MFE, imported by both threads
|
|
15
|
+
* import { z } from '@atolljs/core';
|
|
16
|
+
* import { defineIslandContract } from '@atolljs/islands';
|
|
17
|
+
*
|
|
18
|
+
* export const checkout = defineIslandContract({
|
|
19
|
+
* app: 'checkout',
|
|
20
|
+
* props: z.object({ label: z.string().optional() }),
|
|
21
|
+
* events: { paid: z.object({ total: z.number() }) },
|
|
22
|
+
* worker: () => new Worker(new URL('./checkout.worker.ts', import.meta.url), { type: 'module' }),
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* Enforcement is worker-side: mount/updateProps parse props AFTER
|
|
27
|
+
* `unmarshalCallbackProps` restores `callbackProp` callables (declare those
|
|
28
|
+
* members `z.callback<Fn>()`), and `emit` parses payloads for declared
|
|
29
|
+
* event names. Undeclared event names pass through — a contract describes
|
|
30
|
+
* the wire, it doesn't fence it (a newer worker emitting an event an older
|
|
31
|
+
* shell doesn't know is normal evolution; a mismatched payload on a KNOWN
|
|
32
|
+
* event is the violation).
|
|
33
|
+
*/
|
|
34
|
+
import type { Schema } from '@atolljs/core';
|
|
35
|
+
/**
|
|
36
|
+
* A mountable app contract: the registry key, the prop/event wire schemas,
|
|
37
|
+
* and optionally the worker factory. `P`/`E` are the shell-facing types —
|
|
38
|
+
* they ride the contract as pure type information, so consumers of a
|
|
39
|
+
* framework-rendered island (an Angular component, a Vue SFC) get typed
|
|
40
|
+
* props and narrowed `onEvent` without ever importing that framework.
|
|
41
|
+
*/
|
|
42
|
+
export interface IslandContract<P = Record<string, unknown>, E extends Record<string, unknown> = Record<string, unknown>> {
|
|
43
|
+
readonly islandContract: true;
|
|
44
|
+
/** Registry key — the name `mountIsland({ app })` resolves to. */
|
|
45
|
+
readonly app: string;
|
|
46
|
+
/** Prop wire schema — enforced worker-side at mount and updateProps. */
|
|
47
|
+
readonly props?: Schema<P>;
|
|
48
|
+
/** Declared emit vocabulary — declared names' payloads parse at emit(). */
|
|
49
|
+
readonly events?: {
|
|
50
|
+
readonly [K in keyof E & string]: Schema<E[K]>;
|
|
51
|
+
};
|
|
52
|
+
/** The worker factory — optional; when present the contract object itself
|
|
53
|
+
* is a lazy contract module (`{ app, worker }`). */
|
|
54
|
+
readonly worker?: (() => Worker) | URL;
|
|
55
|
+
}
|
|
56
|
+
export declare function defineIslandContract<P = Record<string, unknown>, E extends Record<string, unknown> = Record<string, unknown>>(contract: {
|
|
57
|
+
app: string;
|
|
58
|
+
props?: Schema<P>;
|
|
59
|
+
events?: {
|
|
60
|
+
[K in keyof E & string]: Schema<E[K]>;
|
|
61
|
+
};
|
|
62
|
+
worker?: (() => Worker) | URL;
|
|
63
|
+
}): IslandContract<P, E>;
|
|
64
|
+
/** Structural contract check — the brand, not the shape, so a hand-rolled
|
|
65
|
+
* `{ app, props }` without `defineIslandContract` stays an app reference. */
|
|
66
|
+
export declare const isIslandContract: (value: unknown) => value is IslandContract;
|
|
67
|
+
/** The props a contract admits — `IslandContract<P>` → `P`. */
|
|
68
|
+
export type IslandContractProps<C> = C extends IslandContract<infer P, infer _E> ? P : Record<string, unknown>;
|
|
69
|
+
/** The event vocabulary a contract declares — name → payload map. */
|
|
70
|
+
export type IslandContractEvents<C> = C extends IslandContract<infer _P, infer E> ? E : Record<string, unknown>;
|
|
71
|
+
/**
|
|
72
|
+
* The `onEvent` signature a contract implies — `(name, payload)` with the
|
|
73
|
+
* payload narrowed per event name. Framework-free sibling of
|
|
74
|
+
* `@atolljs/angular-island`'s `IslandEventHandler<C>`.
|
|
75
|
+
*/
|
|
76
|
+
export type IslandContractEventHandler<C> = <K extends keyof IslandContractEvents<C> & string>(name: K, payload: IslandContractEvents<C>[K]) => void;
|
|
77
|
+
/**
|
|
78
|
+
* `withContract(contract, app)` — attach a contract to a registry app
|
|
79
|
+
* (imperative def or any framework adapter's `RenderedIslandApp`). The
|
|
80
|
+
* stamp rides the app object like `islandAppName`; the worker reads it at
|
|
81
|
+
* mount/updateProps for prop validation and hands it to `emit` for
|
|
82
|
+
* declared-payload checks.
|
|
83
|
+
*
|
|
84
|
+
* apps: {
|
|
85
|
+
* checkout: withContract(checkout, angularIslandApp(CheckoutComponent)),
|
|
86
|
+
* }
|
|
87
|
+
*/
|
|
88
|
+
export declare function withContract<C extends IslandContract, A>(contract: C, app: A): A;
|
|
89
|
+
/** Read the contract a `withContract`-stamped app carries (undefined when
|
|
90
|
+
* unstamped — most registry entries). */
|
|
91
|
+
export declare const contractOf: (app: unknown) => IslandContract | undefined;
|
|
92
|
+
/** The worker factory a contract-carrying `app` reference supplies —
|
|
93
|
+
* mount seams fall back to it when no `worker`/`client` was passed, so
|
|
94
|
+
* `<Island app={contract}/>` and `islandComponent(contract)` are fully
|
|
95
|
+
* self-contained. */
|
|
96
|
+
export declare const contractWorkerOf: (app: unknown) => (() => Worker) | URL | undefined;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { IslandHandle } from './island.js';
|
|
2
|
+
export interface DevtoolsIslandEntry {
|
|
3
|
+
handle: IslandHandle;
|
|
4
|
+
/** The real container element the island replays into. */
|
|
5
|
+
el: HTMLElement;
|
|
6
|
+
/** The props as the caller last gave them (pre-marshal: markers intact). */
|
|
7
|
+
props(): Record<string, unknown>;
|
|
8
|
+
}
|
|
9
|
+
/** Track a mounted island for the dashboard; returns the untrack function. */
|
|
10
|
+
export declare const trackIslandForDevtools: (entry: DevtoolsIslandEntry) => (() => void);
|
|
11
|
+
export interface IslandTreeNode {
|
|
12
|
+
/** Child-index path from the container: '0', '0.2', '0.2.s' (shadow root). */
|
|
13
|
+
id: string;
|
|
14
|
+
/** Lowercase tag, or '#text' / '#shadow-root'. */
|
|
15
|
+
tag: string;
|
|
16
|
+
attrs: [string, string][];
|
|
17
|
+
text?: string;
|
|
18
|
+
children: IslandTreeNode[];
|
|
19
|
+
/** Children omitted once the node budget ran out. */
|
|
20
|
+
more?: number;
|
|
21
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON-safe deep copy of caller-given props: functions and `callbackProp`
|
|
3
|
+
* markers become '[fn]', bigints `'<n>n'`, binary data a size label,
|
|
4
|
+
* cycles '[cycle]'. The shape the dashboard can display and round-trip.
|
|
5
|
+
*/
|
|
6
|
+
export declare const jsonSafe: (value: unknown) => unknown;
|
|
7
|
+
/** `island:props` payload: a bounded preview with callbacks as '[fn]'. */
|
|
8
|
+
export declare const propsPreview: (props: Record<string, unknown>) => string;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The main-thread surface of @atolljs/islands — React trees (or
|
|
3
|
+
* imperative proxy-DOM apps) rendered inside Web Workers, replayed onto
|
|
4
|
+
* real DOM here as a serialized op stream. There is no React on this side.
|
|
5
|
+
*
|
|
6
|
+
* const island = await mountIsland({
|
|
7
|
+
* client: connectIslandWorker({
|
|
8
|
+
* worker: () => new Worker(new URL('./render.worker.ts', import.meta.url), { type: 'module' }),
|
|
9
|
+
* }),
|
|
10
|
+
* el: document.getElementById('island')!,
|
|
11
|
+
* app: 'controls',
|
|
12
|
+
* });
|
|
13
|
+
*/
|
|
14
|
+
export { connectIslandWorker, isKeepAliveClient, mountIsland } from './island.js';
|
|
15
|
+
export type { ConnectIslandWorkerConfig, IslandClient, IslandHandle, IslandWorkerDefinition, IslandWorkerOptions, Mode, MountIslandOptions, } from './island.js';
|
|
16
|
+
export { makeDoorbell } from './memory.js';
|
|
17
|
+
export type { DoorbellSpec } from './memory.js';
|
|
18
|
+
export { islandApp, islandAppNameOf } from './app.js';
|
|
19
|
+
export type { IslandAppLike, IslandAppProps } from './app.js';
|
|
20
|
+
export { defineIslandContract, isIslandContract, withContract, contractOf, contractWorkerOf, } from './contract.js';
|
|
21
|
+
export type { IslandContract, IslandContractEventHandler, IslandContractEvents, IslandContractProps, } from './contract.js';
|
|
22
|
+
export { callbackProp } from './callbackProps.js';
|
|
23
|
+
export { isEventRef } from './ops.js';
|
|
24
|
+
export type { EventPayload, EventRef, IslandWorkerMethods, MeasuredRect, Op, WireProps, } from './ops.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import {
|
|
2
|
+
callbackProp,
|
|
3
|
+
connectIslandWorker,
|
|
4
|
+
contractOf,
|
|
5
|
+
contractWorkerOf,
|
|
6
|
+
defineIslandContract,
|
|
7
|
+
isEventRef,
|
|
8
|
+
isIslandContract,
|
|
9
|
+
isKeepAliveClient,
|
|
10
|
+
islandApp,
|
|
11
|
+
islandAppNameOf,
|
|
12
|
+
makeDoorbell,
|
|
13
|
+
mountIsland,
|
|
14
|
+
withContract
|
|
15
|
+
} from "./chunk-TX4FAHRB.js";
|
|
16
|
+
export {
|
|
17
|
+
callbackProp,
|
|
18
|
+
connectIslandWorker,
|
|
19
|
+
contractOf,
|
|
20
|
+
contractWorkerOf,
|
|
21
|
+
defineIslandContract,
|
|
22
|
+
isEventRef,
|
|
23
|
+
isIslandContract,
|
|
24
|
+
isKeepAliveClient,
|
|
25
|
+
islandApp,
|
|
26
|
+
islandAppNameOf,
|
|
27
|
+
makeDoorbell,
|
|
28
|
+
mountIsland,
|
|
29
|
+
withContract
|
|
30
|
+
};
|
package/dist/island.d.ts
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import type { ConnectWorkerConfig, SharedSpec, WorkerClient, WorkerDefinition } from '@atolljs/core';
|
|
2
|
+
import { type DoorbellSpec } from './memory.js';
|
|
3
|
+
import { type IslandWorkerMethods, type Op } from './ops.js';
|
|
4
|
+
import type { ProxyElement } from './worker/dom/element.js';
|
|
5
|
+
export type Mode = 'push' | 'poll';
|
|
6
|
+
/** The worker definition every `definePolyWorker` call produces. */
|
|
7
|
+
export type IslandWorkerDefinition = WorkerDefinition<DoorbellSpec, IslandWorkerMethods>;
|
|
8
|
+
/** One island client: one dedicated worker, one doorbell buffer. */
|
|
9
|
+
export type IslandClient = WorkerClient<IslandWorkerDefinition, DoorbellSpec>;
|
|
10
|
+
/**
|
|
11
|
+
* An island client is ONE worker holding its islands' trees (one per mount
|
|
12
|
+
* on it), so pooling is disabled by construction — the type omits
|
|
13
|
+
* `workers`/`poolSize`/`worker`/`sharedMemory` (all island-internal) and the
|
|
14
|
+
* literal below pins `workers: 1` after the spread, so a pool can't sneak
|
|
15
|
+
* through a cast either. `worker` is supplied per call — the package can't
|
|
16
|
+
* know where the consumer's worker entry lives — everything else
|
|
17
|
+
* (taskTimeout, respawn, lazy…) still passes through. The pool-only
|
|
18
|
+
* `concurrency`/`maxQueue` are accepted but have no effect.
|
|
19
|
+
*/
|
|
20
|
+
export type IslandWorkerOptions = Omit<ConnectWorkerConfig<SharedSpec>, 'sharedMemory' | 'worker' | 'workers' | 'poolSize'>;
|
|
21
|
+
export interface ConnectIslandWorkerConfig extends IslandWorkerOptions {
|
|
22
|
+
/**
|
|
23
|
+
* Bundler-detectable factory `() => new Worker(new URL('./x.worker.ts',
|
|
24
|
+
* import.meta.url), { type: 'module' })`, or a URL. The worker script must
|
|
25
|
+
* call `definePolyWorker({ apps })` from '@atolljs/islands/worker'.
|
|
26
|
+
*/
|
|
27
|
+
worker: (() => Worker) | URL;
|
|
28
|
+
/**
|
|
29
|
+
* Default true — the client carries a SharedArrayBuffer doorbell for
|
|
30
|
+
* push-mode flush (requires COOP/COEP cross-origin isolation). Pass
|
|
31
|
+
* `false` for a message-only client: `setMode('push')` falls back to
|
|
32
|
+
* polling and the page needs no special headers.
|
|
33
|
+
*/
|
|
34
|
+
doorbell?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Default false — when true, the last island to destroy on this client
|
|
37
|
+
* leaves the worker ALIVE but idle: the instance still unmounts (dispose
|
|
38
|
+
* hooks run, timers clear, ops stop, driver state releases) but the
|
|
39
|
+
* thread, its module graph, and any worker-side caches stay resident, so
|
|
40
|
+
* the next `mount` on this client is a warm start. Nothing runs while
|
|
41
|
+
* idle — the instance is gone; only the process survives.
|
|
42
|
+
*/
|
|
43
|
+
keepAlive?: boolean;
|
|
44
|
+
}
|
|
45
|
+
/** True when this client stays resident after its last island destroys. */
|
|
46
|
+
export declare const isKeepAliveClient: (client: object) => boolean;
|
|
47
|
+
/** One island client: one dedicated worker, one doorbell buffer. */
|
|
48
|
+
export declare const connectIslandWorker: <W extends IslandWorkerDefinition = IslandWorkerDefinition>({ worker, doorbell, keepAlive, ...options }: ConnectIslandWorkerConfig) => WorkerClient<W, DoorbellSpec>;
|
|
49
|
+
interface MountIslandBaseOptions {
|
|
50
|
+
/**
|
|
51
|
+
* Container element the island's ops are applied into — a real element on
|
|
52
|
+
* the shell side, or a `ProxyElement` inside a worker-rendered island
|
|
53
|
+
* (nested mount: the sub-island's ops replay into the parent instance's
|
|
54
|
+
* shadow tree and tunnel upward through its op stream). Required.
|
|
55
|
+
*/
|
|
56
|
+
el: HTMLElement | ProxyElement;
|
|
57
|
+
/**
|
|
58
|
+
* Registry app name — a key of the `apps` map passed to
|
|
59
|
+
* `definePolyWorker`. Optional against a instance worker
|
|
60
|
+
* (`defineMonoWorker`), which resolves its single app regardless.
|
|
61
|
+
*/
|
|
62
|
+
app?: string;
|
|
63
|
+
props?: Record<string, unknown>;
|
|
64
|
+
/** Island → shell channel: receives every `emit` op the app produces. */
|
|
65
|
+
onEvent?: (name: string, payload: unknown) => void;
|
|
66
|
+
/**
|
|
67
|
+
* Transclusion slots — worker markup renders `<div data-atoll-slot="name">`
|
|
68
|
+
* as a LEAF; when its create op lands, the real element is handed to
|
|
69
|
+
* `slots[name](el)` so the shell can mount main-thread content inside it
|
|
70
|
+
* (a widget, a canvas, even a main-thread React root — real DOM, real
|
|
71
|
+
* events, zero wire). Called again with `null` when the worker removes or
|
|
72
|
+
* renames the element, so the shell can tear down. The element itself
|
|
73
|
+
* stays worker-owned — its box/layout props apply normally.
|
|
74
|
+
*
|
|
75
|
+
* Nested mounts (a ProxyElement `el`) receive the anchor's ProxyElement
|
|
76
|
+
* instead, and only claim names present in this object (`name in slots`);
|
|
77
|
+
* unclaimed slot names bubble up to the outer island's `slots`.
|
|
78
|
+
*/
|
|
79
|
+
slots?: Record<string, (el: HTMLElement | null) => void>;
|
|
80
|
+
/** Fired after each applied op batch — the shell uses it for stats. */
|
|
81
|
+
onActivity?: () => void;
|
|
82
|
+
/**
|
|
83
|
+
* Perf hook — fired after each op batch is replayed with the batch and the
|
|
84
|
+
* main-thread replay time in ms (performance.now). Pair with client call
|
|
85
|
+
* timing to split worker-vs-main cost for a sub-application.
|
|
86
|
+
*/
|
|
87
|
+
onOps?: (ops: readonly Op[], elapsedMs: number) => void;
|
|
88
|
+
/**
|
|
89
|
+
* Initial flush mode — 'push' (default) subscribes the shared-memory
|
|
90
|
+
* doorbell once the mount handshake lands; 'poll' drains committed ops on
|
|
91
|
+
* a 50ms interval. With the `worker` shorthand, 'poll' also builds the
|
|
92
|
+
* client without a doorbell — no SharedArrayBuffer, so no COOP/COEP
|
|
93
|
+
* cross-origin isolation requirement. Switch later with `handle.setMode`.
|
|
94
|
+
*/
|
|
95
|
+
mode?: Mode;
|
|
96
|
+
/**
|
|
97
|
+
* Optional renderer/framework tag — pure observability metadata forwarded
|
|
98
|
+
* to devtools on `island:mount` ('react', 'vue', 'svelte', …). When
|
|
99
|
+
* omitted (and devtools is on), the driver asks the worker: package
|
|
100
|
+
* adapters report their renderer, imperative apps report none and the
|
|
101
|
+
* map draws them as plain workers. An explicit tag always wins.
|
|
102
|
+
*/
|
|
103
|
+
framework?: string;
|
|
104
|
+
/**
|
|
105
|
+
* Milliseconds the mount handshake (mount + whoami) may take before the
|
|
106
|
+
* returned promise rejects — default 15_000, `0` disables. A worker entry
|
|
107
|
+
* that loads but never answers (no definePolyWorker/defineMonoWorker
|
|
108
|
+
* call, an import that hangs) otherwise leaves mount pending forever;
|
|
109
|
+
* hard failures (module error, crash) already reject immediately.
|
|
110
|
+
*/
|
|
111
|
+
mountTimeout?: number;
|
|
112
|
+
/**
|
|
113
|
+
* This mount's `destroy()` never terminates the client: the instance
|
|
114
|
+
* unmounts (dispose hooks, `clear` op replay) but the thread stays
|
|
115
|
+
* resident and idle for a warm remount. The mount-level version of
|
|
116
|
+
* `connectIslandWorker({ keepAlive: true })` — either flag marks the
|
|
117
|
+
* client warm for this island's teardown.
|
|
118
|
+
*/
|
|
119
|
+
keepAlive?: boolean;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* The mount needs one worker-side endpoint: either a `client` a
|
|
123
|
+
* `connectIslandWorker` call produced (shareable — several islands can
|
|
124
|
+
* mount into one worker), or a `worker` entry factory/URL this call builds
|
|
125
|
+
* its own client from (the common one-island-per-worker form — the client
|
|
126
|
+
* is island-internal and dies with `destroy()`).
|
|
127
|
+
*/
|
|
128
|
+
export type MountIslandOptions = MountIslandBaseOptions & ({
|
|
129
|
+
client: IslandClient;
|
|
130
|
+
worker?: undefined;
|
|
131
|
+
} | (IslandWorkerOptions & {
|
|
132
|
+
worker: (() => Worker) | URL;
|
|
133
|
+
client?: undefined;
|
|
134
|
+
}));
|
|
135
|
+
export interface IslandHandle {
|
|
136
|
+
readonly app: string;
|
|
137
|
+
/** The worker-side instance's random id — proof each island is a distinct worker. */
|
|
138
|
+
readonly pid: string;
|
|
139
|
+
/**
|
|
140
|
+
* The wire instance key — `app@N` for a top-level island, `parent~app@N`
|
|
141
|
+
* when mounted into a proxy element inside a worker island.
|
|
142
|
+
*/
|
|
143
|
+
readonly instance: string;
|
|
144
|
+
readonly mode: Mode;
|
|
145
|
+
opsApplied: number;
|
|
146
|
+
flushCalls: number;
|
|
147
|
+
/** Re-render the island's root with new serializable props. */
|
|
148
|
+
updateProps(props: Record<string, unknown>): Promise<void>;
|
|
149
|
+
/**
|
|
150
|
+
* Switch how async commits are noticed. The mode given at mount ('push'
|
|
151
|
+
* by default) is started automatically once the handshake lands — call
|
|
152
|
+
* this only to switch modes afterwards. Rebinds of the doorbell contract
|
|
153
|
+
* (in-process harnesses bind every contract on each pool spawn) re-watch
|
|
154
|
+
* transparently.
|
|
155
|
+
*/
|
|
156
|
+
setMode(mode: Mode): void;
|
|
157
|
+
/** Manual flush — drains ops committed outside task calls. */
|
|
158
|
+
flush(): Promise<void>;
|
|
159
|
+
/**
|
|
160
|
+
* Stop transport timers/subscriptions and release the instance. When this
|
|
161
|
+
* island owns the client the worker terminates; when the client is shared
|
|
162
|
+
* (several islands mounted into it) the instance unmounts and the worker
|
|
163
|
+
* lives on for its siblings — it dies with the last island to leave.
|
|
164
|
+
*/
|
|
165
|
+
destroy(): void;
|
|
166
|
+
}
|
|
167
|
+
export declare const assertCloneableProps: (props: Record<string, unknown>, context: string) => void;
|
|
168
|
+
/** Coerce a wire style value to a CSS string — px-suffixes bare numbers
|
|
169
|
+
* on non-unitless keys (custom properties pass verbatim). Exported for the
|
|
170
|
+
* worker-side nested driver (worker/subIsland.ts), which applies the same
|
|
171
|
+
* unit semantics when replaying style values into proxy elements. */
|
|
172
|
+
export declare const cssStyleValue: (key: string, value: unknown) => string;
|
|
173
|
+
export declare const registerSubIslandMounter: (fn: (opts: MountIslandOptions) => Promise<IslandHandle>) => void;
|
|
174
|
+
export declare function mountIsland(opts: MountIslandOptions): Promise<IslandHandle>;
|
|
175
|
+
export {};
|
package/dist/memory.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The doorbell layout. One counter the worker bumps after every commit —
|
|
3
|
+
* the main thread observe()s it (Atomics.waitAsync underneath) and flushes
|
|
4
|
+
* the op queue on each tick. Ops themselves still ride postMessage; shared
|
|
5
|
+
* memory only replaces the flush() poll with a push.
|
|
6
|
+
*/
|
|
7
|
+
declare const doorbellSpec: {
|
|
8
|
+
opsVersion: import("@atolljs/core").FieldDescriptor<number>;
|
|
9
|
+
};
|
|
10
|
+
/** The spec `renderMemory`/`makeDoorbell` share — pinned to the doorbell layout. */
|
|
11
|
+
export type DoorbellSpec = typeof doorbellSpec;
|
|
12
|
+
/**
|
|
13
|
+
* The worker-side contract. A worker script has ONE module-level instance —
|
|
14
|
+
* the pool's INIT_MEMORY handshake binds it to that worker's own buffer, so
|
|
15
|
+
* every island's worker gets an independent doorbell for free.
|
|
16
|
+
*/
|
|
17
|
+
export declare const renderMemory: import("@atolljs/core").SharedMemory<{
|
|
18
|
+
opsVersion: import("@atolljs/core").FieldDescriptor<number>;
|
|
19
|
+
}> & {
|
|
20
|
+
opsVersion: import("@atolljs/core").Connector<number>;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* The main-thread side needs one contract INSTANCE per island: a contract
|
|
24
|
+
* object can only be bound to one buffer at a time (bind() rewires its
|
|
25
|
+
* connectors), and each island client creates its own pool with its own
|
|
26
|
+
* SharedArrayBuffer. Same spec, separate instance → separate buffer → a
|
|
27
|
+
* doorbell that only rings for that island's worker.
|
|
28
|
+
*/
|
|
29
|
+
export declare const makeDoorbell: () => import("@atolljs/core").SharedMemory<{
|
|
30
|
+
opsVersion: import("@atolljs/core").FieldDescriptor<number>;
|
|
31
|
+
}> & {
|
|
32
|
+
opsVersion: import("@atolljs/core").Connector<number>;
|
|
33
|
+
};
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal bookkeeping for measuring the island engine's own cost, separate
|
|
3
|
+
* from application/render work. Disabled by default — the flag check is one
|
|
4
|
+
* predictable branch per chokepoint, so production mounts pay nothing.
|
|
5
|
+
*
|
|
6
|
+
* The one subtlety is re-entrancy: a proxy-DOM method like `el.appendChild`
|
|
7
|
+
* calls `pushOp`, which is itself instrumented. Timing every frame would
|
|
8
|
+
* double-count, so `enter`/`exit` share a depth counter — only the
|
|
9
|
+
* outermost instrumented frame accumulates. The residual
|
|
10
|
+
* (`workerMs − recordMs`) is then application/adapter time.
|
|
11
|
+
*
|
|
12
|
+
* The bench spec additionally calls {@link instrumentPrototype} on the
|
|
13
|
+
* worker-side dom/* classes so imperative-app shadow-tree maintenance is
|
|
14
|
+
* captured too; framework adapters reach the same sinks directly.
|
|
15
|
+
*/
|
|
16
|
+
export declare const proxyMetrics: {
|
|
17
|
+
enabled: boolean;
|
|
18
|
+
/** Frames currently inside instrumented proxy code (re-entrancy guard). */
|
|
19
|
+
depth: number;
|
|
20
|
+
/** ms inside outermost instrumented frames since reset(). */
|
|
21
|
+
recordMs: number;
|
|
22
|
+
/** Ops pushed since reset() — a count, free to keep. */
|
|
23
|
+
opsPushed: number;
|
|
24
|
+
reset(): void;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Enter an instrumented frame — returns a start timestamp for the outermost
|
|
28
|
+
* frame, or -1 when nested (in which case exit records nothing).
|
|
29
|
+
*/
|
|
30
|
+
export declare const enterProxyFrame: () => number;
|
|
31
|
+
/** Pair with {@link enterProxyFrame} — accumulates only for t0 >= 0. */
|
|
32
|
+
export declare const exitProxyFrame: (t0: number) => void;
|
|
33
|
+
/**
|
|
34
|
+
* Wrap every method/getter/setter on a class prototype with timing. Live
|
|
35
|
+
* for the rest of the process — intended for benchmark instrumentation,
|
|
36
|
+
* not production.
|
|
37
|
+
*/
|
|
38
|
+
export declare function instrumentPrototype(proto: object): void;
|