@hew-lang/sandbox-vm 0.6.2 → 0.6.3
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 +1 -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 +75902 -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 +430 -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,165 @@ 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
|
+
NodeAllowPeer: refused("NodeAllowPeer"),
|
|
560
|
+
NodeConnect: refused("NodeConnect"),
|
|
561
|
+
NodeId: refused("NodeId"),
|
|
562
|
+
NodeIdDisplay: refused("NodeIdDisplay"),
|
|
563
|
+
LocationNodeId: refused("LocationNodeId"),
|
|
564
|
+
LocationIncarnation: refused("LocationIncarnation"),
|
|
565
|
+
LocationDisplay: refused("LocationDisplay"),
|
|
566
|
+
NodeIdentityKey: refused("NodeIdentityKey"),
|
|
567
|
+
NodeLoadKeys: refused("NodeLoadKeys"),
|
|
568
|
+
NodeLookup: refused("NodeLookup"),
|
|
569
|
+
NodeRegister: refused("NodeRegister"),
|
|
570
|
+
NodeSetTransport: refused("NodeSetTransport"),
|
|
571
|
+
NodeShutdown: refused("NodeShutdown"),
|
|
572
|
+
NodeStart: refused("NodeStart"),
|
|
573
|
+
MetricCounterRegister: refused("MetricCounterRegister"),
|
|
574
|
+
MetricCounterInc: refused("MetricCounterInc"),
|
|
575
|
+
MetricCounterAdd: refused("MetricCounterAdd"),
|
|
576
|
+
MetricGaugeRegister: refused("MetricGaugeRegister"),
|
|
577
|
+
MetricGaugeSet: refused("MetricGaugeSet"),
|
|
578
|
+
MetricGaugeInc: refused("MetricGaugeInc"),
|
|
579
|
+
MetricGaugeDec: refused("MetricGaugeDec"),
|
|
580
|
+
MetricGaugeAdd: refused("MetricGaugeAdd"),
|
|
581
|
+
MetricHistogramRegister: refused("MetricHistogramRegister"),
|
|
582
|
+
MetricHistogramRegisterSimple: refused("MetricHistogramRegisterSimple"),
|
|
583
|
+
MetricHistogramRecord: refused("MetricHistogramRecord"),
|
|
584
|
+
MetricVecRegister: refused("MetricVecRegister"),
|
|
585
|
+
MetricVecWith: refused("MetricVecWith"),
|
|
586
|
+
ObserveReadU64: refused("ObserveReadU64"),
|
|
587
|
+
ObserveScrape: refused("ObserveScrape"),
|
|
588
|
+
ObserveSeries: refused("ObserveSeries"),
|
|
589
|
+
ObserveBarrier: refused("ObserveBarrier"),
|
|
590
|
+
RcClone: resumable({ handler: "shared", operation: "RcClone" }),
|
|
591
|
+
RcDowngrade: resumable({ handler: "shared", operation: "RcDowngrade" }),
|
|
592
|
+
RcDrop: refused("RcDrop"),
|
|
593
|
+
RcGet: resumable({ handler: "shared", operation: "RcGet" }),
|
|
594
|
+
RcIsUnique: resumable({ handler: "shared", operation: "RcIsUnique" }),
|
|
595
|
+
RcNew: resumable({ handler: "shared", operation: "RcNew" }),
|
|
596
|
+
RcSet: resumable({ handler: "shared", operation: "RcSet" }),
|
|
597
|
+
RcStrongCount: resumable({ handler: "shared", operation: "RcStrongCount" }),
|
|
598
|
+
RcWeakCount: resumable({ handler: "shared", operation: "RcWeakCount" }),
|
|
599
|
+
WeakCloneRc: resumable({ handler: "shared", operation: "WeakCloneRc" }),
|
|
600
|
+
WeakDropRc: refused("WeakDropRc"),
|
|
601
|
+
WeakUpgradeRc: resumable({ handler: "shared", operation: "WeakUpgradeRc" }),
|
|
602
|
+
RegexCapture: refused("RegexCapture"),
|
|
603
|
+
RegexCompile: refused("RegexCompile"),
|
|
604
|
+
RegexFreeCapture: refused("RegexFreeCapture"),
|
|
605
|
+
RegexHandle: refused("RegexHandle"),
|
|
606
|
+
RegexMatch: refused("RegexMatch"),
|
|
607
|
+
ReplyChannelCancel: refused("ReplyChannelCancel"),
|
|
608
|
+
ReplyChannelFree: refused("ReplyChannelFree"),
|
|
609
|
+
ReplyChannelNew: refused("ReplyChannelNew"),
|
|
610
|
+
ReplyPayloadFree: refused("ReplyPayloadFree"),
|
|
611
|
+
ReplyWait: refused("ReplyWait"),
|
|
612
|
+
SelectFirst: refused("SelectFirst"),
|
|
613
|
+
StreamChunks: refused("StreamChunks"),
|
|
614
|
+
StreamForward: refused("StreamForward"),
|
|
615
|
+
StreamLines: refused("StreamLines"),
|
|
616
|
+
StreamNextLayout: refused("StreamNextLayout"),
|
|
617
|
+
StreamSendLayout: refused("StreamSendLayout"),
|
|
618
|
+
StreamTake: refused("StreamTake"),
|
|
619
|
+
StreamTryNextLayout: refused("StreamTryNextLayout"),
|
|
620
|
+
StreamTrySendLayout: refused("StreamTrySendLayout"),
|
|
621
|
+
StructuralFormat: resumable({ handler: "structural_format" }),
|
|
622
|
+
StringLines: refused("StringLines"),
|
|
623
|
+
ProcessExit: refused("ProcessExit"),
|
|
624
|
+
SupervisorDirectId: refused("SupervisorDirectId"),
|
|
625
|
+
SupervisorChildGet: refused("SupervisorChildGet"),
|
|
626
|
+
LocalPidSupervisorChildGet: refused("LocalPidSupervisorChildGet"),
|
|
627
|
+
SupervisorNestedGet: refused("SupervisorNestedGet"),
|
|
628
|
+
SupervisorPoolChildGet: refused("SupervisorPoolChildGet"),
|
|
629
|
+
LocalPidSupervisorPoolChildRefGet: refused("LocalPidSupervisorPoolChildRefGet"),
|
|
630
|
+
SupervisorPoolLen: refused("SupervisorPoolLen"),
|
|
631
|
+
SupervisorStop: refused("SupervisorStop"),
|
|
632
|
+
TlsAttachLocal: refused("TlsAttachLocal"),
|
|
633
|
+
WebSocketAttachLocal: refused("WebSocketAttachLocal"),
|
|
634
|
+
TaskFree: refused("TaskFree"),
|
|
635
|
+
GeneratorFree: refused("GeneratorFree"),
|
|
636
|
+
VecAppend: refused("VecAppend"),
|
|
637
|
+
VecClear: refused("VecClear"),
|
|
638
|
+
VecClone: refused("VecClone"),
|
|
639
|
+
VecCloneLayout: refused("VecCloneLayout"),
|
|
640
|
+
VecCloneOwned: refused("VecCloneOwned"),
|
|
641
|
+
VecContainsLayout: refused("VecContainsLayout"),
|
|
642
|
+
VecTakeAll: refused("VecTakeAll"),
|
|
643
|
+
VecContainsOwned: refused("VecContainsOwned"),
|
|
644
|
+
VecIsEmpty: refused("VecIsEmpty"),
|
|
645
|
+
VecJoinStr: refused("VecJoinStr"),
|
|
646
|
+
VecLen: refused("VecLen"),
|
|
647
|
+
VecNew: refused("VecNew"),
|
|
648
|
+
VecPopBool: refused("VecPopBool"),
|
|
649
|
+
VecPopLayout: refused("VecPopLayout"),
|
|
650
|
+
VecPopOwned: refused("VecPopOwned"),
|
|
651
|
+
VecPushBool: refused("VecPushBool"),
|
|
652
|
+
VecPushLayout: refused("VecPushLayout"),
|
|
653
|
+
VecPushOwned: refused("VecPushOwned"),
|
|
654
|
+
VecPushOwnedMove: refused("VecPushOwnedMove"),
|
|
655
|
+
VecRemoveAtBool: refused("VecRemoveAtBool"),
|
|
656
|
+
VecRemoveAtLayout: refused("VecRemoveAtLayout"),
|
|
657
|
+
VecRemoveAtOwned: refused("VecRemoveAtOwned"),
|
|
658
|
+
VecSetBool: refused("VecSetBool"),
|
|
659
|
+
VecSetLayout: refused("VecSetLayout"),
|
|
660
|
+
VecSetOwned: refused("VecSetOwned"),
|
|
661
|
+
VecSetOwnedMove: refused("VecSetOwnedMove"),
|
|
662
|
+
VtableDispatchPanicOnOob: refused("VtableDispatchPanicOnOob"),
|
|
391
663
|
};
|
|
392
664
|
const VECTOR_SHIMS = {
|
|
393
665
|
New: () => ({ kind: "vector", elementType: "", items: [] }),
|
|
@@ -596,8 +868,6 @@ const FLOAT_METHOD_SHIMS = {
|
|
|
596
868
|
},
|
|
597
869
|
IsSignNegative: (_host, args) => bool(toBits(real(args, 0)) >> 63n === 1n),
|
|
598
870
|
};
|
|
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
871
|
const INT_WIDTHS = {
|
|
602
872
|
I8: { bits: 8, signed: true },
|
|
603
873
|
I16: { bits: 16, signed: true },
|
|
@@ -610,15 +880,6 @@ const INT_WIDTHS = {
|
|
|
610
880
|
U64: { bits: 64, signed: false },
|
|
611
881
|
Usize: { bits: 64, signed: false },
|
|
612
882
|
};
|
|
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
883
|
function wrapTo(width, value) {
|
|
623
884
|
return width.signed
|
|
624
885
|
? BigInt.asIntN(width.bits, value)
|
|
@@ -642,11 +903,8 @@ function popcount(value) {
|
|
|
642
903
|
/// works on the receiver's unsigned bit pattern and the rotate amount is taken
|
|
643
904
|
/// modulo the width.
|
|
644
905
|
function intMethodShim(detail) {
|
|
645
|
-
const
|
|
646
|
-
|
|
647
|
-
return undefined;
|
|
648
|
-
}
|
|
649
|
-
const [op, width] = parsed;
|
|
906
|
+
const [op, name] = detail;
|
|
907
|
+
const width = INT_WIDTHS[name];
|
|
650
908
|
const bits = BigInt(width.bits);
|
|
651
909
|
const unsigned = (args) => BigInt.asUintN(width.bits, integer(args, 0));
|
|
652
910
|
const result = (pattern) => int(wrapTo(width, pattern));
|
|
@@ -703,30 +961,34 @@ function intMethodShim(detail) {
|
|
|
703
961
|
return (_host, args) => rotate(args, true);
|
|
704
962
|
case "RotateRight":
|
|
705
963
|
return (_host, args) => rotate(args, false);
|
|
706
|
-
default:
|
|
707
|
-
|
|
964
|
+
default: {
|
|
965
|
+
const exhaustive = op;
|
|
966
|
+
throw new Error(`unknown integer operation ${String(exhaustive)}`);
|
|
967
|
+
}
|
|
708
968
|
}
|
|
709
969
|
}
|
|
710
970
|
/// Non-trapping integer arithmetic at the receiver's width: wrapping keeps
|
|
711
971
|
/// the low bits, saturating clamps to the width's bounds and checked answers
|
|
712
972
|
/// `None` where native's overflow flag is set.
|
|
713
973
|
function intArithShim(detail) {
|
|
714
|
-
const
|
|
715
|
-
|
|
716
|
-
return undefined;
|
|
717
|
-
}
|
|
718
|
-
const [kind, width] = parsed;
|
|
974
|
+
const [kind, name] = detail;
|
|
975
|
+
const width = INT_WIDTHS[name];
|
|
719
976
|
const [min, max] = intBounds(width);
|
|
977
|
+
const add = (x, y) => x + y;
|
|
978
|
+
const sub = (x, y) => x - y;
|
|
979
|
+
const mul = (x, y) => x * y;
|
|
720
980
|
const operations = {
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
981
|
+
WrappingAdd: ["Wrapping", add],
|
|
982
|
+
WrappingSub: ["Wrapping", sub],
|
|
983
|
+
WrappingMul: ["Wrapping", mul],
|
|
984
|
+
SaturatingAdd: ["Saturating", add],
|
|
985
|
+
SaturatingSub: ["Saturating", sub],
|
|
986
|
+
SaturatingMul: ["Saturating", mul],
|
|
987
|
+
CheckedAdd: ["Checked", add],
|
|
988
|
+
CheckedSub: ["Checked", sub],
|
|
989
|
+
CheckedMul: ["Checked", mul],
|
|
724
990
|
};
|
|
725
|
-
const mode
|
|
726
|
-
const apply = mode ? operations[kind.slice(mode.length)] : undefined;
|
|
727
|
-
if (!mode || !apply) {
|
|
728
|
-
return undefined;
|
|
729
|
-
}
|
|
991
|
+
const [mode, apply] = operations[kind];
|
|
730
992
|
const exact = (args) => apply(wrapTo(width, integer(args, 0)), wrapTo(width, integer(args, 1)));
|
|
731
993
|
switch (mode) {
|
|
732
994
|
case "Wrapping":
|
|
@@ -766,6 +1028,27 @@ function bigMax(left, right) {
|
|
|
766
1028
|
}
|
|
767
1029
|
// ── externs ─────────────────────────────────────────────────────────────────
|
|
768
1030
|
const EXTERN_SHIMS = {
|
|
1031
|
+
hew_path_separator: () => str("/"),
|
|
1032
|
+
hew_calendar_format: {
|
|
1033
|
+
kind: "ordinary",
|
|
1034
|
+
bridge: "calendarBridge",
|
|
1035
|
+
shim: (host, args, _variant, shape) => executeCalendar(host.calendarBridge, "hew_calendar_format", args, shape),
|
|
1036
|
+
},
|
|
1037
|
+
hew_calendar_parse: {
|
|
1038
|
+
kind: "ordinary",
|
|
1039
|
+
bridge: "calendarBridge",
|
|
1040
|
+
shim: (host, args, _variant, shape) => executeCalendar(host.calendarBridge, "hew_calendar_parse", args, shape),
|
|
1041
|
+
},
|
|
1042
|
+
hew_calendar_components: {
|
|
1043
|
+
kind: "ordinary",
|
|
1044
|
+
bridge: "calendarBridge",
|
|
1045
|
+
shim: (host, args, _variant, shape) => executeCalendar(host.calendarBridge, "hew_calendar_components", args, shape),
|
|
1046
|
+
},
|
|
1047
|
+
hew_calendar_from_parts: {
|
|
1048
|
+
kind: "ordinary",
|
|
1049
|
+
bridge: "calendarBridge",
|
|
1050
|
+
shim: (host, args, _variant, shape) => executeCalendar(host.calendarBridge, "hew_calendar_from_parts", args, shape),
|
|
1051
|
+
},
|
|
769
1052
|
hew_args_count: (host) => int(BigInt(host.argv.length)),
|
|
770
1053
|
// A native null managed string is canonical empty. Each result owns fresh
|
|
771
1054
|
// string storage; releasing it cannot change the host's supplied arguments.
|
|
@@ -904,9 +1187,6 @@ function pattern(host, value) {
|
|
|
904
1187
|
return value.kind === "string" ? value.value : renderStdout(value);
|
|
905
1188
|
}
|
|
906
1189
|
// ── operand helpers ─────────────────────────────────────────────────────────
|
|
907
|
-
function detailName(detail) {
|
|
908
|
-
return typeof detail === "string" ? detail : "";
|
|
909
|
-
}
|
|
910
1190
|
function arg(args, at) {
|
|
911
1191
|
return args[at] ?? UNIT;
|
|
912
1192
|
}
|