@atolljs/islands 0.1.12 → 0.1.14
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,274 @@
|
|
|
1
|
+
import type { HostInstance } from '../instance.js';
|
|
2
|
+
import type { EventPayload, MeasuredRect } from '../../ops.js';
|
|
3
|
+
import { ProxyNode, ProxyText, ProxyComment, ProxyFragment, type ProxyEventHandler } from './node.js';
|
|
4
|
+
import { ProxyElement } from './element.js';
|
|
5
|
+
import type { WindowShim, WindowFacadeBundle } from './window.js';
|
|
6
|
+
export interface ProxyDocument {
|
|
7
|
+
/**
|
|
8
|
+
* The island's root container — driver-side id 0. `body` and
|
|
9
|
+
* `documentElement` are aliases of it; appending to either lands elements
|
|
10
|
+
* at the island root. Its own attr/style/listen mutations target the real
|
|
11
|
+
* container element.
|
|
12
|
+
*/
|
|
13
|
+
readonly body: ProxyElement;
|
|
14
|
+
readonly documentElement: ProxyElement;
|
|
15
|
+
createElement(tag: string): ProxyElement;
|
|
16
|
+
/**
|
|
17
|
+
* Namespaced creation for SVG/MathML trees — the `create` op carries the
|
|
18
|
+
* namespace so the driver uses `createElementNS`. Needed by libraries that
|
|
19
|
+
* build SVG imperatively (d3-style code).
|
|
20
|
+
*/
|
|
21
|
+
createElementNS(ns: string, tag: string): ProxyElement;
|
|
22
|
+
createTextNode(text: string): ProxyText;
|
|
23
|
+
/**
|
|
24
|
+
* A comment node — nodeType 8 backed by a REAL empty text node
|
|
25
|
+
* driver-side (the wire has no comment op) so it anchors `before:`
|
|
26
|
+
* positions like a real comment. `data` writes stay shadow-only.
|
|
27
|
+
*/
|
|
28
|
+
createComment(data?: string): ProxyComment;
|
|
29
|
+
/**
|
|
30
|
+
* A phantom container for batching — appending the fragment splices its
|
|
31
|
+
* children into the target like the DOM does (each child emits its own
|
|
32
|
+
* append op). Fragments never exist driver-side.
|
|
33
|
+
*/
|
|
34
|
+
createDocumentFragment(): ProxyFragment;
|
|
35
|
+
/** DOM `importNode` semantics — a deep/shallow clone through this
|
|
36
|
+
* document (proxy nodes are single-instance, so cloning IS importing). */
|
|
37
|
+
importNode(node: ProxyNode, deep?: boolean): ProxyNode;
|
|
38
|
+
/** 'about:blank' — no real document URL exists worker-side. */
|
|
39
|
+
readonly baseURI: string;
|
|
40
|
+
/**
|
|
41
|
+
* Document-level listeners: emitted as `listen` ops on id 0 — the driver
|
|
42
|
+
* attaches them to the island's real container element, so delegated
|
|
43
|
+
* handlers see every event that bubbles inside the island. This is what
|
|
44
|
+
* library-style `document.addEventListener('click', delegate)` needs.
|
|
45
|
+
* `options` carries `{once, passive, capture}` onto the wire.
|
|
46
|
+
*/
|
|
47
|
+
addEventListener(type: string, fn: ProxyEventHandler, options?: boolean | AddEventListenerOptions): void;
|
|
48
|
+
removeEventListener(type: string, fn: ProxyEventHandler, options?: boolean | EventListenerOptions): void;
|
|
49
|
+
/** id-map lookup over the CONNECTED shadow tree (disconnected nodes with
|
|
50
|
+
* an id set are remembered but not returned, matching real-DOM scoping). */
|
|
51
|
+
getElementById(id: string): ProxyElement | null;
|
|
52
|
+
/** Simple matcher: tag/.class/#id/[attr]/[attr="v"] + descendant
|
|
53
|
+
* combinators. Anything else throws a clear unsupported-selector error. */
|
|
54
|
+
querySelector(selector: string): ProxyElement | null;
|
|
55
|
+
querySelectorAll(selector: string): ProxyElement[];
|
|
56
|
+
/** Wrap an existing host-instance record (e.g. a React-rendered element
|
|
57
|
+
* reached via the shared `instances` map) so imperative code can navigate
|
|
58
|
+
* or mutate around it — the bridge for nesting proxy trees inside
|
|
59
|
+
* React-rendered parents and vice versa. */
|
|
60
|
+
adopt(instance: HostInstance): ProxyNode;
|
|
61
|
+
/**
|
|
62
|
+
* Mark `el` as reporting the pushed container size — the driver's only
|
|
63
|
+
* measured box is the island container, so geometry reads
|
|
64
|
+
* (`clientWidth/Height`, `offsetWidth/Height`, `getBoundingClientRect`)
|
|
65
|
+
* on marked elements return the last `setSize` push exactly like
|
|
66
|
+
* `doc.body`/`documentElement`. Only honest for elements that actually
|
|
67
|
+
* fill the island's box (a map viewport, a canvas host).
|
|
68
|
+
*/
|
|
69
|
+
markContainer(el: ProxyElement): void;
|
|
70
|
+
/**
|
|
71
|
+
* Request REAL geometry for `el` — emits a `measure` op asking the driver
|
|
72
|
+
* to measure the actual node and ResizeObserver it. `cb` fires inside the
|
|
73
|
+
* instance's task scope on every `setRects` push (the first arrives as
|
|
74
|
+
* soon as the driver answers, then on every element resize), so observer
|
|
75
|
+
* mutations emit ops like onResize handlers. The element's geometry reads
|
|
76
|
+
* (`clientWidth`, `getBoundingClientRect`, …) serve the last pushed rect
|
|
77
|
+
* from then on. Returns a detacher — removing the last observer emits
|
|
78
|
+
* `unmeasure`. This backs the `ResizeObserver` shim; call it directly for
|
|
79
|
+
* the plain (rect) => void form.
|
|
80
|
+
*/
|
|
81
|
+
observeSize(el: ProxyElement, cb: (rect: MeasuredRect) => void): () => void;
|
|
82
|
+
/**
|
|
83
|
+
* Register a handler fired every time the driver pushes a new container
|
|
84
|
+
* size — the app's resize signal. Handlers run inside the instance's task
|
|
85
|
+
* scope, so their proxy-DOM mutations emit ops and `emit` routes.
|
|
86
|
+
*/
|
|
87
|
+
onResize(cb: (w: number, h: number) => void): void;
|
|
88
|
+
/**
|
|
89
|
+
* The window facade `installDomShim` installed this document under —
|
|
90
|
+
* what `document.defaultView` reads as (`window.getComputedStyle` etc).
|
|
91
|
+
* undefined until the shim installs.
|
|
92
|
+
*/
|
|
93
|
+
readonly defaultView?: WindowShim;
|
|
94
|
+
/** No measurement channel — returns an all-empty declaration (warns once). */
|
|
95
|
+
getComputedStyle(el: ProxyElement): CSSStyleDeclaration;
|
|
96
|
+
/** Unregister every handler this document's listeners hold. Called by the
|
|
97
|
+
* worker on rebuild so stale handler ids can't be dispatched into dead
|
|
98
|
+
* nodes; mutating a disposed document throws. */
|
|
99
|
+
dispose(): void;
|
|
100
|
+
}
|
|
101
|
+
export declare class InternalDocument implements ProxyDocument {
|
|
102
|
+
readonly instance: string;
|
|
103
|
+
readonly _root: ProxyElement;
|
|
104
|
+
readonly _wrappers: Map<number, ProxyNode>;
|
|
105
|
+
readonly _ids: Map<string, ProxyElement>;
|
|
106
|
+
/** handler ids this document registered — disposed on rebuild. */
|
|
107
|
+
readonly _handlerIds: Set<number>;
|
|
108
|
+
/**
|
|
109
|
+
* instance ids geometry reads answer for — id 0 (the root) plus every
|
|
110
|
+
* markContainer()ed element. The pushed box is the ISLAND CONTAINER's,
|
|
111
|
+
* so a marked element claims "my box is the container's box".
|
|
112
|
+
*/
|
|
113
|
+
readonly _containerIds: Set<number>;
|
|
114
|
+
/** Handlers fired when a setSize task pushes a new container size. */
|
|
115
|
+
private readonly _resizeHandlers;
|
|
116
|
+
/** element id → observeSize callbacks, fired on each setRects push. */
|
|
117
|
+
private readonly _sizeObservers;
|
|
118
|
+
/** ids a `measure` op was already emitted for — dedupes observeSize and
|
|
119
|
+
* the lazy auto-request a bare geometry read performs. */
|
|
120
|
+
readonly _measureRequested: Set<number>;
|
|
121
|
+
/** The window facade bundle — built lazily by windowFacadeFor, shared by
|
|
122
|
+
* installDomShim and the instance dispatcher. */
|
|
123
|
+
_windowBundle?: WindowFacadeBundle;
|
|
124
|
+
/** what `document.defaultView` reads as (`window.getComputedStyle` etc). */
|
|
125
|
+
get defaultView(): WindowShim | undefined;
|
|
126
|
+
/** Document-level listeners — separate table from the root element's, so
|
|
127
|
+
* doc.addEventListener and body.addEventListener don't wrongly dedupe
|
|
128
|
+
* against each other. Both emit `listen` on id 0. */
|
|
129
|
+
private readonly _docListeners;
|
|
130
|
+
private readonly _warned;
|
|
131
|
+
_disposed: boolean;
|
|
132
|
+
/** Set by installDomShim — restore globals when this document dies. */
|
|
133
|
+
_uninstallShim: (() => void) | null;
|
|
134
|
+
constructor(instance: string);
|
|
135
|
+
get body(): ProxyElement;
|
|
136
|
+
get documentElement(): ProxyElement;
|
|
137
|
+
/** No hit-testing exists worker-side — honest null (a11y-layer probing). */
|
|
138
|
+
elementFromPoint(_x: number, _y: number): null;
|
|
139
|
+
_assertAlive(): void;
|
|
140
|
+
_warn(feature: string, message?: string): void;
|
|
141
|
+
/** Scroll-geometry warn — the measure channel delivers border boxes, not
|
|
142
|
+
* scroll offsets/overflow extents, so scroll* reads stay honest 0. */
|
|
143
|
+
_scrollWarn(feature: string): void;
|
|
144
|
+
markContainer(el: ProxyElement): void;
|
|
145
|
+
/**
|
|
146
|
+
* Emit `measure` for `el` exactly once — shared by observeSize (explicit
|
|
147
|
+
* subscription) and by geometry reads on unmarked connected elements (the
|
|
148
|
+
* lazy path: a library reading clientWidth gets the honest 0 for now, and
|
|
149
|
+
* REAL geometry on subsequent reads once the driver's push lands).
|
|
150
|
+
* Disconnected/phantom nodes have no driver-side element to measure;
|
|
151
|
+
* requesting is skipped until the read happens while connected.
|
|
152
|
+
*/
|
|
153
|
+
_requestMeasure(el: ProxyElement): void;
|
|
154
|
+
observeSize(el: ProxyElement, cb: (rect: MeasuredRect) => void): () => void;
|
|
155
|
+
/**
|
|
156
|
+
* Store pushed rects and fire per-element observers — the `setRects`
|
|
157
|
+
* task calls this inside the instance's scope, so observer mutations
|
|
158
|
+
* emit ops and ride back in the task's return batch.
|
|
159
|
+
*/
|
|
160
|
+
_notifyRects(rects: MeasuredRect[]): void;
|
|
161
|
+
/**
|
|
162
|
+
* The rect a geometry read on `el` may report: the element's own measured
|
|
163
|
+
* box when a setRects push arrived for it, else the pushed CONTAINER box
|
|
164
|
+
* when `el` is the root or was markContainer()ed (the old contract — a
|
|
165
|
+
* marked element claims "my box is the container's"), undefined otherwise
|
|
166
|
+
* (also undefined when nothing has been pushed yet — reads return 0).
|
|
167
|
+
*/
|
|
168
|
+
_rectFor(el: ProxyElement): {
|
|
169
|
+
x: number;
|
|
170
|
+
y: number;
|
|
171
|
+
w: number;
|
|
172
|
+
h: number;
|
|
173
|
+
} | undefined;
|
|
174
|
+
onResize(cb: (w: number, h: number) => void): void;
|
|
175
|
+
/**
|
|
176
|
+
* Fire the doc's resize handlers — the worker's `setSize` task calls this
|
|
177
|
+
* inside the instance's scope, so handler mutations emit ops on the instance
|
|
178
|
+
* queue and come back in the task's return batch.
|
|
179
|
+
*/
|
|
180
|
+
_notifySize(w: number, h: number): void;
|
|
181
|
+
/** Keep the getElementById map pointing at each element's CURRENT id. */
|
|
182
|
+
_trackId(el: ProxyElement): void;
|
|
183
|
+
/** The synthetic text child an element's `textContent` setter leaves in
|
|
184
|
+
* the shadow tree — no driver-side node, so its writes retarget parent. */
|
|
185
|
+
_phantomText(parent: ProxyNode, text: string): ProxyText;
|
|
186
|
+
/**
|
|
187
|
+
* Enrich a dispatched payload before handing it to a proxy listener:
|
|
188
|
+
* - `target` = the proxy node for targetId, looked up in the shared
|
|
189
|
+
* instance space and wrapped in THIS document's wrapper map (so
|
|
190
|
+
* `e.target.closest`/`.dataset`/`.contains` behave like the real DOM
|
|
191
|
+
* for proxy-created nodes).
|
|
192
|
+
* - `currentTarget` = `self` — the node/document/facade the listener was
|
|
193
|
+
* attached to (the handler is also invoked with `this` = self). For
|
|
194
|
+
* document/window listeners this is the document/facade OBJECT, not
|
|
195
|
+
* the id-0 root element dispatch() would otherwise stamp.
|
|
196
|
+
* - `composedPath()` = synthesized from the enriched target's parent
|
|
197
|
+
* chain, with `self` appended when the chain doesn't already reach it
|
|
198
|
+
* (delegated handlers iterate the path until they hit their own
|
|
199
|
+
* element — Svelte's handle_event_propagation terminates there).
|
|
200
|
+
* - `preventDefault`/`stopPropagation`/`stopImmediatePropagation` =
|
|
201
|
+
* synthesized NO-OPS. They cannot cancel anything — the real event
|
|
202
|
+
* already dispatched on the main thread before this payload crossed
|
|
203
|
+
* postMessage — but library code written against real DOM events calls
|
|
204
|
+
* them unconditionally, so the wrapper supplies them.
|
|
205
|
+
*/
|
|
206
|
+
_enrichEvent(payload: EventPayload, self?: unknown): EventPayload;
|
|
207
|
+
createElement(tag: string): ProxyElement;
|
|
208
|
+
createElementNS(ns: string, tag: string): ProxyElement;
|
|
209
|
+
private _newElement;
|
|
210
|
+
createTextNode(text: string): ProxyText;
|
|
211
|
+
adopt(instance: HostInstance): ProxyNode;
|
|
212
|
+
createDocumentFragment(): ProxyFragment;
|
|
213
|
+
/**
|
|
214
|
+
* A comment — nodeType 8 over a real EMPTY text instance. The wire has no
|
|
215
|
+
* comment op: the `text` op with '' gives it a driver-side node that can
|
|
216
|
+
* anchor `before:` positions, while `data` stays shadow-only (emitting it
|
|
217
|
+
* would render comment text on the page).
|
|
218
|
+
*/
|
|
219
|
+
createComment(data?: string): ProxyComment;
|
|
220
|
+
/**
|
|
221
|
+
* DOM `importNode` — a clone through this document. Foreign (non-proxy)
|
|
222
|
+
* nodes have no shadow shape to copy; they're rejected like any other
|
|
223
|
+
* foreign child.
|
|
224
|
+
*/
|
|
225
|
+
importNode(node: ProxyNode, deep?: boolean): ProxyNode;
|
|
226
|
+
/**
|
|
227
|
+
* 'about:blank' — no real document URL exists worker-side. A plain field
|
|
228
|
+
* (not a getter) so adapters may assign it like a normal document prop.
|
|
229
|
+
*/
|
|
230
|
+
readonly baseURI: string;
|
|
231
|
+
/** Wrap (or return the existing wrapper for) a shared instance record. */
|
|
232
|
+
_wrap(instance: HostInstance): ProxyNode;
|
|
233
|
+
/**
|
|
234
|
+
* Document-level listener — same currency as element addEventListener but
|
|
235
|
+
* targeting id 0 (the island's container element). The driver's listen op
|
|
236
|
+
* attaches a real DOM listener on the container, so events bubbling up
|
|
237
|
+
* from any island child dispatch back here. Used by library code doing
|
|
238
|
+
* delegated `document.addEventListener(...)`.
|
|
239
|
+
*/
|
|
240
|
+
addEventListener(type: string, fn: ProxyEventHandler, options?: boolean | AddEventListenerOptions): void;
|
|
241
|
+
removeEventListener(type: string, fn: ProxyEventHandler, options?: boolean | EventListenerOptions): void;
|
|
242
|
+
getElementById(id: string): ProxyElement | null;
|
|
243
|
+
querySelector(selector: string): ProxyElement | null;
|
|
244
|
+
querySelectorAll(selector: string): ProxyElement[];
|
|
245
|
+
getComputedStyle(el: ProxyElement): CSSStyleDeclaration;
|
|
246
|
+
dispose(): void;
|
|
247
|
+
}
|
|
248
|
+
export declare const createProxyDocument: (instance: string) => ProxyDocument;
|
|
249
|
+
/**
|
|
250
|
+
* The instance's proxy document, creating it lazily — the getPublicInstance
|
|
251
|
+
* path (React mounts only need a document when a library holds a ref or a
|
|
252
|
+
* portal target).
|
|
253
|
+
*/
|
|
254
|
+
export declare const docForInstance: (instance: string) => InternalDocument;
|
|
255
|
+
/** The instance's proxy document if one was materialized — never creates.
|
|
256
|
+
* Rendered instances may hold none (React's host config writes instance
|
|
257
|
+
* records, not proxy nodes, until a ref/portal adopts them). */
|
|
258
|
+
export declare const peekInstanceDoc: (instance: string) => InternalDocument | undefined;
|
|
259
|
+
/** Dispose the instance's proxy document if one exists — covers docs
|
|
260
|
+
* materialized through `docForInstance`, not just `ctx.doc`, so unmount
|
|
261
|
+
* can't leave a stale entry for ambient-document resolution. */
|
|
262
|
+
export declare const disposeInstanceDoc: (instance: string) => void;
|
|
263
|
+
/**
|
|
264
|
+
* The document `globalThis.document` should mean right now: the active
|
|
265
|
+
* instance's when a task holds one; the single registered document when only
|
|
266
|
+
* one instance exists (every real island worker — timers and promise
|
|
267
|
+
* continuations run outside instance tasks but unambiguously belong to it);
|
|
268
|
+
* the most recently active instance's otherwise (multi-instance in-process tests
|
|
269
|
+
* still route deferred library callbacks sensibly).
|
|
270
|
+
*/
|
|
271
|
+
export declare const activeInstanceDoc: () => InternalDocument | undefined;
|
|
272
|
+
/** The ambient document: the sole registered doc, or the most recently
|
|
273
|
+
* active instance's — for out-of-task readers (timers, continuations). */
|
|
274
|
+
export declare const ambientDoc: () => InternalDocument | undefined;
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import type { ElementInstance } from '../instance.js';
|
|
2
|
+
import { ProxyNode, ProxyFragment, type ProxyEventHandler } from './node.js';
|
|
3
|
+
import { type ProxyClassList } from './css.js';
|
|
4
|
+
/** Positions `insertAdjacentHTML`/`insertAdjacentElement` accept. */
|
|
5
|
+
export type AdjacentPosition = 'beforebegin' | 'afterbegin' | 'beforeend' | 'afterend';
|
|
6
|
+
export declare class ProxyElement extends ProxyNode {
|
|
7
|
+
readonly instance: ElementInstance;
|
|
8
|
+
readonly _attrs: Map<string, string>;
|
|
9
|
+
_classes: Set<string>;
|
|
10
|
+
readonly _styleProps: Record<string, string>;
|
|
11
|
+
private readonly _listeners;
|
|
12
|
+
get nodeType(): number;
|
|
13
|
+
get tagName(): string;
|
|
14
|
+
/** The element's namespace URI — HTML for ordinary elements, the `create`
|
|
15
|
+
* op's `ns` for namespaced (svg/mathml) ones. */
|
|
16
|
+
get namespaceURI(): string;
|
|
17
|
+
/** Element children only — the shadow tree's HTMLCollection equivalent. */
|
|
18
|
+
get children(): ProxyElement[];
|
|
19
|
+
get id(): string;
|
|
20
|
+
set id(v: string);
|
|
21
|
+
get className(): string;
|
|
22
|
+
set className(v: string);
|
|
23
|
+
getAttribute(name: string): string | null;
|
|
24
|
+
hasAttribute(name: string): boolean;
|
|
25
|
+
setAttribute(name: string, value: string): void;
|
|
26
|
+
removeAttribute(name: string): void;
|
|
27
|
+
setAttributeNS(_ns: string | null, qualifiedName: string, value: string): void;
|
|
28
|
+
getAttributeNS(_ns: string | null, name: string): string | null;
|
|
29
|
+
removeAttributeNS(_ns: string | null, name: string): void;
|
|
30
|
+
get classList(): ProxyClassList;
|
|
31
|
+
/**
|
|
32
|
+
* Inline style — a Proxy over a plain prop record. Writes re-send only
|
|
33
|
+
* the changed key; `delete style.x`/`style.removeProperty('x')` send ''
|
|
34
|
+
* (the protocol's "clear this key"). `setProperty`/`getPropertyValue`
|
|
35
|
+
* accept kebab-case and camelize it, like the real CSSStyleDeclaration.
|
|
36
|
+
*/
|
|
37
|
+
get style(): CSSStyleDeclaration;
|
|
38
|
+
/**
|
|
39
|
+
* dataset — a Proxy mapping camelCase keys to `data-*` attribute ops.
|
|
40
|
+
* `swatch.dataset.color = c` emits attr {name:'data-color', value:c};
|
|
41
|
+
* `delete el.dataset.x` emits the removal form.
|
|
42
|
+
*/
|
|
43
|
+
get dataset(): DOMStringMap;
|
|
44
|
+
/**
|
|
45
|
+
* Focus/blur — NO-OPS. Real focus can't be delivered over async postMessage
|
|
46
|
+
* (the driver's dispatch fires after the event; there is no focus op).
|
|
47
|
+
* They exist because gesture libraries call `el.focus()` unconditionally
|
|
48
|
+
* during mousedown paths (Leaflet's Keyboard handler does).
|
|
49
|
+
*/
|
|
50
|
+
focus(): void;
|
|
51
|
+
blur(): void;
|
|
52
|
+
addEventListener(type: string, fn: ProxyEventHandler, options?: boolean | AddEventListenerOptions): void;
|
|
53
|
+
removeEventListener(type: string, fn: ProxyEventHandler, options?: boolean | EventListenerOptions): void;
|
|
54
|
+
/** Live-descendant search over the shadow tree. Nodes mounted by the
|
|
55
|
+
* reconciler aren't reachable (the op stream doesn't mirror React's
|
|
56
|
+
* structure into _children) — adopted subtrees match only their own
|
|
57
|
+
* proxy-built descendants. Class matching reads _classes AND the
|
|
58
|
+
* instance's serialized className prop, so adopted React elements with
|
|
59
|
+
* className set still match. */
|
|
60
|
+
getElementsByClassName(name: string): ProxyElement[];
|
|
61
|
+
getElementsByTagName(tag: string): ProxyElement[];
|
|
62
|
+
getBBox(): {
|
|
63
|
+
x: number;
|
|
64
|
+
y: number;
|
|
65
|
+
width: number;
|
|
66
|
+
height: number;
|
|
67
|
+
top: number;
|
|
68
|
+
right: number;
|
|
69
|
+
bottom: number;
|
|
70
|
+
left: number;
|
|
71
|
+
};
|
|
72
|
+
getTotalLength(): number;
|
|
73
|
+
getComputedTextLength(): number;
|
|
74
|
+
matches(selector: string): boolean;
|
|
75
|
+
/** Nearest element (self inclusive) matching the selector — walks the
|
|
76
|
+
* shadow tree upward through ancestors. */
|
|
77
|
+
closest(selector: string): ProxyElement | null;
|
|
78
|
+
/** Scoped local-tree query — descendants only, same engine and the same
|
|
79
|
+
* supported-selector subset as document.querySelectorAll. */
|
|
80
|
+
querySelector(selector: string): ProxyElement | null;
|
|
81
|
+
querySelectorAll(selector: string): ProxyElement[];
|
|
82
|
+
/** Serialized shadow-tree children — the only innerHTML there CAN be over
|
|
83
|
+
* an async op channel (it reflects writes made through this facade, not
|
|
84
|
+
* the real DOM's current markup). */
|
|
85
|
+
get innerHTML(): string;
|
|
86
|
+
get outerHTML(): string;
|
|
87
|
+
/**
|
|
88
|
+
* Parse `html` worker-side (htmlparser2 — pure JS, worker-safe) and
|
|
89
|
+
* rebuild this element's children as proxy nodes: each parsed element is
|
|
90
|
+
* createElement + setAttribute + recursive children, each text run a
|
|
91
|
+
* createTextNode — all emitting ordinary create/attr/append ops. Existing
|
|
92
|
+
* children are removed first (one remove op each). Comments and
|
|
93
|
+
* directives are skipped.
|
|
94
|
+
*/
|
|
95
|
+
set innerHTML(html: string);
|
|
96
|
+
/**
|
|
97
|
+
* Parse `html` and insert the resulting nodes relative to this element —
|
|
98
|
+
* 'beforebegin'/'afterend' require a parent and no-op without one (like
|
|
99
|
+
* the DOM on detached elements).
|
|
100
|
+
*/
|
|
101
|
+
insertAdjacentHTML(position: AdjacentPosition, html: string): void;
|
|
102
|
+
/** insertAdjacentElement — returns the inserted element like the DOM. */
|
|
103
|
+
insertAdjacentElement(position: AdjacentPosition, el: ProxyElement): ProxyElement | null;
|
|
104
|
+
private _insertAt;
|
|
105
|
+
/**
|
|
106
|
+
* `<template>.content` — a fragment VIEW sharing the element's shadow
|
|
107
|
+
* child array (same backing store) AND the element's instance id, so
|
|
108
|
+
* `content.appendChild` emits `append` ops targeted at the template. The
|
|
109
|
+
* driver routes template-parented ops into `el.content` — the DOM spec's
|
|
110
|
+
* home for template children anyway. Non-template elements read
|
|
111
|
+
* undefined.
|
|
112
|
+
*/
|
|
113
|
+
get content(): ProxyFragment | undefined;
|
|
114
|
+
/**
|
|
115
|
+
* Clone as new ops — the copy gets its own instance id (it's a real new
|
|
116
|
+
* element on the main thread, not a shared record). Attributes, the
|
|
117
|
+
* namespace and the style-proxy properties are copied; listeners are NOT
|
|
118
|
+
* (matches the DOM). `deep` clones children polymorphically — comment
|
|
119
|
+
* children keep nodeType 8, texts and nested elements/fragments their
|
|
120
|
+
* own kind.
|
|
121
|
+
*/
|
|
122
|
+
cloneNode(deep?: boolean): ProxyElement;
|
|
123
|
+
getBoundingClientRect(): DOMRect;
|
|
124
|
+
get clientWidth(): number;
|
|
125
|
+
get clientHeight(): number;
|
|
126
|
+
get offsetWidth(): number;
|
|
127
|
+
get offsetHeight(): number;
|
|
128
|
+
/** Border edge widths — honestly 0 (the pushed box doesn't measure borders). */
|
|
129
|
+
get clientLeft(): number;
|
|
130
|
+
get clientTop(): number;
|
|
131
|
+
/** Position within offsetParent — not measured; 0 is honest for root-level boxes. */
|
|
132
|
+
get offsetLeft(): number;
|
|
133
|
+
get offsetTop(): number;
|
|
134
|
+
get offsetParent(): null;
|
|
135
|
+
get scrollTop(): number;
|
|
136
|
+
set scrollTop(_v: number);
|
|
137
|
+
get scrollLeft(): number;
|
|
138
|
+
set scrollLeft(_v: number);
|
|
139
|
+
get scrollHeight(): number;
|
|
140
|
+
get scrollWidth(): number;
|
|
141
|
+
/**
|
|
142
|
+
* Reflected properties. Library code assigns `img.src = url`,
|
|
143
|
+
* `el.tabIndex = 0`, `link.href = '#'` — on a bare class instance those
|
|
144
|
+
* become silent expandos and nothing crosses the wire. The attribute-backed
|
|
145
|
+
* accessors below (defined for the properties real libraries poke) make
|
|
146
|
+
* those assignments emit ordinary `attr` ops. Everything else still falls
|
|
147
|
+
* through to a plain own-property — which is also exactly what library
|
|
148
|
+
* expandos like `_leaflet_pos` need, so proxy elements are deliberately
|
|
149
|
+
* NOT frozen/sealed.
|
|
150
|
+
*/
|
|
151
|
+
get src(): string;
|
|
152
|
+
set src(v: string);
|
|
153
|
+
get srcset(): string;
|
|
154
|
+
set srcset(v: string);
|
|
155
|
+
get href(): string;
|
|
156
|
+
set href(v: string);
|
|
157
|
+
get alt(): string;
|
|
158
|
+
set alt(v: string);
|
|
159
|
+
get title(): string;
|
|
160
|
+
set title(v: string);
|
|
161
|
+
get tabIndex(): number;
|
|
162
|
+
set tabIndex(v: number);
|
|
163
|
+
get draggable(): boolean;
|
|
164
|
+
set draggable(v: boolean);
|
|
165
|
+
get crossOrigin(): string | null;
|
|
166
|
+
set crossOrigin(v: string | null);
|
|
167
|
+
get width(): number;
|
|
168
|
+
set width(v: number);
|
|
169
|
+
get height(): number;
|
|
170
|
+
set height(v: number);
|
|
171
|
+
get type(): string;
|
|
172
|
+
set type(v: string);
|
|
173
|
+
get loading(): string;
|
|
174
|
+
set loading(v: string);
|
|
175
|
+
get decoding(): string;
|
|
176
|
+
set decoding(v: string);
|
|
177
|
+
get value(): string;
|
|
178
|
+
set value(v: string);
|
|
179
|
+
get checked(): boolean;
|
|
180
|
+
set checked(v: boolean);
|
|
181
|
+
get disabled(): boolean;
|
|
182
|
+
set disabled(v: boolean);
|
|
183
|
+
/** Geometry read shared by the size getters above. */
|
|
184
|
+
_geom(feature: string, pick: (rect: {
|
|
185
|
+
x: number;
|
|
186
|
+
y: number;
|
|
187
|
+
w: number;
|
|
188
|
+
h: number;
|
|
189
|
+
}) => number): number;
|
|
190
|
+
_writeStyle(key: string, value: string): void;
|
|
191
|
+
/** style.cssText — a FULL replace, not another key. Parse the declarations
|
|
192
|
+
* and write each through the dedup path; keys absent from the new text
|
|
193
|
+
* clear. Storing the text under a 'cssText' key left stale per-key values
|
|
194
|
+
* that deduped real writes away (a hide's `visibility:hidden` stuck after
|
|
195
|
+
* a show's cssText replay). */
|
|
196
|
+
_replaceStyleText(cssText: string): void;
|
|
197
|
+
private _setAttr;
|
|
198
|
+
private _afterAttrChange;
|
|
199
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ProxyNode } from './node.js';
|
|
2
|
+
import type { InternalDocument } from './document.js';
|
|
3
|
+
export declare function parseChildren(doc: InternalDocument, html: string): ProxyNode[];
|
|
4
|
+
/** Serialize a shadow node — elements with attrs (+ inline style from the
|
|
5
|
+
* style proxy), text escaped, comments round-tripping as `<!--data-->`.
|
|
6
|
+
* Reads the shadow tree only; nothing the proxy didn't write appears here. */
|
|
7
|
+
export declare function serializeNode(node: ProxyNode): string;
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import type { HostInstance, TextInstance } from '../instance.js';
|
|
2
|
+
import type { EventPayload, Op } from '../../ops.js';
|
|
3
|
+
import type { InternalDocument, ProxyDocument } from './document.js';
|
|
4
|
+
/** Handler signature for proxy addEventListener — the wire payload plus a
|
|
5
|
+
* synthesized `target` (the proxy node for `targetId`, when known).
|
|
6
|
+
* `this` is bound to the node/document/facade the listener was attached
|
|
7
|
+
* to, like the real DOM's currentTarget. */
|
|
8
|
+
export type ProxyEventHandler = (this: unknown, payload: EventPayload) => void;
|
|
9
|
+
/** The subset of AddEventListenerOptions the `listen`/`unlisten` ops carry. */
|
|
10
|
+
export interface WireListenerOpts {
|
|
11
|
+
once?: boolean;
|
|
12
|
+
passive?: boolean;
|
|
13
|
+
capture?: boolean;
|
|
14
|
+
}
|
|
15
|
+
/** Normalize the DOM's `options | captureFlag` argument into concrete flags. */
|
|
16
|
+
export declare const normalizeListenerOptions: (options?: boolean | AddEventListenerOptions | EventListenerOptions | null) => {
|
|
17
|
+
once: boolean;
|
|
18
|
+
passive: boolean;
|
|
19
|
+
capture: boolean;
|
|
20
|
+
};
|
|
21
|
+
/** The `opts` field for a listen/unlisten op — undefined when every flag is
|
|
22
|
+
* off so plain listeners emit the same op shape as before. */
|
|
23
|
+
export declare const listenerOptsForWire: (options?: boolean | AddEventListenerOptions | EventListenerOptions | null) => WireListenerOpts | undefined;
|
|
24
|
+
export declare const hyphenate: (k: string) => string;
|
|
25
|
+
export declare const camelize: (k: string) => string;
|
|
26
|
+
export declare const allocPhantomId: () => number;
|
|
27
|
+
/**
|
|
28
|
+
* A node that isn't a ProxyNode can only arrive via a foreign `document`
|
|
29
|
+
* (the dispatcher's real-DOM fallback or a poisoned override) — typically a
|
|
30
|
+
* library's deferred callback running after its instance was torn down, or
|
|
31
|
+
* globals restored while worker-side timers still fire. Adopting it would
|
|
32
|
+
* crash later on `child.instance`; reject it here with the actual cause.
|
|
33
|
+
*/
|
|
34
|
+
export declare const rejectForeignChild: (child: unknown) => never;
|
|
35
|
+
/**
|
|
36
|
+
* Detach `child` from its recorded parent, tolerating a stale/foreign
|
|
37
|
+
* `_parent` link (undefined, or a non-proxy object) instead of crashing on
|
|
38
|
+
* `_detach` — a corrupted link is cleared, a valid one is honored.
|
|
39
|
+
*/
|
|
40
|
+
export declare const detachFromParent: (child: ProxyNode) => void;
|
|
41
|
+
export declare class ProxyNode {
|
|
42
|
+
/** The shared host-instance record — same objects `instances` holds. */
|
|
43
|
+
readonly instance: HostInstance;
|
|
44
|
+
/** The document that created/wrapped this node (internal fields below). */
|
|
45
|
+
readonly doc: InternalDocument;
|
|
46
|
+
_parent: ProxyNode | null;
|
|
47
|
+
_children: ProxyNode[];
|
|
48
|
+
constructor(doc: InternalDocument, instance: HostInstance);
|
|
49
|
+
get nodeType(): number;
|
|
50
|
+
/**
|
|
51
|
+
* '#text'/'#comment'/'#document-fragment' for character/fragment nodes;
|
|
52
|
+
* the tag name for elements — uppercase in the HTML namespace, verbatim
|
|
53
|
+
* for namespaced elements (svg 'foreignObject' keeps its case, matching
|
|
54
|
+
* the real DOM).
|
|
55
|
+
*/
|
|
56
|
+
get nodeName(): string;
|
|
57
|
+
/** The proxy document that owns this node — what real DOM code reads as
|
|
58
|
+
* `el.ownerDocument`. */
|
|
59
|
+
get ownerDocument(): ProxyDocument;
|
|
60
|
+
get parentNode(): ProxyNode | null;
|
|
61
|
+
get parentElement(): ProxyNode | null;
|
|
62
|
+
/** A copy of the shadow child list — structural changes go through
|
|
63
|
+
* appendChild/insertBefore/removeChild so ops stay in sync. */
|
|
64
|
+
get childNodes(): ProxyNode[];
|
|
65
|
+
get firstChild(): ProxyNode | null;
|
|
66
|
+
get lastChild(): ProxyNode | null;
|
|
67
|
+
get nextSibling(): ProxyNode | null;
|
|
68
|
+
get previousSibling(): ProxyNode | null;
|
|
69
|
+
/** Attached to the document's root (driver-side id 0 container)? */
|
|
70
|
+
get isConnected(): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* The topmost shadow-tree ancestor — the root container element when the
|
|
73
|
+
* node is connected. (The facade has no separate Document node object;
|
|
74
|
+
* `doc.body`/`documentElement` ARE that root.)
|
|
75
|
+
*/
|
|
76
|
+
getRootNode(): ProxyNode;
|
|
77
|
+
/** Concatenated descendant text — walked from the shadow tree. Comments
|
|
78
|
+
* are excluded: the DOM's descendant text content is Text-node data only. */
|
|
79
|
+
get textContent(): string;
|
|
80
|
+
set textContent(value: string);
|
|
81
|
+
contains(other: ProxyNode): boolean;
|
|
82
|
+
appendChild<T extends ProxyNode>(child: T): T;
|
|
83
|
+
insertBefore<T extends ProxyNode>(child: T, ref: ProxyNode | null): T;
|
|
84
|
+
removeChild<T extends ProxyNode>(child: T): T;
|
|
85
|
+
/** Detach from the parent — no-op when already orphaned (like the DOM). */
|
|
86
|
+
remove(): void;
|
|
87
|
+
before(...nodes: Array<ProxyNode | string>): void;
|
|
88
|
+
after(...nodes: Array<ProxyNode | string>): void;
|
|
89
|
+
replaceWith(...nodes: Array<ProxyNode | string>): void;
|
|
90
|
+
/** append(...nodes) — strings become text nodes, like the DOM. */
|
|
91
|
+
append(...nodes: Array<ProxyNode | string>): void;
|
|
92
|
+
/** prepend(...nodes) — inserts at the front, in argument order. */
|
|
93
|
+
prepend(...nodes: Array<ProxyNode | string>): void;
|
|
94
|
+
/** replaceChildren(...nodes) — remove every child, then append the set. */
|
|
95
|
+
replaceChildren(...nodes: Array<ProxyNode | string>): void;
|
|
96
|
+
/**
|
|
97
|
+
* Structural clone — each concrete kind implements it. The copy is a
|
|
98
|
+
* FRESH instance (own id, own create op), not a shared record; listeners
|
|
99
|
+
* never cross, matching the DOM.
|
|
100
|
+
*/
|
|
101
|
+
cloneNode(_deep?: boolean): ProxyNode;
|
|
102
|
+
/**
|
|
103
|
+
* Queue an op on this node's instance — the same routing hostConfig uses for
|
|
104
|
+
* instance-bound ops. Outside a instance task the op still lands on the right
|
|
105
|
+
* queue, and the doorbell is bumped so push-mode islands pick it up.
|
|
106
|
+
*/
|
|
107
|
+
_op(op: Op): void;
|
|
108
|
+
/** Detach a child from the shadow list WITHOUT emitting an op — used when
|
|
109
|
+
* a following append op will move the real node on the main thread. */
|
|
110
|
+
_detach(child: ProxyNode): void;
|
|
111
|
+
/** Handler ids this node's records own: addEventListener hids (element
|
|
112
|
+
* subclass only) plus the prop-listener slots on the instance record. */
|
|
113
|
+
_recordHandlerIds(): number[];
|
|
114
|
+
/** Tombstone this subtree's instance/handler records (removeChild). */
|
|
115
|
+
_detachRecords(): void;
|
|
116
|
+
/** Restore this subtree's records on re-append (idempotent — a live node
|
|
117
|
+
* is simply not in the tombstone maps). */
|
|
118
|
+
_attachRecords(): void;
|
|
119
|
+
}
|
|
120
|
+
export declare class ProxyText extends ProxyNode {
|
|
121
|
+
readonly instance: TextInstance;
|
|
122
|
+
constructor(doc: InternalDocument, instance: TextInstance);
|
|
123
|
+
get nodeType(): number;
|
|
124
|
+
/**
|
|
125
|
+
* The driver-side id a text write targets. Real text instances write
|
|
126
|
+
* their own id; phantoms (created by an element's `textContent` setter)
|
|
127
|
+
* have no driver-side node, so writes retarget the parent — whose real
|
|
128
|
+
* `textContent` IS this node's whole text.
|
|
129
|
+
*/
|
|
130
|
+
get _utextTarget(): number;
|
|
131
|
+
get data(): string;
|
|
132
|
+
set data(v: string);
|
|
133
|
+
get nodeValue(): string;
|
|
134
|
+
set nodeValue(v: string);
|
|
135
|
+
get textContent(): string;
|
|
136
|
+
set textContent(v: string);
|
|
137
|
+
private _write;
|
|
138
|
+
/** Fresh text node — the clone is a new `text` op, not a shared record. */
|
|
139
|
+
cloneNode(_deep?: boolean): ProxyText;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Comment — nodeType 8, backed by a REAL empty text node driver-side: the
|
|
143
|
+
* wire has no comment op, so `createComment` emits a `text` op with ''
|
|
144
|
+
* giving the node a `before:`-addressable position for anchors (Svelte's
|
|
145
|
+
* `<!>` block boundaries, Vue/Angular comment anchors).
|
|
146
|
+
*
|
|
147
|
+
* `data`/`nodeValue`/`textContent` writes update the shadow record ONLY —
|
|
148
|
+
* emitting `utext` would render the comment's data as visible page text.
|
|
149
|
+
*/
|
|
150
|
+
export declare class ProxyComment extends ProxyText {
|
|
151
|
+
get nodeType(): number;
|
|
152
|
+
get data(): string;
|
|
153
|
+
set data(v: string);
|
|
154
|
+
get nodeValue(): string;
|
|
155
|
+
set nodeValue(v: string);
|
|
156
|
+
get textContent(): string;
|
|
157
|
+
set textContent(v: string);
|
|
158
|
+
private _shadowWrite;
|
|
159
|
+
cloneNode(_deep?: boolean): ProxyComment;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* DocumentFragment — a PHANTOM parent: it never exists driver-side, so its
|
|
163
|
+
* `instance.id` is negative (no ops ever target it). Appending it to a real
|
|
164
|
+
* parent splices its children out like the DOM does; libraries use it to
|
|
165
|
+
* batch insertions (Leaflet's GridLayer builds each zoom level in one).
|
|
166
|
+
*/
|
|
167
|
+
export declare class ProxyFragment extends ProxyNode {
|
|
168
|
+
get nodeType(): number;
|
|
169
|
+
/** Fresh fragment; `deep` clones children polymorphically so comment
|
|
170
|
+
* anchors keep nodeType 8. */
|
|
171
|
+
cloneNode(deep?: boolean): ProxyFragment;
|
|
172
|
+
}
|