@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.
Files changed (126) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +23 -0
  3. package/esm/cabi/async_values.js +162 -0
  4. package/esm/cabi/bulk_lists.js +198 -0
  5. package/esm/cabi/context.js +42 -0
  6. package/esm/cabi/flatten.js +145 -0
  7. package/esm/cabi/float.js +67 -0
  8. package/esm/cabi/handles.js +253 -0
  9. package/esm/cabi/layout.js +149 -0
  10. package/esm/cabi/lift.js +196 -0
  11. package/esm/cabi/load.js +146 -0
  12. package/esm/cabi/lower.js +141 -0
  13. package/esm/cabi/memory.js +182 -0
  14. package/esm/cabi/mod.js +22 -0
  15. package/esm/cabi/store.js +186 -0
  16. package/esm/cabi/strings.js +336 -0
  17. package/esm/cabi/trap.js +38 -0
  18. package/esm/cabi/types.js +264 -0
  19. package/esm/cabi/values.js +64 -0
  20. package/esm/cache/core.js +156 -0
  21. package/esm/cache/dir.js +170 -0
  22. package/esm/cache/mod.js +4 -0
  23. package/esm/cache/web.js +136 -0
  24. package/esm/digest/digest.js +332 -0
  25. package/esm/digest/mod.js +3 -0
  26. package/esm/digest/verify.js +129 -0
  27. package/esm/embedder/casing.js +56 -0
  28. package/esm/embedder/copy.js +42 -0
  29. package/esm/embedder/errors.js +26 -0
  30. package/esm/embedder/imports.js +63 -0
  31. package/esm/embedder/instantiate.js +978 -0
  32. package/esm/embedder/mod.js +40 -0
  33. package/esm/embedder/resources.js +406 -0
  34. package/esm/embedder/streams.js +770 -0
  35. package/esm/embedder/values.js +450 -0
  36. package/esm/embedder/version.js +273 -0
  37. package/esm/exec/boundary.js +1902 -0
  38. package/esm/exec/executor.js +1004 -0
  39. package/esm/exec/host_streams.js +818 -0
  40. package/esm/exec/mod.js +4 -0
  41. package/esm/intrinsics/async_builtins.js +510 -0
  42. package/esm/intrinsics/context.js +90 -0
  43. package/esm/intrinsics/errors.js +13 -0
  44. package/esm/intrinsics/fact_calls.js +865 -0
  45. package/esm/intrinsics/mod.js +564 -0
  46. package/esm/intrinsics/stream_builtins.js +578 -0
  47. package/esm/intrinsics/transcode.js +443 -0
  48. package/esm/jspi/bridge.js +579 -0
  49. package/esm/jspi/mechanics.js +89 -0
  50. package/esm/jspi/mod.js +5 -0
  51. package/esm/jspi/suspending.js +15 -0
  52. package/esm/jspi/types.js +29 -0
  53. package/esm/package.json +3 -0
  54. package/esm/plan/format.js +5 -0
  55. package/esm/plan/loader.js +657 -0
  56. package/esm/plan/mod.js +3 -0
  57. package/esm/shim/mod.js +2 -0
  58. package/esm/shim/translator.js +94 -0
  59. package/esm/task/mod.js +483 -0
  60. package/esm/task/scheduler.js +1028 -0
  61. package/esm/task/streams.js +786 -0
  62. package/esm/task/subtask.js +135 -0
  63. package/esm/task/thread.js +255 -0
  64. package/esm/task/waitable.js +144 -0
  65. package/package.json +91 -0
  66. package/types/cabi/async_values.d.ts +35 -0
  67. package/types/cabi/bulk_lists.d.ts +18 -0
  68. package/types/cabi/context.d.ts +59 -0
  69. package/types/cabi/flatten.d.ts +14 -0
  70. package/types/cabi/float.d.ts +14 -0
  71. package/types/cabi/handles.d.ts +70 -0
  72. package/types/cabi/layout.d.ts +13 -0
  73. package/types/cabi/lift.d.ts +25 -0
  74. package/types/cabi/load.d.ts +14 -0
  75. package/types/cabi/lower.d.ts +10 -0
  76. package/types/cabi/memory.d.ts +58 -0
  77. package/types/cabi/mod.d.ts +15 -0
  78. package/types/cabi/store.d.ts +12 -0
  79. package/types/cabi/strings.d.ts +23 -0
  80. package/types/cabi/trap.d.ts +11 -0
  81. package/types/cabi/types.d.ts +206 -0
  82. package/types/cabi/values.d.ts +5 -0
  83. package/types/cache/core.d.ts +97 -0
  84. package/types/cache/dir.d.ts +6 -0
  85. package/types/cache/mod.d.ts +3 -0
  86. package/types/cache/web.d.ts +10 -0
  87. package/types/digest/digest.d.ts +17 -0
  88. package/types/digest/mod.d.ts +2 -0
  89. package/types/digest/verify.d.ts +48 -0
  90. package/types/embedder/casing.d.ts +40 -0
  91. package/types/embedder/copy.d.ts +24 -0
  92. package/types/embedder/errors.d.ts +11 -0
  93. package/types/embedder/imports.d.ts +47 -0
  94. package/types/embedder/instantiate.d.ts +88 -0
  95. package/types/embedder/mod.d.ts +11 -0
  96. package/types/embedder/resources.d.ts +158 -0
  97. package/types/embedder/streams.d.ts +202 -0
  98. package/types/embedder/values.d.ts +70 -0
  99. package/types/embedder/version.d.ts +85 -0
  100. package/types/exec/boundary.d.ts +360 -0
  101. package/types/exec/executor.d.ts +125 -0
  102. package/types/exec/host_streams.d.ts +165 -0
  103. package/types/exec/mod.d.ts +3 -0
  104. package/types/intrinsics/async_builtins.d.ts +69 -0
  105. package/types/intrinsics/context.d.ts +28 -0
  106. package/types/intrinsics/errors.d.ts +5 -0
  107. package/types/intrinsics/fact_calls.d.ts +120 -0
  108. package/types/intrinsics/mod.d.ts +187 -0
  109. package/types/intrinsics/stream_builtins.d.ts +113 -0
  110. package/types/intrinsics/transcode.d.ts +21 -0
  111. package/types/jspi/bridge.d.ts +227 -0
  112. package/types/jspi/mechanics.d.ts +50 -0
  113. package/types/jspi/mod.d.ts +3 -0
  114. package/types/jspi/suspending.d.ts +1 -0
  115. package/types/jspi/types.d.ts +26 -0
  116. package/types/plan/format.d.ts +369 -0
  117. package/types/plan/loader.d.ts +113 -0
  118. package/types/plan/mod.d.ts +2 -0
  119. package/types/shim/mod.d.ts +1 -0
  120. package/types/shim/translator.d.ts +55 -0
  121. package/types/task/mod.d.ts +257 -0
  122. package/types/task/scheduler.d.ts +421 -0
  123. package/types/task/streams.d.ts +370 -0
  124. package/types/task/subtask.d.ts +96 -0
  125. package/types/task/thread.d.ts +73 -0
  126. package/types/task/waitable.d.ts +67 -0
