@hew-lang/sandbox-vm 0.8.0 → 0.9.2

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.
@@ -11,7 +11,9 @@ export declare class ShimFault extends Error {
11
11
  export interface ShimHost {
12
12
  readonly argv: readonly string[];
13
13
  unixTimeMillis(): number;
14
+ monotonicTimeNanos(): bigint;
14
15
  fileError(operation: "HasError" | "LastErrorKind" | "LastErrno" | "LastError"): VmValue;
16
+ setFileError(message: string | null): void;
15
17
  calendarBridge?: (request: string) => string;
16
18
  codecBridge?: (request: string) => string;
17
19
  encodingError?(format: EncodingFormat, message?: string): string;
@@ -48,7 +50,7 @@ type Ordinary = {
48
50
  bridge?: BridgeRequirement;
49
51
  };
50
52
  export type RuntimeContinuation = {
51
- handler: "actor_caller" | "actor_refusal_log" | "structural_format" | "utf8_decode" | "close";
53
+ handler: "actor_caller" | "context_actor_id" | "context_supervisor" | "context_trace_span" | "actor_refusal_log" | "structural_format" | "utf8_decode" | "close";
52
54
  } | {
53
55
  handler: "supervisor_pool";
54
56
  operation: Extract<RuntimeFamilyEntry, {
@@ -16,6 +16,22 @@ export class ShimFault extends Error {
16
16
  this.name = "ShimFault";
17
17
  }
18
18
  }
19
+ function checkedWrite(host, value, stderr) {
20
+ try {
21
+ if (value.length !== 0) {
22
+ if (stderr)
23
+ host.writeStderr(value);
24
+ else
25
+ host.writeStdout(value);
26
+ }
27
+ host.setFileError(null);
28
+ return int(0n);
29
+ }
30
+ catch (error) {
31
+ host.setFileError(error instanceof Error ? error.message : String(error));
32
+ return int(-1n);
33
+ }
34
+ }
19
35
  function ordinary(shim) {
20
36
  return { kind: "ordinary", shim };
21
37
  }
@@ -519,6 +535,9 @@ const UNIT_FAMILIES = {
519
535
  ActorLink: refused("ActorLink"),
520
536
  ActorMonitor: refused("ActorMonitor"),
521
537
  ActorCaller: resumable({ handler: "actor_caller" }),
538
+ ContextActorId: resumable({ handler: "context_actor_id" }),
539
+ ContextSupervisor: resumable({ handler: "context_supervisor" }),
540
+ ContextTraceSpan: resumable({ handler: "context_trace_span" }),
522
541
  ActorRefusalLog: resumable({ handler: "actor_refusal_log" }),
523
542
  ActorUnlink: refused("ActorUnlink"),
524
543
  AutoMutexAlloc: refused("AutoMutexAlloc"),
@@ -570,9 +589,9 @@ const UNIT_FAMILIES = {
570
589
  HashSetNewWithLayout: refused("HashSetNewWithLayout"),
571
590
  HashSetRemoveLayout: refused("HashSetRemoveLayout"),
572
591
  HashSetToVecLayout: refused("HashSetToVecLayout"),
573
- InstantDurationSince: refused("InstantDurationSince"),
574
- InstantElapsed: refused("InstantElapsed"),
575
- InstantNow: refused("InstantNow"),
592
+ InstantDurationSince: (_host, args) => int(saturatingI64(integer(args, 0) - integer(args, 1))),
593
+ InstantElapsed: (host, args) => int(saturatingI64(saturatingI64(host.monotonicTimeNanos()) - integer(args, 0))),
594
+ InstantNow: (host) => int(saturatingI64(host.monotonicTimeNanos())),
576
595
  NodeConnect: refused("NodeConnect"),
577
596
  NodeId: refused("NodeId"),
578
597
  NodeIdDisplay: refused("NodeIdDisplay"),
@@ -1068,6 +1087,9 @@ function bigMin(left, right) {
1068
1087
  function bigMax(left, right) {
1069
1088
  return right > left ? right : left;
1070
1089
  }
1090
+ function saturatingI64(value) {
1091
+ return bigMax(-(1n << 63n), bigMin((1n << 63n) - 1n, value));
1092
+ }
1071
1093
  // ── externs ─────────────────────────────────────────────────────────────────
1072
1094
  const EXTERN_SHIMS = {
1073
1095
  hew_semaphore_new: (host, args) => host.semaphores.create(integer(args, 0)),
@@ -1131,7 +1153,9 @@ const EXTERN_SHIMS = {
1131
1153
  host.pipes.freePair(arg(args, 0));
1132
1154
  return UNIT;
1133
1155
  },
1134
- hew_stream_last_error: () => str(""),
1156
+ hew_stream_last_error: (host) => host.fileError("LastError"),
1157
+ hew_io_write: (host, args) => checkedWrite(host, text(args, 0), false),
1158
+ hew_io_write_err: (host, args) => checkedWrite(host, text(args, 0), true),
1135
1159
  hew_regex_new: (host, args) => compileRegex(host, args),
1136
1160
  hew_regex_clone: (_host, args) => cloneValue(arg(args, 0)),
1137
1161
  // Releasing a handle the VM traces by reference is nothing to do.
@@ -209,7 +209,8 @@ export function admitPackage(pkg, bridges = {}) {
209
209
  const id = term.operation.supervisor;
210
210
  const supervisor = pkg.supervisors?.find((layout) => layout.id === id);
211
211
  const config = term.args.length -
212
- (supervisor?.children.some((child) => child.is_pool) ? 1 : 0);
212
+ (supervisor?.children.some((child) => child.is_pool) ? 1 : 0) -
213
+ (supervisor?.backoff ? 2 : 0);
213
214
  if (!supervisor ||
214
215
  config < 0 ||
215
216
  supervisor.children.some((child) => {
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@hew-lang/sandbox-vm",
3
- "version": "0.8.0",
3
+ "version": "0.9.2",
4
4
  "hewSource": {
5
- "commit": "9322b962e46f92cc9c595b7cf742f73202751d1a",
6
- "tag": "v0.8.0",
5
+ "commit": "997da30ad61f9afc3c12d92e9f1c159ac9d79354",
6
+ "tag": "v0.9.2",
7
7
  "dirty": false
8
8
  },
9
9
  "description": "Deterministic TypeScript interpreter for the Hew educational sandbox",
@@ -21,7 +21,7 @@
21
21
  "cli/"
22
22
  ],
23
23
  "dependencies": {
24
- "@hew-lang/wasm": "0.8.0"
24
+ "@hew-lang/wasm": "0.9.2"
25
25
  },
26
26
  "keywords": [
27
27
  "hew",