@ai-ecoverse/slicc-kernel 1.163.1 → 1.164.0

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 CHANGED
@@ -427,6 +427,10 @@ The module's default export (or its `main` export) is called with a context and
427
427
  - **What `fn` gets:** a fresh array of V8 CallSites holding only the program's own frames (its modules, `data:` imports, `sync.runScript` scripts and code they `eval`), `node:` frames and native frames. Kernel frames are dropped by script identity, so a script named like a kernel file doesn't let them through, and so are host files. A program's strict frames give `getFunction()` and `getThis()` as `undefined`.
428
428
  - **Fallback:** if `fn` throws or returns a non-string, or an error is formatted while `fn` runs, the default stack is used.
429
429
  - **How it works:** process workers start with `--expose-internals`, so the worker can install the formatter before the lockdown. Host flags a worker refuses are dropped. If the worker still can't start with the flag, the method is absent. Every `internal/*` and `node:internal/*` module stays refused to programs, as do `node:module` and `node:worker_threads`.
430
+ - `sync.errorSource(error)` (#1610, slicc-jsh#1082) is Node only, so check it with `typeof ctx.sync.errorSource === 'function'`. It gives `{ sourceLine, lineNumber, startColumn }` (null-prototype and frozen), the source line Node prints over an uncaught error, for an error V8 raised in the program's own code. That includes a direct `eval` of a value that isn't a string literal (`const s = 'null.d'; eval(s)` gives `null.d` and line 1) and a `sync.runScript` script.
431
+ - **Only the program's own code:** it answers only when the error's top frame is a program frame and the position V8 kept is in that same script and line.
432
+ - **`undefined` cases:** kernel-made errors; values that aren't native errors; an error V8 kept no position for (a `new Error()` the program constructs); a script that borrows the kernel worker's name; and an error an own `Error.prepareStackTrace` formats.
433
+ - **How it works:** it reads V8's message through Node's internal errors binding, which the worker loads at start-up through the same `--expose-internals` as `setStackFormatter`. It prints no warning and needs no inspector.
430
434
  - **Kernel frames in a program's stacks** (#1583): on the Node entry, the process worker's bundle names itself `slicc-kernel:/node-process-worker.js` (a `sourceURL`), so the kernel's own frames in an error a program sees (its own errors, a failed `ctx` call, `runScript`) show that name and not the host directory the kernel is installed in. The same holds in `CallSite.toString()` and `getScriptNameOrSourceURL()`, which a program's own `Error.prepareStackTrace` gets; `getFileName()` still returns the bundle's file URL. Line and column numbers are unchanged, so they still point into `dist/node-process-worker.js`. Don't run an embedder with `--enable-source-maps` if program-visible paths matter: Node then maps the kernel's frames back to the absolute paths of its sources. In a browser the frames keep the bundle's URL, because Chrome ignores `sourceURL` in a module worker loaded by URL.
431
435
  - `module` (#1598, slicc-jsh#566) is a frozen `{ path }` with the command module's own path in the kernel's file system (e.g. `/usr/lib/node_modules/jsh/dist/jsh.mjs`), so a program can read its package's other files through `ctx.fs` on first use. It's the path the kernel found the package under, with symlinks left as they are (a pnpm-style `node_modules/<name>` link stays in it), and reads the same files through `ctx.fs`. It's a kernel path, never a host one, and a thread gets the same. It's absent for the kernel's built-in programs (`sudo`, `crontab`) and for a program run from inline source with no file.
432
436
  - `memory()`, synchronous and without a kernel call, measures the calling isolate: each `thread` answers for its own (#1240, slicc-jsh#397). It returns a fresh plain object of numbers in bytes, each field only where it's measured: `heapUsed`, `heapTotal`, `heapLimit` (V8's heap size limit), `external`, `arrayBuffers` and `rss`. On the Node entry they come from V8's heap statistics and Node's memory usage, through functions the worker captured before its lockdown, so nothing reachable from the program leads back to `process` or `v8`. `rss` is the host process's resident set size, as a Node worker thread reports it in `process.memoryUsage().rss`: it isn't per process, but shared by every process and thread of the kernel, and by any other kernel in that host process (#1563, slicc-jsh#539). In a browser `memory()` answers `{}` for now, with no `rss`.
@@ -8437,7 +8437,7 @@ function satisfies(version, range2) {
8437
8437
  }
8438
8438
 
8439
8439
  // src/version.ts
8440
- var KERNEL_VERSION = true ? "1.163.1" : "0.0.0-dev";
8440
+ var KERNEL_VERSION = true ? "1.164.0" : "0.0.0-dev";
8441
8441
  var OS_RELEASE = "6.0.0-slicc";
8442
8442
  function procVersion() {
8443
8443
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -1418,10 +1418,33 @@ async function hostDriver(start, load) {
1418
1418
 
1419
1419
  // src/node-lockdown.ts
1420
1420
  import { isBuiltin, registerHooks } from "node:module";
1421
- import { types } from "node:util";
1421
+ import { types as types2 } from "node:util";
1422
1422
 
1423
1423
  // src/node-stack.ts
1424
1424
  import { createRequire } from "node:module";
1425
+ import { types } from "node:util";
1426
+ function quietly(target, run) {
1427
+ const emit = target.emitWarning;
1428
+ target.emitWarning = () => {
1429
+ };
1430
+ try {
1431
+ return run();
1432
+ } finally {
1433
+ target.emitWarning = emit;
1434
+ }
1435
+ }
1436
+ function positionsOf(load) {
1437
+ try {
1438
+ const { internalBinding } = quietly(
1439
+ process,
1440
+ () => load("internal/test/binding")
1441
+ );
1442
+ const get = internalBinding("errors").getErrorSourcePositions;
1443
+ return typeof get === "function" ? get : void 0;
1444
+ } catch {
1445
+ return void 0;
1446
+ }
1447
+ }
1425
1448
  var apply = Reflect.apply;
1426
1449
  var push = Array.prototype.push;
1427
1450
  var startsWith = String.prototype.startsWith;
@@ -1430,6 +1453,9 @@ var lastIndexOf = String.prototype.lastIndexOf;
1430
1453
  var indexOf2 = String.prototype.indexOf;
1431
1454
  var setHas = Set.prototype.has;
1432
1455
  var setAdd = Set.prototype.add;
1456
+ var mapGet = WeakMap.prototype.get;
1457
+ var mapSet = WeakMap.prototype.set;
1458
+ var isNativeError = types.isNativeError;
1433
1459
  function internals() {
1434
1460
  try {
1435
1461
  const load = createRequire(import.meta.url);
@@ -1442,7 +1468,8 @@ function internals() {
1442
1468
  if (typeof set !== "function" || typeof fallback !== "function") return void 0;
1443
1469
  return {
1444
1470
  setInternalPrepareStackTrace: set,
1445
- fallback
1471
+ fallback,
1472
+ positions: positionsOf(load)
1446
1473
  };
1447
1474
  } catch {
1448
1475
  return void 0;
@@ -1468,6 +1495,11 @@ var fileOf = proto.getFileName;
1468
1495
  var hashOf = proto.getScriptHash;
1469
1496
  var isEval = proto.isEval;
1470
1497
  var originOf = proto.getEvalOrigin;
1498
+ var lineOf = proto.getLineNumber;
1499
+ var ownNames = /* @__PURE__ */ new Set([
1500
+ apply(fileOf, self, []),
1501
+ apply(proto.getScriptNameOrSourceURL, self, [])
1502
+ ]);
1471
1503
  var ownHash = apply(hashOf, self, []);
1472
1504
  var programHashes = /* @__PURE__ */ new Set();
1473
1505
  var programNames = /* @__PURE__ */ new Set();
@@ -1519,8 +1551,12 @@ function keptFrames(trace) {
1519
1551
  }
1520
1552
  var formatter = null;
1521
1553
  var formatting = false;
1554
+ var tops = /* @__PURE__ */ new WeakMap();
1522
1555
  function stackDispatcher(fallback) {
1523
1556
  return (error, trace) => {
1557
+ if (typeof error === "object" && error !== null && trace.length > 0) {
1558
+ apply(mapSet, tops, [error, trace[0]]);
1559
+ }
1524
1560
  const fn = formatter;
1525
1561
  if (fn === null || formatting) return apply(fallback, void 0, [error, trace]);
1526
1562
  formatting = true;
@@ -1536,6 +1572,7 @@ function stackDispatcher(fallback) {
1536
1572
  }
1537
1573
  var found = internals();
1538
1574
  if (found) found.setInternalPrepareStackTrace(stackDispatcher(found.fallback));
1575
+ var positions = found?.positions;
1539
1576
 
1540
1577
  // src/process/js/lockdown.ts
1541
1578
  var BLOCKED_GLOBALS = [
@@ -1694,7 +1731,7 @@ function nodeLockdown(scope = globalThis) {
1694
1731
  vacate(scope, NODE_SLOTS);
1695
1732
  refuseModules();
1696
1733
  }
1697
- var isPromise = types.isPromise;
1734
+ var isPromise = types2.isPromise;
1698
1735
  var hasOwn = Object.hasOwn;
1699
1736
  var endsWith = String.prototype.endsWith;
1700
1737
  var sliceOf = String.prototype.slice;