@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,273 @@
1
+ // Version-canonical import resolution (contracts/embedder-api.md
2
+ // §"Version canonicalization"; C2 checklist item 1).
3
+ //
4
+ // Authorities, read before writing this:
5
+ // * Explainer.md §"canonical interface names" (`canonversion`) — the spec's
6
+ // compatibility-track split;
7
+ // * wasmtime-environ `component::names::{NameMap, alternate_lookup_key}`,
8
+ // which is what `component::Linker` and `Component::get_export` actually
9
+ // do. This file is a transcription of `alternate_lookup_key`'s rule plus
10
+ // the linker's max-wins track claim.
11
+ //
12
+ // The rule in one paragraph: an import id is matched **exactly** first; if
13
+ // that fails, it is matched against whatever provider claimed its
14
+ // *compatibility track*, and a track is claimed by the highest-versioned
15
+ // registration on it. Prereleases and `0.0.z` have no track and so are
16
+ // exact-only. Registering both a track key and full-versioned keys on one
17
+ // track is an ambiguity, refused at registration rather than resolved by a
18
+ // precedence rule.
19
+ /** Fault in how the embedder registered its imports. */
20
+ export class ImportRegistrationError extends Error {
21
+ constructor(message) {
22
+ super(message);
23
+ this.name = "ImportRegistrationError";
24
+ }
25
+ }
26
+ /** Fault resolving a component's import against the registered providers. */
27
+ export class ImportResolutionError extends Error {
28
+ constructor(message) {
29
+ super(message);
30
+ this.name = "ImportResolutionError";
31
+ }
32
+ }
33
+ const SEMVER = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+([0-9A-Za-z.-]+))?$/;
34
+ /**
35
+ * Split an interface id at its LAST `@`.
36
+ *
37
+ * Last, not first: a package name may not contain `@`, but being explicit
38
+ * costs nothing and matches how wasmtime splits (`name.rfind('@')`).
39
+ */
40
+ export function parseInterfaceId(id) {
41
+ const at = id.lastIndexOf("@");
42
+ if (at < 0)
43
+ return { base: id, version: null, semver: null };
44
+ const base = id.slice(0, at);
45
+ const version = id.slice(at + 1);
46
+ return { base, version, semver: parseSemver(version) };
47
+ }
48
+ export function parseSemver(v) {
49
+ const m = SEMVER.exec(v);
50
+ if (m === null)
51
+ return null;
52
+ return {
53
+ major: Number(m[1]),
54
+ minor: Number(m[2]),
55
+ patch: Number(m[3]),
56
+ prerelease: m[4] === undefined ? [] : m[4].split("."),
57
+ build: m[5] ?? null,
58
+ };
59
+ }
60
+ /**
61
+ * The compatibility-track key of an interface id, or null when the id belongs
62
+ * to no track (unversioned, unparseable, prerelease, or `0.0.z`).
63
+ *
64
+ * Mirrors wasmtime `alternate_lookup_key`:
65
+ * - `major > 0` -> `base@{major}` (`1.2.3` -> `@1`)
66
+ * - `major == 0, minor > 0`-> `base@0.{minor}` (`0.2.6` -> `@0.2`)
67
+ * - `0.0.z` -> none (patch-only versions are compatible with
68
+ * nothing)
69
+ * - any prerelease -> none (wasmtime treats prereleases as
70
+ * exact-only; the historic WASI `0.2.0-rc`
71
+ * snapshots are exactly the phenomenon this
72
+ * exclusion protects — same track on paper,
73
+ * divergent function sets in fact)
74
+ *
75
+ * Build metadata is ignored for track purposes (`2.1.2+abc` -> `@2`), as
76
+ * semver requires.
77
+ */
78
+ export function trackKey(id) {
79
+ const p = parseInterfaceId(id);
80
+ if (p.semver === null)
81
+ return null;
82
+ return trackKeyOf(p.base, p.semver);
83
+ }
84
+ function trackKeyOf(base, v) {
85
+ if (v.prerelease.length > 0)
86
+ return null;
87
+ if (v.major > 0)
88
+ return `${base}@${v.major}`;
89
+ if (v.minor > 0)
90
+ return `${base}@0.${v.minor}`;
91
+ return null; // 0.0.z
92
+ }
93
+ /**
94
+ * Is `id` itself spelled as a *track key* (`ns:pkg/iface@0.2`, `…@1`)?
95
+ *
96
+ * Note `semver::Version::parse("0.2")` fails — which is exactly why the two
97
+ * mechanisms compose: a track key can never be mistaken for a full version,
98
+ * and a full version never generates a track key equal to itself.
99
+ */
100
+ export function asTrackKeySpelling(id) {
101
+ const p = parseInterfaceId(id);
102
+ if (p.version === null || p.semver !== null)
103
+ return null;
104
+ // `@0` is refused: no version canonicalizes to it (major 0 tracks the
105
+ // MINOR, `@0.n`), so registering it could only ever be a dead entry.
106
+ if (/^\d+$/.test(p.version))
107
+ return p.version === "0" ? null : id;
108
+ if (/^0\.\d+$/.test(p.version))
109
+ return id;
110
+ return null;
111
+ }
112
+ /**
113
+ * Registration table over the embedder's imports record.
114
+ *
115
+ * Only the *interface-id* keys participate: world-level bare imports live at
116
+ * the record's top level under camelCase names and are matched by exact
117
+ * string equality, never by version machinery.
118
+ */
119
+ export class ImportResolver {
120
+ #exact = new Map();
121
+ #tracks = new Map();
122
+ /** base id -> the unversioned key registered for it, if any. */
123
+ #unversioned = new Map();
124
+ constructor(record) {
125
+ for (const key of Object.keys(record)) {
126
+ if (this.#exact.has(key)) {
127
+ throw new ImportRegistrationError(`duplicate import key '${key}'`);
128
+ }
129
+ this.#exact.set(key, record[key]);
130
+ this.#register(key);
131
+ }
132
+ }
133
+ #register(key) {
134
+ const trackSpelling = asTrackKeySpelling(key);
135
+ if (trackSpelling !== null) {
136
+ this.#claim(trackSpelling, { key, version: null });
137
+ return;
138
+ }
139
+ const p = parseInterfaceId(key);
140
+ if (p.version === "0") {
141
+ throw new ImportRegistrationError(`import key '${key}': '@0' is not a compatibility track. Major 0 ` +
142
+ `tracks the MINOR version (\`@0.2\`), so no version canonicalizes ` +
143
+ `to '@0' and this registration could never be resolved.`);
144
+ }
145
+ if (p.version === null) {
146
+ // Unversioned: matched exactly and never folded onto a track (C0 D-1's
147
+ // actual defect was version-agnostic keys merging distinct semver
148
+ // tracks). Recorded so resolution can *say so* instead of reporting a
149
+ // bare "not provided".
150
+ if (p.base.includes("/") || p.base.includes(":")) {
151
+ this.#unversioned.set(p.base, key);
152
+ }
153
+ return;
154
+ }
155
+ if (p.semver === null)
156
+ return; // unparseable version: exact-only
157
+ const track = trackKeyOf(p.base, p.semver);
158
+ if (track !== null)
159
+ this.#claim(track, { key, version: p.semver });
160
+ }
161
+ #claim(track, claim) {
162
+ const held = this.#tracks.get(track);
163
+ if (held === undefined) {
164
+ this.#tracks.set(track, claim);
165
+ return;
166
+ }
167
+ // "Registering both a track key and full-versioned keys on the same track
168
+ // is refused at registration (ambiguity is an error, not a precedence
169
+ // rule)" — contracts/embedder-api.md §"Version canonicalization".
170
+ if ((held.version === null) !== (claim.version === null)) {
171
+ const [t, f] = held.version === null
172
+ ? [held.key, claim.key]
173
+ : [claim.key, held.key];
174
+ throw new ImportRegistrationError(`import registration is ambiguous on compatibility track '${track}': ` +
175
+ `the track key '${t}' and the full version '${f}' are both ` +
176
+ `registered. Register one or the other, never both.`);
177
+ }
178
+ if (held.version === null) {
179
+ throw new ImportRegistrationError(`compatibility track '${track}' is claimed twice ('${held.key}' and ` +
180
+ `'${claim.key}')`);
181
+ }
182
+ // max-wins (wasmtime's linker rule).
183
+ if (compareSemver(claim.version, held.version) > 0) {
184
+ this.#tracks.set(track, claim);
185
+ }
186
+ }
187
+ /** Every registered key, in registration order. */
188
+ keys() {
189
+ return [...this.#exact.keys()];
190
+ }
191
+ /**
192
+ * Resolve one component import name. Returns `undefined` when nothing is
193
+ * registered for it; throws when a registration *nearly* matches in a way
194
+ * the contract bans (unversioned folding), because silently reporting
195
+ * "not provided" would hide the real mistake.
196
+ */
197
+ resolve(id) {
198
+ if (this.#exact.has(id))
199
+ return { key: id, value: this.#exact.get(id) };
200
+ const p = parseInterfaceId(id);
201
+ if (p.semver !== null) {
202
+ const track = trackKeyOf(p.base, p.semver);
203
+ if (track !== null) {
204
+ const claim = this.#tracks.get(track);
205
+ if (claim !== undefined) {
206
+ return { key: claim.key, value: this.#exact.get(claim.key) };
207
+ }
208
+ }
209
+ // CONTRACT: contracts/embedder-api.md bans "unversioned folding" (C0
210
+ // D-1) and the C2 dispatch summarises that as "unversioned keys ->
211
+ // error". Read conservatively: an unversioned key is still a legal
212
+ // *exact* match for an unversioned import (the ban is about folding
213
+ // distinct semver tracks together, and unversioned WIT interfaces
214
+ // exist), but it may never serve a *versioned* import. That attempt is
215
+ // refused loudly here rather than reported as a plain "not provided".
216
+ const un = this.#unversioned.get(p.base);
217
+ if (un !== undefined) {
218
+ throw new ImportResolutionError(`import '${id}' is versioned but the only registration for ` +
219
+ `'${p.base}' is the unversioned key '${un}'. Version-agnostic ` +
220
+ `folding is banned (contracts/embedder-api.md, C0 finding D-1): ` +
221
+ `register '${p.base}@${p.version}' or the compatibility-track ` +
222
+ `key '${trackKeyOf(p.base, p.semver) ?? p.base + "@" + p.version}'.`);
223
+ }
224
+ return undefined;
225
+ }
226
+ if (p.version === null) {
227
+ // An unversioned import against versioned registrations: the same ban,
228
+ // read in the other direction.
229
+ const near = [...this.#exact.keys()].filter((k) => parseInterfaceId(k).base === p.base);
230
+ if (near.length > 0) {
231
+ throw new ImportResolutionError(`import '${id}' is unversioned but the registrations for it are ` +
232
+ `versioned (${near.join(", ")}). Version-agnostic folding is ` +
233
+ `banned (contracts/embedder-api.md, C0 finding D-1).`);
234
+ }
235
+ }
236
+ return undefined;
237
+ }
238
+ }
239
+ /** Semver precedence, prerelease-aware (semver.org §11). */
240
+ export function compareSemver(a, b) {
241
+ if (a.major !== b.major)
242
+ return a.major - b.major;
243
+ if (a.minor !== b.minor)
244
+ return a.minor - b.minor;
245
+ if (a.patch !== b.patch)
246
+ return a.patch - b.patch;
247
+ const ap = a.prerelease, bp = b.prerelease;
248
+ if (ap.length === 0 && bp.length === 0)
249
+ return 0;
250
+ if (ap.length === 0)
251
+ return 1; // a release outranks a prerelease
252
+ if (bp.length === 0)
253
+ return -1;
254
+ for (let i = 0; i < Math.max(ap.length, bp.length); i++) {
255
+ const x = ap[i], y = bp[i];
256
+ if (x === undefined)
257
+ return -1;
258
+ if (y === undefined)
259
+ return 1;
260
+ const xn = /^\d+$/.test(x), yn = /^\d+$/.test(y);
261
+ if (xn && yn) {
262
+ if (Number(x) !== Number(y))
263
+ return Number(x) - Number(y);
264
+ }
265
+ else if (xn !== yn) {
266
+ return xn ? -1 : 1; // numeric identifiers rank lower
267
+ }
268
+ else if (x !== y) {
269
+ return x < y ? -1 : 1;
270
+ }
271
+ }
272
+ return 0;
273
+ }