@poe-platform/safe-js 0.1.24 → 0.1.26

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
@@ -33,7 +33,7 @@ console.log(result.returnValue);
33
33
 
34
34
  - **JavaScript control flow:** functions and closures, async/await, loops, destructuring, spread, templates, exceptions, and synchronous generators.
35
35
  - **Guest function objects:** own properties on functions and arrows; ordinary constructors with shared prototypes, inherited methods and `instanceof`. `Object.create`, `getPrototypeOf`, `setPrototypeOf`, own-property inspection, and data descriptors work on ordinary sandbox records.
36
- - **Data processing:** arrays, objects, strings, numbers, JSON, Math, Map, Set, Float32Array, promises, and a bounded regular-expression subset. These are selected APIs, not complete ECMAScript implementations.
36
+ - **Data processing:** arrays, objects, strings, numbers, JSON, Math, Date, Map, Set, Float32Array, promises, and a bounded regular-expression subset. These are selected APIs, not complete ECMAScript implementations.
37
37
  - **Explicit capabilities:** named, default, and namespace imports resolve against host-supplied modules. Optional helpers cover agents, MCP tools, files, environment reads, time, logging, and metrics.
38
38
  - **Persistent realms:** keep guest state across evaluations; register trusted extensions with explicit grants, live host objects, revocable callbacks, and ordered cleanup.
39
39
  - **Execution controls:** step, call-depth, string, array, and retained-data budgets; an absolute deadline; host cancellation; console and telemetry sinks.