@@ -0,0 +1,97 @@
1
+ import type { WirePlan } from "../plan/format.js";
2
+ /**
3
+ * The minimal surface `translateCached`/`keyFor` need from a translator.
4
+ * Structural (not `Translator` itself) so tests can substitute a spy that
5
+ * proves the shim path was/wasn't exercised, without subclassing the real
6
+ * wasm-backed client.
7
+ */
8
+ export interface TranslatorLike {
9
+ readonly buildHash: string | null;
10
+ translateRaw(componentBytes: Uint8Array): string;
11
+ }
12
+ /** Cache layout version. Bumped on any incompatible on-disk/on-Cache-API
13
+ * schema change; an unrecognized version is read back as a miss (never a
14
+ * crash) so stale caches from an older build self-heal by re-translating —
15
+ * and this self-healing holds even when the cache root itself is
16
+ * unwritable (issue #196): the eviction attempt that a layout mismatch
17
+ * triggers is swallowed internally by the backend, so a read-only
18
+ * pre-warmed cache from an older layout degrades to "always miss, always
19
+ * re-translate" rather than throwing. */
20
+ export declare const CACHE_LAYOUT_VERSION = 1;
21
+ /** The three-part identity a translation is content-addressed by. */
22
+ export interface CacheKey {
23
+ /** hex sha256 of the component bytes (matches `plan.component.sha256`). */
24
+ componentSha256: string;
25
+ /**
26
+ * hex sha256 of the translator (shim) wasm bytes — `Translator.buildHash`.
27
+ * NOT the envelope's `producer.shimVersion`/`wasmtimeEnviron`: those don't
28
+ * change across a shim rebuild with identical pinned versions but
29
+ * different generated code (see `Translator.buildHash` docs).
30
+ */
31
+ translatorBuildHash: string;
32
+ /** wasmparser feature set used, order-insensitive. */
33
+ features: string[];
34
+ }
35
+ /** What a cache hit returns: enough to instantiate, given the caller's own
36
+ * (already-in-hand) component bytes. */
37
+ export interface CachedArtifacts {
38
+ plan: WirePlan;
39
+ /** Adapter artifacts keyed by `plan.modules[].file`, same shape as
40
+ * `TranslationResult.adapters`. */
41
+ adapters: Map<string, Uint8Array>;
42
+ }
43
+ export interface ArtifactCache {
44
+ get(key: CacheKey): Promise<CachedArtifacts | null>;
45
+ put(key: CacheKey, artifacts: CachedArtifacts): Promise<void>;
46
+ /** Remove a poisoned/stale entry. Cache backends also call this
47
+ * internally on a failed integrity check during `get`. */
48
+ evict(key: CacheKey): Promise<void>;
49
+ }
50
+ /** On-disk / on-Cache-API metadata envelope stored alongside the plan. */
51
+ export interface CacheMeta {
52
+ layoutVersion: number;
53
+ componentSha256: string;
54
+ translatorBuildHash: string;
55
+ features: string[];
56
+ }
57
+ /**
58
+ * The stable cache key string: sha256 over a canonical JSON encoding of the
59
+ * `CacheKey` (features sorted so order never causes a spurious miss).
60
+ */
61
+ export declare function keyHex(key: CacheKey): Promise<string>;
62
+ /** Compute the `CacheKey` for a `(translator, componentBytes)` pair. Throws
63
+ * if the translator has no `buildHash` (constructed from a pre-compiled
64
+ * `WebAssembly.Module` with no bytes available — see `Translator.create`). */
65
+ export declare function keyFor(translator: TranslatorLike, componentBytes: Uint8Array, features?: string[]): Promise<CacheKey>;
66
+ export interface TranslateCachedOptions {
67
+ features?: string[];
68
+ /**
69
+ * Opt-in determinism guard (tests only, per dispatch): after a cache miss,
70
+ * translate a second time and assert byte-identical envelope JSON before
71
+ * trusting/storing the result. Throws `Error` on mismatch.
72
+ */
73
+ verifyDeterminism?: boolean;
74
+ /**
75
+ * Opt-in diagnostic (issue #196): invoked when a `cache.get`/`cache.put`
76
+ * failure is swallowed so the degradation is observable without this
77
+ * library ever writing to the console itself. `op` identifies which
78
+ * call failed; `err` is the original thrown value, unmodified. Default
79
+ * is to do nothing. If this callback itself throws, that throw is also
80
+ * swallowed — a diagnostic hook must never become a new way to fail a
81
+ * translation.
82
+ */
83
+ onCacheError?: (op: "get" | "put", err: unknown) => void;
84
+ }
85
+ export interface TranslateCachedResult {
86
+ plan: WirePlan;
87
+ adapters: Map<string, Uint8Array>;
88
+ /** Whether this result came from the cache (`true`) or a fresh shim
89
+ * translation (`false`). Exposed for tests/observability; not part of the
90
+ * `ArtifactCache` contract itself. */
91
+ fromCache: boolean;
92
+ }
93
+ /**
94
+ * Orchestration helper: cache hit -> stored artifacts, cache miss ->
95
+ * translate with the shim, store, return.
96
+ */
97
+ export declare function translateCached(translator: TranslatorLike, componentBytes: Uint8Array, cache: ArtifactCache, opts?: TranslateCachedOptions): Promise<TranslateCachedResult>;
@@ -0,0 +1,6 @@
1
+ import type { ArtifactCache } from "./core.js";
2
+ /** A filesystem-backed `ArtifactCache` rooted at `path` (created on first
3
+ * `put` if missing). Deno only: every method calls `Deno.*` directly. On other
4
+ * platforms use `webCache()` (./web.ts), or supply your own `ArtifactCache` —
5
+ * the interface is three methods (./core.ts). */
6
+ export declare function dirCache(path: string): ArtifactCache;
@@ -0,0 +1,3 @@
1
+ export * from "./core.js";
2
+ export * from "./dir.js";
3
+ export * from "./web.js";
@@ -0,0 +1,10 @@
1
+ import type { ArtifactCache } from "./core.js";
2
+ /** Thrown when the Cache API isn't available in this environment. */
3
+ export declare class WebCacheUnavailableError extends Error {
4
+ constructor();
5
+ }
6
+ /** A `Cache`-API-backed `ArtifactCache` under the given cache name. Throws
7
+ * `WebCacheUnavailableError` (at call time, not construction time, so
8
+ * feature-detection failures surface where they're actually hit) when
9
+ * `globalThis.caches` doesn't exist. */
10
+ export declare function webCache(name: string): ArtifactCache;
@@ -0,0 +1,17 @@
1
+ import type { WirePlan } from "../plan/format.js";
2
+ export declare const CEWD_VERSION = 1;
3
+ export declare class DigestError extends Error {
4
+ constructor(message: string);
5
+ }
6
+ export interface WorldDigestResult {
7
+ canonicalJson: string;
8
+ digest: string;
9
+ }
10
+ /** Compute the canonical world digest from a loaded wire plan. */
11
+ export declare function computeWorldDigest(plan: WirePlan): Promise<WorldDigestResult>;
12
+ /**
13
+ * Recursively sort object keys (alphabetically) and serialize with no extra
14
+ * whitespace. Array order is preserved verbatim — this must match
15
+ * `crates/bindgen/src/digest.rs::canonical_string` byte-for-byte.
16
+ */
17
+ export declare function canonicalStringify(v: unknown): string;
@@ -0,0 +1,2 @@
1
+ export * from "./digest.js";
2
+ export * from "./verify.js";
@@ -0,0 +1,48 @@
1
+ import type { WirePlan } from "../plan/format.js";
2
+ export interface DigestMismatch {
3
+ expected: string;
4
+ actual: string;
5
+ /** Human-readable description of the first structural divergence found,
6
+ * or `null` if a divergence exists but no finer-grained cause could be
7
+ * isolated (e.g. the two canonical JSON trees have the same top-level
8
+ * shape but the digest still differs — should not happen in practice
9
+ * since the digest is a pure hash of that JSON, but guarded anyway). */
10
+ firstDivergence: string | null;
11
+ }
12
+ /**
13
+ * Thrown by generated `instantiate` wrappers when the loaded plan's world
14
+ * digest does not match the constant bindgen embedded at generation time
15
+ * (contracts/digest.md: "fails fast with a structural diff on mismatch").
16
+ * Raised BEFORE the component is instantiated, so no guest code has run
17
+ * when a caller catches this.
18
+ *
19
+ * Named and catchable: `err instanceof WorldDigestMismatchError`, or
20
+ * `err.name === "WorldDigestMismatchError"` across realms.
21
+ */
22
+ export declare class WorldDigestMismatchError extends Error {
23
+ readonly name = "WorldDigestMismatchError";
24
+ /** The world these bindings were generated from. */
25
+ readonly world: string;
26
+ /** The full mismatch report (expected/actual digest, first divergence). */
27
+ readonly mismatch: DigestMismatch;
28
+ constructor(world: string, mismatch: DigestMismatch);
29
+ /** Digest the generated bindings were built against. */
30
+ get expected(): string;
31
+ /** Digest computed from the plan actually loaded. */
32
+ get actual(): string;
33
+ }
34
+ /**
35
+ * Verify `plan`'s computed world digest against `expectedDigest` (the
36
+ * constant bindgen embedded at generation time). Returns `null` on match,
37
+ * or a `DigestMismatch` report naming the first divergent path on
38
+ * mismatch.
39
+ */
40
+ export declare function verifyWorldDigest(plan: WirePlan, expectedDigest: string): Promise<DigestMismatch | null>;
41
+ /**
42
+ * `diffWorldDigest` — richer variant for tests/tooling: compare against
43
+ * another plan's (or a WIT-derived) canonical JSON directly, walking both
44
+ * trees in parallel to name the first divergent import/export/type path.
45
+ * `expectedCanonicalJson` is normally produced by `crates/bindgen`'s
46
+ * `digest --json` output, or by `computeWorldDigest` on a reference plan.
47
+ */
48
+ export declare function diffWorldDigest(plan: WirePlan, expectedCanonicalJson: string): Promise<DigestMismatch | null>;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * `get-resolution` -> `getResolution`.
3
+ *
4
+ * The rule, stated exactly: split the label on `-`; the first fragment is
5
+ * unchanged; every later fragment has its first character upper-cased and its
6
+ * remainder preserved. Preserving the remainder is what keeps acronym
7
+ * fragments intact — `outgoing-HTTP-request` -> `outgoingHTTPRequest` — which
8
+ * a naive `toLowerCase()` of the tail would destroy.
9
+ *
10
+ * WIT labels are already lower-kebab in practice, so the first fragment needs
11
+ * no adjustment; nothing here lower-cases anything.
12
+ */
13
+ export declare function camelCase(label: string): string;
14
+ /** `tcp-socket` -> `TcpSocket` (resource class names). */
15
+ export declare function pascalCase(label: string): string;
16
+ /**
17
+ * A leaf name in `plan.exports` / `plan.imports`, decoded.
18
+ *
19
+ * The Component Model mangles resource membership into the name itself
20
+ * (`[constructor]counter`, `[method]counter.increment`,
21
+ * `[static]counter.merge`); C0 finding #2 was embedders hand-transcribing
22
+ * these. Assembling and disassembling them is a runtime obligation.
23
+ */
24
+ export type LeafName = {
25
+ form: "plain";
26
+ name: string;
27
+ } | {
28
+ form: "constructor";
29
+ resource: string;
30
+ } | {
31
+ form: "method";
32
+ resource: string;
33
+ member: string;
34
+ } | {
35
+ form: "static";
36
+ resource: string;
37
+ member: string;
38
+ };
39
+ /** Decode a mangled leaf name; unmangled names come back as `plain`. */
40
+ export declare function parseLeafName(raw: string): LeafName;
@@ -0,0 +1,24 @@
1
+ /** The URL of this copy of the runtime. Identity of the copy. */
2
+ export declare const COPY_URL: string;
3
+ /**
4
+ * The `@polyengine/runtime` version this copy was built from, recorded in the copy
5
+ * registry alongside the URL.
6
+ *
7
+ * Hardcoded on purpose: embedder code paths run without filesystem
8
+ * permissions (and a browser bundle has no filesystem at all), so reading
9
+ * `runtime/deno.json` at runtime is not an option.
10
+ *
11
+ * INVARIANT: keep in sync with `version` in runtime/deno.json — pinned by
12
+ * runtime/tests/embedder/cross_copy_test.ts.
13
+ */
14
+ export declare const RUNTIME_VERSION = "0.1.0";
15
+ /**
16
+ * Compose a cross-copy diagnostic: what was foreign, which copy is speaking,
17
+ * the census of every copy in the graph, and the by-value remediation.
18
+ *
19
+ * Kept to one line but complete — the whole point of A9's stateful half is
20
+ * that "recognized but foreign" is a NAMED failure, never a silent
21
+ * adaptation (a foreign `Stream` pumped as an async iterable) and never a
22
+ * misleading generic ("handle is not an error-context").
23
+ */
24
+ export declare function describeCrossCopy(what: string, remedy?: string): string;
@@ -0,0 +1,11 @@
1
+ export { DroppedError, InvalidHandleError, isDroppedError, isInvalidHandleError, isPeerTrappedError, isStreamProducerError, isTrap, isComponentException, PeerTrappedError, Trap, ComponentException, } from "@polyengine/protocol";
2
+ /**
3
+ * Two WIT labels in one scope camelCase to the same JS name.
4
+ *
5
+ * A footgun is a design defect (contract principle 2): silently letting one
6
+ * field/flag/function shadow another would corrupt values at the boundary with
7
+ * no diagnostic anywhere. Refused at facade build instead.
8
+ */
9
+ export declare class NameCollisionError extends Error {
10
+ constructor(message: string);
11
+ }
@@ -0,0 +1,47 @@
1
+ import type { WirePlan } from "../plan/format.js";
2
+ import type { LoadedPlan } from "../plan/loader.js";
3
+ import type { ValType } from "../cabi/types.js";
4
+ import { type LeafName } from "./casing.js";
5
+ /** Function type summary of an import leaf (names are docs-only; §"Functions"). */
6
+ export interface FuncSummary {
7
+ params: {
8
+ name: string;
9
+ type: ValType;
10
+ }[];
11
+ results: ValType[];
12
+ /** True for an `async func` — an import may then be a plain async function. */
13
+ async: boolean;
14
+ }
15
+ /** One linkable import leaf. */
16
+ export interface ImportLeaf {
17
+ /**
18
+ * The record key this leaf is provided under: a fully-qualified WIT
19
+ * interface id verbatim (version included) for interface imports, or the
20
+ * component's bare world-level import name.
21
+ */
22
+ interfaceId: string;
23
+ /** Path from the record key to the leaf, verbatim (mangled names included). */
24
+ path: string[];
25
+ /** The raw, still-mangled leaf name (`[method]counter.increment`). */
26
+ leaf: string;
27
+ /** `func`, `resource`, `instance`, … — the plan's own kind string. */
28
+ kind: string;
29
+ /** Decoded resource membership of `leaf`. */
30
+ member: LeafName;
31
+ /**
32
+ * The JS name this leaf is looked up under: camelCase for functions and
33
+ * world-level imports, PascalCase for a resource *type* (the class), and —
34
+ * for a mangled leaf — the JS name of the class **member** it dispatches to.
35
+ */
36
+ jsName: string;
37
+ /** For a mangled leaf: the PascalCase class it belongs to. */
38
+ jsClass?: string;
39
+ /** Present for `kind === "func"`. */
40
+ type?: FuncSummary;
41
+ }
42
+ /** Anything `requiredImports` accepts. */
43
+ export type PlanLike = WirePlan | LoadedPlan | {
44
+ plan: WirePlan;
45
+ };
46
+ /** Enumerate the component's linkable import leaves. */
47
+ export declare function requiredImports(input: PlanLike): ImportLeaf[];
@@ -0,0 +1,88 @@
1
+ import type { WirePlan } from "../plan/format.js";
2
+ import { type ComponentHandle } from "../exec/mod.js";
3
+ import { Translator } from "../shim/mod.js";
4
+ import { type ImportLeaf } from "./imports.js";
5
+ /** The shim's output plus the component bytes it describes. */
6
+ export interface ComponentArtifacts {
7
+ plan: WirePlan;
8
+ componentBytes: Uint8Array;
9
+ adapters?: Map<string, Uint8Array>;
10
+ }
11
+ /**
12
+ * Untranslated alternative to `ComponentArtifacts` (embedder-api.md
13
+ * amendment A3): hand `instantiate` the raw component plus the translator
14
+ * and it runs the translation internally — the pipeline collapses to
15
+ * bytes-in, instance-out.
16
+ *
17
+ * `translator` accepts the translator-shim wasm bytes (simplest; compiles
18
+ * the shim per call) or an already-created `Translator` (preferred when
19
+ * instantiating more than one component, or the same component more than
20
+ * once — create it once and reuse; translation itself is sub-millisecond
21
+ * warm, the wasm compile is the cost being shared). `requiredImports`
22
+ * still needs a plan: translate explicitly when you want to inspect the
23
+ * import surface before instantiating.
24
+ */
25
+ export interface UntranslatedArtifacts {
26
+ componentBytes: Uint8Array;
27
+ translator: Uint8Array | Translator;
28
+ }
29
+ /** Either artifacts shape accepted by `instantiate`. */
30
+ export type InstantiateSource = ComponentArtifacts | UntranslatedArtifacts;
31
+ /**
32
+ * Reconstitute `ComponentArtifacts` from a translation ENVELOPE — the
33
+ * single-file JSON emitted by build-time translation (`tools/translate`,
34
+ * or `Translator.translateRaw`), carrying the plan and the FACT adapter
35
+ * modules. The production deploy set is `component.wasm` + its envelope +
36
+ * the runtime: no translator ships (embedder-api.md amendment A4).
37
+ *
38
+ * Pure and fetch-agnostic: acquire the two blobs however the platform
39
+ * likes (HTTP, fs, bundler asset) and hand them over. The envelope embeds
40
+ * the component's sha-256, which `instantiate` verifies — a mismatched
41
+ * pair fails loudly at instantiation, never subtly at runtime.
42
+ */
43
+ export declare function artifactsFromEnvelope(envelopeJson: string, componentBytes: Uint8Array): ComponentArtifacts;
44
+ /**
45
+ * Normalize either accepted input form to `ComponentArtifacts` — i.e. make
46
+ * the PLAN available without instantiating anything. Exported because the
47
+ * world-digest handshake (contracts/digest.md) must complete before any
48
+ * guest code runs: generated `instantiate` wrappers call this, verify the
49
+ * plan, and only then delegate to `instantiate` below.
50
+ */
51
+ export declare function resolveArtifacts(src: InstantiateSource): Promise<ComponentArtifacts>;
52
+ export interface EmbedderOptions {
53
+ /** Opt in to JSPI-backed suspension (see `InstantiateInput.jspi`). */
54
+ jspi?: boolean;
55
+ /** Verify `plan.component.sha256` against the bytes (default true). */
56
+ verifyHash?: boolean;
57
+ }
58
+ /** An instantiated component, conventions-shaped. */
59
+ export interface EmbedderInstance {
60
+ /**
61
+ * Nested record keyed by verbatim WIT interface id; world-level exports at
62
+ * the top level under camelCase names.
63
+ */
64
+ exports: Record<string, any>;
65
+ /** The raw runtime handle. Internal surface, no stability promise. */
66
+ handle: ComponentHandle;
67
+ /** The leaves this component required (the same list `requiredImports` gives). */
68
+ imports: ImportLeaf[];
69
+ }
70
+ /**
71
+ * Instantiate a component behind the embedder conventions.
72
+ *
73
+ * `imports` is the canonical nested record of
74
+ * contracts/embedder-api.md §"Module wiring and instantiation": keys are
75
+ * verbatim WIT interface ids (version included) or world-level camelCase
76
+ * names; interface-id keys additionally participate in compatibility-track
77
+ * resolution (see `version.ts`).
78
+ */
79
+ export declare function instantiate(source: InstantiateSource, imports?: Record<string, unknown>, opts?: EmbedderOptions): Promise<EmbedderInstance>;
80
+ /** Alias matching the C2 dispatch's spelling. */
81
+ export declare const instantiateEmbedder: typeof instantiate;
82
+ /**
83
+ * Symbol-keyed, deliberately NOT re-exported from `mod.ts`: the
84
+ * host-resource registries of an instance, by `ResourceIndex`. Diagnostics and
85
+ * white-box tests only — it is not part of the embedder API surface and no
86
+ * generated code may depend on it.
87
+ */
88
+ export declare const INTERNAL_HOST_REGISTRIES: unique symbol;
@@ -0,0 +1,11 @@
1
+ export { COPY_URL, RUNTIME_VERSION } from "./copy.js";
2
+ export { copyCensus, DROPPED, ERROR_CONTEXT, FUTURE, hasBrand, INVALID_HANDLE, isDroppedError, isInvalidHandleError, isPeerTrappedError, isStreamProducerError, isSuspending, isTrap, isComponentException, PEER_TRAPPED, PROTOCOL_GENERATION, registerRuntimeCopy, RESOURCE_STATE, type RuntimeCopy, runtimeCopies, STREAM, STREAM_PRODUCER, SUSPENDING, TRAP, COMPONENT_EXCEPTION, } from "@polyengine/protocol";
3
+ export { artifactsFromEnvelope, type ComponentArtifacts, type EmbedderInstance, type EmbedderOptions, type InstantiateSource, type UntranslatedArtifacts, instantiate, instantiateEmbedder, resolveArtifacts, } from "./instantiate.js";
4
+ export { type FuncSummary, type ImportLeaf, type PlanLike, requiredImports } from "./imports.js";
5
+ export { DroppedError, InvalidHandleError, NameCollisionError, PeerTrappedError, Trap, ComponentException, } from "./errors.js";
6
+ export { type Chunk, type ElemCodec, ErrorContext, Future, type FutureSource, Stream, StreamProducerError, type StreamSource, StreamWriter, } from "./streams.js";
7
+ export { GuestResource, HostResourceRegistry } from "./resources.js";
8
+ export { camelCase, type LeafName, parseLeafName, pascalCase } from "./casing.js";
9
+ export { suspending } from "../jspi/suspending.js";
10
+ export { asTrackKeySpelling, compareSemver, ImportRegistrationError, ImportResolutionError, ImportResolver, type ParsedId, parseInterfaceId, parseSemver, type Semver, trackKey, } from "./version.js";
11
+ export { type AdapterOptions, BorrowScope, fromHost, toHost, type ValueBridge, } from "./values.js";
@@ -0,0 +1,158 @@
1
+ import type { ResourceTypeInfo, ValType } from "../cabi/types.js";
2
+ /**
3
+ * Internal state of a guest-resource wrapper.
4
+ *
5
+ * The KEY is the process-global `polyengine.resourceState/1` brand since amendment
6
+ * A9 (it used to be a module-local `Symbol(...)`, on the now-repealed
7
+ * assumption that bundle and source runtimes are never mixed in one process —
8
+ * issue #83 showed they routinely are). The state SHAPE stays strictly
9
+ * runtime-internal, exactly as the A9 brand table notes: another copy may
10
+ * RECOGNIZE a wrapper, and must never read or write this object. `copyUrl` is
11
+ * what lets this copy tell its own wrappers from a foreign copy's.
12
+ */
13
+ declare const STATE: symbol;
14
+ interface WrapperState {
15
+ /** The runtime copy that minted this wrapper (A9). */
16
+ copyUrl: string;
17
+ rep: number;
18
+ /** False once the handle was transferred away or dropped. */
19
+ valid: boolean;
20
+ /** True for `own` wrappers, which are responsible for dropping. */
21
+ owns: boolean;
22
+ rt: ResourceTypeInfo;
23
+ className: string;
24
+ /**
25
+ * Host-side `ResourceHandle.num_lends` (#86). The reference models a
26
+ * host-held `own` as a table entry whose `num_lends` is bumped every time
27
+ * it is lifted as a `borrow` (definitions.py `Subtask.add_lender`, line
28
+ * 890, reached from `lift_borrow`, line 1516) and decremented when the
29
+ * borrowing call's subtask delivers its resolution (`deliver_resolve`,
30
+ * line 902). `lift_own` and `canon_resource_drop` both trap while it is
31
+ * non-zero (lines 1508 / 2325).
32
+ *
33
+ * Here the host holds bare reps rather than table entries, so the counter
34
+ * lives on the wrapper. Its lifecycle point is the *lowering scope* of the
35
+ * call the wrapper was passed into (`instantiate.ts` `#lowerParams`), which
36
+ * is released exactly when that call ends — the host-side analogue of the
37
+ * subtask's resolve delivery.
38
+ */
39
+ lends: number;
40
+ /**
41
+ * A drop (explicit or via the GC backstop) that arrived while `lends > 0`.
42
+ * The reference would trap; the host has no frame to trap into by then, so
43
+ * the drop is deferred to the last release instead of running the dtor
44
+ * under a live guest borrow (which is the use-after-free #86 reports).
45
+ */
46
+ pendingDrop: boolean;
47
+ }
48
+ /** Base of every runtime-built guest-resource class. */
49
+ export declare class GuestResource {
50
+ [STATE]: WrapperState;
51
+ /** Drop the handle (alias of `[Symbol.dispose]`, so TS `using` works). */
52
+ drop(): void;
53
+ [Symbol.dispose](): void;
54
+ }
55
+ /**
56
+ * Simulate the GC backstop firing for `w` (the FinalizationRegistry callback,
57
+ * verbatim). Test seam: real GC finalization is unschedulable, and #86 is
58
+ * precisely about what the backstop does in a window a test must control.
59
+ *
60
+ * @internal
61
+ */
62
+ export declare function simulateFinalizationForTest(w: object): void;
63
+ export declare function initWrapper(w: GuestResource, state: Omit<WrapperState, "copyUrl"> & {
64
+ copyUrl?: string;
65
+ }): void;
66
+ /**
67
+ * This copy's state for a wrapper, or `undefined`.
68
+ *
69
+ * A wrapper minted by ANOTHER copy carries the same (process-global) brand key
70
+ * but its state belongs to that copy — reading it here would be reading a
71
+ * foreign copy's private shape (A9). So it is not a state: it is
72
+ * `undefined` here, and `requireLive` turns that into the named cross-copy
73
+ * error rather than a misleading "not a resource handle" / "not live".
74
+ */
75
+ export declare function wrapperState(w: object): WrapperState | undefined;
76
+ /**
77
+ * Record that a host-held `own` wrapper was lowered as `borrow<R>` into a
78
+ * guest call, and return the (idempotent) release for the end of that call.
79
+ *
80
+ * definitions.py: `lift_borrow` -> `Subtask.add_lender` (line 890) on the way
81
+ * in, `Subtask.deliver_resolve` (line 902) on the way out.
82
+ */
83
+ export declare function lendWrapper(w: object): () => void;
84
+ /** Host-side `num_lends` — diagnostics and white-box tests. */
85
+ export declare function wrapperLends(w: object): number;
86
+ /** Invalidate a wrapper without dropping (used to end a borrow's lifetime). */
87
+ export declare function invalidateWrapper(w: object): void;
88
+ /** Read a wrapper's rep for a lowering site, applying the ownership rule. */
89
+ export declare function takeRep(w: unknown, own: boolean, what: string): number;
90
+ /** Everything needed to build one guest-resource class. */
91
+ export interface GuestResourceSpec {
92
+ /** WIT resource name (kebab). */
93
+ name: string;
94
+ /** The raw `[constructor]r` lifted function, if the resource has one. */
95
+ ctor: ((...a: unknown[]) => unknown) | null;
96
+ ctorParams: ValType[] | null;
97
+ methods: {
98
+ member: string;
99
+ raw: (...a: unknown[]) => unknown;
100
+ params: ValType[];
101
+ results: ValType[];
102
+ }[];
103
+ statics: {
104
+ member: string;
105
+ raw: (...a: unknown[]) => unknown;
106
+ params: ValType[];
107
+ results: ValType[];
108
+ }[];
109
+ }
110
+ export type CallAdapter = (raw: (...a: unknown[]) => unknown, params: ValType[], results: ValType[], where: string, args: unknown[]) => Promise<unknown>;
111
+ /**
112
+ * Build the class for a guest-implemented resource.
113
+ *
114
+ * The JS constructor is **synchronous**: a JS constructor cannot return a
115
+ * Promise, so the contract's "exports are uniformly Promise-shaped" rule has
116
+ * one unavoidable exception here. A guest constructor that does not complete
117
+ * synchronously is reported as such rather than silently returning a
118
+ * half-built object (see the report's contract-friction list).
119
+ */
120
+ export declare function buildGuestResourceClass(spec: GuestResourceSpec, rt: ResourceTypeInfo, adapt: CallAdapter, lowerArgs: (args: unknown[], params: ValType[], where: string) => unknown[]): any;
121
+ /** Materialize an `own`/`borrow` wrapper for a rep coming out of a guest. */
122
+ export declare function makeWrapper(cls: any, rep: number, rt: ResourceTypeInfo, owns: boolean): GuestResource;
123
+ /**
124
+ * Runtime-owned instance <-> rep mapping for a host-implemented resource.
125
+ *
126
+ * The rep->instance direction is a **strong** map for exactly as long as the
127
+ * guest holds handles: the guest's handle is the only reference keeping a
128
+ * host object alive across calls, and a weak map here would let it be
129
+ * collected under the guest's feet.
130
+ */
131
+ export declare class HostResourceRegistry {
132
+ #private;
133
+ readonly className: string;
134
+ constructor(className: string);
135
+ /** The host is passing an instance to the guest: allocate (or reuse) a rep. */
136
+ repFor(instance: unknown): number;
137
+ /** Is this instance already registered with a live rep? */
138
+ hasInstance(instance: unknown): boolean;
139
+ /** Is `rep` live? Diagnostics and white-box tests. */
140
+ hasRep(rep: number): boolean;
141
+ /** Release a rep if it is still live; no dtor, no error when already gone. */
142
+ releaseIfPresent(rep: number): void;
143
+ /** A `borrow<R>` arrived from the guest: the host's own instance, mapping kept. */
144
+ lookup(rep: number): object;
145
+ /**
146
+ * An `own<R>` arrived from the guest: the host gets its instance back, the
147
+ * guest's handle is gone, and **no dispose runs** (the contract's 2x4 table).
148
+ */
149
+ release(rep: number): object;
150
+ /**
151
+ * The guest dropped its last own handle: run the destructor. This is the
152
+ * `HostResourceType` dtor the executor calls from `canon_resource_drop`.
153
+ */
154
+ dtor(rep: number): void;
155
+ /** Live handle count — diagnostics and tests. */
156
+ get liveCount(): number;
157
+ }
158
+ export {};