@poe-platform/safe-js 0.1.26 → 0.1.27
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 +16 -2
- package/dist/safe-js/chunks/{chunk-I2SNTMRS.js → chunk-6V2VGVEH.js} +2 -2
- package/dist/safe-js/chunks/{chunk-2LVAGOJR.js → chunk-MCF7GT3X.js} +211 -91
- package/dist/safe-js/chunks/chunk-MCF7GT3X.js.map +7 -0
- package/dist/safe-js/cli.js +2 -2
- package/dist/safe-js/core.d.ts +1 -1
- package/dist/safe-js/core.js +1 -1
- package/dist/safe-js/index.d.ts +1 -1
- package/dist/safe-js/index.js +2 -2
- package/dist/safe-js/index.js.map +1 -1
- package/dist/safe-js/interp/host-capabilities.d.ts +11 -0
- package/dist/safe-js/interp/iteration.d.ts +9 -0
- package/package.json +2 -2
- package/dist/safe-js/chunks/chunk-2LVAGOJR.js.map +0 -7
- /package/dist/safe-js/chunks/{chunk-I2SNTMRS.js.map → chunk-6V2VGVEH.js.map} +0 -0
package/README.md
CHANGED
|
@@ -212,7 +212,7 @@ The manifest requires `version: 1` and a nonempty `name`. Optional `capabilities
|
|
|
212
212
|
| `signal` | Realm cancellation signal; aborted on close or failure. |
|
|
213
213
|
| `onCleanup(fn)` | Register a sync/async disposer. Cleanup runs in reverse order, awaits every disposer, and reports failures without skipping the rest. |
|
|
214
214
|
| `chargeWork(units = 1)` | Charge a nonnegative integer against the shared execution budget. Fatal exhaustion cannot be swallowed to continue execution. |
|
|
215
|
-
| `createHostObject({ properties?, methods? })` | Create a realm-owned capability. Properties declare synchronous `get`/`set` functions; methods are host functions. Undeclared members expose no native prototype. |
|
|
215
|
+
| `createHostObject({ properties?, methods?, indexed? })` | Create a realm-owned capability. Properties declare synchronous `get`/`set` functions; methods are host functions. Optional `indexed` exposes a bounded live collection. Undeclared members expose no native prototype. |
|
|
216
216
|
| `invokeCallback(callback, { thisValue?, args? })` | Invoke a captured guest function with the realm's state, cancellation and budgets. Same operation as on the realm. |
|
|
217
217
|
| `releaseCallback(callback)` | Revoke the callback and release its retained guest state. |
|
|
218
218
|
| `retainGuestArguments(operation, from)` | During setup, opt an operation into opaque argument references starting at the zero-based index `from`. Requires declared and granted `guest:retain`. Earlier arguments keep normal conversion; live host methods preserve the declaration. |
|
|
@@ -224,7 +224,21 @@ For a timer-shaped `schedule(callback, delay, ...args)`, register `context.retai
|
|
|
224
224
|
|
|
225
225
|
Release each reference when the host no longer needs it; returning it does not release it. Retained graphs count against data budgets and `limits.guestReferences`. Synchronous native failure releases references captured for that call; asynchronous operations must release theirs in host cleanup. Close revokes all remaining references. Handles cannot be inspected, used in another realm, or serialized into replay/error data. Unmarked operations still copy values.
|
|
226
226
|
|
|
227
|
-
|
|
227
|
+
For a live collection, keep the elements in your adapter and expose virtual indices instead of declaring one getter per element:
|
|
228
|
+
|
|
229
|
+
```js
|
|
230
|
+
const collection = context.createHostObject({ indexed: {
|
|
231
|
+
length: () => elements.length,
|
|
232
|
+
get: index => elements[index],
|
|
233
|
+
maxLength: 4096
|
|
234
|
+
} });
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
`length()` and `get(index)` must be synchronous. `maxLength` is required: an integer from 1 to 65,536. Every reported length must be a nonnegative integer within that cap and the execution array-length budget. Return existing `HostObject` handles for elements that need live identity; ordinary results use the normal copy boundary.
|
|
238
|
+
|
|
239
|
+
Saved collections observe current host contents. Index reads, `Object.keys`/`values`/`entries`, `Object.hasOwn`, `in`, `for...in`, `for...of`, array/object spread and `Array.from` use the live view. Enumerable keys include current indices and fixed members, but not `length`. `Array.from` preserves element identity and interleaves mapping with reads. Noncanonical and out-of-range indices never call `get`; fixed members cannot reuse `length` or canonical index names. Enumeration and traversal consume execution budgets, without eagerly allocating virtual properties.
|
|
240
|
+
|
|
241
|
+
Indexed members and their `length` are read-only. Live objects reject deletion, freezing, native prototype access, property-descriptor manipulation and 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.
|
|
228
242
|
|
|
229
243
|
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.
|
|
230
244
|
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
validateMigrationSemantics,
|
|
28
28
|
validateSnapshotData,
|
|
29
29
|
validateSnapshotMigration
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-MCF7GT3X.js";
|
|
31
31
|
|
|
32
32
|
// packages/safe-js/src/migrate.ts
|
|
33
33
|
import { createHash } from "node:crypto";
|
|
@@ -8245,4 +8245,4 @@ export {
|
|
|
8245
8245
|
parseMcpConfig,
|
|
8246
8246
|
makeMcpModule
|
|
8247
8247
|
};
|
|
8248
|
-
//# sourceMappingURL=chunk-
|
|
8248
|
+
//# sourceMappingURL=chunk-6V2VGVEH.js.map
|
|
@@ -6331,6 +6331,7 @@ function serializedDateTime(value) {
|
|
|
6331
6331
|
}
|
|
6332
6332
|
|
|
6333
6333
|
// packages/safe-js/src/interp/host-capabilities.ts
|
|
6334
|
+
var MAX_INDEXED_LENGTH = 65536;
|
|
6334
6335
|
var hostObjects = /* @__PURE__ */ new WeakMap();
|
|
6335
6336
|
var guestObjects = /* @__PURE__ */ new WeakMap();
|
|
6336
6337
|
var guestCallbacks = /* @__PURE__ */ new WeakMap();
|
|
@@ -6355,8 +6356,23 @@ function revokeGuestReference(reference, owner) {
|
|
|
6355
6356
|
}
|
|
6356
6357
|
function createLiveHostObject(definition, controller) {
|
|
6357
6358
|
const input = readDataRecord(definition, "Host object definition");
|
|
6358
|
-
if (Object.keys(input).some((key) => key !== "properties" && key !== "methods"))
|
|
6359
|
+
if (Object.keys(input).some((key) => key !== "properties" && key !== "methods" && key !== "indexed"))
|
|
6359
6360
|
throw new TypeError("Unknown host object definition field.");
|
|
6361
|
+
let indexed;
|
|
6362
|
+
if (input.indexed !== void 0) {
|
|
6363
|
+
const data = readDataRecord(input.indexed, "Indexed host capability");
|
|
6364
|
+
if (Object.keys(data).some((key) => !["length", "get", "maxLength"].includes(key)))
|
|
6365
|
+
throw new TypeError("Unknown indexed host capability field.");
|
|
6366
|
+
if (typeof data.length !== "function" || typeof data.get !== "function")
|
|
6367
|
+
throw new TypeError("Indexed length and get must be synchronous functions.");
|
|
6368
|
+
if (typeof data.maxLength !== "number" || !Number.isInteger(data.maxLength) || data.maxLength < 1 || data.maxLength > MAX_INDEXED_LENGTH)
|
|
6369
|
+
throw new RangeError(`Indexed maxLength must be an integer from 1 to ${MAX_INDEXED_LENGTH}.`);
|
|
6370
|
+
indexed = {
|
|
6371
|
+
length: data.length,
|
|
6372
|
+
get: data.get,
|
|
6373
|
+
maxLength: data.maxLength
|
|
6374
|
+
};
|
|
6375
|
+
}
|
|
6360
6376
|
const properties = /* @__PURE__ */ new Map();
|
|
6361
6377
|
for (const [name, inputProperty] of Object.entries(
|
|
6362
6378
|
readDataRecord(input.properties ?? {}, "Host properties")
|
|
@@ -6376,6 +6392,8 @@ function createLiveHostObject(definition, controller) {
|
|
|
6376
6392
|
for (const name of [...properties.keys(), ...Object.keys(operations)]) {
|
|
6377
6393
|
if (["constructor", "prototype", "__proto__"].includes(name))
|
|
6378
6394
|
throw new TypeError(`Reserved host member '${name}'.`);
|
|
6395
|
+
if (indexed !== void 0 && (name === "length" || canonicalIndex(name) !== void 0))
|
|
6396
|
+
throw new TypeError(`Conflicting indexed host member '${name}'.`);
|
|
6379
6397
|
}
|
|
6380
6398
|
controller.assertActive();
|
|
6381
6399
|
controller.chargeWork(properties.size + Object.keys(operations).length + 1);
|
|
@@ -6387,7 +6405,7 @@ function createLiveHostObject(definition, controller) {
|
|
|
6387
6405
|
controller.method(operation)
|
|
6388
6406
|
])
|
|
6389
6407
|
);
|
|
6390
|
-
const state = { host, guest, controller, properties, methods };
|
|
6408
|
+
const state = { host, guest, controller, properties, methods, indexed };
|
|
6391
6409
|
hostObjects.set(host, state);
|
|
6392
6410
|
guestObjects.set(guest, state);
|
|
6393
6411
|
return host;
|
|
@@ -6444,11 +6462,20 @@ function revokeHostObject(value, owner) {
|
|
|
6444
6462
|
throw new TypeError("Foreign host object.");
|
|
6445
6463
|
state.properties.clear();
|
|
6446
6464
|
state.methods.clear();
|
|
6465
|
+
state.indexed = void 0;
|
|
6447
6466
|
}
|
|
6448
6467
|
function getHostObjectMember(value, key) {
|
|
6449
6468
|
const state = guestObjects.get(value);
|
|
6450
6469
|
state.controller.assertActive();
|
|
6451
6470
|
state.controller.chargeWork();
|
|
6471
|
+
if (state.indexed !== void 0) {
|
|
6472
|
+
if (key === "length") return indexedLength(state);
|
|
6473
|
+
const index = canonicalIndex(key);
|
|
6474
|
+
if (index !== void 0) {
|
|
6475
|
+
if (index >= state.indexed.maxLength || index >= indexedLength(state)) return void 0;
|
|
6476
|
+
return state.controller.read(() => state.indexed.get(index));
|
|
6477
|
+
}
|
|
6478
|
+
}
|
|
6452
6479
|
const property = state.properties.get(key);
|
|
6453
6480
|
if (property !== void 0)
|
|
6454
6481
|
return property.get === void 0 ? void 0 : state.controller.read(property.get);
|
|
@@ -6465,7 +6492,65 @@ function setHostObjectMember(value, key, entry) {
|
|
|
6465
6492
|
function getHostObjectKeys(value) {
|
|
6466
6493
|
const state = guestObjects.get(value);
|
|
6467
6494
|
state.controller.assertActive();
|
|
6468
|
-
|
|
6495
|
+
const length = state.indexed === void 0 ? 0 : indexedLength(state);
|
|
6496
|
+
const size = length + state.properties.size + state.methods.size;
|
|
6497
|
+
state.controller.checkLength(size);
|
|
6498
|
+
state.controller.chargeWork(size + 1);
|
|
6499
|
+
return [
|
|
6500
|
+
...Array.from({ length }, (_entry, index) => String(index)),
|
|
6501
|
+
...state.properties.keys(),
|
|
6502
|
+
...state.methods.keys()
|
|
6503
|
+
];
|
|
6504
|
+
}
|
|
6505
|
+
function hasHostObjectMember(value, key, enumerableOnly = false) {
|
|
6506
|
+
const state = guestObjects.get(value);
|
|
6507
|
+
state.controller.assertActive();
|
|
6508
|
+
state.controller.chargeWork();
|
|
6509
|
+
if (state.indexed !== void 0) {
|
|
6510
|
+
if (key === "length") return !enumerableOnly;
|
|
6511
|
+
const index = canonicalIndex(key);
|
|
6512
|
+
if (index !== void 0) return index < state.indexed.maxLength && index < indexedLength(state);
|
|
6513
|
+
}
|
|
6514
|
+
return state.properties.has(key) || state.methods.has(key);
|
|
6515
|
+
}
|
|
6516
|
+
function measureHostObjectData(value) {
|
|
6517
|
+
const state = guestObjects.get(value);
|
|
6518
|
+
let size = state.indexed === void 0 ? 0 : 16;
|
|
6519
|
+
for (const key of state.properties.keys()) size += key.length + 1;
|
|
6520
|
+
for (const key of state.methods.keys()) size += key.length + 1;
|
|
6521
|
+
return size;
|
|
6522
|
+
}
|
|
6523
|
+
function getHostObjectIterator(value) {
|
|
6524
|
+
const state = guestObjects.get(value);
|
|
6525
|
+
state.controller.assertActive();
|
|
6526
|
+
if (state.indexed === void 0) return void 0;
|
|
6527
|
+
let index = 0;
|
|
6528
|
+
let exhausted = false;
|
|
6529
|
+
return {
|
|
6530
|
+
next: () => {
|
|
6531
|
+
state.controller.assertActive();
|
|
6532
|
+
state.controller.chargeWork();
|
|
6533
|
+
if (exhausted) return { done: true, value: void 0 };
|
|
6534
|
+
if (index >= indexedLength(state)) {
|
|
6535
|
+
exhausted = true;
|
|
6536
|
+
return { done: true, value: void 0 };
|
|
6537
|
+
}
|
|
6538
|
+
const position = index++;
|
|
6539
|
+
return { done: false, value: state.controller.read(() => state.indexed.get(position)) };
|
|
6540
|
+
}
|
|
6541
|
+
};
|
|
6542
|
+
}
|
|
6543
|
+
function indexedLength(state) {
|
|
6544
|
+
state.controller.chargeWork();
|
|
6545
|
+
const length = state.controller.read(state.indexed.length);
|
|
6546
|
+
if (typeof length !== "number" || !Number.isInteger(length) || length < 0 || length > state.indexed.maxLength)
|
|
6547
|
+
throw new RangeError("Indexed length must be a non-negative integer within maxLength.");
|
|
6548
|
+
state.controller.checkLength(length);
|
|
6549
|
+
return length;
|
|
6550
|
+
}
|
|
6551
|
+
function canonicalIndex(key) {
|
|
6552
|
+
const index = Number(key);
|
|
6553
|
+
return Number.isInteger(index) && index >= 0 && index < 4294967295 && String(index) === key ? index : void 0;
|
|
6469
6554
|
}
|
|
6470
6555
|
|
|
6471
6556
|
// packages/safe-js/src/interp/values.ts
|
|
@@ -8406,6 +8491,7 @@ function assertSnapshotInactive(snapshot) {
|
|
|
8406
8491
|
|
|
8407
8492
|
// packages/safe-js/src/interp/iteration.ts
|
|
8408
8493
|
function getSandboxIterator(value) {
|
|
8494
|
+
if (isGuestHostObject(value)) return getHostObjectIterator(value);
|
|
8409
8495
|
if (isFloat32Array(value)) {
|
|
8410
8496
|
return syncIterator(Float32Array.prototype.values.call(value));
|
|
8411
8497
|
}
|
|
@@ -9563,7 +9649,13 @@ function createSandboxClosure(input) {
|
|
|
9563
9649
|
return Object.freeze(closure);
|
|
9564
9650
|
}
|
|
9565
9651
|
function ownEnumerableSandboxEntries(value) {
|
|
9566
|
-
if (isGuestHostObject(value))
|
|
9652
|
+
if (isGuestHostObject(value)) {
|
|
9653
|
+
const entries = [];
|
|
9654
|
+
for (const key of getHostObjectKeys(value)) {
|
|
9655
|
+
if (hasHostObjectMember(value, key, true)) entries.push([key, getHostObjectMember(value, key)]);
|
|
9656
|
+
}
|
|
9657
|
+
return entries;
|
|
9658
|
+
}
|
|
9567
9659
|
if (value === null || value === void 0) throw new TypeError("Cannot convert undefined or null to object.");
|
|
9568
9660
|
if (isGuestClosure(value)) return Object.entries(value.properties ?? {});
|
|
9569
9661
|
if (isSandboxClosure(value) || isSandboxGenerator(value) || isSandboxMap(value) || isSandboxSet(value) || isSandboxPromise(value) || isSandboxRegex(value)) return [];
|
|
@@ -9721,7 +9813,7 @@ function measureSandboxData(values, options = {}) {
|
|
|
9721
9813
|
return;
|
|
9722
9814
|
}
|
|
9723
9815
|
if (isGuestHostObject(value)) {
|
|
9724
|
-
|
|
9816
|
+
usage += measureHostObjectData(value);
|
|
9725
9817
|
return;
|
|
9726
9818
|
}
|
|
9727
9819
|
const prototype = getSandboxPrototype(value);
|
|
@@ -22962,6 +23054,86 @@ function hoistVarDeclarations(node, scope) {
|
|
|
22962
23054
|
}
|
|
22963
23055
|
}
|
|
22964
23056
|
|
|
23057
|
+
// packages/safe-js/src/interp/string-coercion.ts
|
|
23058
|
+
function sandboxString(value, budget, context, joining = /* @__PURE__ */ new Set()) {
|
|
23059
|
+
if (value === null || typeof value !== "object") {
|
|
23060
|
+
if (typeof value === "function") throw new TypeError("Expected a sandbox value.");
|
|
23061
|
+
return budget.allocateString(String(value));
|
|
23062
|
+
}
|
|
23063
|
+
return stringifyObject(value, budget, context, joining);
|
|
23064
|
+
}
|
|
23065
|
+
async function stringifyObject(value, budget, context, joining) {
|
|
23066
|
+
const leaveCall = budget.enterCall();
|
|
23067
|
+
try {
|
|
23068
|
+
budget.visitNode();
|
|
23069
|
+
for (const name of ["toString", "valueOf"]) {
|
|
23070
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, name);
|
|
23071
|
+
let result;
|
|
23072
|
+
if (descriptor === void 0) {
|
|
23073
|
+
if (name === "valueOf") continue;
|
|
23074
|
+
result = await defaultToString(value, budget, context, joining);
|
|
23075
|
+
} else {
|
|
23076
|
+
const hook = ownDataValue(value, name);
|
|
23077
|
+
if (!isSandboxClosure(hook)) continue;
|
|
23078
|
+
if (context?.invokeClosure === void 0) {
|
|
23079
|
+
throw new TypeError("String hooks require a sandbox call context.");
|
|
23080
|
+
}
|
|
23081
|
+
result = await context.invokeClosure(hook, [], value);
|
|
23082
|
+
}
|
|
23083
|
+
if (result === null || typeof result !== "object") {
|
|
23084
|
+
return sandboxString(result, budget, context, joining);
|
|
23085
|
+
}
|
|
23086
|
+
}
|
|
23087
|
+
throw new TypeError("Cannot convert object to primitive value");
|
|
23088
|
+
} finally {
|
|
23089
|
+
leaveCall();
|
|
23090
|
+
}
|
|
23091
|
+
}
|
|
23092
|
+
async function defaultToString(value, budget, context, joining) {
|
|
23093
|
+
if (isSandboxDate(value)) return budget.allocateString(dateString(value));
|
|
23094
|
+
if (Array.isArray(value) || isFloat32Array(value)) {
|
|
23095
|
+
if (Object.hasOwn(value, "join")) {
|
|
23096
|
+
const join = ownDataValue(value, "join");
|
|
23097
|
+
if (!isSandboxClosure(join))
|
|
23098
|
+
return isFloat32Array(value) ? "[object Float32Array]" : "[object Array]";
|
|
23099
|
+
if (context?.invokeClosure === void 0) {
|
|
23100
|
+
throw new TypeError("String hooks require a sandbox call context.");
|
|
23101
|
+
}
|
|
23102
|
+
return context.invokeClosure(join, [], value);
|
|
23103
|
+
}
|
|
23104
|
+
if (joining.has(value)) return "";
|
|
23105
|
+
joining.add(value);
|
|
23106
|
+
try {
|
|
23107
|
+
const length = isFloat32Array(value) ? float32Storage(value).length : value.length;
|
|
23108
|
+
let text = "";
|
|
23109
|
+
for (let index = 0; index < length; index++) {
|
|
23110
|
+
budget.visitNode();
|
|
23111
|
+
const element = ownDataValue(value, String(index));
|
|
23112
|
+
const part = element === null || element === void 0 ? "" : await sandboxString(element, budget, context, joining);
|
|
23113
|
+
text = budget.allocateString(text + (index === 0 ? "" : ",") + part);
|
|
23114
|
+
}
|
|
23115
|
+
return text;
|
|
23116
|
+
} finally {
|
|
23117
|
+
joining.delete(value);
|
|
23118
|
+
}
|
|
23119
|
+
}
|
|
23120
|
+
if (sandboxErrorTypes.has(value)) {
|
|
23121
|
+
const nameValue = ownDataValue(value, "name");
|
|
23122
|
+
const name = nameValue === void 0 ? "Error" : await sandboxString(nameValue, budget, context, joining);
|
|
23123
|
+
const messageValue = ownDataValue(value, "message");
|
|
23124
|
+
const message = messageValue === void 0 ? "" : await sandboxString(messageValue, budget, context, joining);
|
|
23125
|
+
return name === "" ? message : message === "" ? name : `${name}: ${message}`;
|
|
23126
|
+
}
|
|
23127
|
+
return isSandboxPromise(value) ? "[object Promise]" : "[object Object]";
|
|
23128
|
+
}
|
|
23129
|
+
function ownDataValue(value, name) {
|
|
23130
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, name);
|
|
23131
|
+
if (descriptor !== void 0 && !Object.hasOwn(descriptor, "value")) {
|
|
23132
|
+
throw new TypeError("String conversion requires sandbox data properties.");
|
|
23133
|
+
}
|
|
23134
|
+
return descriptor?.value;
|
|
23135
|
+
}
|
|
23136
|
+
|
|
22965
23137
|
// packages/safe-js/src/interp/methods/array.ts
|
|
22966
23138
|
var activeArrayCallbacks = /* @__PURE__ */ new WeakMap();
|
|
22967
23139
|
var arrayMethodNames = /* @__PURE__ */ new Set([
|
|
@@ -25779,7 +25951,11 @@ async function evaluateBinaryExpression(node, context) {
|
|
|
25779
25951
|
if (right.kind !== "normal") {
|
|
25780
25952
|
return right;
|
|
25781
25953
|
}
|
|
25782
|
-
const value =
|
|
25954
|
+
const value = node.operator === "in" && isGuestHostObject(right.value) ? hasHostObjectMember(right.value, await sandboxString(left.value, context.budget, {
|
|
25955
|
+
stack: context.callStack,
|
|
25956
|
+
thisValue: void 0,
|
|
25957
|
+
invokeClosure: (closure, args, thisValue) => invokeSandboxClosure(closure, args, context, context.callStack, void 0, thisValue)
|
|
25958
|
+
})) : applyBinaryOperator(node, left.value, right.value, context);
|
|
25783
25959
|
return {
|
|
25784
25960
|
kind: "normal",
|
|
25785
25961
|
hasValue: true,
|
|
@@ -26476,7 +26652,7 @@ function forInKeys(object, budget) {
|
|
|
26476
26652
|
return keys;
|
|
26477
26653
|
}
|
|
26478
26654
|
function hasForInProperty(object, key, budget) {
|
|
26479
|
-
if (isGuestHostObject(object)) return
|
|
26655
|
+
if (isGuestHostObject(object)) return hasHostObjectMember(object, key, true);
|
|
26480
26656
|
let depth = 0;
|
|
26481
26657
|
for (let current = object; current !== null; current = getSandboxPrototype(current, budget)) {
|
|
26482
26658
|
if (depth > 0) budget.visitNode();
|
|
@@ -27937,6 +28113,13 @@ async function evaluateObjectSpread(node, context) {
|
|
|
27937
28113
|
value: []
|
|
27938
28114
|
};
|
|
27939
28115
|
}
|
|
28116
|
+
if (isGuestHostObject(value.value)) {
|
|
28117
|
+
const entries = [];
|
|
28118
|
+
for (const key of getHostObjectKeys(value.value)) {
|
|
28119
|
+
if (hasHostObjectMember(value.value, key, true)) entries.push([key, getHostObjectMember(value.value, key)]);
|
|
28120
|
+
}
|
|
28121
|
+
return { ok: true, value: entries };
|
|
28122
|
+
}
|
|
27940
28123
|
if (isSandboxClosure(value.value) && !isGuestClosure(value.value) || isSandboxPromise(value.value)) {
|
|
27941
28124
|
throw new TypeError(
|
|
27942
28125
|
`Cannot spread ${describeObjectSpreadValue(value.value)} into object literal.`
|
|
@@ -29537,7 +29720,7 @@ async function stringifyValue(value, state, indent) {
|
|
|
29537
29720
|
return stringifyArray(value, state, indent);
|
|
29538
29721
|
}
|
|
29539
29722
|
if (isStringifyObject(value)) {
|
|
29540
|
-
return
|
|
29723
|
+
return stringifyObject2(value, state, indent);
|
|
29541
29724
|
}
|
|
29542
29725
|
return void 0;
|
|
29543
29726
|
}
|
|
@@ -29563,7 +29746,7 @@ ${indent}]`;
|
|
|
29563
29746
|
leaveStringifyObject(value, state);
|
|
29564
29747
|
}
|
|
29565
29748
|
}
|
|
29566
|
-
async function
|
|
29749
|
+
async function stringifyObject2(value, state, indent) {
|
|
29567
29750
|
enterStringifyObject(value, state);
|
|
29568
29751
|
try {
|
|
29569
29752
|
const nextIndent = indent + state.gap;
|
|
@@ -29778,86 +29961,6 @@ function assertStructuredCloneable(value, seen) {
|
|
|
29778
29961
|
}
|
|
29779
29962
|
}
|
|
29780
29963
|
|
|
29781
|
-
// packages/safe-js/src/interp/string-coercion.ts
|
|
29782
|
-
function sandboxString(value, budget, context, joining = /* @__PURE__ */ new Set()) {
|
|
29783
|
-
if (value === null || typeof value !== "object") {
|
|
29784
|
-
if (typeof value === "function") throw new TypeError("Expected a sandbox value.");
|
|
29785
|
-
return budget.allocateString(String(value));
|
|
29786
|
-
}
|
|
29787
|
-
return stringifyObject2(value, budget, context, joining);
|
|
29788
|
-
}
|
|
29789
|
-
async function stringifyObject2(value, budget, context, joining) {
|
|
29790
|
-
const leaveCall = budget.enterCall();
|
|
29791
|
-
try {
|
|
29792
|
-
budget.visitNode();
|
|
29793
|
-
for (const name of ["toString", "valueOf"]) {
|
|
29794
|
-
const descriptor = Object.getOwnPropertyDescriptor(value, name);
|
|
29795
|
-
let result;
|
|
29796
|
-
if (descriptor === void 0) {
|
|
29797
|
-
if (name === "valueOf") continue;
|
|
29798
|
-
result = await defaultToString(value, budget, context, joining);
|
|
29799
|
-
} else {
|
|
29800
|
-
const hook = ownDataValue(value, name);
|
|
29801
|
-
if (!isSandboxClosure(hook)) continue;
|
|
29802
|
-
if (context?.invokeClosure === void 0) {
|
|
29803
|
-
throw new TypeError("String hooks require a sandbox call context.");
|
|
29804
|
-
}
|
|
29805
|
-
result = await context.invokeClosure(hook, [], value);
|
|
29806
|
-
}
|
|
29807
|
-
if (result === null || typeof result !== "object") {
|
|
29808
|
-
return sandboxString(result, budget, context, joining);
|
|
29809
|
-
}
|
|
29810
|
-
}
|
|
29811
|
-
throw new TypeError("Cannot convert object to primitive value");
|
|
29812
|
-
} finally {
|
|
29813
|
-
leaveCall();
|
|
29814
|
-
}
|
|
29815
|
-
}
|
|
29816
|
-
async function defaultToString(value, budget, context, joining) {
|
|
29817
|
-
if (isSandboxDate(value)) return budget.allocateString(dateString(value));
|
|
29818
|
-
if (Array.isArray(value) || isFloat32Array(value)) {
|
|
29819
|
-
if (Object.hasOwn(value, "join")) {
|
|
29820
|
-
const join = ownDataValue(value, "join");
|
|
29821
|
-
if (!isSandboxClosure(join))
|
|
29822
|
-
return isFloat32Array(value) ? "[object Float32Array]" : "[object Array]";
|
|
29823
|
-
if (context?.invokeClosure === void 0) {
|
|
29824
|
-
throw new TypeError("String hooks require a sandbox call context.");
|
|
29825
|
-
}
|
|
29826
|
-
return context.invokeClosure(join, [], value);
|
|
29827
|
-
}
|
|
29828
|
-
if (joining.has(value)) return "";
|
|
29829
|
-
joining.add(value);
|
|
29830
|
-
try {
|
|
29831
|
-
const length = isFloat32Array(value) ? float32Storage(value).length : value.length;
|
|
29832
|
-
let text = "";
|
|
29833
|
-
for (let index = 0; index < length; index++) {
|
|
29834
|
-
budget.visitNode();
|
|
29835
|
-
const element = ownDataValue(value, String(index));
|
|
29836
|
-
const part = element === null || element === void 0 ? "" : await sandboxString(element, budget, context, joining);
|
|
29837
|
-
text = budget.allocateString(text + (index === 0 ? "" : ",") + part);
|
|
29838
|
-
}
|
|
29839
|
-
return text;
|
|
29840
|
-
} finally {
|
|
29841
|
-
joining.delete(value);
|
|
29842
|
-
}
|
|
29843
|
-
}
|
|
29844
|
-
if (sandboxErrorTypes.has(value)) {
|
|
29845
|
-
const nameValue = ownDataValue(value, "name");
|
|
29846
|
-
const name = nameValue === void 0 ? "Error" : await sandboxString(nameValue, budget, context, joining);
|
|
29847
|
-
const messageValue = ownDataValue(value, "message");
|
|
29848
|
-
const message = messageValue === void 0 ? "" : await sandboxString(messageValue, budget, context, joining);
|
|
29849
|
-
return name === "" ? message : message === "" ? name : `${name}: ${message}`;
|
|
29850
|
-
}
|
|
29851
|
-
return isSandboxPromise(value) ? "[object Promise]" : "[object Object]";
|
|
29852
|
-
}
|
|
29853
|
-
function ownDataValue(value, name) {
|
|
29854
|
-
const descriptor = Object.getOwnPropertyDescriptor(value, name);
|
|
29855
|
-
if (descriptor !== void 0 && !Object.hasOwn(descriptor, "value")) {
|
|
29856
|
-
throw new TypeError("String conversion requires sandbox data properties.");
|
|
29857
|
-
}
|
|
29858
|
-
return descriptor?.value;
|
|
29859
|
-
}
|
|
29860
|
-
|
|
29861
29964
|
// packages/safe-js/src/interp/globals/object.ts
|
|
29862
29965
|
function createObjectGlobal(methods, budget) {
|
|
29863
29966
|
const construct = ([value]) => {
|
|
@@ -29951,7 +30054,7 @@ function requireReceiver(value) {
|
|
|
29951
30054
|
}
|
|
29952
30055
|
function hasOwnSandboxProperty(value, key, enumerable) {
|
|
29953
30056
|
requireReceiver(value);
|
|
29954
|
-
if (isGuestHostObject(value)) return
|
|
30057
|
+
if (isGuestHostObject(value)) return hasHostObjectMember(value, key, enumerable);
|
|
29955
30058
|
let properties;
|
|
29956
30059
|
if (isGuestClosure(value)) properties = materializeFunctionProperties(value);
|
|
29957
30060
|
else if (isSandboxClosure(value)) {
|
|
@@ -30110,6 +30213,7 @@ function createObjectArrayGlobals(options) {
|
|
|
30110
30213
|
freeze: createSandboxClosure({
|
|
30111
30214
|
sandbox: true,
|
|
30112
30215
|
call: ([value]) => {
|
|
30216
|
+
if (isGuestHostObject(value)) throw new TypeError("Live host objects cannot be frozen.");
|
|
30113
30217
|
if (typeof value === "object" && value !== null) {
|
|
30114
30218
|
Object.freeze(isGuestClosure(value) ? materializeFunctionProperties(value) : value);
|
|
30115
30219
|
}
|
|
@@ -30324,6 +30428,21 @@ function isAssignableSandboxTarget(value) {
|
|
|
30324
30428
|
async function arrayFromSandboxValues(args, budget) {
|
|
30325
30429
|
const [items, mapFn, thisValue] = args;
|
|
30326
30430
|
const iterator = getSandboxIterator(items);
|
|
30431
|
+
if (isGuestHostObject(items) && iterator !== void 0) {
|
|
30432
|
+
if (mapFn !== void 0 && !isSandboxClosure(mapFn))
|
|
30433
|
+
throw new TypeError("Array.from mapping callback must be a function.");
|
|
30434
|
+
const values2 = [];
|
|
30435
|
+
while (true) {
|
|
30436
|
+
const next = await iterator.next();
|
|
30437
|
+
if (next.done) break;
|
|
30438
|
+
budget.allocateArrayLength(values2.length + 1);
|
|
30439
|
+
const value = mapFn === void 0 ? next.value : await mapFn.call([next.value, values2.length], { stack: [], thisValue });
|
|
30440
|
+
if (isSandboxPromise(value) && value.synchronousPrefix !== void 0)
|
|
30441
|
+
await value.synchronousPrefix;
|
|
30442
|
+
values2.push(value);
|
|
30443
|
+
}
|
|
30444
|
+
return allocateProducedSandboxValue(values2, budget);
|
|
30445
|
+
}
|
|
30327
30446
|
const values = iterator === void 0 ? Reflect.apply(Array.from, Array, [items]) : await collectIteratorValues(iterator);
|
|
30328
30447
|
if (mapFn === void 0 || !isSandboxClosure(mapFn)) {
|
|
30329
30448
|
if (mapFn !== void 0) {
|
|
@@ -30857,6 +30976,7 @@ var RealmState = class {
|
|
|
30857
30976
|
owner: this,
|
|
30858
30977
|
assertActive: this.assertOpen,
|
|
30859
30978
|
chargeWork: this.chargeWork,
|
|
30979
|
+
checkLength: (length) => this.budget.allocateArrayLength(length),
|
|
30860
30980
|
read: (operation) => {
|
|
30861
30981
|
const value = this.invokeHost(operation, operation);
|
|
30862
30982
|
if (types4.isPromise(value)) {
|
|
@@ -32473,4 +32593,4 @@ export {
|
|
|
32473
32593
|
FileSnapshotBackend,
|
|
32474
32594
|
run
|
|
32475
32595
|
};
|
|
32476
|
-
//# sourceMappingURL=chunk-
|
|
32596
|
+
//# sourceMappingURL=chunk-MCF7GT3X.js.map
|