@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,69 @@
|
|
|
1
|
+
import type { SuspensionMode } from "../jspi/mod.js";
|
|
2
|
+
import type { ValType } from "../cabi/types.js";
|
|
3
|
+
import type { ComponentInstanceState } from "../task/mod.js";
|
|
4
|
+
import type { CoreFn, ResolvedOptions } from "../exec/boundary.js";
|
|
5
|
+
/** Services these built-ins need from the executor. */
|
|
6
|
+
export interface AsyncTrampolineContext {
|
|
7
|
+
componentInstance(index: number): ComponentInstanceState;
|
|
8
|
+
/** Resolved canonical options by `canonicalOptions` index. */
|
|
9
|
+
options(index: number): ResolvedOptions;
|
|
10
|
+
/** The element types of an interned results *tuple* (`task-return`). */
|
|
11
|
+
resultTypes(index: number): ValType[];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* `BLOCKED` sentinel of `canon_subtask_cancel` (definitions.py line 2467).
|
|
15
|
+
*/
|
|
16
|
+
export declare const BLOCKED = 4294967295;
|
|
17
|
+
/** definitions.py `canon_task_return` (line 2384). */
|
|
18
|
+
export declare function createTaskReturn(decl: {
|
|
19
|
+
results: number;
|
|
20
|
+
resultType: number | null;
|
|
21
|
+
options: number;
|
|
22
|
+
}, ctx: AsyncTrampolineContext): CoreFn;
|
|
23
|
+
/** definitions.py `canon_task_cancel` (line 2397). */
|
|
24
|
+
export declare function createTaskCancel(): CoreFn;
|
|
25
|
+
/** definitions.py `canon_backpressure_inc` (line 2368). */
|
|
26
|
+
export declare function createBackpressureInc(inst: ComponentInstanceState): CoreFn;
|
|
27
|
+
/** definitions.py `canon_backpressure_dec` (line 2375). */
|
|
28
|
+
export declare function createBackpressureDec(inst: ComponentInstanceState): CoreFn;
|
|
29
|
+
/** definitions.py `canon_waitable_set_new` (line 2406). */
|
|
30
|
+
export declare function createWaitableSetNew(inst: ComponentInstanceState): CoreFn;
|
|
31
|
+
/**
|
|
32
|
+
* definitions.py `canon_waitable_set_wait` (line 2414).
|
|
33
|
+
*
|
|
34
|
+
* The reference blocks the calling thread until the set has an event. From a
|
|
35
|
+
* stackless (callback-ABI) guest there is no wasm stack to suspend, so this
|
|
36
|
+
* only succeeds when an event is *already* pending — which is the reference's
|
|
37
|
+
* own non-blocking branch of `Thread.wait_until`. Otherwise: `needsJspi`.
|
|
38
|
+
*
|
|
39
|
+
* A guest using the callback ABI is expected to return the `WAIT` callback
|
|
40
|
+
* code rather than call this built-in; hitting the JSPI path here means the
|
|
41
|
+
* component uses the stackful async ABI.
|
|
42
|
+
*/
|
|
43
|
+
export declare function createWaitableSetWait(decl: {
|
|
44
|
+
options: number;
|
|
45
|
+
}, ctx: AsyncTrampolineContext, inst: ComponentInstanceState, mode?: SuspensionMode): CoreFn;
|
|
46
|
+
/** definitions.py `canon_waitable_set_poll` (line 2431). */
|
|
47
|
+
export declare function createWaitableSetPoll(decl: {
|
|
48
|
+
options: number;
|
|
49
|
+
}, ctx: AsyncTrampolineContext, inst: ComponentInstanceState): CoreFn;
|
|
50
|
+
/** definitions.py `canon_waitable_set_drop` (line 2441). */
|
|
51
|
+
export declare function createWaitableSetDrop(inst: ComponentInstanceState): CoreFn;
|
|
52
|
+
/** definitions.py `canon_waitable_join` (line 2451). */
|
|
53
|
+
export declare function createWaitableJoin(inst: ComponentInstanceState): CoreFn;
|
|
54
|
+
/** definitions.py `canon_subtask_drop` (line 2494). */
|
|
55
|
+
export declare function createSubtaskDrop(inst: ComponentInstanceState): CoreFn;
|
|
56
|
+
export declare function createSubtaskCancel(decl: {
|
|
57
|
+
async?: boolean;
|
|
58
|
+
}, inst: ComponentInstanceState, mode?: SuspensionMode): CoreFn;
|
|
59
|
+
/**
|
|
60
|
+
* definitions.py `canon_thread_yield` (line 2728).
|
|
61
|
+
*
|
|
62
|
+
* Yielding blocks the calling wasm frame until the scheduler comes back to
|
|
63
|
+
* it. A callback-ABI guest expresses the same intent by returning the `YIELD`
|
|
64
|
+
* callback code, which this runtime implements fully (exec/boundary.ts); the
|
|
65
|
+
* *built-in* form needs a suspendable stack.
|
|
66
|
+
*/
|
|
67
|
+
export declare function createThreadYield(decl: {
|
|
68
|
+
cancellable?: boolean;
|
|
69
|
+
}, mode?: SuspensionMode): CoreFn;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { CoreFn } from "../exec/boundary.js";
|
|
2
|
+
/**
|
|
3
|
+
* Number of `i32` context slots per thread. definitions.py `Thread.storage`
|
|
4
|
+
* is initialised `[0,0]` (line 347) and `canon_context_{get,set}` assert
|
|
5
|
+
* `i < len(thread.storage)` — so exactly two, matching the intrinsic names
|
|
6
|
+
* `context-*-i32-0` and `context-*-i32-1`.
|
|
7
|
+
*/
|
|
8
|
+
export declare const NUM_CONTEXT_SLOTS = 2;
|
|
9
|
+
/**
|
|
10
|
+
* definitions.py `canon_context_get` (line 2348).
|
|
11
|
+
*
|
|
12
|
+
* The storage is **per thread**, not per task: two threads of one task have
|
|
13
|
+
* independent context. wit-bindgen 0.60 keeps its async-executor task pointer
|
|
14
|
+
* in slot 0, which is why this intrinsic is the entry blocker for async
|
|
15
|
+
* guests.
|
|
16
|
+
*/
|
|
17
|
+
export declare function canonContextGet(i: number): number;
|
|
18
|
+
export declare function ctxThreadId(t: unknown): string;
|
|
19
|
+
/** definitions.py `canon_context_set` (line 2358). */
|
|
20
|
+
export declare function canonContextSet(i: number, v: number): void;
|
|
21
|
+
/**
|
|
22
|
+
* Materialize one `unsafe-intrinsic` CoreDef as a core function.
|
|
23
|
+
*
|
|
24
|
+
* Called during initializer resolution — i.e. at instantiate time — so an
|
|
25
|
+
* unimplementable symbol fails instantiation rather than the first call
|
|
26
|
+
* (contracts/plan-format.md "Executor obligations").
|
|
27
|
+
*/
|
|
28
|
+
export declare function createUnsafeIntrinsic(symbol: string): CoreFn;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import type { CoreValue, ValType } from "../cabi/types.js";
|
|
2
|
+
import { ComponentInstanceState } from "../task/mod.js";
|
|
3
|
+
import { type CoreFn, type ExecutionStats } from "../exec/boundary.js";
|
|
4
|
+
/** `START_FLAG_ASYNC_CALLEE` (`component.rs:52`). */
|
|
5
|
+
export declare const START_FLAG_ASYNC_CALLEE = 1;
|
|
6
|
+
/** The state `prepare-call` stashes for the following `*-start-call`. */
|
|
7
|
+
export interface PreparedCall {
|
|
8
|
+
/** `[async-start]` adapter export — the reference's `on_start`. */
|
|
9
|
+
start: CoreFn;
|
|
10
|
+
/** `[async-return]` adapter export — the reference's `on_resolve`. */
|
|
11
|
+
return_: CoreFn;
|
|
12
|
+
callerInst: ComponentInstanceState;
|
|
13
|
+
calleeInst: ComponentInstanceState;
|
|
14
|
+
/** `TypeTupleIndex` of the callee's (lifted) results. */
|
|
15
|
+
taskReturnType: number;
|
|
16
|
+
/** Whether the callee's *function type* is async. */
|
|
17
|
+
calleeAsync: boolean;
|
|
18
|
+
stringEncoding: number;
|
|
19
|
+
resultCountOrMax: number;
|
|
20
|
+
/** The caller's own flat arguments, as forwarded to `prepare-call`. */
|
|
21
|
+
params: CoreValue[];
|
|
22
|
+
/**
|
|
23
|
+
* Where the *caller's* results go, decoded from
|
|
24
|
+
* `result_count_or_max_if_async` exactly as wasmtime's `ResultInfo`
|
|
25
|
+
* (`concurrent.rs:2815-2836`):
|
|
26
|
+
*
|
|
27
|
+
* * async caller **with** a result -> `Heap`, retptr = last param
|
|
28
|
+
* * async caller without a result -> `Stack`
|
|
29
|
+
* * sync caller whose results spill (`result_count > MAX_FLAT_RESULTS`)
|
|
30
|
+
* -> `Heap`, retptr = last param
|
|
31
|
+
* * sync caller otherwise -> `Stack`
|
|
32
|
+
*
|
|
33
|
+
* In the `Heap` case the retptr must be **appended** to the
|
|
34
|
+
* `[async-return]` arguments (`concurrent.rs:2916-2919`) — it is the last
|
|
35
|
+
* parameter of `async_return_signature` (fact/signature.rs:166,178), not
|
|
36
|
+
* something the callee produced.
|
|
37
|
+
*/
|
|
38
|
+
resultInfo: {
|
|
39
|
+
kind: "heap";
|
|
40
|
+
retptr: CoreValue;
|
|
41
|
+
} | {
|
|
42
|
+
kind: "stack";
|
|
43
|
+
};
|
|
44
|
+
/** True when the caller used the async ABI *and* has a result. */
|
|
45
|
+
asyncCallerWithResult: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* The memory `prepare-call` names (`component/info.rs:1059`: "the memory
|
|
48
|
+
* used to verify that the memory specified for the `task.return` that is
|
|
49
|
+
* called at runtime matches the one specified in the lifted export").
|
|
50
|
+
*
|
|
51
|
+
* Decoded faithfully, but NOT usable for that verification: it is the
|
|
52
|
+
* *adapter's* view (`adapter.lift.options...memory`) and is `None` for
|
|
53
|
+
* callees whose own `task.return` options do name a memory. wasmtime gets
|
|
54
|
+
* away with the check because it holds the lift memory first-hand and its
|
|
55
|
+
* comparison is one-sided (concurrent.rs:3344-3358). Kept because it is the
|
|
56
|
+
* wire field and the task's options are structurally built from it; see the
|
|
57
|
+
* comment on the memory half of the check in async_builtins.ts.
|
|
58
|
+
*/
|
|
59
|
+
memory: unknown | null;
|
|
60
|
+
}
|
|
61
|
+
/** Executor services these intrinsics need. */
|
|
62
|
+
export interface FactCallContext {
|
|
63
|
+
componentInstance(index: number): ComponentInstanceState;
|
|
64
|
+
/** Element types of an interned results tuple (a `plan.types` index). */
|
|
65
|
+
resultTypes(index: number): ValType[];
|
|
66
|
+
/**
|
|
67
|
+
* Element types for a *raw* wasmtime `TypeTupleIndex` (what `prepare-call`
|
|
68
|
+
* passes as `task_return_type`), or `null` if the plan maps none — plan v3,
|
|
69
|
+
* see `LoadedPlan.resultTupleTypes`.
|
|
70
|
+
*/
|
|
71
|
+
resultTypesForTuple(tupleIndex: number): ValType[] | null;
|
|
72
|
+
/** `RuntimeCallbackIndex` -> the callee's callback core function. */
|
|
73
|
+
callback(index: number): CoreFn;
|
|
74
|
+
/** `RuntimeMemoryIndex` -> the memory `task.return` must match, if any. */
|
|
75
|
+
memoryToken(index: number): unknown;
|
|
76
|
+
stats: ExecutionStats;
|
|
77
|
+
/** Suspension discipline (jspi/bridge.ts). */
|
|
78
|
+
suspensionMode: import("../jspi/mod.js").SuspensionMode;
|
|
79
|
+
/**
|
|
80
|
+
* Can this specific callee's code reach a suspension point? Computed per
|
|
81
|
+
* core instance at instantiation (see `Executor.suspendableFuncs`). Decides
|
|
82
|
+
* whether the callee gets its own `promising` entry.
|
|
83
|
+
*/
|
|
84
|
+
calleeCanBlock?(fn: unknown): boolean;
|
|
85
|
+
/**
|
|
86
|
+
* The single in-flight prepared call. wasmtime keeps this per *task*; a
|
|
87
|
+
* single slot is equivalent here because `prepare-call` and its
|
|
88
|
+
* `*-start-call` are emitted back-to-back in one adapter body
|
|
89
|
+
* (`trampoline.rs:486-508`) with no suspension point between them, so two
|
|
90
|
+
* preparations can never be outstanding at once. Asserted, not assumed.
|
|
91
|
+
*/
|
|
92
|
+
prepared: {
|
|
93
|
+
current: PreparedCall | null;
|
|
94
|
+
};
|
|
95
|
+
/** See `TrampolineContext.factStartScopes` (intrinsics/mod.ts). */
|
|
96
|
+
factStartScopes: import("./mod.js").FactStartScope[];
|
|
97
|
+
}
|
|
98
|
+
export declare function createPrepareCall(decl: {
|
|
99
|
+
memory: number | null;
|
|
100
|
+
}, ctx: FactCallContext): CoreFn;
|
|
101
|
+
/**
|
|
102
|
+
* A sync-lowered import calling an async-lifted export
|
|
103
|
+
* (`compile_sync_to_async_adapter`, trampoline.rs:607). The caller's wasm frame
|
|
104
|
+
* is blocked for the duration, so this must produce the results *now*.
|
|
105
|
+
*/
|
|
106
|
+
export declare function createSyncStartCall(decl: {
|
|
107
|
+
callback: number | null;
|
|
108
|
+
}, ctx: FactCallContext): CoreFn;
|
|
109
|
+
/**
|
|
110
|
+
* An async-lowered import calling any export (`compile_async_to_async_adapter`
|
|
111
|
+
* / `compile_async_to_sync_adapter`). Returns the packed subtask status the
|
|
112
|
+
* guest already knows how to interpret — the same
|
|
113
|
+
* `state | (subtaski << 4)` encoding `canon_lower` produces
|
|
114
|
+
* (definitions.py line 2308), so the caller's callback loop and waitable sets
|
|
115
|
+
* work unchanged.
|
|
116
|
+
*/
|
|
117
|
+
export declare function createAsyncStartCall(decl: {
|
|
118
|
+
callback: number | null;
|
|
119
|
+
postReturn: number | null;
|
|
120
|
+
}, ctx: FactCallContext): CoreFn;
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { ResourceHandle } from "../cabi/handles.js";
|
|
2
|
+
import type { ResourceTypeInfo } from "../cabi/types.js";
|
|
3
|
+
import type { ComponentInstanceState } from "../task/mod.js";
|
|
4
|
+
import type { WireTrampoline } from "../plan/format.js";
|
|
5
|
+
import type { CoreFn, ExecutionStats } from "../exec/boundary.js";
|
|
6
|
+
import { type PreparedCall } from "./fact_calls.js";
|
|
7
|
+
import { type TranscodeMemory } from "./transcode.js";
|
|
8
|
+
export * from "./transcode.js";
|
|
9
|
+
export * from "./context.js";
|
|
10
|
+
export * from "./async_builtins.js";
|
|
11
|
+
export * from "./fact_calls.js";
|
|
12
|
+
export * from "./stream_builtins.js";
|
|
13
|
+
/**
|
|
14
|
+
* Where a host trap thrown *inside* a FACT adapter is remembered.
|
|
15
|
+
*
|
|
16
|
+
* FACT wraps every adapter body in a `try_table … catch_all` exception
|
|
17
|
+
* barrier (wasmtime-environ 47.0.3 `fact/trampoline.rs:3939`
|
|
18
|
+
* `enter_exception_barrier`) so that a guest exception escaping a component
|
|
19
|
+
* becomes a trap rather than unwinding into the caller. In wasmtime a host
|
|
20
|
+
* trap unwinds out of band and is unaffected; in a JS host our traps *are*
|
|
21
|
+
* JS exceptions, so the barrier swallows them and re-raises the generic
|
|
22
|
+
* `UncaughtException` FACT trap — which would violate contracts/intrinsics.md
|
|
23
|
+
* §"Universal semantics" 2 ("traps ... must not be catchable by guest code").
|
|
24
|
+
*
|
|
25
|
+
* The fix is to remember the trap on the way out and restore it when the
|
|
26
|
+
* barrier reports `UncaughtException`. A genuine guest exception leaves
|
|
27
|
+
* `pending` untouched and keeps the generic trap.
|
|
28
|
+
*
|
|
29
|
+
* **Residual limitation (inherent to a JS host).** wasmtime's traps are
|
|
30
|
+
* unforgeable and uncatchable: they unwind out of band, and no guest
|
|
31
|
+
* construct can observe or swallow one. Ours are ordinary JS exceptions, so
|
|
32
|
+
* a guest that wraps a call in its own `try_table (catch_all …)` *can* catch
|
|
33
|
+
* a host trap mid-flight and continue — the Component Model says that must be
|
|
34
|
+
* impossible. Recovering full unforgeability needs an out-of-band channel
|
|
35
|
+
* (e.g. a poison flag consulted at every host boundary crossing) and is not
|
|
36
|
+
* attempted here; the barrier case above is the one that occurs in practice,
|
|
37
|
+
* because FACT emits it on every adapter. Recorded as a known gap.
|
|
38
|
+
*/
|
|
39
|
+
export interface HostTrapState {
|
|
40
|
+
pending: unknown;
|
|
41
|
+
}
|
|
42
|
+
export { UnsupportedFeatureError } from "./errors.js";
|
|
43
|
+
/**
|
|
44
|
+
* The borrow bookkeeping of one in-flight synchronous cross-component call,
|
|
45
|
+
* bracketed by the FACT adapter's `enter-sync-call` / `exit-sync-call`
|
|
46
|
+
* imports (wasmtime-environ 47.0.3 `fact/trampoline.rs:810,904`: enter is
|
|
47
|
+
* emitted *before* argument translation and exit *after* the callee returns,
|
|
48
|
+
* so every resource transfer for the call happens inside the bracket).
|
|
49
|
+
*
|
|
50
|
+
* It plays the role definitions.py gives the callee `Subtask`/`Task`:
|
|
51
|
+
*
|
|
52
|
+
* - `lenders` — handles lent to the callee (`Subtask.lenders`); each
|
|
53
|
+
* `num_lends` is dropped again when the call returns, which is what makes
|
|
54
|
+
* a lender's own handle liftable again afterwards.
|
|
55
|
+
* - `numBorrows` — borrow handles lowered into the callee's table
|
|
56
|
+
* (`Task.num_borrows`); the callee must drop them all before returning
|
|
57
|
+
* (definitions.py `Task.return_`: `trap_if(self.num_borrows > 0)`).
|
|
58
|
+
*
|
|
59
|
+
* Structurally satisfies cabi's `TaskBorrowScope` and `SubtaskBorrowScope`.
|
|
60
|
+
*/
|
|
61
|
+
export declare class SyncCallScope {
|
|
62
|
+
numBorrows: number;
|
|
63
|
+
readonly lenders: ResourceHandle[];
|
|
64
|
+
/**
|
|
65
|
+
* definitions.py `Subtask.add_lender` (line 890) — note there is **no**
|
|
66
|
+
* `own` check, and `lift_borrow` (line 1516) calls it unconditionally: a
|
|
67
|
+
* component that received a borrow may lend it onward, and the borrow
|
|
68
|
+
* handle's own `num_lends` is what blocks `resource.drop` on it until the
|
|
69
|
+
* onward call returns (`canon_resource_drop`, line 2325, traps on
|
|
70
|
+
* `num_lends != 0` for owning *and* borrowed handles alike).
|
|
71
|
+
* wasmtime 47.0.3 `vm/component/resources.rs:285` (`resource_lift_borrow`)
|
|
72
|
+
* agrees.
|
|
73
|
+
*/
|
|
74
|
+
addLender(h: ResourceHandle): void;
|
|
75
|
+
/** definitions.py `Subtask.deliver_resolve` (lines 902-906): releases lenders at delivery time. */
|
|
76
|
+
releaseLenders(): void;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The borrow bookkeeping of one FACT `[async-start]` argument-copy window —
|
|
80
|
+
* the prepare/start protocol's analogue of `SyncCallScope`. Live only for
|
|
81
|
+
* the synchronous `callCore(prepared.start, …)` call inside `mkCalleeTask`'s
|
|
82
|
+
* `on_start` (the copy adapters cannot block, so the window never suspends).
|
|
83
|
+
*
|
|
84
|
+
* Reference mapping (definitions.py): `taskScope` is the callee `Task` —
|
|
85
|
+
* `lower_borrow` (line 1821) counts `num_borrows` there, and
|
|
86
|
+
* `Task.return_`/`cancel` trap while it is non-zero; `lenders` is the
|
|
87
|
+
* caller-side `Subtask` (async-start-call) or a plain scope released when
|
|
88
|
+
* the caller's blocked frame gets its results (sync-start-call) —
|
|
89
|
+
* `lift_borrow` (line 1517) adds lenders there, released at
|
|
90
|
+
* `deliver_resolve` (line 904). Found by the #18 polymorph-tls smoke: the
|
|
91
|
+
* suite is the first corpus with borrow-carrying composed calls through
|
|
92
|
+
* prepare/start adapters, which previously asserted "transfer-borrow
|
|
93
|
+
* outside an enter-sync-call/exit-sync-call bracket".
|
|
94
|
+
*/
|
|
95
|
+
export interface FactStartScope {
|
|
96
|
+
/** The callee task (satisfies cabi's `TaskBorrowScope`). */
|
|
97
|
+
taskScope: import("../cabi/context.js").TaskBorrowScope;
|
|
98
|
+
/** The caller-side lender registrar (satisfies `SubtaskBorrowScope`). */
|
|
99
|
+
lenders: {
|
|
100
|
+
addLender(h: ResourceHandle): void;
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/** Executor services a trampoline body needs (provided by executor.ts). */
|
|
104
|
+
export interface TrampolineContext {
|
|
105
|
+
componentInstance(index: number): ComponentInstanceState;
|
|
106
|
+
resourceToken(index: number): ResourceTypeInfo;
|
|
107
|
+
/**
|
|
108
|
+
* The component instance that *owns* resource table `index`
|
|
109
|
+
* (`TypeResourceTable::Concrete.instance`), i.e. whose handle table the
|
|
110
|
+
* FACT transfer intrinsics move handles between. Throws for abstract
|
|
111
|
+
* (type-only) tables, which have no runtime state.
|
|
112
|
+
*/
|
|
113
|
+
resourceTableInstance(index: number): ComponentInstanceState;
|
|
114
|
+
/**
|
|
115
|
+
* A live view of runtime memory `index` (`RuntimeMemoryIndex`), for the
|
|
116
|
+
* string-transcoder trampolines.
|
|
117
|
+
*/
|
|
118
|
+
runtimeMemory(index: number): TranscodeMemory;
|
|
119
|
+
/**
|
|
120
|
+
* Stack of in-flight synchronous cross-component calls (innermost last),
|
|
121
|
+
* owned by the executor so all trampolines of one instantiation share it.
|
|
122
|
+
*/
|
|
123
|
+
syncCallStack: SyncCallScope[];
|
|
124
|
+
/**
|
|
125
|
+
* Stack of in-flight FACT `[async-start]` argument-copy windows (innermost
|
|
126
|
+
* last; see `FactStartScope`). Separate from `syncCallStack` because the
|
|
127
|
+
* prepare/start protocol has no enter/exit-sync-call bracket — the borrow
|
|
128
|
+
* bookkeeping attaches to the callee `Task` and the caller-side subtask
|
|
129
|
+
* instead (definitions.py `lower_borrow` line 1821 / `lift_borrow` line
|
|
130
|
+
* 1517).
|
|
131
|
+
*/
|
|
132
|
+
factStartScopes: FactStartScope[];
|
|
133
|
+
/** See `FactCallContext.calleeCanBlock` (intrinsics/fact_calls.ts). */
|
|
134
|
+
calleeCanBlock?(fn: unknown): boolean;
|
|
135
|
+
/** See `HostTrapState`. */
|
|
136
|
+
trapState: HostTrapState;
|
|
137
|
+
/**
|
|
138
|
+
* Resolved canonical options by index, and the element types of an interned
|
|
139
|
+
* results tuple — needed by the async built-ins (task.return,
|
|
140
|
+
* waitable-set.{wait,poll}). See `AsyncTrampolineContext`.
|
|
141
|
+
*/
|
|
142
|
+
options(index: number): import("../exec/boundary.js").ResolvedOptions;
|
|
143
|
+
resultTypes(index: number): import("../cabi/types.js").ValType[];
|
|
144
|
+
/** `RuntimeCallbackIndex` -> the extracted callback core function. */
|
|
145
|
+
callback(index: number): CoreFn;
|
|
146
|
+
/** `RuntimeMemoryIndex` -> an identity token for `task.return` checks. */
|
|
147
|
+
memoryToken(index: number): unknown;
|
|
148
|
+
/** The single in-flight FACT preparation (see `PreparedCall`). */
|
|
149
|
+
prepared: {
|
|
150
|
+
current: PreparedCall | null;
|
|
151
|
+
};
|
|
152
|
+
/** Suspension discipline (jspi/bridge.ts). */
|
|
153
|
+
suspensionMode: import("../jspi/mod.js").SuspensionMode;
|
|
154
|
+
/** Element types of the plan v2 stream/future tables. */
|
|
155
|
+
streamElem(index: number): import("../cabi/types.js").ValType | null;
|
|
156
|
+
futureElem(index: number): import("../cabi/types.js").ValType | null;
|
|
157
|
+
streamTableInstance(index: number): ComponentInstanceState;
|
|
158
|
+
futureTableInstance(index: number): ComponentInstanceState;
|
|
159
|
+
/**
|
|
160
|
+
* The component instance owning error-context table `index`
|
|
161
|
+
* (`TypeComponentLocalErrorContextTableIndex`, plan v3 `errorContextTables`).
|
|
162
|
+
* Its own index space — NOT the resource-table one it used to borrow.
|
|
163
|
+
*/
|
|
164
|
+
errorContextTableInstance(index: number): ComponentInstanceState;
|
|
165
|
+
/**
|
|
166
|
+
* Element types of the *raw* wasmtime `TypeTupleIndex` FACT's
|
|
167
|
+
* `prepare-call` passes as `task_return_type`, or `null` when the plan
|
|
168
|
+
* carries no mapping for it (see `LoadedPlan.resultTupleTypes`).
|
|
169
|
+
*/
|
|
170
|
+
resultTypesForTuple(tupleIndex: number): import("../cabi/types.js").ValType[] | null;
|
|
171
|
+
/** Build the lowered-import body for `lowered` (LoweredIndex). */
|
|
172
|
+
loweredImport(decl: {
|
|
173
|
+
lowered: number;
|
|
174
|
+
options: number;
|
|
175
|
+
type: number;
|
|
176
|
+
}): CoreFn;
|
|
177
|
+
stats: ExecutionStats;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Create the JS function backing one plan trampoline. Called during
|
|
181
|
+
* initializer/arg/export resolution — i.e. at instantiate time — so an
|
|
182
|
+
* unsupported kind fails instantiation, not the first call
|
|
183
|
+
* (plan-format.md "Executor obligations"). Unreferenced trampolines are
|
|
184
|
+
* never created and therefore never fail (intrinsics.md §B tolerates e.g.
|
|
185
|
+
* an unreferenced task-return until M2).
|
|
186
|
+
*/
|
|
187
|
+
export declare function createTrampoline(decl: WireTrampoline, ctx: TrampolineContext): CoreFn;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { SuspensionMode } from "../jspi/mod.js";
|
|
2
|
+
import type { ValType } from "../cabi/types.js";
|
|
3
|
+
import { type ComponentInstanceState } from "../task/mod.js";
|
|
4
|
+
import { type CoreFn, type ResolvedOptions } from "../exec/boundary.js";
|
|
5
|
+
export declare function traceCopy(msg: string): void;
|
|
6
|
+
/** Services the stream/future built-ins need from the executor. */
|
|
7
|
+
export interface StreamTrampolineContext {
|
|
8
|
+
componentInstance(index: number): ComponentInstanceState;
|
|
9
|
+
options(index: number): ResolvedOptions;
|
|
10
|
+
/** Element type of a `TypeStreamTableIndex` (plan v2 `streamTables`). */
|
|
11
|
+
streamElem(index: number): ValType | null;
|
|
12
|
+
/** Element type of a `TypeFutureTableIndex` (plan v2 `futureTables`). */
|
|
13
|
+
futureElem(index: number): ValType | null;
|
|
14
|
+
/** Suspension discipline; decides whether site 4 blocks or signals. */
|
|
15
|
+
suspensionMode?: SuspensionMode;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* definitions.py `canon_stream_new` (line 2504) / `canon_future_new` (2512).
|
|
19
|
+
* Returns both handles packed into an i64: `ri | (wi << 32)`.
|
|
20
|
+
*/
|
|
21
|
+
export declare function createStreamNew(decl: {
|
|
22
|
+
streamTable: number;
|
|
23
|
+
}, ctx: StreamTrampolineContext, inst: ComponentInstanceState): CoreFn;
|
|
24
|
+
export declare function createFutureNew(decl: {
|
|
25
|
+
futureTable: number;
|
|
26
|
+
}, ctx: StreamTrampolineContext, inst: ComponentInstanceState): CoreFn;
|
|
27
|
+
/**
|
|
28
|
+
* definitions.py `canon_error_context_new` (line 2778).
|
|
29
|
+
*
|
|
30
|
+
* The reference is deliberately non-committal about the message: under
|
|
31
|
+
* `DETERMINISTIC_PROFILE` it stores the empty string, otherwise it may apply a
|
|
32
|
+
* `host_defined_transformation`. We keep the guest's message verbatim — the
|
|
33
|
+
* most useful behaviour for a debugging aid, and within what the spec allows
|
|
34
|
+
* (the message is explicitly not semantically load-bearing).
|
|
35
|
+
*/
|
|
36
|
+
export declare function createErrorContextNew(decl: {
|
|
37
|
+
options: number;
|
|
38
|
+
}, ctx: StreamTrampolineContext, inst: ComponentInstanceState): CoreFn;
|
|
39
|
+
/** definitions.py `canon_error_context_debug_message` (line 2792). */
|
|
40
|
+
export declare function createErrorContextDebugMessage(decl: {
|
|
41
|
+
options: number;
|
|
42
|
+
}, ctx: StreamTrampolineContext, inst: ComponentInstanceState): CoreFn;
|
|
43
|
+
/** definitions.py `canon_error_context_drop` (line 2803). */
|
|
44
|
+
export declare function createErrorContextDrop(inst: ComponentInstanceState): CoreFn;
|
|
45
|
+
export declare function createStreamRead(d: {
|
|
46
|
+
streamTable: number;
|
|
47
|
+
options: number;
|
|
48
|
+
}, ctx: StreamTrampolineContext, inst: ComponentInstanceState): CoreFn;
|
|
49
|
+
export declare function createStreamWrite(d: {
|
|
50
|
+
streamTable: number;
|
|
51
|
+
options: number;
|
|
52
|
+
}, ctx: StreamTrampolineContext, inst: ComponentInstanceState): CoreFn;
|
|
53
|
+
export declare function createFutureRead(d: {
|
|
54
|
+
futureTable: number;
|
|
55
|
+
options: number;
|
|
56
|
+
}, ctx: StreamTrampolineContext, inst: ComponentInstanceState): CoreFn;
|
|
57
|
+
export declare function createFutureWrite(d: {
|
|
58
|
+
futureTable: number;
|
|
59
|
+
options: number;
|
|
60
|
+
}, ctx: StreamTrampolineContext, inst: ComponentInstanceState): CoreFn;
|
|
61
|
+
export declare function createStreamCancelRead(d: {
|
|
62
|
+
streamTable: number;
|
|
63
|
+
async: boolean;
|
|
64
|
+
}, ctx: StreamTrampolineContext, inst: ComponentInstanceState): CoreFn;
|
|
65
|
+
export declare function createStreamCancelWrite(d: {
|
|
66
|
+
streamTable: number;
|
|
67
|
+
async: boolean;
|
|
68
|
+
}, ctx: StreamTrampolineContext, inst: ComponentInstanceState): CoreFn;
|
|
69
|
+
export declare function createFutureCancelRead(d: {
|
|
70
|
+
futureTable: number;
|
|
71
|
+
async: boolean;
|
|
72
|
+
}, ctx: StreamTrampolineContext, inst: ComponentInstanceState): CoreFn;
|
|
73
|
+
export declare function createFutureCancelWrite(d: {
|
|
74
|
+
futureTable: number;
|
|
75
|
+
async: boolean;
|
|
76
|
+
}, ctx: StreamTrampolineContext, inst: ComponentInstanceState): CoreFn;
|
|
77
|
+
export declare function createStreamDropReadable(d: {
|
|
78
|
+
streamTable: number;
|
|
79
|
+
}, ctx: StreamTrampolineContext, inst: ComponentInstanceState): CoreFn;
|
|
80
|
+
export declare function createStreamDropWritable(d: {
|
|
81
|
+
streamTable: number;
|
|
82
|
+
}, ctx: StreamTrampolineContext, inst: ComponentInstanceState): CoreFn;
|
|
83
|
+
export declare function createFutureDropReadable(d: {
|
|
84
|
+
futureTable: number;
|
|
85
|
+
}, ctx: StreamTrampolineContext, inst: ComponentInstanceState): CoreFn;
|
|
86
|
+
export declare function createFutureDropWritable(d: {
|
|
87
|
+
futureTable: number;
|
|
88
|
+
}, ctx: StreamTrampolineContext, inst: ComponentInstanceState): CoreFn;
|
|
89
|
+
/** Services the transfer intrinsics need beyond `StreamTrampolineContext`. */
|
|
90
|
+
export interface AsyncTransferContext extends StreamTrampolineContext {
|
|
91
|
+
streamTableInstance(index: number): ComponentInstanceState;
|
|
92
|
+
futureTableInstance(index: number): ComponentInstanceState;
|
|
93
|
+
}
|
|
94
|
+
export declare function createStreamTransfer(ctx: AsyncTransferContext): CoreFn;
|
|
95
|
+
export declare function createFutureTransfer(ctx: AsyncTransferContext): CoreFn;
|
|
96
|
+
/**
|
|
97
|
+
* error-context transfer. Unlike stream/future ends, an `error-context` is
|
|
98
|
+
* shareable: `lift_error_context` (definitions.py line 1451) *reads* the handle
|
|
99
|
+
* rather than removing it, so the source keeps its own.
|
|
100
|
+
*/
|
|
101
|
+
/**
|
|
102
|
+
* Plan v3 (contracts/plan-format.md v3 amendment 2): `instanceOf` resolves
|
|
103
|
+
* through the plan's `errorContextTables` section — the
|
|
104
|
+
* `TypeComponentLocalErrorContextTableIndex` space these arguments actually
|
|
105
|
+
* live in. It replaced a resource-table lookup, which shared neither the
|
|
106
|
+
* index space nor (in a multi-instance composition) the answer.
|
|
107
|
+
*
|
|
108
|
+
* The arguments are the trampoline's own core parameters, so a missing one is
|
|
109
|
+
* an arity fault, not a zero: no `?? 0` defaults — `instanceOf(undefined!)`
|
|
110
|
+
* would be a silent table-0 read. `assert_` instead, and the accessor itself
|
|
111
|
+
* raises a `PlanError` for an out-of-range table.
|
|
112
|
+
*/
|
|
113
|
+
export declare function createErrorContextTransfer(ctx: AsyncTransferContext, instanceOf: (table: number) => ComponentInstanceState): CoreFn;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A live view of one `WebAssembly.Memory`. Views are re-derived per access:
|
|
3
|
+
* a transcoder can be called after the guest grew a memory, which detaches
|
|
4
|
+
* the previous `ArrayBuffer`.
|
|
5
|
+
*/
|
|
6
|
+
export declare class TranscodeMemory {
|
|
7
|
+
#private;
|
|
8
|
+
constructor(provider: () => WebAssembly.Memory | undefined, label: string);
|
|
9
|
+
bytes(): Uint8Array;
|
|
10
|
+
}
|
|
11
|
+
/** The `Transcode` op names as emitted by the shim (`Transcode::desc()`). */
|
|
12
|
+
export type TranscodeOp = "utf8-to-utf8" | "utf16-to-utf16" | "latin1-to-latin1" | "latin1-to-utf16" | "latin1-to-utf8" | "utf16-to-compact-probably-utf16" | "utf16-to-compact-utf16" | "utf16-to-latin1" | "utf16-to-utf8" | "utf8-to-compact-utf16" | "utf8-to-latin1" | "utf8-to-utf16";
|
|
13
|
+
export declare const TRANSCODE_OPS: readonly TranscodeOp[];
|
|
14
|
+
/**
|
|
15
|
+
* Build the JS function backing one `Transcoder` trampoline.
|
|
16
|
+
*
|
|
17
|
+
* Result shape follows the core signature in `fact/transcode.rs`: no result,
|
|
18
|
+
* one result (a number), or two results (a `[srcRead, dstWritten]` pair — the
|
|
19
|
+
* JS API delivers a multi-value return as an array).
|
|
20
|
+
*/
|
|
21
|
+
export declare function createTranscoder(op: TranscodeOp, from: TranscodeMemory, to: TranscodeMemory): (...args: number[]) => unknown;
|