@polyengine/runtime 0.1.0-pre.g633468a
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/LICENSE +202 -0
- package/README.md +23 -0
- package/esm/cabi/async_values.js +162 -0
- package/esm/cabi/bulk_lists.js +198 -0
- package/esm/cabi/context.js +42 -0
- package/esm/cabi/flatten.js +145 -0
- package/esm/cabi/float.js +67 -0
- package/esm/cabi/handles.js +253 -0
- package/esm/cabi/layout.js +149 -0
- package/esm/cabi/lift.js +196 -0
- package/esm/cabi/load.js +146 -0
- package/esm/cabi/lower.js +141 -0
- package/esm/cabi/memory.js +182 -0
- package/esm/cabi/mod.js +22 -0
- package/esm/cabi/store.js +186 -0
- package/esm/cabi/strings.js +336 -0
- package/esm/cabi/trap.js +38 -0
- package/esm/cabi/types.js +264 -0
- package/esm/cabi/values.js +64 -0
- package/esm/cache/core.js +156 -0
- package/esm/cache/dir.js +170 -0
- package/esm/cache/mod.js +4 -0
- package/esm/cache/web.js +136 -0
- package/esm/digest/digest.js +332 -0
- package/esm/digest/mod.js +3 -0
- package/esm/digest/verify.js +129 -0
- package/esm/embedder/casing.js +56 -0
- package/esm/embedder/copy.js +42 -0
- package/esm/embedder/errors.js +26 -0
- package/esm/embedder/imports.js +63 -0
- package/esm/embedder/instantiate.js +978 -0
- package/esm/embedder/mod.js +40 -0
- package/esm/embedder/resources.js +406 -0
- package/esm/embedder/streams.js +770 -0
- package/esm/embedder/values.js +450 -0
- package/esm/embedder/version.js +273 -0
- package/esm/exec/boundary.js +1902 -0
- package/esm/exec/executor.js +1004 -0
- package/esm/exec/host_streams.js +818 -0
- package/esm/exec/mod.js +4 -0
- package/esm/intrinsics/async_builtins.js +510 -0
- package/esm/intrinsics/context.js +90 -0
- package/esm/intrinsics/errors.js +13 -0
- package/esm/intrinsics/fact_calls.js +865 -0
- package/esm/intrinsics/mod.js +564 -0
- package/esm/intrinsics/stream_builtins.js +578 -0
- package/esm/intrinsics/transcode.js +443 -0
- package/esm/jspi/bridge.js +579 -0
- package/esm/jspi/mechanics.js +89 -0
- package/esm/jspi/mod.js +5 -0
- package/esm/jspi/suspending.js +15 -0
- package/esm/jspi/types.js +29 -0
- package/esm/package.json +3 -0
- package/esm/plan/format.js +5 -0
- package/esm/plan/loader.js +657 -0
- package/esm/plan/mod.js +3 -0
- package/esm/shim/mod.js +2 -0
- package/esm/shim/translator.js +94 -0
- package/esm/task/mod.js +483 -0
- package/esm/task/scheduler.js +1028 -0
- package/esm/task/streams.js +786 -0
- package/esm/task/subtask.js +135 -0
- package/esm/task/thread.js +255 -0
- package/esm/task/waitable.js +144 -0
- package/package.json +91 -0
- package/types/cabi/async_values.d.ts +35 -0
- package/types/cabi/bulk_lists.d.ts +18 -0
- package/types/cabi/context.d.ts +59 -0
- package/types/cabi/flatten.d.ts +14 -0
- package/types/cabi/float.d.ts +14 -0
- package/types/cabi/handles.d.ts +70 -0
- package/types/cabi/layout.d.ts +13 -0
- package/types/cabi/lift.d.ts +25 -0
- package/types/cabi/load.d.ts +14 -0
- package/types/cabi/lower.d.ts +10 -0
- package/types/cabi/memory.d.ts +58 -0
- package/types/cabi/mod.d.ts +15 -0
- package/types/cabi/store.d.ts +12 -0
- package/types/cabi/strings.d.ts +23 -0
- package/types/cabi/trap.d.ts +11 -0
- package/types/cabi/types.d.ts +206 -0
- package/types/cabi/values.d.ts +5 -0
- package/types/cache/core.d.ts +97 -0
- package/types/cache/dir.d.ts +6 -0
- package/types/cache/mod.d.ts +3 -0
- package/types/cache/web.d.ts +10 -0
- package/types/digest/digest.d.ts +17 -0
- package/types/digest/mod.d.ts +2 -0
- package/types/digest/verify.d.ts +48 -0
- package/types/embedder/casing.d.ts +40 -0
- package/types/embedder/copy.d.ts +24 -0
- package/types/embedder/errors.d.ts +11 -0
- package/types/embedder/imports.d.ts +47 -0
- package/types/embedder/instantiate.d.ts +88 -0
- package/types/embedder/mod.d.ts +11 -0
- package/types/embedder/resources.d.ts +158 -0
- package/types/embedder/streams.d.ts +202 -0
- package/types/embedder/values.d.ts +70 -0
- package/types/embedder/version.d.ts +85 -0
- package/types/exec/boundary.d.ts +360 -0
- package/types/exec/executor.d.ts +125 -0
- package/types/exec/host_streams.d.ts +165 -0
- package/types/exec/mod.d.ts +3 -0
- package/types/intrinsics/async_builtins.d.ts +69 -0
- package/types/intrinsics/context.d.ts +28 -0
- package/types/intrinsics/errors.d.ts +5 -0
- package/types/intrinsics/fact_calls.d.ts +120 -0
- package/types/intrinsics/mod.d.ts +187 -0
- package/types/intrinsics/stream_builtins.d.ts +113 -0
- package/types/intrinsics/transcode.d.ts +21 -0
- package/types/jspi/bridge.d.ts +227 -0
- package/types/jspi/mechanics.d.ts +50 -0
- package/types/jspi/mod.d.ts +3 -0
- package/types/jspi/suspending.d.ts +1 -0
- package/types/jspi/types.d.ts +26 -0
- package/types/plan/format.d.ts +369 -0
- package/types/plan/loader.d.ts +113 -0
- package/types/plan/mod.d.ts +2 -0
- package/types/shim/mod.d.ts +1 -0
- package/types/shim/translator.d.ts +55 -0
- package/types/task/mod.d.ts +257 -0
- package/types/task/scheduler.d.ts +421 -0
- package/types/task/streams.d.ts +370 -0
- package/types/task/subtask.d.ts +96 -0
- package/types/task/thread.d.ts +73 -0
- package/types/task/waitable.d.ts +67 -0
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
import { type CanonicalOptions, type ComponentValue, type CoreFuncType, type CoreType, type CoreValue, type FuncType, type PtrType, ResourceTypeInfo } from "../cabi/mod.js";
|
|
2
|
+
import { type BlockRequest, type Cancelled, ComponentInstanceState, Store, Task, Thread } from "../task/mod.js";
|
|
3
|
+
import { type SuspensionMode } from "../jspi/mod.js";
|
|
4
|
+
/**
|
|
5
|
+
* Structural view of an intrinsics `SyncCallScope`: everything this module
|
|
6
|
+
* needs in order to unwind a FACT sync-call bracket a trap escaped.
|
|
7
|
+
*/
|
|
8
|
+
export interface LenderScope {
|
|
9
|
+
releaseLenders(): void;
|
|
10
|
+
}
|
|
11
|
+
/** A raw core function as exposed through the JS WebAssembly API. */
|
|
12
|
+
export type CoreFn = (...args: any[]) => unknown;
|
|
13
|
+
/** Counters exposed for tests/diagnostics on the component handle. */
|
|
14
|
+
export interface ExecutionStats {
|
|
15
|
+
liftedCalls: number;
|
|
16
|
+
tasksResolved: number;
|
|
17
|
+
postReturnsRun: number;
|
|
18
|
+
loweredCalls: number;
|
|
19
|
+
enterSyncCalls: number;
|
|
20
|
+
exitSyncCalls: number;
|
|
21
|
+
/** Callback-export invocations of the async lift loop (`canon_lift`). */
|
|
22
|
+
callbackInvocations: number;
|
|
23
|
+
}
|
|
24
|
+
export declare function newStats(): ExecutionStats;
|
|
25
|
+
/**
|
|
26
|
+
* A `MemInst`-shaped view over a `WebAssembly.Memory` that never goes stale:
|
|
27
|
+
* `bytes`/`view` re-derive from `memory.buffer` whenever the buffer identity
|
|
28
|
+
* changes (memory.grow detaches the previous ArrayBuffer — a cached
|
|
29
|
+
* Uint8Array would silently drop writes). The provider indirection also
|
|
30
|
+
* covers plan-order effects: canonical options can reference a memory whose
|
|
31
|
+
* `extract-memory` initializer runs later; accesses before extraction fail
|
|
32
|
+
* with a PlanError.
|
|
33
|
+
*
|
|
34
|
+
* Structurally compatible with cabi's `MemInst` (same public surface).
|
|
35
|
+
*/
|
|
36
|
+
export declare class LiveMemory {
|
|
37
|
+
#private;
|
|
38
|
+
readonly addrType: PtrType;
|
|
39
|
+
constructor(provider: () => WebAssembly.Memory | undefined, label: string);
|
|
40
|
+
get bytes(): Uint8Array;
|
|
41
|
+
get view(): DataView;
|
|
42
|
+
get length(): number;
|
|
43
|
+
ptrType(): PtrType;
|
|
44
|
+
ptrSize(): 4 | 8;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Canonical options resolved against executor state. `memory` is a
|
|
48
|
+
* LiveMemory (or null); `realloc`/`postReturn`/`callback` resolve lazily so
|
|
49
|
+
* options can be constructed before the corresponding extract initializers
|
|
50
|
+
* run (wasmtime semantics: options hold indices, resolved at use).
|
|
51
|
+
*/
|
|
52
|
+
export interface ResolvedOptions {
|
|
53
|
+
stringEncoding: "utf8" | "utf16" | "latin1+utf16";
|
|
54
|
+
memory: LiveMemory | null;
|
|
55
|
+
realloc: (() => CoreFn | undefined) | null;
|
|
56
|
+
postReturn: (() => CoreFn | undefined) | null;
|
|
57
|
+
callback: (() => CoreFn | undefined) | null;
|
|
58
|
+
async: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* `CanonicalOptions.cancellable` (wasmtime-environ 47.0.3
|
|
61
|
+
* `component/info.rs:540`), i.e. whether a built-in reached through these
|
|
62
|
+
* options is a *cancellable* block point.
|
|
63
|
+
*
|
|
64
|
+
* It lives in the options, not in the trampoline: `Trampoline::
|
|
65
|
+
* WaitableSetWait`/`WaitableSetPoll` carry only `{instance, options}`
|
|
66
|
+
* (info.rs:815-831). definitions.py takes it as the first parameter of
|
|
67
|
+
* `canon_waitable_set_wait` / `canon_waitable_set_poll` (lines 2414/2431),
|
|
68
|
+
* which is the same information arriving by a different route.
|
|
69
|
+
*
|
|
70
|
+
* (`thread.yield` and `subtask.cancel` are the exceptions: wasmtime puts
|
|
71
|
+
* their `cancellable` / `async` flags on the *trampoline*, and those
|
|
72
|
+
* built-ins read them from the decl.)
|
|
73
|
+
*/
|
|
74
|
+
cancellable: boolean;
|
|
75
|
+
coreType: CoreFuncType;
|
|
76
|
+
instance: ComponentInstanceState;
|
|
77
|
+
}
|
|
78
|
+
/** cabi-facing options object (LiftLowerOptions + flatten inputs). */
|
|
79
|
+
export declare function cabiOptions(opts: ResolvedOptions): CanonicalOptions;
|
|
80
|
+
/**
|
|
81
|
+
* Call a core function, mapping core-wasm exceptions to canonical-ABI traps
|
|
82
|
+
* (reference `call_and_trap_on_throw`). Component traps and internal errors
|
|
83
|
+
* of ours propagate unchanged.
|
|
84
|
+
*/
|
|
85
|
+
/**
|
|
86
|
+
* Layering rule: a core-wasm trap's message is engine-specific text (V8,
|
|
87
|
+
* SpiderMonkey, JSC each word `unreachable` differently, for instance) and is
|
|
88
|
+
* passed through here UNTOUCHED — it is diagnostics only, "engine-flavored"
|
|
89
|
+
* and not normalized to any particular host's wording. The runtime never
|
|
90
|
+
* emulates another host's (e.g. wasmtime's) message text.
|
|
91
|
+
*
|
|
92
|
+
* Suite-wording normalization (matching the official test suite's
|
|
93
|
+
* `assert_trap` expectations, which are typically worded per wasmtime) lives
|
|
94
|
+
* in the harness instead: see `TRAP_MESSAGE_EQUIVALENTS` in
|
|
95
|
+
* harness/src/runner.ts, which maps engine-specific spellings to the
|
|
96
|
+
* suite-expected forms at comparison time. (The FACT *adapter* traps take a
|
|
97
|
+
* different route entirely — they arrive as numeric codes through the `trap`
|
|
98
|
+
* trampoline and are runtime-authored text, see `FACT_TRAP_MESSAGES` in
|
|
99
|
+
* intrinsics/mod.ts; that table is untouched by this layering rule.)
|
|
100
|
+
*/
|
|
101
|
+
export declare function callCore(fn: CoreFn, args: CoreValue[]): CoreValue[];
|
|
102
|
+
/**
|
|
103
|
+
* Normalize raw JS-API core values to cabi's canonical lane representation:
|
|
104
|
+
* i32 lanes as unsigned numbers (the JS API yields signed), i64 lanes as
|
|
105
|
+
* unsigned bigints, floats as numbers.
|
|
106
|
+
*/
|
|
107
|
+
export declare function normalizeCoreValues(values: CoreValue[], lanes: CoreType[], what: string): CoreValue[];
|
|
108
|
+
/**
|
|
109
|
+
* THE asynchronous driving loop, exported for the one other driver in the
|
|
110
|
+
* runtime: `HostActivity` in exec/host_streams.ts, which must pump the store
|
|
111
|
+
* BETWEEN export calls (when no lifted call is in flight) with exactly these
|
|
112
|
+
* semantics — service settled tails, tick to quiescence, then await the race
|
|
113
|
+
* of every outstanding promise (parked activations AND `pendingHostCalls`),
|
|
114
|
+
* repeat. Reimplementing it there diverged: that copy only drained
|
|
115
|
+
* `store.awaiting` and never awaited `pendingHostCalls`, so a guest parked on
|
|
116
|
+
* a Promise-returning host import was never resumed and the host's read of
|
|
117
|
+
* the stream it was feeding hung (C0 finding R-1).
|
|
118
|
+
*
|
|
119
|
+
* Callers that must not hit the deadlock traps below (the host pump: an
|
|
120
|
+
* embedder that never does its half is documented to hang, not trap) can
|
|
121
|
+
* exclude them entirely — BOTH trap sites require
|
|
122
|
+
* `store.pendingHostCalls.size === 0`, and both are reached only through the
|
|
123
|
+
* synchronous fall-through from `done()`, so a `done` that returns true
|
|
124
|
+
* whenever `pendingHostCalls` is empty provably never traps.
|
|
125
|
+
*/
|
|
126
|
+
export declare function driveStoreAsync(store: Store, done: () => boolean, what: string): Promise<void>;
|
|
127
|
+
export declare function storeDriverDepth(store: Store): number;
|
|
128
|
+
/** Resolves once no `driveAsync` loop is live on `store`. */
|
|
129
|
+
export declare function whenStoreDriverIdle(store: Store): Promise<void>;
|
|
130
|
+
/**
|
|
131
|
+
* Ensure a settlement pump is watching `store`'s real outstanding host calls.
|
|
132
|
+
* Idempotent and cheap; called at every driver exit. Never throws.
|
|
133
|
+
*/
|
|
134
|
+
export declare function ensureSettlementPump(store: Store): void;
|
|
135
|
+
/**
|
|
136
|
+
* Build the host-callable function for one lifted export (reference
|
|
137
|
+
* `Store.lift` + `canon_lift`, definitions.py lines 578 and 2154).
|
|
138
|
+
*
|
|
139
|
+
* All three lift shapes go through one `Task` + implicit `Thread`:
|
|
140
|
+
*
|
|
141
|
+
* * **sync** (`not ft.async`) — call, lift results, `task.return_`,
|
|
142
|
+
* post-return, then the sync driving loop until the task resolves;
|
|
143
|
+
* * **async + callback** (stackless) — the packed-code loop
|
|
144
|
+
* (EXIT / YIELD / WAIT), fully implemented here;
|
|
145
|
+
* * **async, no callback** (stackful) — the guest blocks mid-stack, which
|
|
146
|
+
* needs genuine wasm-frame suspension: `needsJspi`, at the precise point.
|
|
147
|
+
*/
|
|
148
|
+
/**
|
|
149
|
+
* The plain-entered variant of a `[constructor]` export in jspi mode,
|
|
150
|
+
* attached to the promising-wrapped lifted function under this symbol.
|
|
151
|
+
*
|
|
152
|
+
* A WIT constructor is surfaced as a JS class constructor
|
|
153
|
+
* (contracts/embedder-api.md §"Resources"), and a JS constructor cannot
|
|
154
|
+
* await — but in jspi mode every promising-wrapped entry returns a Promise
|
|
155
|
+
* even when the activation completes without suspending (jspi pin (e)). So
|
|
156
|
+
* constructor exports carry a second lifted function whose ENTRY is plain
|
|
157
|
+
* (unwrapped): a constructor that completes synchronously — the
|
|
158
|
+
* overwhelmingly common case; WIT constructors are always sync-typed —
|
|
159
|
+
* returns its rep synchronously through it.
|
|
160
|
+
*
|
|
161
|
+
* The cost is confined to genuinely-suspending constructors, which no JS
|
|
162
|
+
* host can surface as `new` anyway: a blocking built-in reached through the
|
|
163
|
+
* plain entry signals `NeedsJspi` (a capability error, instance left
|
|
164
|
+
* enterable), and a Suspending-wrapped host import reached from the
|
|
165
|
+
* unwrapped frame fails as a trap. Both name the constructor rather than
|
|
166
|
+
* silently deadlocking.
|
|
167
|
+
*/
|
|
168
|
+
export declare const CONSTRUCTOR_SYNC_ENTRY: unique symbol;
|
|
169
|
+
export declare function createLiftedFunction(input: {
|
|
170
|
+
name: string;
|
|
171
|
+
ft: FuncType;
|
|
172
|
+
opts: ResolvedOptions;
|
|
173
|
+
core: CoreFn;
|
|
174
|
+
stats: ExecutionStats;
|
|
175
|
+
/**
|
|
176
|
+
* Suspension discipline for this instantiation (jspi/bridge.ts). In `jspi`
|
|
177
|
+
* mode the export's core function is `promising`-wrapped, so the whole
|
|
178
|
+
* activation can suspend and the lifted function necessarily returns a
|
|
179
|
+
* Promise.
|
|
180
|
+
*/
|
|
181
|
+
suspensionMode?: SuspensionMode;
|
|
182
|
+
/** Optional; see intrinsics `HostTrapState`. */
|
|
183
|
+
trapState?: {
|
|
184
|
+
pending: unknown;
|
|
185
|
+
};
|
|
186
|
+
/**
|
|
187
|
+
* Optional; the executor's sync-call scope stack (intrinsics
|
|
188
|
+
* `SyncCallScope`). Structural, to keep this module free of an import
|
|
189
|
+
* cycle with `../intrinsics/`.
|
|
190
|
+
*/
|
|
191
|
+
syncCallStack?: LenderScope[];
|
|
192
|
+
/**
|
|
193
|
+
* Optional; every component instance of this component, for restoring
|
|
194
|
+
* `may_leave` when a trap unwinds out of a FACT adapter.
|
|
195
|
+
*/
|
|
196
|
+
allInstances?: () => Iterable<{
|
|
197
|
+
mayLeave: boolean;
|
|
198
|
+
}>;
|
|
199
|
+
/**
|
|
200
|
+
* Opt out of the reference's *synchronous* driving loop (`driveSyncLift`,
|
|
201
|
+
* definitions.py `canon_lift` line 2213) for a sync-typed lift whose caller
|
|
202
|
+
* does not need a synchronous answer — today only the host-initiated
|
|
203
|
+
* resource destructor (#160; `createDtorEntry` below, `drop(): void` is
|
|
204
|
+
* documented non-blocking).
|
|
205
|
+
*
|
|
206
|
+
* This is not a weakening of the deadlock trap: `drive` below enforces the
|
|
207
|
+
* same "no ready thread, no pending host call, nothing awaiting" trap, just
|
|
208
|
+
* asynchronously — which is exactly the substitution jspi mode already
|
|
209
|
+
* makes unconditionally (see the comment at the `driveSyncLift` call).
|
|
210
|
+
* It matters only when a *plain*-mode core returns a thenable, i.e. a
|
|
211
|
+
* host-supplied JS destructor: the sync loop sees a thread parked on a
|
|
212
|
+
* Promise, which it can never advance, and declares a bogus deadlock.
|
|
213
|
+
*/
|
|
214
|
+
allowAsyncCompletion?: boolean;
|
|
215
|
+
}): (...args: ComponentValue[]) => unknown;
|
|
216
|
+
/**
|
|
217
|
+
* Build the host-callable entry for a resource destructor — a full canonical
|
|
218
|
+
* **lift**, exactly as definitions.py `canon_resource_drop` (line 2319) does:
|
|
219
|
+
*
|
|
220
|
+
* ```python
|
|
221
|
+
* opts = CanonicalOptions(async_ = False)
|
|
222
|
+
* ft = FuncType([U32Type()], [], async_ = False)
|
|
223
|
+
* dtor = rt.dtor or (lambda rep: [])
|
|
224
|
+
* callee = inst.store.lift(dtor, ft, opts, rt.impl)
|
|
225
|
+
* ```
|
|
226
|
+
*
|
|
227
|
+
* Before #160 the host-initiated path (embedder `drop()`, the GC backstop,
|
|
228
|
+
* `dropOwn`) hand-rolled the bracket in cabi/handles.ts `callDtorGated`: a
|
|
229
|
+
* bare call to the dtor with `enterFrom(null)` HELD across the returned
|
|
230
|
+
* promise. Three defects followed from having no Task/Thread behind the
|
|
231
|
+
* activation:
|
|
232
|
+
*
|
|
233
|
+
* - **#160 itself**: the held bracket left the impl instance non-enterable,
|
|
234
|
+
* so `Store.tick`'s enterability filter (#155) could never resume a
|
|
235
|
+
* suspension point belonging to the dtor's own activation. The completion
|
|
236
|
+
* promise sat in `pendingHostCalls` looking like external work, and every
|
|
237
|
+
* driver parked on it forever.
|
|
238
|
+
* - it was the runtime's only `enterFrom(null)` bracket spanning an await —
|
|
239
|
+
* the macro-scale reachability window of the #156 class, through which a
|
|
240
|
+
* sibling instance looked non-enterable from the synthetic root.
|
|
241
|
+
* - built-ins reached inside the dtor had no ambient task (`currentTask()`
|
|
242
|
+
* → `PendingCapability`, or a foreign-task misattribution, the #24 class).
|
|
243
|
+
*
|
|
244
|
+
* Under the lift harness all three go away structurally: the activation has a
|
|
245
|
+
* real `Task` + implicit `Thread`, the entry bracket is released when the
|
|
246
|
+
* first segment parks (`leave()` before `drive`), and settled tails flow
|
|
247
|
+
* through `serviceSettled` like any other lifted sync call.
|
|
248
|
+
*
|
|
249
|
+
* The returned function takes the rep and returns either `undefined` (the
|
|
250
|
+
* activation completed synchronously — the overwhelmingly common case) or a
|
|
251
|
+
* Promise, exactly like any lifted sync export in jspi mode.
|
|
252
|
+
*/
|
|
253
|
+
export declare function createDtorEntry(input: {
|
|
254
|
+
/** Diagnostic name; appears in deadlock/trap messages. */
|
|
255
|
+
name?: string;
|
|
256
|
+
/**
|
|
257
|
+
* The destructor's core function, unwrapped: `createLiftedFunction` applies
|
|
258
|
+
* `enterWasm` itself per `suspensionMode`. `null` is the reference's
|
|
259
|
+
* `rt.dtor or (lambda rep: [])` — the bracket still runs.
|
|
260
|
+
*/
|
|
261
|
+
dtor: CoreFn | null;
|
|
262
|
+
/** `rt.impl`, the implementing instance the lift enters. */
|
|
263
|
+
instance: ComponentInstanceState;
|
|
264
|
+
suspensionMode?: SuspensionMode;
|
|
265
|
+
stats?: ExecutionStats;
|
|
266
|
+
trapState?: {
|
|
267
|
+
pending: unknown;
|
|
268
|
+
};
|
|
269
|
+
syncCallStack?: LenderScope[];
|
|
270
|
+
allInstances?: () => Iterable<{
|
|
271
|
+
mayLeave: boolean;
|
|
272
|
+
}>;
|
|
273
|
+
}): (rep: number) => unknown;
|
|
274
|
+
/**
|
|
275
|
+
* Run a host-initiated drop of a guest (or host-implemented) resource rep —
|
|
276
|
+
* the observable remainder of `canon_resource_drop` for an owning handle when
|
|
277
|
+
* the holder is the host (`caller = None`, `Store.invoke`).
|
|
278
|
+
*
|
|
279
|
+
* A failure that arrives asynchronously has no frame to propagate into, so it
|
|
280
|
+
* is parked on the store's host-failure channel (first failure wins), where
|
|
281
|
+
* the next driven call surfaces it. The completion promise is deliberately
|
|
282
|
+
* NOT registered in `store.pendingHostCalls`: that registration was #160's
|
|
283
|
+
* lie — it claims *external* work for a promise whose settlement may need
|
|
284
|
+
* this very scheduler. The dtor's genuine external dependencies (its host
|
|
285
|
+
* imports) register themselves when they park. Poisoning on a trap now
|
|
286
|
+
* happens inside the lift harness (`poison()` in `createLiftedFunction`).
|
|
287
|
+
*/
|
|
288
|
+
export declare function hostDtorCall(rt: ResourceTypeInfo, rep: number): void;
|
|
289
|
+
/**
|
|
290
|
+
* Call into wasm and hand back the result, awaiting it only if it is a
|
|
291
|
+
* Promise.
|
|
292
|
+
*
|
|
293
|
+
* This is the whole of the jspi entry seam. In **plain** mode the entry is not
|
|
294
|
+
* `promising`-wrapped, `callCore` returns core values, and this returns them
|
|
295
|
+
* without yielding — no await, no Promise allocation, the identical
|
|
296
|
+
* synchronous path M1 shipped. In **jspi** mode the entry *is* wrapped, so the
|
|
297
|
+
* call returns a Promise (jspi pin (e)) and we park the thread on it via the
|
|
298
|
+
* `awaitValue` block request; the driving loop resumes us with the values, or
|
|
299
|
+
* throws the rejection in (a post-resume trap).
|
|
300
|
+
*/
|
|
301
|
+
export declare function awaitCore(fn: CoreFn, args: CoreValue[], thread: any): Generator<BlockRequest, CoreValue[], unknown>;
|
|
302
|
+
/** definitions.py `CallbackCode` (line 2220). */
|
|
303
|
+
declare enum CallbackCode {
|
|
304
|
+
EXIT = 0,
|
|
305
|
+
YIELD = 1,
|
|
306
|
+
WAIT = 2
|
|
307
|
+
}
|
|
308
|
+
/** definitions.py `unpack_callback_result` (line 2226). */
|
|
309
|
+
export declare function unpackCallbackResult(packed: number): [code: CallbackCode, waitableSetIndex: number];
|
|
310
|
+
/**
|
|
311
|
+
* Build the core-callable body for one lowered host import (reference
|
|
312
|
+
* `canon_lower`, definitions.py line 2242).
|
|
313
|
+
*
|
|
314
|
+
* Sync and async lowers share one `Subtask` and one pair of
|
|
315
|
+
* `on_start`/`on_resolve` closures, exactly as the reference does; the sync
|
|
316
|
+
* case is the degenerate one where the callee resolves before returning.
|
|
317
|
+
*
|
|
318
|
+
* The host callee is a plain JS function. If it returns a **Promise**, the
|
|
319
|
+
* subtask resolves when that promise settles:
|
|
320
|
+
*
|
|
321
|
+
* * async lower — fully supported and JSPI-free. The guest gets a STARTED
|
|
322
|
+
* subtask back, joins it to a waitable set, returns WAIT from its
|
|
323
|
+
* callback, and the scheduler delivers the SUBTASK event once the promise
|
|
324
|
+
* settles. This is the flagship capability of this phase: an ordinary
|
|
325
|
+
* `async` JS function is a valid Component Model async import.
|
|
326
|
+
* * sync lower — the guest's wasm frame would have to block
|
|
327
|
+
* (`thread.wait_until(subtask.resolved)`, line 2286), so: `needsJspi`.
|
|
328
|
+
*/
|
|
329
|
+
export declare function createLoweredImport(input: {
|
|
330
|
+
name: string;
|
|
331
|
+
ft: FuncType;
|
|
332
|
+
opts: ResolvedOptions;
|
|
333
|
+
hostFn: (...args: unknown[]) => unknown;
|
|
334
|
+
stats: ExecutionStats;
|
|
335
|
+
/** Executor's suspension mode; decides whether a sync lower may park. */
|
|
336
|
+
mode: SuspensionMode;
|
|
337
|
+
/** Host fn carries the `suspending()` brand (embedder-api.md A1). */
|
|
338
|
+
suspendable: boolean;
|
|
339
|
+
}): CoreFn;
|
|
340
|
+
/**
|
|
341
|
+
* The callback-ABI dispatch loop of `canon_lift` (definitions.py lines
|
|
342
|
+
* 2183-2214), factored out so both entry points share one implementation:
|
|
343
|
+
*
|
|
344
|
+
* * a host-boundary lift (`liftBody` above), and
|
|
345
|
+
* * a FACT cross-component call, where the host invokes an async-lifted
|
|
346
|
+
* callee on the caller's behalf (`intrinsics/fact_calls.ts`).
|
|
347
|
+
*
|
|
348
|
+
* `packed` is the code the *initial* activation returned; the loop runs until
|
|
349
|
+
* it sees EXIT, invoking the callback export with each delivered event.
|
|
350
|
+
*/
|
|
351
|
+
export declare function runCallbackLoop(input: {
|
|
352
|
+
name: string;
|
|
353
|
+
task: Task;
|
|
354
|
+
thread: Thread;
|
|
355
|
+
inst: ComponentInstanceState;
|
|
356
|
+
callback: CoreFn;
|
|
357
|
+
packed: number;
|
|
358
|
+
stats: ExecutionStats;
|
|
359
|
+
}): Generator<BlockRequest, void, Cancelled>;
|
|
360
|
+
export {};
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import type { ComponentValue } from "../cabi/types.js";
|
|
2
|
+
import { ComponentInstanceState } from "../task/mod.js";
|
|
3
|
+
import type { WirePlan } from "../plan/format.js";
|
|
4
|
+
import type { LoadedPlan } from "../plan/loader.js";
|
|
5
|
+
import { type ExecutionStats } from "./boundary.js";
|
|
6
|
+
/**
|
|
7
|
+
* Host-provided imports: a nested record keyed by the component's *exact*
|
|
8
|
+
* import strings. A plan import with a non-empty `path` (an item extracted
|
|
9
|
+
* from an imported instance — plan-format.md v0.1 amendment #4) is looked up
|
|
10
|
+
* by walking `imports[name]` then each path segment in order. So an import
|
|
11
|
+
* of `"ns:pkg/iface"` exposing `f` is supplied as
|
|
12
|
+
* `{ "ns:pkg/iface": { f: (…) => … } }`.
|
|
13
|
+
*
|
|
14
|
+
* Leaf values by import kind:
|
|
15
|
+
* - `func` — a JS function; arguments/results are host-shaped
|
|
16
|
+
* component values (contracts/descriptor-ir.md).
|
|
17
|
+
* - `resource` — a `HostResourceType` (see `hostResourceType`).
|
|
18
|
+
* - `instance` — a plain object; only its leaves are ever read.
|
|
19
|
+
* - `module` — not supported (see `InstantiateModule::Import` below).
|
|
20
|
+
*/
|
|
21
|
+
export type HostImports = Record<string, unknown>;
|
|
22
|
+
/**
|
|
23
|
+
* Identity token for a resource type **defined by the host** and imported by
|
|
24
|
+
* a component (plan `importedResources`). One object per resource type;
|
|
25
|
+
* object identity is the type identity, exactly as for guest-defined
|
|
26
|
+
* resources whose identity is the per-instantiation `ResourceTypeInfo`.
|
|
27
|
+
*/
|
|
28
|
+
export declare class HostResourceType {
|
|
29
|
+
readonly options: {
|
|
30
|
+
/** Debug name, used in error messages only. */
|
|
31
|
+
readonly name?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Destructor for handles owned by a component and dropped there.
|
|
34
|
+
* Per docs/architecture.md §7 / CanonicalABI.md `canon resource.drop`, it runs
|
|
35
|
+
* synchronously and may not block.
|
|
36
|
+
*/
|
|
37
|
+
readonly dtor?: (rep: number) => void;
|
|
38
|
+
};
|
|
39
|
+
constructor(options?: {
|
|
40
|
+
/** Debug name, used in error messages only. */
|
|
41
|
+
readonly name?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Destructor for handles owned by a component and dropped there.
|
|
44
|
+
* Per docs/architecture.md §7 / CanonicalABI.md `canon resource.drop`, it runs
|
|
45
|
+
* synchronously and may not block.
|
|
46
|
+
*/
|
|
47
|
+
readonly dtor?: (rep: number) => void;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/** Convenience constructor for {@link HostResourceType}. */
|
|
51
|
+
export declare function hostResourceType(options?: HostResourceType["options"]): HostResourceType;
|
|
52
|
+
export interface InstantiateInput {
|
|
53
|
+
plan: WirePlan;
|
|
54
|
+
/** The original component binary (embedded modules are sliced from it). */
|
|
55
|
+
componentBytes: Uint8Array;
|
|
56
|
+
/** FACT adapter artifacts keyed by `plan.modules[].file`. */
|
|
57
|
+
adapters?: Map<string, Uint8Array>;
|
|
58
|
+
imports?: HostImports;
|
|
59
|
+
/** Verify plan.component.sha256 against componentBytes (default true). */
|
|
60
|
+
verifyHash?: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Opt in to JSPI-backed suspension (docs/architecture.md §6 role 1-3).
|
|
63
|
+
*
|
|
64
|
+
* Off by default, and deliberately so: in this mode every lifted export
|
|
65
|
+
* returns a Promise (empirical fact (e) — `WebAssembly.promising` always
|
|
66
|
+
* does), which is an API-shape change. Ignored on an engine without JSPI,
|
|
67
|
+
* where every blocking site keeps raising the precise `NeedsJspi` it raises
|
|
68
|
+
* today (the M3 degradation path).
|
|
69
|
+
*/
|
|
70
|
+
jspi?: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* A plan already converted by `loadPlan`, used instead of re-loading.
|
|
73
|
+
*
|
|
74
|
+
* Why this exists: the conventions layer (`src/embedder/`) must have the
|
|
75
|
+
* per-instantiation `ResourceTypeInfo` identity tokens and the converted
|
|
76
|
+
* types table *before* instantiation begins, because host imports genuinely
|
|
77
|
+
* fire DURING it — a core module's `start` function runs inside
|
|
78
|
+
* `runInitializers`, and real guests do call imports from it (Go's runtime
|
|
79
|
+
* calls `monotonic-clock.now()` from `schedinit`). Reading them off the
|
|
80
|
+
* returned `ComponentHandle.loadedPlan` is therefore too late. Handing the
|
|
81
|
+
* same `LoadedPlan` in keeps the tokens identical on both sides.
|
|
82
|
+
*
|
|
83
|
+
* Contract: one `LoadedPlan` per instantiation (tokens must be fresh per
|
|
84
|
+
* component instance), and `loadedPlan.wire` must be `plan`. Both are
|
|
85
|
+
* checked.
|
|
86
|
+
*/
|
|
87
|
+
loadedPlan?: LoadedPlan;
|
|
88
|
+
}
|
|
89
|
+
/** An instantiated component: its export surface plus introspection state. */
|
|
90
|
+
export interface ComponentHandle {
|
|
91
|
+
/** Lifted functions / nested instance objects, by export name. */
|
|
92
|
+
exports: Record<string, unknown>;
|
|
93
|
+
stats: ExecutionStats;
|
|
94
|
+
componentInstances: ComponentInstanceState[];
|
|
95
|
+
coreInstances: WebAssembly.Instance[];
|
|
96
|
+
/** See `Executor.suspendableFuncs`. */
|
|
97
|
+
suspendableFuncs: WeakSet<object>;
|
|
98
|
+
taskMayBlock: WebAssembly.Global;
|
|
99
|
+
/** `ResourceIndex` -> the `HostResourceType` bound to it, if any. */
|
|
100
|
+
hostResourceTypes: Map<number, HostResourceType>;
|
|
101
|
+
/**
|
|
102
|
+
* Plan exports deliberately absent from `exports`, by export path, with the
|
|
103
|
+
* reason. Only `type` exports appear here; a missing *function* export is
|
|
104
|
+
* always an error, never an omission (see `Executor.buildExport`).
|
|
105
|
+
*/
|
|
106
|
+
omittedExports: Map<string, string>;
|
|
107
|
+
/**
|
|
108
|
+
* The plan as loaded for THIS instantiation.
|
|
109
|
+
*
|
|
110
|
+
* Exposed for the conventions layer (`src/embedder/`), which needs the two
|
|
111
|
+
* things only the executor's own `loadPlan` call can supply: the per-instance
|
|
112
|
+
* `ResourceTypeInfo` identity tokens (`resourceTokens`) — the same objects
|
|
113
|
+
* the `own`/`borrow` types in every signature point at, and the only route to
|
|
114
|
+
* a resource's destructor for a *host-initiated* drop of a guest handle
|
|
115
|
+
* (definitions.py `canon_resource_drop` runs `rt.dtor(rep)`; the host holds
|
|
116
|
+
* reps, never table indices, so there is no handle to drop through) — and the
|
|
117
|
+
* converted `types` table it reads function signatures from.
|
|
118
|
+
*
|
|
119
|
+
* Introspection only: mutating it is undefined behaviour.
|
|
120
|
+
*/
|
|
121
|
+
loadedPlan: LoadedPlan;
|
|
122
|
+
}
|
|
123
|
+
export declare function instantiateComponent(input: InstantiateInput): Promise<ComponentHandle>;
|
|
124
|
+
/** Convenience for callers: typed view of a lifted export. */
|
|
125
|
+
export type LiftedFunction = (...args: ComponentValue[]) => unknown;
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import type { ComponentValue, ValType } from "../cabi/types.js";
|
|
2
|
+
import { CopyResult, type PayloadChunk, sameElemType } from "../task/mod.js";
|
|
3
|
+
/**
|
|
4
|
+
* A buffer over JS values. Sibling of `GuestBuffer`, same four methods, no
|
|
5
|
+
* memory access. Used in one of two directions:
|
|
6
|
+
*
|
|
7
|
+
* * as a *readable* buffer (host supplies `values`, the guest reads them);
|
|
8
|
+
* * as a *writable* buffer (host supplies capacity, the guest fills it and
|
|
9
|
+
* `taken()` is what arrived).
|
|
10
|
+
*
|
|
11
|
+
* u8 payloads stay `Uint8Array` through both directions (issue #54): `read`
|
|
12
|
+
* slices the typed array (bulk, and the ONE semantically required copy — the
|
|
13
|
+
* chunk is only borrowed by the stream until the write settles, so the reader
|
|
14
|
+
* must receive owned bytes), and `write` keeps arriving chunks whole instead
|
|
15
|
+
* of exploding them element-by-element into a plain array.
|
|
16
|
+
*/
|
|
17
|
+
export declare class HostBuffer {
|
|
18
|
+
#private;
|
|
19
|
+
readonly t: ValType | null;
|
|
20
|
+
private readonly values;
|
|
21
|
+
readonly length: number;
|
|
22
|
+
progress: number;
|
|
23
|
+
constructor(t: ValType | null, values: PayloadChunk | null, length: number);
|
|
24
|
+
remain(): number;
|
|
25
|
+
isZeroLength(): boolean;
|
|
26
|
+
/** Guest side is reading from us. */
|
|
27
|
+
read(n: number): PayloadChunk;
|
|
28
|
+
/** Guest side is writing into us. */
|
|
29
|
+
write(vs: PayloadChunk): void;
|
|
30
|
+
/**
|
|
31
|
+
* Everything written into this buffer, in arrival order.
|
|
32
|
+
*
|
|
33
|
+
* For a u8 element type the result is a `Uint8Array`; in the common case —
|
|
34
|
+
* one rendezvous before the read resolves — the writer's chunk is returned
|
|
35
|
+
* as-is, so the whole host-side read costs exactly the one rendezvous copy.
|
|
36
|
+
* Every other element type yields a plain array regardless of the shape the
|
|
37
|
+
* writer used.
|
|
38
|
+
*/
|
|
39
|
+
taken(): PayloadChunk;
|
|
40
|
+
}
|
|
41
|
+
/** Host end the embedder WRITES; the guest reads. */
|
|
42
|
+
export interface HostWritableEnd<T> {
|
|
43
|
+
/**
|
|
44
|
+
* Offer `values`. Resolves with how many the guest actually took — a
|
|
45
|
+
* partial copy is normal, not an error (definitions.py copies
|
|
46
|
+
* `min(remain, remain)`). Re-offer the remainder to finish.
|
|
47
|
+
*
|
|
48
|
+
* `values` is BORROWED until the returned promise settles (the buffer may
|
|
49
|
+
* stay parked across several partial reads); mutating it in that window is
|
|
50
|
+
* misuse. Readers always receive their own copy.
|
|
51
|
+
*/
|
|
52
|
+
write(values: T[]): Promise<number>;
|
|
53
|
+
/**
|
|
54
|
+
* Offer `values` repeatedly until all of them have been taken or the reader
|
|
55
|
+
* goes away. Convenience over `write`, and the shape most embedders want.
|
|
56
|
+
*
|
|
57
|
+
* The loop is unavoidable in the single-shot form because of *which side
|
|
58
|
+
* arrives second*: when the host arrives second the reference completes the
|
|
59
|
+
* arriving call with just the count copied in that rendezvous
|
|
60
|
+
* (`SharedStreamImpl.write` -> `on_copy_done(COMPLETED)`), leaving the rest
|
|
61
|
+
* of the offer unsent. When the host arrives *first* it stays parked and is
|
|
62
|
+
* drained across several guest reads. `writeAll` papers over the difference.
|
|
63
|
+
*
|
|
64
|
+
* Resolves with the total accepted, which is less than `values.length` only
|
|
65
|
+
* if the reader dropped.
|
|
66
|
+
*/
|
|
67
|
+
writeAll(values: T[]): Promise<number>;
|
|
68
|
+
/**
|
|
69
|
+
* Cancel an in-flight `write`/`writeAll` (definitions.py
|
|
70
|
+
* `SharedStreamImpl.cancel` -> `CopyResult.CANCELLED`). No-op when nothing
|
|
71
|
+
* of ours is parked. Surfaced per the R-fix review's stream advisory 1: the
|
|
72
|
+
* cancel channel existed on the shared object but had no embedder-facing
|
|
73
|
+
* spelling, so a host writer could only be abandoned, never retracted.
|
|
74
|
+
*/
|
|
75
|
+
cancelWrite(): void;
|
|
76
|
+
/** definitions.py `SharedStreamImpl.drop`: notifies a parked reader. */
|
|
77
|
+
drop(): void;
|
|
78
|
+
/**
|
|
79
|
+
* Fire `fn` once the stream becomes dropped — by either end, including
|
|
80
|
+
* the A7 teardown walk (immediately, if it already is). The embedder's
|
|
81
|
+
* producer pump uses it to cancel a producer parked on an external
|
|
82
|
+
* event (amendment A13's cancellation companion).
|
|
83
|
+
*/
|
|
84
|
+
onDropped(fn: () => void): void;
|
|
85
|
+
}
|
|
86
|
+
/** Host end the embedder READS; the guest writes. */
|
|
87
|
+
export interface HostReadableEnd<T> {
|
|
88
|
+
/**
|
|
89
|
+
* Resolves with up to `max` values once the guest writes (or an empty
|
|
90
|
+
* chunk on drop). A u8 stream resolves with a `Uint8Array` (see
|
|
91
|
+
* `HostBuffer.taken`); every other element type resolves with a plain
|
|
92
|
+
* array.
|
|
93
|
+
*/
|
|
94
|
+
read(max: number): Promise<T[]>;
|
|
95
|
+
/** Cancel an in-flight `read`; see `HostWritableEnd.cancelWrite`. */
|
|
96
|
+
cancelRead(): void;
|
|
97
|
+
drop(): void;
|
|
98
|
+
}
|
|
99
|
+
export interface HostStream<T> {
|
|
100
|
+
readable: HostReadableEnd<T>;
|
|
101
|
+
writable: HostWritableEnd<T>;
|
|
102
|
+
/**
|
|
103
|
+
* The value to pass across the boundary. Lowering it into a guest gives the
|
|
104
|
+
* guest the **readable** end (`lower_stream`), so an embedder feeding a
|
|
105
|
+
* guest uses `writable`; an embedder consuming a guest-produced stream gets
|
|
106
|
+
* its shared object from the lift and wraps it with `hostStreamFor`.
|
|
107
|
+
*/
|
|
108
|
+
value: ComponentValue;
|
|
109
|
+
}
|
|
110
|
+
/** Create a host-owned stream of `element` (`null` = zero-width payload). */
|
|
111
|
+
export declare function hostStream<T>(element: ValType | null): HostStream<T>;
|
|
112
|
+
/**
|
|
113
|
+
* Wrap a stream that came *out* of a guest (from `liftStream`). Idempotent:
|
|
114
|
+
* a shared object that already has a host wrapper (it was created by
|
|
115
|
+
* `hostStream`, or lifted before) yields that same wrapper.
|
|
116
|
+
*/
|
|
117
|
+
export declare function hostStreamFor<T>(value: ComponentValue): HostStream<T>;
|
|
118
|
+
export interface HostFuture<T> {
|
|
119
|
+
/** Deliver the future's single value. */
|
|
120
|
+
write(value: T): Promise<void>;
|
|
121
|
+
/** Await the future's single value. */
|
|
122
|
+
read(): Promise<T | undefined>;
|
|
123
|
+
/**
|
|
124
|
+
* `read`, but reporting *why* it settled. A future carries at most one
|
|
125
|
+
* value, so `read`'s `undefined` is ambiguous between "the value was
|
|
126
|
+
* `undefined`" (a `future<void>`) and "the write end dropped without ever
|
|
127
|
+
* writing" — the case the conventions layer must turn into a
|
|
128
|
+
* `DroppedError` (R-fix review advisory 4). `result` disambiguates:
|
|
129
|
+
* `COMPLETED` iff `value` is real.
|
|
130
|
+
*/
|
|
131
|
+
readResult(): Promise<{
|
|
132
|
+
value: T | undefined;
|
|
133
|
+
result: CopyResult;
|
|
134
|
+
}>;
|
|
135
|
+
/** Cancel an in-flight `read`/`write`; see `HostWritableEnd.cancelWrite`. */
|
|
136
|
+
cancel(): void;
|
|
137
|
+
/**
|
|
138
|
+
* Release this future. Total and idempotent (#90): it never throws, and a
|
|
139
|
+
* second call is a no-op.
|
|
140
|
+
*
|
|
141
|
+
* Three cases, per the #90 ruling:
|
|
142
|
+
*
|
|
143
|
+
* * the value was already delivered (the normal write-then-drop path) —
|
|
144
|
+
* plain state cleanup, the spec's `WritableFutureEnd.drop` precondition
|
|
145
|
+
* (definitions.py:1183-1184) is satisfied;
|
|
146
|
+
* * never written, and the future was **lowered** into a guest (the guest
|
|
147
|
+
* holds the readable end, so this wrapper plays the spec's writable
|
|
148
|
+
* role) — *abandon*: the reader can never be satisfied, so it is armed
|
|
149
|
+
* with the rendezvous-point trap (task/streams.ts `abandonSharedFuture`)
|
|
150
|
+
* rather than being handed a DROPPED it may not observe;
|
|
151
|
+
* * never written and never lowered — no guest ever saw it; plain
|
|
152
|
+
* cleanup.
|
|
153
|
+
*/
|
|
154
|
+
drop(): void;
|
|
155
|
+
value: ComponentValue;
|
|
156
|
+
}
|
|
157
|
+
/** Create a host-owned future of `element`. */
|
|
158
|
+
export declare function hostFuture<T>(element: ValType | null): HostFuture<T>;
|
|
159
|
+
/**
|
|
160
|
+
* Wrap a future that came *out* of a guest (from `liftFuture`). Idempotent —
|
|
161
|
+
* see `hostStreamFor`.
|
|
162
|
+
*/
|
|
163
|
+
export declare function hostFutureFor<T>(value: ComponentValue): HostFuture<T>;
|
|
164
|
+
/** Re-exported so embedders can build element types without importing cabi. */
|
|
165
|
+
export { sameElemType };
|