@hew-lang/sandbox-vm 0.6.2 → 0.6.4
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/README.md +43 -4
- package/cli/test-runner.mjs +4 -1
- package/dist/interpreter/interpreter.d.ts +1 -1
- package/dist/interpreter/interpreter.js +1 -1
- package/dist/interpreter/parity-runner.js +26 -1
- package/dist/interpreter/run-program.d.ts +3 -2
- package/dist/interpreter/run-program.js +5 -3
- package/dist/interpreter/schema-validator.d.ts +9 -4
- package/dist/interpreter/schema-validator.js +15 -49
- package/dist/interpreter/types.d.ts +4 -0
- package/dist/interpreter/v1/browser-directory.d.ts +107 -0
- package/dist/interpreter/v1/browser-directory.js +288 -0
- package/dist/interpreter/v1/calendar.d.ts +4 -0
- package/dist/interpreter/v1/calendar.js +64 -0
- package/dist/interpreter/v1/codecs.js +2 -2
- package/dist/interpreter/v1/exec.d.ts +2 -2
- package/dist/interpreter/v1/exec.js +439 -183
- package/dist/interpreter/v1/instructions.generated.d.ts +1135 -0
- package/dist/interpreter/v1/instructions.generated.js +106 -0
- package/dist/interpreter/v1/package-graph.d.ts +2 -0
- package/dist/interpreter/v1/package-graph.js +729 -0
- package/dist/interpreter/v1/package-validator.generated.d.ts +3 -0
- package/dist/interpreter/v1/package-validator.generated.js +75846 -0
- package/dist/interpreter/v1/package.d.ts +5 -680
- package/dist/interpreter/v1/package.js +0 -12
- package/dist/interpreter/v1/scheduler.d.ts +5 -1
- package/dist/interpreter/v1/scheduler.js +32 -3
- package/dist/interpreter/v1/shims.d.ts +250 -7
- package/dist/interpreter/v1/shims.js +429 -150
- package/dist/interpreter/v1/structural.d.ts +2 -28
- package/dist/interpreter/v1/timestamp.d.ts +7 -0
- package/dist/interpreter/v1/timestamp.js +54 -0
- package/dist/interpreter/v1/validate.d.ts +8 -2
- package/dist/interpreter/v1/validate.js +190 -202
- package/dist/interpreter/v1/value-operations.d.ts +7 -2
- package/dist/interpreter/v1/value-operations.js +13 -6
- package/dist/interpreter/values.d.ts +4 -0
- package/dist/interpreter/values.js +6 -0
- package/dist/interpreter/worker.js +4 -3
- package/package.json +4 -4
|
@@ -1,12 +1,8 @@
|
|
|
1
|
+
import { DIRECTORY_OPERATIONS, } from "./browser-directory.js";
|
|
2
|
+
import { executeCalendar } from "./calendar.js";
|
|
1
3
|
import { charProperty, charCase } from "../unicode.js";
|
|
2
|
-
///
|
|
3
|
-
///
|
|
4
|
-
/// This table is the runtime-family admission authority: a package may name a
|
|
5
|
-
/// runtime family or an extern symbol exactly when there is a shim here for it.
|
|
6
|
-
/// A family or symbol with no entry is rejected at load, so there is no second
|
|
7
|
-
/// reject list to keep in step with this one. `FileRead` is refused by its
|
|
8
|
-
/// absence, and a `NativeIo` suspension by an operation missing from
|
|
9
|
-
/// [`SUPPORTED_NATIVE_IO`].
|
|
4
|
+
/// Runtime implementations and their host execution registration. Admission and
|
|
5
|
+
/// execution consume the same ordinary, resumable or refused disposition.
|
|
10
6
|
import { UNIT, cloneValue, compareUtf8, stringValue, renderStdout, } from "../values.js";
|
|
11
7
|
import { seededMt } from "./mt19937.js";
|
|
12
8
|
/// A language-visible fault raised inside a shim. The executor routes it to the
|
|
@@ -19,127 +15,252 @@ export class ShimFault extends Error {
|
|
|
19
15
|
this.name = "ShimFault";
|
|
20
16
|
}
|
|
21
17
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
18
|
+
function ordinary(shim) {
|
|
19
|
+
return { kind: "ordinary", shim };
|
|
20
|
+
}
|
|
21
|
+
function refused(capability, native = false) {
|
|
22
|
+
return {
|
|
23
|
+
kind: "refused",
|
|
24
|
+
category: native ? "native_only" : "not_implemented",
|
|
25
|
+
capability,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function resumable(continuation) {
|
|
29
|
+
return { kind: "resumable", ...continuation };
|
|
30
|
+
}
|
|
31
|
+
/// A registered algorithm may still require a host-supplied Wasm bridge.
|
|
32
|
+
export function registrationRefusal(registration, bridges) {
|
|
33
|
+
if (registration.kind === "refused")
|
|
34
|
+
return registration;
|
|
35
|
+
if (registration.kind === "directory" &&
|
|
36
|
+
registration.operation.action === "root" &&
|
|
37
|
+
!bridges.directoryRoots?.[registration.operation.access])
|
|
38
|
+
return {
|
|
39
|
+
...refused(`directoryRoots.${registration.operation.access}`),
|
|
40
|
+
message: `This operation requires a host-supplied OPFS ${registration.operation.access} directory handle.`,
|
|
41
|
+
};
|
|
42
|
+
return "bridge" in registration &&
|
|
43
|
+
registration.bridge &&
|
|
44
|
+
typeof bridges[registration.bridge] !== "function"
|
|
45
|
+
? refused(registration.bridge)
|
|
46
|
+
: null;
|
|
47
|
+
}
|
|
48
|
+
export const CODEC_REGISTRATION = {
|
|
49
|
+
kind: "resumable",
|
|
50
|
+
bridge: "codecBridge",
|
|
51
|
+
};
|
|
52
|
+
/// Each typed runtime identity has exactly one host disposition. An added Rust
|
|
53
|
+
/// family or nested operation must acquire a disposition before TypeScript builds.
|
|
54
|
+
export function resolveRuntime(entry) {
|
|
26
55
|
switch (entry.family) {
|
|
27
56
|
case "SupervisorPool":
|
|
28
|
-
return
|
|
29
|
-
? () => {
|
|
30
|
-
throw new Error("SupervisorPool requires its resumable executor");
|
|
31
|
-
}
|
|
32
|
-
: undefined;
|
|
33
|
-
case "ActorCaller":
|
|
34
|
-
case "ActorRefusalLog":
|
|
35
|
-
case "StructuralFormat":
|
|
36
|
-
return () => {
|
|
37
|
-
throw new Error("StructuralFormat requires its resumable executor");
|
|
38
|
-
};
|
|
39
|
-
case "FileRead":
|
|
40
|
-
return entry.detail === "LastError" ? () => str("") : undefined;
|
|
57
|
+
return resumable({ handler: "supervisor_pool", operation: entry.detail });
|
|
41
58
|
case "Print":
|
|
42
|
-
return printShim(entry.detail);
|
|
43
|
-
case "
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
case "RcStrongCount":
|
|
52
|
-
case "RcWeakCount":
|
|
53
|
-
return () => {
|
|
54
|
-
throw new Error("shared operation requires its resumable executor");
|
|
55
|
-
};
|
|
56
|
-
case "Vector":
|
|
57
|
-
return ["Contains", "Set", "Clear"].includes(String(entry.detail))
|
|
58
|
-
? () => {
|
|
59
|
-
throw new Error("vector Contains requires its selected Eq executor");
|
|
59
|
+
return ordinary(printShim(entry.detail));
|
|
60
|
+
case "FileRead":
|
|
61
|
+
switch (entry.detail) {
|
|
62
|
+
case "HasError":
|
|
63
|
+
case "LastErrorKind":
|
|
64
|
+
case "LastErrno":
|
|
65
|
+
case "LastError": {
|
|
66
|
+
const operation = entry.detail;
|
|
67
|
+
return ordinary((host) => host.fileError(operation));
|
|
60
68
|
}
|
|
61
|
-
:
|
|
69
|
+
default:
|
|
70
|
+
return refused(`FileRead::${entry.detail}`, true);
|
|
71
|
+
}
|
|
72
|
+
case "AsyncIo":
|
|
73
|
+
case "Tcp":
|
|
74
|
+
return refused(`${entry.family}::${entry.detail}`, true);
|
|
75
|
+
case "Semaphore":
|
|
76
|
+
case "Service":
|
|
77
|
+
case "VecContainsScalar":
|
|
78
|
+
case "VecGet":
|
|
79
|
+
case "VecSliceRange":
|
|
80
|
+
return refused(`${entry.family}::${entry.detail}`);
|
|
81
|
+
case "Encoding":
|
|
82
|
+
case "VecScalar":
|
|
83
|
+
return refused(entry.family);
|
|
84
|
+
case "Vector":
|
|
85
|
+
switch (entry.detail) {
|
|
86
|
+
case "Contains":
|
|
87
|
+
case "Set":
|
|
88
|
+
case "Clear":
|
|
89
|
+
return resumable({
|
|
90
|
+
handler: "collection",
|
|
91
|
+
family: "Vector",
|
|
92
|
+
operation: entry.detail,
|
|
93
|
+
});
|
|
94
|
+
case "Pop":
|
|
95
|
+
case "GetBorrow":
|
|
96
|
+
case "TakeFirst":
|
|
97
|
+
case "TakeAll":
|
|
98
|
+
case "Append":
|
|
99
|
+
return refused(`Vector::${entry.detail}`);
|
|
100
|
+
default:
|
|
101
|
+
return ordinary(VECTOR_SHIMS[entry.detail]);
|
|
102
|
+
}
|
|
62
103
|
case "Array":
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
104
|
+
switch (entry.detail) {
|
|
105
|
+
case "Set":
|
|
106
|
+
return resumable({
|
|
107
|
+
handler: "collection",
|
|
108
|
+
family: "Vector",
|
|
109
|
+
operation: entry.detail,
|
|
110
|
+
});
|
|
111
|
+
case "Len":
|
|
112
|
+
case "Index":
|
|
113
|
+
case "IndexBorrow":
|
|
114
|
+
return ordinary(VECTOR_SHIMS[entry.detail]);
|
|
115
|
+
default: {
|
|
116
|
+
const exhaustive = entry;
|
|
117
|
+
throw new Error(`unknown array operation ${String(exhaustive)}`);
|
|
66
118
|
}
|
|
67
|
-
|
|
68
|
-
? (_host, args) => sequenceElement(args)
|
|
69
|
-
: ["Len", "Index"].includes(String(entry.detail))
|
|
70
|
-
? VECTOR_SHIMS[detailName(entry.detail)]
|
|
71
|
-
: undefined;
|
|
119
|
+
}
|
|
72
120
|
case "Map":
|
|
121
|
+
return resumable({
|
|
122
|
+
handler: "collection",
|
|
123
|
+
family: "Map",
|
|
124
|
+
operation: entry.detail,
|
|
125
|
+
});
|
|
73
126
|
case "Set":
|
|
74
|
-
return
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
"GetBorrow",
|
|
80
|
-
"ContainsKey",
|
|
81
|
-
"Contains",
|
|
82
|
-
"Insert",
|
|
83
|
-
"Remove",
|
|
84
|
-
"Clear",
|
|
85
|
-
"Keys",
|
|
86
|
-
"Values",
|
|
87
|
-
"Entries",
|
|
88
|
-
"Elements",
|
|
89
|
-
].includes(detailName(entry.detail))
|
|
90
|
-
? () => {
|
|
91
|
-
throw new Error("collection operation requires its resumable executor");
|
|
92
|
-
}
|
|
93
|
-
: undefined;
|
|
127
|
+
return resumable({
|
|
128
|
+
handler: "collection",
|
|
129
|
+
family: "Set",
|
|
130
|
+
operation: entry.detail,
|
|
131
|
+
});
|
|
94
132
|
case "MathIntrinsic":
|
|
95
|
-
return MATH_SHIMS[
|
|
133
|
+
return ordinary(MATH_SHIMS[entry.detail]);
|
|
96
134
|
case "FloatMethod":
|
|
97
|
-
return FLOAT_METHOD_SHIMS[
|
|
135
|
+
return ordinary(FLOAT_METHOD_SHIMS[entry.detail]);
|
|
98
136
|
case "IntMethod":
|
|
99
|
-
return intMethodShim(entry.detail);
|
|
137
|
+
return ordinary(intMethodShim(entry.detail));
|
|
100
138
|
case "IntArith":
|
|
101
|
-
return intArithShim(entry.detail);
|
|
102
|
-
default:
|
|
103
|
-
|
|
139
|
+
return ordinary(intArithShim(entry.detail));
|
|
140
|
+
default: {
|
|
141
|
+
const registration = UNIT_FAMILIES[entry.family];
|
|
142
|
+
return typeof registration === "function"
|
|
143
|
+
? ordinary(registration)
|
|
144
|
+
: registration;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
export function resolveExtern(entry) {
|
|
149
|
+
if (Object.hasOwn(DIRECTORY_OPERATIONS, entry.symbol))
|
|
150
|
+
return {
|
|
151
|
+
kind: "directory",
|
|
152
|
+
operation: DIRECTORY_OPERATIONS[entry.symbol],
|
|
153
|
+
};
|
|
154
|
+
const registration = Object.hasOwn(EXTERN_SHIMS, entry.symbol)
|
|
155
|
+
? EXTERN_SHIMS[entry.symbol]
|
|
156
|
+
: undefined;
|
|
157
|
+
if (typeof registration === "function")
|
|
158
|
+
return ordinary(registration);
|
|
159
|
+
return (registration ?? {
|
|
160
|
+
...refused(entry.symbol, entry.native_capability != null),
|
|
161
|
+
description: entry.native_capability ?? undefined,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
const SUSPENSION_ROUTES = {
|
|
165
|
+
GeneratorNext: "GeneratorNext",
|
|
166
|
+
Yield: "Yield",
|
|
167
|
+
Sleep: "Sleep",
|
|
168
|
+
Safepoint: "Safepoint",
|
|
169
|
+
Ask: "Ask",
|
|
170
|
+
Await: "Await",
|
|
171
|
+
Join: "Join",
|
|
172
|
+
Select: "Select",
|
|
173
|
+
StreamSend: "StreamSend",
|
|
174
|
+
StreamNext: "StreamNext",
|
|
175
|
+
NativeIo: "NativeIo",
|
|
176
|
+
Read: refused("Read", true),
|
|
177
|
+
Accept: refused("Accept", true),
|
|
178
|
+
SleepUntil: refused("SleepUntil"),
|
|
179
|
+
ServiceAcquire: refused("ServiceAcquire"),
|
|
180
|
+
SemaphoreAcquire: refused("SemaphoreAcquire"),
|
|
181
|
+
ActorSend: refused("ActorSend"),
|
|
182
|
+
RestartWait: refused("RestartWait"),
|
|
183
|
+
CallClosure: refused("CallClosure"),
|
|
184
|
+
Timeout: refused("Timeout"),
|
|
185
|
+
ScopeDeadline: refused("ScopeDeadline"),
|
|
186
|
+
Offload: refused("Offload"),
|
|
187
|
+
};
|
|
188
|
+
export function suspensionRefusal(kind) {
|
|
189
|
+
const route = SUSPENSION_ROUTES[kind];
|
|
190
|
+
return typeof route === "string" ? null : route;
|
|
191
|
+
}
|
|
192
|
+
function executableSuspension(term) {
|
|
193
|
+
return suspensionRefusal(term.kind) === null;
|
|
194
|
+
}
|
|
195
|
+
const NATIVE_IO_ROUTES = {
|
|
196
|
+
StdinReadLine: "StdinReadLine",
|
|
197
|
+
SinkFinish: "SinkFinish",
|
|
198
|
+
TcpRead: refused("NativeIo::TcpRead", true),
|
|
199
|
+
TcpWrite: refused("NativeIo::TcpWrite", true),
|
|
200
|
+
TcpAccept: refused("NativeIo::TcpAccept", true),
|
|
201
|
+
TcpConnect: refused("NativeIo::TcpConnect", true),
|
|
202
|
+
TcpConnectTimeout: refused("NativeIo::TcpConnectTimeout", true),
|
|
203
|
+
TlsConnect: refused("NativeIo::TlsConnect", true),
|
|
204
|
+
TlsRead: refused("NativeIo::TlsRead", true),
|
|
205
|
+
TlsWrite: refused("NativeIo::TlsWrite", true),
|
|
206
|
+
FileRead: "FileRead",
|
|
207
|
+
FileWrite: "FileWrite",
|
|
208
|
+
};
|
|
209
|
+
function nativeIoRefusal(operation) {
|
|
210
|
+
const route = NATIVE_IO_ROUTES[operation];
|
|
211
|
+
return typeof route === "string" ? null : route;
|
|
212
|
+
}
|
|
213
|
+
function executableNativeIo(term) {
|
|
214
|
+
return nativeIoRefusal(term.detail.operation) === null;
|
|
215
|
+
}
|
|
216
|
+
/// The executor handles exactly the resumable identities registered above.
|
|
217
|
+
export function resolveSuspension(term) {
|
|
218
|
+
if (!executableSuspension(term))
|
|
219
|
+
return suspensionRefusal(term.kind);
|
|
220
|
+
if (term.kind === "NativeIo") {
|
|
221
|
+
if (!executableNativeIo(term))
|
|
222
|
+
return nativeIoRefusal(term.detail.operation);
|
|
223
|
+
return { kind: "resumable", term };
|
|
104
224
|
}
|
|
225
|
+
return { kind: "resumable", term };
|
|
105
226
|
}
|
|
106
|
-
export function resolveExternShim(symbol) {
|
|
107
|
-
return EXTERN_SHIMS[symbol];
|
|
108
|
-
}
|
|
109
|
-
/// The suspend kinds a sequential package may carry. `NativeIo` is admitted
|
|
110
|
-
/// per operation through [`SUPPORTED_NATIVE_IO`] instead.
|
|
111
|
-
export const SUPPORTED_SUSPEND_KINDS = new Set([
|
|
112
|
-
"GeneratorNext",
|
|
113
|
-
"Yield",
|
|
114
|
-
"Sleep",
|
|
115
|
-
"Safepoint",
|
|
116
|
-
"Ask",
|
|
117
|
-
"Await",
|
|
118
|
-
"Join",
|
|
119
|
-
"Select",
|
|
120
|
-
"StreamSend",
|
|
121
|
-
"StreamNext",
|
|
122
|
-
]);
|
|
123
|
-
/// The VM serves replay standard input and in-memory sink closure.
|
|
124
|
-
export const SUPPORTED_NATIVE_IO = new Set([
|
|
125
|
-
"StdinReadLine",
|
|
126
|
-
"SinkFinish",
|
|
127
|
-
]);
|
|
128
227
|
// ── families ────────────────────────────────────────────────────────────────
|
|
129
228
|
/// `Print { kind, newline }`. The rendering follows the value's own
|
|
130
229
|
/// representation: casts normalize an integer into its target range, so the
|
|
131
230
|
/// declared `kind` never changes how a value prints.
|
|
132
231
|
function printShim(detail) {
|
|
133
|
-
|
|
134
|
-
return undefined;
|
|
135
|
-
}
|
|
136
|
-
const newline = detail.newline === true;
|
|
232
|
+
const newline = detail.newline;
|
|
137
233
|
return (host, args) => {
|
|
138
234
|
host.writeStdout(newline ? `${renderStdout(arg(args, 0))}\n` : renderStdout(arg(args, 0)));
|
|
139
235
|
return UNIT;
|
|
140
236
|
};
|
|
141
237
|
}
|
|
142
|
-
const
|
|
238
|
+
const UNIT_FAMILIES = {
|
|
239
|
+
TimestampNow: (host, _args, _variant, aggregate) => {
|
|
240
|
+
const millis = host.unixTimeMillis();
|
|
241
|
+
if (!Number.isFinite(millis))
|
|
242
|
+
throw new ShimFault("integer_overflow", "host wall clock is not finite");
|
|
243
|
+
const seconds = Math.floor(millis / 1000);
|
|
244
|
+
let nanos = Math.round((millis - seconds * 1000) * 1_000_000);
|
|
245
|
+
let whole = BigInt(seconds);
|
|
246
|
+
if (nanos === 1_000_000_000) {
|
|
247
|
+
whole += 1n;
|
|
248
|
+
nanos = 0;
|
|
249
|
+
}
|
|
250
|
+
if (whole < -(1n << 63n) ||
|
|
251
|
+
whole >= 1n << 63n ||
|
|
252
|
+
nanos < 0 ||
|
|
253
|
+
nanos >= 1_000_000_000)
|
|
254
|
+
throw new ShimFault("integer_overflow", "host wall clock exceeds timestamp range");
|
|
255
|
+
if (!aggregate || aggregate.builtin !== "Timestamp")
|
|
256
|
+
throw new TypeError("timestamp clock lacks its aggregate descriptor");
|
|
257
|
+
return {
|
|
258
|
+
kind: "record",
|
|
259
|
+
typeId: aggregate.name,
|
|
260
|
+
shape: aggregate.id,
|
|
261
|
+
fields: [int(whole), int(BigInt(nanos))],
|
|
262
|
+
};
|
|
263
|
+
},
|
|
143
264
|
StderrWrite: (host, args) => {
|
|
144
265
|
host.writeStderr(text(args, 0));
|
|
145
266
|
return UNIT;
|
|
@@ -156,14 +277,8 @@ const UNIT_FAMILY_SHIMS = {
|
|
|
156
277
|
StreamFromGenerator: (host, args) => host.generatorStream(arg(args, 0)),
|
|
157
278
|
SinkFromEncoder: (host, args) => host.encoderSink(arg(args, 0), arg(args, 1)),
|
|
158
279
|
SinkClone: (host, args) => host.cloneSink(arg(args, 0)),
|
|
159
|
-
SinkClose: (
|
|
160
|
-
|
|
161
|
-
return UNIT;
|
|
162
|
-
},
|
|
163
|
-
StreamClose: (host, args) => {
|
|
164
|
-
host.closePipe(arg(args, 0));
|
|
165
|
-
return UNIT;
|
|
166
|
-
},
|
|
280
|
+
SinkClose: resumable({ handler: "close" }),
|
|
281
|
+
StreamClose: resumable({ handler: "close" }),
|
|
167
282
|
StringConcat: (_host, args) => str(`${text(args, 0)}${text(args, 1)}`),
|
|
168
283
|
StringClone: (_host, args) => cloneValue(arg(args, 0)),
|
|
169
284
|
StringEquals: (_host, args) => bool(text(args, 0) === text(args, 1)),
|
|
@@ -291,9 +406,7 @@ const UNIT_FAMILY_SHIMS = {
|
|
|
291
406
|
CharFromI64: checkedChar,
|
|
292
407
|
CharFromU64: checkedChar,
|
|
293
408
|
CharToString: (_host, args) => str(renderStdout(arg(args, 0))),
|
|
294
|
-
BytesDecodeUtf8: (
|
|
295
|
-
throw new Error("UTF-8 decode requires its checked result carrier");
|
|
296
|
-
},
|
|
409
|
+
BytesDecodeUtf8: resumable({ handler: "utf8_decode" }),
|
|
297
410
|
// TextDecoder replaces each maximal invalid subsequence with U+FFFD, as
|
|
298
411
|
// native lossy decoding does.
|
|
299
412
|
BytesDecodeUtf8Lossy: (_host, args) => str(decodeUtf8(arg(args, 0))),
|
|
@@ -388,6 +501,164 @@ const UNIT_FAMILY_SHIMS = {
|
|
|
388
501
|
],
|
|
389
502
|
};
|
|
390
503
|
},
|
|
504
|
+
ActorDemonitor: refused("ActorDemonitor"),
|
|
505
|
+
ActorLink: refused("ActorLink"),
|
|
506
|
+
ActorMonitor: refused("ActorMonitor"),
|
|
507
|
+
ActorCaller: resumable({ handler: "actor_caller" }),
|
|
508
|
+
ActorRefusalLog: resumable({ handler: "actor_refusal_log" }),
|
|
509
|
+
ActorUnlink: refused("ActorUnlink"),
|
|
510
|
+
AutoMutexAlloc: refused("AutoMutexAlloc"),
|
|
511
|
+
AutoMutexFree: refused("AutoMutexFree"),
|
|
512
|
+
AutoMutexLock: refused("AutoMutexLock"),
|
|
513
|
+
AutoMutexUnlock: refused("AutoMutexUnlock"),
|
|
514
|
+
DequePopFront: refused("DequePopFront"),
|
|
515
|
+
DequePopBack: refused("DequePopBack"),
|
|
516
|
+
CancelTokenIsRequested: refused("CancelTokenIsRequested"),
|
|
517
|
+
CancelTokenRelease: refused("CancelTokenRelease"),
|
|
518
|
+
CancelTokenRetain: refused("CancelTokenRetain"),
|
|
519
|
+
ActorRequestRelease: refused("ActorRequestRelease"),
|
|
520
|
+
ActorCallFree: refused("ActorCallFree"),
|
|
521
|
+
ActorRequestTake: refused("ActorRequestTake"),
|
|
522
|
+
DurationAbs: refused("DurationAbs"),
|
|
523
|
+
DurationHours: refused("DurationHours"),
|
|
524
|
+
DurationIsZero: refused("DurationIsZero"),
|
|
525
|
+
DurationMicros: refused("DurationMicros"),
|
|
526
|
+
DurationMillis: refused("DurationMillis"),
|
|
527
|
+
DurationMins: refused("DurationMins"),
|
|
528
|
+
DurationNanos: refused("DurationNanos"),
|
|
529
|
+
DurationSecs: refused("DurationSecs"),
|
|
530
|
+
DynBoxAlloc: refused("DynBoxAlloc"),
|
|
531
|
+
DynBoxFree: refused("DynBoxFree"),
|
|
532
|
+
HashMapContainsKeyLayout: refused("HashMapContainsKeyLayout"),
|
|
533
|
+
HashMapClearLayout: refused("HashMapClearLayout"),
|
|
534
|
+
HashMapCloneLayout: refused("HashMapCloneLayout"),
|
|
535
|
+
HashMapEntriesLayout: refused("HashMapEntriesLayout"),
|
|
536
|
+
HashMapFreeLayout: refused("HashMapFreeLayout"),
|
|
537
|
+
HashMapGetLayout: refused("HashMapGetLayout"),
|
|
538
|
+
HashMapInsertLayout: refused("HashMapInsertLayout"),
|
|
539
|
+
HashMapKeysLayout: refused("HashMapKeysLayout"),
|
|
540
|
+
HashMapLenLayout: refused("HashMapLenLayout"),
|
|
541
|
+
HashMapNew: refused("HashMapNew"),
|
|
542
|
+
HashMapNewWithLayout: refused("HashMapNewWithLayout"),
|
|
543
|
+
HashMapRemoveLayout: refused("HashMapRemoveLayout"),
|
|
544
|
+
HashMapValuesLayout: refused("HashMapValuesLayout"),
|
|
545
|
+
HashSetContainsLayout: refused("HashSetContainsLayout"),
|
|
546
|
+
HashSetClearLayout: refused("HashSetClearLayout"),
|
|
547
|
+
HashSetCloneLayout: refused("HashSetCloneLayout"),
|
|
548
|
+
HashSetFreeLayout: refused("HashSetFreeLayout"),
|
|
549
|
+
HashSetInsertLayout: refused("HashSetInsertLayout"),
|
|
550
|
+
HashSetIsEmptyLayout: refused("HashSetIsEmptyLayout"),
|
|
551
|
+
HashSetLenLayout: refused("HashSetLenLayout"),
|
|
552
|
+
HashSetNew: refused("HashSetNew"),
|
|
553
|
+
HashSetNewWithLayout: refused("HashSetNewWithLayout"),
|
|
554
|
+
HashSetRemoveLayout: refused("HashSetRemoveLayout"),
|
|
555
|
+
HashSetToVecLayout: refused("HashSetToVecLayout"),
|
|
556
|
+
InstantDurationSince: refused("InstantDurationSince"),
|
|
557
|
+
InstantElapsed: refused("InstantElapsed"),
|
|
558
|
+
InstantNow: refused("InstantNow"),
|
|
559
|
+
NodeConnect: refused("NodeConnect"),
|
|
560
|
+
NodeId: refused("NodeId"),
|
|
561
|
+
NodeIdDisplay: refused("NodeIdDisplay"),
|
|
562
|
+
LocationNodeId: refused("LocationNodeId"),
|
|
563
|
+
LocationIncarnation: refused("LocationIncarnation"),
|
|
564
|
+
LocationDisplay: refused("LocationDisplay"),
|
|
565
|
+
NodeIdentityKey: refused("NodeIdentityKey"),
|
|
566
|
+
NodeLoadKeys: refused("NodeLoadKeys"),
|
|
567
|
+
NodeLookup: refused("NodeLookup"),
|
|
568
|
+
NodeRegister: refused("NodeRegister"),
|
|
569
|
+
NodeSetTransport: refused("NodeSetTransport"),
|
|
570
|
+
NodeShutdown: refused("NodeShutdown"),
|
|
571
|
+
NodeStart: refused("NodeStart"),
|
|
572
|
+
MetricCounterRegister: refused("MetricCounterRegister"),
|
|
573
|
+
MetricCounterInc: refused("MetricCounterInc"),
|
|
574
|
+
MetricCounterAdd: refused("MetricCounterAdd"),
|
|
575
|
+
MetricGaugeRegister: refused("MetricGaugeRegister"),
|
|
576
|
+
MetricGaugeSet: refused("MetricGaugeSet"),
|
|
577
|
+
MetricGaugeInc: refused("MetricGaugeInc"),
|
|
578
|
+
MetricGaugeDec: refused("MetricGaugeDec"),
|
|
579
|
+
MetricGaugeAdd: refused("MetricGaugeAdd"),
|
|
580
|
+
MetricHistogramRegister: refused("MetricHistogramRegister"),
|
|
581
|
+
MetricHistogramRegisterSimple: refused("MetricHistogramRegisterSimple"),
|
|
582
|
+
MetricHistogramRecord: refused("MetricHistogramRecord"),
|
|
583
|
+
MetricVecRegister: refused("MetricVecRegister"),
|
|
584
|
+
MetricVecWith: refused("MetricVecWith"),
|
|
585
|
+
ObserveReadU64: refused("ObserveReadU64"),
|
|
586
|
+
ObserveScrape: refused("ObserveScrape"),
|
|
587
|
+
ObserveSeries: refused("ObserveSeries"),
|
|
588
|
+
ObserveBarrier: refused("ObserveBarrier"),
|
|
589
|
+
RcClone: resumable({ handler: "shared", operation: "RcClone" }),
|
|
590
|
+
RcDowngrade: resumable({ handler: "shared", operation: "RcDowngrade" }),
|
|
591
|
+
RcDrop: refused("RcDrop"),
|
|
592
|
+
RcGet: resumable({ handler: "shared", operation: "RcGet" }),
|
|
593
|
+
RcIsUnique: resumable({ handler: "shared", operation: "RcIsUnique" }),
|
|
594
|
+
RcNew: resumable({ handler: "shared", operation: "RcNew" }),
|
|
595
|
+
RcSet: resumable({ handler: "shared", operation: "RcSet" }),
|
|
596
|
+
RcStrongCount: resumable({ handler: "shared", operation: "RcStrongCount" }),
|
|
597
|
+
RcWeakCount: resumable({ handler: "shared", operation: "RcWeakCount" }),
|
|
598
|
+
WeakCloneRc: resumable({ handler: "shared", operation: "WeakCloneRc" }),
|
|
599
|
+
WeakDropRc: refused("WeakDropRc"),
|
|
600
|
+
WeakUpgradeRc: resumable({ handler: "shared", operation: "WeakUpgradeRc" }),
|
|
601
|
+
RegexCapture: refused("RegexCapture"),
|
|
602
|
+
RegexCompile: refused("RegexCompile"),
|
|
603
|
+
RegexFreeCapture: refused("RegexFreeCapture"),
|
|
604
|
+
RegexHandle: refused("RegexHandle"),
|
|
605
|
+
RegexMatch: refused("RegexMatch"),
|
|
606
|
+
ReplyChannelCancel: refused("ReplyChannelCancel"),
|
|
607
|
+
ReplyChannelFree: refused("ReplyChannelFree"),
|
|
608
|
+
ReplyChannelNew: refused("ReplyChannelNew"),
|
|
609
|
+
ReplyPayloadFree: refused("ReplyPayloadFree"),
|
|
610
|
+
ReplyWait: refused("ReplyWait"),
|
|
611
|
+
SelectFirst: refused("SelectFirst"),
|
|
612
|
+
StreamChunks: refused("StreamChunks"),
|
|
613
|
+
StreamForward: refused("StreamForward"),
|
|
614
|
+
StreamLines: refused("StreamLines"),
|
|
615
|
+
StreamNextLayout: refused("StreamNextLayout"),
|
|
616
|
+
StreamSendLayout: refused("StreamSendLayout"),
|
|
617
|
+
StreamTake: refused("StreamTake"),
|
|
618
|
+
StreamTryNextLayout: refused("StreamTryNextLayout"),
|
|
619
|
+
StreamTrySendLayout: refused("StreamTrySendLayout"),
|
|
620
|
+
StructuralFormat: resumable({ handler: "structural_format" }),
|
|
621
|
+
StringLines: refused("StringLines"),
|
|
622
|
+
ProcessExit: refused("ProcessExit"),
|
|
623
|
+
SupervisorDirectId: refused("SupervisorDirectId"),
|
|
624
|
+
SupervisorChildGet: refused("SupervisorChildGet"),
|
|
625
|
+
LocalPidSupervisorChildGet: refused("LocalPidSupervisorChildGet"),
|
|
626
|
+
SupervisorNestedGet: refused("SupervisorNestedGet"),
|
|
627
|
+
SupervisorPoolChildGet: refused("SupervisorPoolChildGet"),
|
|
628
|
+
LocalPidSupervisorPoolChildRefGet: refused("LocalPidSupervisorPoolChildRefGet"),
|
|
629
|
+
SupervisorPoolLen: refused("SupervisorPoolLen"),
|
|
630
|
+
SupervisorStop: refused("SupervisorStop"),
|
|
631
|
+
TlsAttachLocal: refused("TlsAttachLocal"),
|
|
632
|
+
WebSocketAttachLocal: refused("WebSocketAttachLocal"),
|
|
633
|
+
TaskFree: refused("TaskFree"),
|
|
634
|
+
GeneratorFree: refused("GeneratorFree"),
|
|
635
|
+
VecAppend: refused("VecAppend"),
|
|
636
|
+
VecClear: refused("VecClear"),
|
|
637
|
+
VecClone: refused("VecClone"),
|
|
638
|
+
VecCloneLayout: refused("VecCloneLayout"),
|
|
639
|
+
VecCloneOwned: refused("VecCloneOwned"),
|
|
640
|
+
VecContainsLayout: refused("VecContainsLayout"),
|
|
641
|
+
VecTakeAll: refused("VecTakeAll"),
|
|
642
|
+
VecContainsOwned: refused("VecContainsOwned"),
|
|
643
|
+
VecIsEmpty: refused("VecIsEmpty"),
|
|
644
|
+
VecJoinStr: refused("VecJoinStr"),
|
|
645
|
+
VecLen: refused("VecLen"),
|
|
646
|
+
VecNew: refused("VecNew"),
|
|
647
|
+
VecPopBool: refused("VecPopBool"),
|
|
648
|
+
VecPopLayout: refused("VecPopLayout"),
|
|
649
|
+
VecPopOwned: refused("VecPopOwned"),
|
|
650
|
+
VecPushBool: refused("VecPushBool"),
|
|
651
|
+
VecPushLayout: refused("VecPushLayout"),
|
|
652
|
+
VecPushOwned: refused("VecPushOwned"),
|
|
653
|
+
VecPushOwnedMove: refused("VecPushOwnedMove"),
|
|
654
|
+
VecRemoveAtBool: refused("VecRemoveAtBool"),
|
|
655
|
+
VecRemoveAtLayout: refused("VecRemoveAtLayout"),
|
|
656
|
+
VecRemoveAtOwned: refused("VecRemoveAtOwned"),
|
|
657
|
+
VecSetBool: refused("VecSetBool"),
|
|
658
|
+
VecSetLayout: refused("VecSetLayout"),
|
|
659
|
+
VecSetOwned: refused("VecSetOwned"),
|
|
660
|
+
VecSetOwnedMove: refused("VecSetOwnedMove"),
|
|
661
|
+
VtableDispatchPanicOnOob: refused("VtableDispatchPanicOnOob"),
|
|
391
662
|
};
|
|
392
663
|
const VECTOR_SHIMS = {
|
|
393
664
|
New: () => ({ kind: "vector", elementType: "", items: [] }),
|
|
@@ -596,8 +867,6 @@ const FLOAT_METHOD_SHIMS = {
|
|
|
596
867
|
},
|
|
597
868
|
IsSignNegative: (_host, args) => bool(toBits(real(args, 0)) >> 63n === 1n),
|
|
598
869
|
};
|
|
599
|
-
/// The receiver width an `IntMethod`/`IntArith` detail names. The VM is a
|
|
600
|
-
/// 64-bit target, so the pointer-sized widths are 64 bits wide.
|
|
601
870
|
const INT_WIDTHS = {
|
|
602
871
|
I8: { bits: 8, signed: true },
|
|
603
872
|
I16: { bits: 16, signed: true },
|
|
@@ -610,15 +879,6 @@ const INT_WIDTHS = {
|
|
|
610
879
|
U64: { bits: 64, signed: false },
|
|
611
880
|
Usize: { bits: 64, signed: false },
|
|
612
881
|
};
|
|
613
|
-
/// `[op, width]`, as `RuntimeCallFamily` serializes a two-field variant.
|
|
614
|
-
function intDetail(detail) {
|
|
615
|
-
if (!Array.isArray(detail) || detail.length !== 2) {
|
|
616
|
-
return undefined;
|
|
617
|
-
}
|
|
618
|
-
const [op, width] = detail;
|
|
619
|
-
const shape = typeof width === "string" ? INT_WIDTHS[width] : undefined;
|
|
620
|
-
return typeof op === "string" && shape ? [op, shape] : undefined;
|
|
621
|
-
}
|
|
622
882
|
function wrapTo(width, value) {
|
|
623
883
|
return width.signed
|
|
624
884
|
? BigInt.asIntN(width.bits, value)
|
|
@@ -642,11 +902,8 @@ function popcount(value) {
|
|
|
642
902
|
/// works on the receiver's unsigned bit pattern and the rotate amount is taken
|
|
643
903
|
/// modulo the width.
|
|
644
904
|
function intMethodShim(detail) {
|
|
645
|
-
const
|
|
646
|
-
|
|
647
|
-
return undefined;
|
|
648
|
-
}
|
|
649
|
-
const [op, width] = parsed;
|
|
905
|
+
const [op, name] = detail;
|
|
906
|
+
const width = INT_WIDTHS[name];
|
|
650
907
|
const bits = BigInt(width.bits);
|
|
651
908
|
const unsigned = (args) => BigInt.asUintN(width.bits, integer(args, 0));
|
|
652
909
|
const result = (pattern) => int(wrapTo(width, pattern));
|
|
@@ -703,30 +960,34 @@ function intMethodShim(detail) {
|
|
|
703
960
|
return (_host, args) => rotate(args, true);
|
|
704
961
|
case "RotateRight":
|
|
705
962
|
return (_host, args) => rotate(args, false);
|
|
706
|
-
default:
|
|
707
|
-
|
|
963
|
+
default: {
|
|
964
|
+
const exhaustive = op;
|
|
965
|
+
throw new Error(`unknown integer operation ${String(exhaustive)}`);
|
|
966
|
+
}
|
|
708
967
|
}
|
|
709
968
|
}
|
|
710
969
|
/// Non-trapping integer arithmetic at the receiver's width: wrapping keeps
|
|
711
970
|
/// the low bits, saturating clamps to the width's bounds and checked answers
|
|
712
971
|
/// `None` where native's overflow flag is set.
|
|
713
972
|
function intArithShim(detail) {
|
|
714
|
-
const
|
|
715
|
-
|
|
716
|
-
return undefined;
|
|
717
|
-
}
|
|
718
|
-
const [kind, width] = parsed;
|
|
973
|
+
const [kind, name] = detail;
|
|
974
|
+
const width = INT_WIDTHS[name];
|
|
719
975
|
const [min, max] = intBounds(width);
|
|
976
|
+
const add = (x, y) => x + y;
|
|
977
|
+
const sub = (x, y) => x - y;
|
|
978
|
+
const mul = (x, y) => x * y;
|
|
720
979
|
const operations = {
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
980
|
+
WrappingAdd: ["Wrapping", add],
|
|
981
|
+
WrappingSub: ["Wrapping", sub],
|
|
982
|
+
WrappingMul: ["Wrapping", mul],
|
|
983
|
+
SaturatingAdd: ["Saturating", add],
|
|
984
|
+
SaturatingSub: ["Saturating", sub],
|
|
985
|
+
SaturatingMul: ["Saturating", mul],
|
|
986
|
+
CheckedAdd: ["Checked", add],
|
|
987
|
+
CheckedSub: ["Checked", sub],
|
|
988
|
+
CheckedMul: ["Checked", mul],
|
|
724
989
|
};
|
|
725
|
-
const mode
|
|
726
|
-
const apply = mode ? operations[kind.slice(mode.length)] : undefined;
|
|
727
|
-
if (!mode || !apply) {
|
|
728
|
-
return undefined;
|
|
729
|
-
}
|
|
990
|
+
const [mode, apply] = operations[kind];
|
|
730
991
|
const exact = (args) => apply(wrapTo(width, integer(args, 0)), wrapTo(width, integer(args, 1)));
|
|
731
992
|
switch (mode) {
|
|
732
993
|
case "Wrapping":
|
|
@@ -766,6 +1027,27 @@ function bigMax(left, right) {
|
|
|
766
1027
|
}
|
|
767
1028
|
// ── externs ─────────────────────────────────────────────────────────────────
|
|
768
1029
|
const EXTERN_SHIMS = {
|
|
1030
|
+
hew_path_separator: () => str("/"),
|
|
1031
|
+
hew_calendar_format: {
|
|
1032
|
+
kind: "ordinary",
|
|
1033
|
+
bridge: "calendarBridge",
|
|
1034
|
+
shim: (host, args, _variant, shape) => executeCalendar(host.calendarBridge, "hew_calendar_format", args, shape),
|
|
1035
|
+
},
|
|
1036
|
+
hew_calendar_parse: {
|
|
1037
|
+
kind: "ordinary",
|
|
1038
|
+
bridge: "calendarBridge",
|
|
1039
|
+
shim: (host, args, _variant, shape) => executeCalendar(host.calendarBridge, "hew_calendar_parse", args, shape),
|
|
1040
|
+
},
|
|
1041
|
+
hew_calendar_components: {
|
|
1042
|
+
kind: "ordinary",
|
|
1043
|
+
bridge: "calendarBridge",
|
|
1044
|
+
shim: (host, args, _variant, shape) => executeCalendar(host.calendarBridge, "hew_calendar_components", args, shape),
|
|
1045
|
+
},
|
|
1046
|
+
hew_calendar_from_parts: {
|
|
1047
|
+
kind: "ordinary",
|
|
1048
|
+
bridge: "calendarBridge",
|
|
1049
|
+
shim: (host, args, _variant, shape) => executeCalendar(host.calendarBridge, "hew_calendar_from_parts", args, shape),
|
|
1050
|
+
},
|
|
769
1051
|
hew_args_count: (host) => int(BigInt(host.argv.length)),
|
|
770
1052
|
// A native null managed string is canonical empty. Each result owns fresh
|
|
771
1053
|
// string storage; releasing it cannot change the host's supplied arguments.
|
|
@@ -904,9 +1186,6 @@ function pattern(host, value) {
|
|
|
904
1186
|
return value.kind === "string" ? value.value : renderStdout(value);
|
|
905
1187
|
}
|
|
906
1188
|
// ── operand helpers ─────────────────────────────────────────────────────────
|
|
907
|
-
function detailName(detail) {
|
|
908
|
-
return typeof detail === "string" ? detail : "";
|
|
909
|
-
}
|
|
910
1189
|
function arg(args, at) {
|
|
911
1190
|
return args[at] ?? UNIT;
|
|
912
1191
|
}
|