@@ -55,6 +55,58 @@ const result = await run(`
55
55
 
56
56
  Properties stay inside the interpreter, not on native host functions. Arrows and object methods remain nonconstructible. Prototype links between callable or exotic objects (such as arrays) and accessor descriptors are unsupported; native `Function.prototype` is never exposed.
57
57
 
58
+ <details>
59
+ <summary>Object inspection and prototypes</summary>
60
+
61
+ Ordinary objects inherit a sandbox-owned `Object.prototype`. Cached inspection works:
62
+
63
+ ```js
64
+ const result = await run(`
65
+ const inspect = ({}).toString;
66
+ return [inspect.call([]), inspect.call(new Date(0)),
67
+ Object.getPrototypeOf({}) === Object.prototype];
68
+ `);
69
+ // result.returnValue: ["[object Array]", "[object Date]", true]
70
+ ```
71
+
72
+ - `Object()` / `new Object()` create ordinary objects; passing an object preserves its identity.
73
+ - `toString`, `valueOf`, `hasOwnProperty`, `propertyIsEnumerable` and `isPrototypeOf` support ordinary inspection. Type tags use sandbox brands, not guest-supplied fields.
74
+ - Intrinsic methods are non-enumerable. Guest constructor prototypes inherit the ordinary Object prototype; explicit null/custom prototypes work with `Object.create`, `Object.setPrototypeOf` and literal `__proto__`. A computed `['__proto__']` remains an own data property.
75
+ - Prototype mutations stay inside the current run or persistent realm and consume its retained-data budget. They never change native prototypes or another realm.
76
+
77
+ Primitive boxing, inherited accessors, symbols and full Array/Function/exotic prototype graphs are unsupported. Use borrowed Object methods for inspecting those supported values. Explicit prototype links and mutated Object intrinsics are not portable checkpoint/copy data; project own data before crossing those boundaries. The conservative `AS011` lint rule still flags explicit `prototype`/`constructor` access; `run()` executes it without automatic linting.
78
+
79
+ </details>
80
+
81
+ <details>
82
+ <summary>Dates and clocks</summary>
83
+
84
+ `new Date(0).toISOString()` returns `1970-01-01T00:00:00.000Z`. Both `Date.now()` and `+new Date` work without a host shim.
85
+
86
+ | Operation | Supported |
87
+ | --- | --- |
88
+ | Construction | Current time, epoch milliseconds, strings, another Date, or calendar components; `Date()` returns a time string. |
89
+ | Static methods | `now`, `parse`, `UTC`. |
90
+ | Reading | `getTime`, `valueOf`, `getTimezoneOffset`; local and UTC getters for full year, month, date, day, hours, minutes, seconds and milliseconds. |
91
+ | Mutation | `setTime`; local and UTC setters for full year, month, date, hours, minutes, seconds and milliseconds. Overflow and invalid dates follow Date semantics. |
92
+ | Formatting | `toISOString`, `toJSON`, `toString`, `toUTCString`, `toDateString`, `toTimeString`. Invalid dates stringify as `Invalid Date`, become JSON `null`, and throw on `toISOString`. |
93
+
94
+ Current time defaults to wall time. Supply a clock for controlled reads:
95
+
96
+ ```js
97
+ const result = await run("return [Date.now(), new Date().toISOString()];", {
98
+ clock: { now: () => 0, snapshot: () => undefined }
99
+ });
100
+ ```
101
+
102
+ Current-time reads are recorded for replay; replay does not call `now()` again. A stateful provider can implement `restore({ next })` to advance its state after each replayed read. `snapshot()` retains its existing clock-metadata role. The same clock option works in persistent realms.
103
+
104
+ Date values copy by value across host bindings, preserving aliases within a graph. Checkpoints preserve epoch values, invalid dates and mutations rather than converting dates to strings. Parsing is limited to 4,096 characters and consumes the work/string budgets; retained values consume data budget. Local methods and non-ISO parsing follow the host timezone/runtime, so use explicit-zone ISO strings and UTC methods for portable output.
105
+
106
+ Unsupported: locale formatting, legacy `getYear`/`setYear`/`toGMTString`, subclassing, custom argument coercion, Date-instance own properties and prototype modification. These are restrictions, not stubs; no native constructor or prototype is exposed to guest code.
107
+
108
+ </details>
109
+
58
110
  ## Add a host capability
59
111
 
60
112
  Expose a small module rather than an entire application client:
@@ -110,7 +162,7 @@ try {
110
162
 
111
163
  This prints `2`. Evaluations share declarations, closures and object identity without rerunning earlier source. Budgets are cumulative. `evaluate(source, { filename? })` returns `ok`, `returnValue` or `error`, and `stats`; it can also reject. Concurrent evaluations are rejected. Deferred callbacks can run while guest code awaits their result; overlapping invocation of the same callback is rejected. Close cancels pending work, revokes capabilities and awaits cleanup; repeated close does not rerun cleanup. Unhandled execution failures also close the realm.
112
164
 
113
- `createRealm(options?)` accepts `bindings`, `modules`, `budget`, `signal`, `sink` and `randomSeed` as described below, plus:
165
+ `createRealm(options?)` accepts `bindings`, `modules`, `budget`, `clock`, `signal`, `sink` and `randomSeed` as described below, plus:
114
166
 
115
167
  | Option | Purpose / default |
116
168
  | --- | --- |
@@ -174,7 +226,7 @@ Release each reference when the host no longer needs it; returning it does not r
174
226
 
175
227
  Live objects do not support native prototypes, property-descriptor manipulation or portable serialization. Realm state is not a checkpoint: snapshot/replay and live-capability error-data conversion are rejected. Extensions are trusted native code; grants are a registration contract, not OS isolation. Native work still needs host timeouts and external process supervision for hard limits. No DOM, timers or browser engine are bundled.
176
228
 
177
- For one-shot use, `run(source, { extensions, grants, ... })` accepts the same realm options plus `filename`, returns data only, and closes resources before settling. Run-only features such as snapshots, `entryPointArgs`, `importMeta`, custom clocks/random generators and telemetry are rejected in this mode rather than silently ignored.
229
+ For one-shot use, `run(source, { extensions, grants, ... })` accepts the same realm options plus `filename`, returns data only, and closes resources before settling. Run-only features such as snapshots, `entryPointArgs`, `importMeta`, custom random generators and telemetry are rejected in this mode rather than silently ignored.
178
230
 
179
231
  </details>
180
232
 
@@ -197,7 +249,7 @@ For one-shot use, `run(source, { extensions, grants, ... })` accepts the same re
197
249
  | `sink` | Console destination with `log(...args)` and `error(...args)`; defaults to the host console. |
198
250
  | `otelSink` | Telemetry with `startSpan` and `recordException`; spans implement `setAttribute`, `addEvent`, and `end`. Optional; `noopOtelSink` is available. |
199
251
  | `randomSeed`, `random` | Seed for built-in `Math.random`, or a custom `{ next, seed, snapshot }` generator. `random` takes precedence. |
200
- | `clock` | Clock-state provider with `snapshot()` returning `{ next }` or `undefined`; not a replacement for host time. |
252
+ | `clock` | Optional `now()` supplies Date current-time reads; defaults to wall time. `snapshot()` returns `{ next }` or `undefined`; optional `restore({ next })` advances state on replayed reads. Snapshot-only providers remain valid. |
201
253
  | `snapshot` | Previously captured state to resume. |
202
254
  | `snapshotPath`, `snapshotBackend` | Checkpoint output file or custom backend (`read`, `write`, `remove`); backend takes precedence. Neither automatically loads state into `snapshot`. |
203
255
  | `snapshotIntervalMs` | Periodic checkpoint interval when persistence is configured: 30,000 ms; `0` disables periodic writes. Capture happens at interpreter yield points. |