@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,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
|
+
}
|