poe-code 14.0.6 → 14.0.8

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.
Files changed (54) hide show
  1. package/dist/index.js +944 -143
  2. package/dist/index.js.map +4 -4
  3. package/dist/metafile.json +1 -1
  4. package/package.json +1 -1
  5. package/packages/safe-js/dist/chunks/{chunk-2M6MNQBY.js → chunk-MO3YD4ID.js} +888 -133
  6. package/packages/safe-js/dist/chunks/chunk-MO3YD4ID.js.map +7 -0
  7. package/packages/safe-js/dist/chunks/{chunk-QSSQJNKE.js → chunk-RXLDJ6LQ.js} +2 -2
  8. package/packages/safe-js/dist/cli.js +2 -2
  9. package/packages/safe-js/dist/core.d.ts +1 -1
  10. package/packages/safe-js/dist/core.js +1 -1
  11. package/packages/safe-js/dist/extensions.d.ts +2 -0
  12. package/packages/safe-js/dist/index.d.ts +1 -1
  13. package/packages/safe-js/dist/index.js +2 -2
  14. package/packages/safe-js/dist/index.js.map +1 -1
  15. package/packages/safe-js/dist/interp/async.js +1 -0
  16. package/packages/safe-js/dist/interp/date.d.ts +19 -0
  17. package/packages/safe-js/dist/interp/date.js +129 -0
  18. package/packages/safe-js/dist/interp/globals/console-json.js +5 -1
  19. package/packages/safe-js/dist/interp/globals/date.d.ts +10 -0
  20. package/packages/safe-js/dist/interp/globals/date.js +95 -0
  21. package/packages/safe-js/dist/interp/globals/object-array.d.ts +4 -3
  22. package/packages/safe-js/dist/interp/globals/object-array.js +42 -5
  23. package/packages/safe-js/dist/interp/globals/object.d.ts +4 -0
  24. package/packages/safe-js/dist/interp/globals/object.js +153 -0
  25. package/packages/safe-js/dist/interp/globals.d.ts +4 -1
  26. package/packages/safe-js/dist/interp/globals.js +2 -0
  27. package/packages/safe-js/dist/interp/host-bridge.d.ts +4 -0
  28. package/packages/safe-js/dist/interp/host-bridge.js +21 -2
  29. package/packages/safe-js/dist/interp/host-call.js +4 -0
  30. package/packages/safe-js/dist/interp/host-capabilities.d.ts +28 -1
  31. package/packages/safe-js/dist/interp/host-capabilities.js +220 -5
  32. package/packages/safe-js/dist/interp/interpreter.js +46 -11
  33. package/packages/safe-js/dist/interp/iteration.js +3 -0
  34. package/packages/safe-js/dist/interp/object-model.d.ts +3 -1
  35. package/packages/safe-js/dist/interp/object-model.js +39 -9
  36. package/packages/safe-js/dist/interp/string-coercion.js +3 -0
  37. package/packages/safe-js/dist/interp/values.d.ts +3 -1
  38. package/packages/safe-js/dist/interp/values.js +34 -6
  39. package/packages/safe-js/dist/lint/rules/known-globals.d.ts +1 -1
  40. package/packages/safe-js/dist/lint/rules/known-globals.js +1 -0
  41. package/packages/safe-js/dist/parse/parser.js +4 -2
  42. package/packages/safe-js/dist/realm.d.ts +4 -1
  43. package/packages/safe-js/dist/realm.js +89 -10
  44. package/packages/safe-js/dist/run.d.ts +2 -0
  45. package/packages/safe-js/dist/run.js +3 -1
  46. package/packages/safe-js/dist/snapshot/dump-format.js +8 -3
  47. package/packages/safe-js/dist/snapshot/replay-data.d.ts +4 -1
  48. package/packages/safe-js/dist/snapshot/replay-data.js +11 -0
  49. package/packages/safe-js/dist/snapshot/restore.js +6 -0
  50. package/packages/safe-js/dist/snapshot/serialize.d.ts +5 -2
  51. package/packages/safe-js/dist/snapshot/serialize.js +8 -2
  52. package/packages/safe-js/dist/snapshot/validation.js +18 -1
  53. package/packages/safe-js/dist/chunks/chunk-2M6MNQBY.js.map +0 -7
  54. /package/packages/safe-js/dist/chunks/{chunk-QSSQJNKE.js.map → chunk-RXLDJ6LQ.js.map} +0 -0
@@ -4263,8 +4263,9 @@ var Parser = class {
4263
4263
  }
4264
4264
  break;
4265
4265
  }
4266
- this.expectPunctuator("(");
4267
- const args = this.parseArguments();
4266
+ const optional = this.consumePunctuator("?.");
4267
+ if (optional !== void 0) throw new DisallowedSyntaxError("new optional chain", optional.start);
4268
+ const args = this.consumePunctuator("(") === void 0 ? [] : this.parseArguments();
4268
4269
  const end = this.previousToken();
4269
4270
  return {
4270
4271
  node: {
@@ -6207,14 +6208,199 @@ function copyFloat32Storage(value, state) {
6207
6208
  return new Float32Array(buffer, storage.byteOffset, storage.length);
6208
6209
  }
6209
6210
 
6211
+ // packages/safe-js/src/interp/date.ts
6212
+ import { types as types2 } from "node:util";
6213
+ var NativeDate = Date;
6214
+ var readTime = NativeDate.prototype.getTime;
6215
+ var writeTime = NativeDate.prototype.setTime;
6216
+ var dates = /* @__PURE__ */ new WeakSet();
6217
+ function isSandboxDate(value) {
6218
+ return typeof value === "object" && value !== null && dates.has(value);
6219
+ }
6220
+ function createSandboxDate(time) {
6221
+ const value = new NativeDate(time);
6222
+ dates.add(value);
6223
+ return Object.freeze(value);
6224
+ }
6225
+ function dateTime(value) {
6226
+ return Reflect.apply(readTime, value, []);
6227
+ }
6228
+ function copyNativeDate(value) {
6229
+ if (!types2.isDate(value)) return void 0;
6230
+ if (Object.getPrototypeOf(value) !== NativeDate.prototype || Reflect.ownKeys(value).length > 0)
6231
+ throw new TypeError("Date subclasses and own properties are not supported.");
6232
+ return createSandboxDate(dateTime(value));
6233
+ }
6234
+ function exportDate(value) {
6235
+ return new NativeDate(dateTime(value));
6236
+ }
6237
+ function dateNumber(value) {
6238
+ if (isSandboxDate(value)) return dateTime(value);
6239
+ if (typeof value === "object" && value !== null || typeof value === "function" || typeof value === "symbol" || typeof value === "bigint")
6240
+ throw new TypeError("Date arguments require primitive values; custom coercion is unsupported.");
6241
+ return Number(value);
6242
+ }
6243
+ function parseDate(value, budget) {
6244
+ if (typeof value === "object" && value !== null || typeof value === "function")
6245
+ throw new TypeError("Date parsing requires a primitive value.");
6246
+ const text = String(value);
6247
+ if (text.length > 4096) throw new RangeError("Date input exceeds the 4096 character limit.");
6248
+ budget.allocateString(text);
6249
+ for (let index = 0; index < text.length; index++) budget.visitNode();
6250
+ return NativeDate.parse(text);
6251
+ }
6252
+ function dateFromParts(args, utc) {
6253
+ const parts = args.slice(0, 7).map(dateNumber);
6254
+ return utc ? Reflect.apply(NativeDate.UTC, NativeDate, parts) : dateTime(Reflect.construct(NativeDate, parts));
6255
+ }
6256
+ var methodNames = [
6257
+ "getTime",
6258
+ "valueOf",
6259
+ "getDate",
6260
+ "getDay",
6261
+ "getFullYear",
6262
+ "getHours",
6263
+ "getMilliseconds",
6264
+ "getMinutes",
6265
+ "getMonth",
6266
+ "getSeconds",
6267
+ "getTimezoneOffset",
6268
+ "getUTCDate",
6269
+ "getUTCDay",
6270
+ "getUTCFullYear",
6271
+ "getUTCHours",
6272
+ "getUTCMilliseconds",
6273
+ "getUTCMinutes",
6274
+ "getUTCMonth",
6275
+ "getUTCSeconds",
6276
+ "setTime",
6277
+ "setDate",
6278
+ "setFullYear",
6279
+ "setHours",
6280
+ "setMilliseconds",
6281
+ "setMinutes",
6282
+ "setMonth",
6283
+ "setSeconds",
6284
+ "setUTCDate",
6285
+ "setUTCFullYear",
6286
+ "setUTCHours",
6287
+ "setUTCMilliseconds",
6288
+ "setUTCMinutes",
6289
+ "setUTCMonth",
6290
+ "setUTCSeconds",
6291
+ "toDateString",
6292
+ "toISOString",
6293
+ "toString",
6294
+ "toTimeString",
6295
+ "toUTCString",
6296
+ "toJSON"
6297
+ ];
6298
+ var dateMethods = new Map(
6299
+ methodNames.map((name) => {
6300
+ const native = NativeDate.prototype[name];
6301
+ return [
6302
+ name,
6303
+ {
6304
+ length: native.length,
6305
+ invoke: (date, args) => {
6306
+ if (name === "toJSON")
6307
+ return Number.isNaN(dateTime(date)) ? null : Reflect.apply(NativeDate.prototype.toISOString, date, []);
6308
+ return Reflect.apply(
6309
+ native,
6310
+ date,
6311
+ name.startsWith("set") ? args.slice(0, native.length).map(dateNumber) : []
6312
+ );
6313
+ }
6314
+ }
6315
+ ];
6316
+ })
6317
+ );
6318
+ function dateString(value) {
6319
+ return dateMethods.get("toString").invoke(value, []);
6320
+ }
6321
+ function restoreDateTime(value) {
6322
+ if (value !== null && (typeof value !== "number" || !Number.isInteger(value) || Math.abs(value) > 864e13 || Object.is(value, -0)))
6323
+ throw new TypeError("Invalid serialized Date epoch.");
6324
+ const date = createSandboxDate(0);
6325
+ Reflect.apply(writeTime, date, [value === null ? NaN : value]);
6326
+ return date;
6327
+ }
6328
+ function serializedDateTime(value) {
6329
+ const time = dateTime(value);
6330
+ return Number.isNaN(time) ? null : time;
6331
+ }
6332
+
6210
6333
  // packages/safe-js/src/interp/host-capabilities.ts
6334
+ import { types as types3 } from "node:util";
6335
+ var MAX_INDEXED_LENGTH = 65536;
6336
+ var MAX_NAMED_KEYS = 65536;
6337
+ var MAX_NAMED_KEY_CODE_UNITS = 1048576;
6211
6338
  var hostObjects = /* @__PURE__ */ new WeakMap();
6212
6339
  var guestObjects = /* @__PURE__ */ new WeakMap();
6213
6340
  var guestCallbacks = /* @__PURE__ */ new WeakMap();
6341
+ var guestReferences = /* @__PURE__ */ new WeakMap();
6342
+ function createGuestReference(root, owner, assertActive) {
6343
+ const reference = Object.freeze(/* @__PURE__ */ Object.create(null));
6344
+ guestReferences.set(reference, { root, owner, assertActive });
6345
+ return reference;
6346
+ }
6347
+ function readGuestReference(reference, owner) {
6348
+ const state = typeof reference === "object" && reference !== null ? guestReferences.get(reference) : void 0;
6349
+ if (state === void 0 || state.owner !== owner)
6350
+ throw new TypeError("Foreign or invalid guest reference.");
6351
+ state.assertActive();
6352
+ if (state.root === void 0) throw new TypeError("Guest reference is revoked.");
6353
+ return state.root[0];
6354
+ }
6355
+ function revokeGuestReference(reference, owner) {
6356
+ const state = guestReferences.get(reference);
6357
+ if (state === void 0 || state.owner !== owner) throw new TypeError("Foreign guest reference.");
6358
+ state.root = void 0;
6359
+ }
6214
6360
  function createLiveHostObject(definition, controller) {
6215
6361
  const input = readDataRecord(definition, "Host object definition");
6216
- if (Object.keys(input).some((key) => key !== "properties" && key !== "methods"))
6362
+ if (Object.keys(input).some((key) => !["properties", "methods", "indexed", "named"].includes(key)))
6217
6363
  throw new TypeError("Unknown host object definition field.");
6364
+ let indexed;
6365
+ if (input.indexed !== void 0) {
6366
+ const data = readDataRecord(input.indexed, "Indexed host capability");
6367
+ if (Object.keys(data).some((key) => !["length", "get", "maxLength"].includes(key)))
6368
+ throw new TypeError("Unknown indexed host capability field.");
6369
+ if (typeof data.length !== "function" || typeof data.get !== "function")
6370
+ throw new TypeError("Indexed length and get must be synchronous functions.");
6371
+ if (typeof data.maxLength !== "number" || !Number.isInteger(data.maxLength) || data.maxLength < 1 || data.maxLength > MAX_INDEXED_LENGTH)
6372
+ throw new RangeError(`Indexed maxLength must be an integer from 1 to ${MAX_INDEXED_LENGTH}.`);
6373
+ indexed = {
6374
+ length: data.length,
6375
+ get: data.get,
6376
+ maxLength: data.maxLength
6377
+ };
6378
+ }
6379
+ let named;
6380
+ if (input.named !== void 0) {
6381
+ const data = readDataRecord(input.named, "Named host capability");
6382
+ if (Object.keys(data).some(
6383
+ (key) => !["keys", "get", "maxKeys", "maxKeyCodeUnits", "enumerable"].includes(key)
6384
+ ))
6385
+ throw new TypeError("Unknown named host capability field.");
6386
+ if (typeof data.keys !== "function" || typeof data.get !== "function")
6387
+ throw new TypeError("Named keys and get must be synchronous functions.");
6388
+ if (typeof data.maxKeys !== "number" || !Number.isInteger(data.maxKeys) || data.maxKeys < 1 || data.maxKeys > MAX_NAMED_KEYS)
6389
+ throw new RangeError(`Named maxKeys must be an integer from 1 to ${MAX_NAMED_KEYS}.`);
6390
+ if (typeof data.maxKeyCodeUnits !== "number" || !Number.isInteger(data.maxKeyCodeUnits) || data.maxKeyCodeUnits < 1 || data.maxKeyCodeUnits > MAX_NAMED_KEY_CODE_UNITS)
6391
+ throw new RangeError(
6392
+ `Named maxKeyCodeUnits must be an integer from 1 to ${MAX_NAMED_KEY_CODE_UNITS}.`
6393
+ );
6394
+ if (data.enumerable !== void 0 && typeof data.enumerable !== "boolean")
6395
+ throw new TypeError("Named enumerable must be a boolean.");
6396
+ named = {
6397
+ keys: data.keys,
6398
+ get: data.get,
6399
+ maxKeys: data.maxKeys,
6400
+ maxKeyCodeUnits: data.maxKeyCodeUnits,
6401
+ enumerable: data.enumerable
6402
+ };
6403
+ }
6218
6404
  const properties = /* @__PURE__ */ new Map();
6219
6405
  for (const [name, inputProperty] of Object.entries(
6220
6406
  readDataRecord(input.properties ?? {}, "Host properties")
@@ -6234,6 +6420,8 @@ function createLiveHostObject(definition, controller) {
6234
6420
  for (const name of [...properties.keys(), ...Object.keys(operations)]) {
6235
6421
  if (["constructor", "prototype", "__proto__"].includes(name))
6236
6422
  throw new TypeError(`Reserved host member '${name}'.`);
6423
+ if (indexed !== void 0 && (name === "length" || canonicalIndex(name) !== void 0))
6424
+ throw new TypeError(`Conflicting indexed host member '${name}'.`);
6237
6425
  }
6238
6426
  controller.assertActive();
6239
6427
  controller.chargeWork(properties.size + Object.keys(operations).length + 1);
@@ -6245,7 +6433,7 @@ function createLiveHostObject(definition, controller) {
6245
6433
  controller.method(operation)
6246
6434
  ])
6247
6435
  );
6248
- const state = { host, guest, controller, properties, methods };
6436
+ const state = { host, guest, controller, properties, methods, indexed, named };
6249
6437
  hostObjects.set(host, state);
6250
6438
  guestObjects.set(guest, state);
6251
6439
  return host;
@@ -6254,9 +6442,10 @@ function isGuestHostObject(value) {
6254
6442
  return typeof value === "object" && value !== null && guestObjects.has(value);
6255
6443
  }
6256
6444
  function isLiveCapability(value) {
6257
- return (typeof value === "object" && value !== null || typeof value === "function") && (hostObjects.has(value) || guestObjects.has(value) || guestCallbacks.has(value));
6445
+ return (typeof value === "object" && value !== null || typeof value === "function") && (hostObjects.has(value) || guestObjects.has(value) || guestCallbacks.has(value) || guestReferences.has(value));
6258
6446
  }
6259
6447
  function importHostCapability(value, owner) {
6448
+ if (guestReferences.has(value)) return readGuestReference(value, owner);
6260
6449
  const object = hostObjects.get(value);
6261
6450
  if (object !== void 0) {
6262
6451
  if (object.controller.owner !== owner) throw new TypeError("Foreign realm host capability.");
@@ -6301,15 +6490,29 @@ function revokeHostObject(value, owner) {
6301
6490
  throw new TypeError("Foreign host object.");
6302
6491
  state.properties.clear();
6303
6492
  state.methods.clear();
6493
+ state.indexed = void 0;
6494
+ state.named = void 0;
6304
6495
  }
6305
6496
  function getHostObjectMember(value, key) {
6306
6497
  const state = guestObjects.get(value);
6307
6498
  state.controller.assertActive();
6308
6499
  state.controller.chargeWork();
6500
+ if (state.indexed !== void 0) {
6501
+ if (key === "length") return indexedLength(state);
6502
+ const index = canonicalIndex(key);
6503
+ if (index !== void 0) {
6504
+ if (index >= state.indexed.maxLength || index >= indexedLength(state)) return void 0;
6505
+ return state.controller.read(() => state.indexed.get(index));
6506
+ }
6507
+ }
6309
6508
  const property = state.properties.get(key);
6310
6509
  if (property !== void 0)
6311
6510
  return property.get === void 0 ? void 0 : state.controller.read(property.get);
6312
- return state.methods.get(key);
6511
+ const method = state.methods.get(key);
6512
+ if (method !== void 0) return method;
6513
+ if (state.named !== void 0 && namedKeys(state).includes(key))
6514
+ return state.controller.read(() => state.named.get(key));
6515
+ return void 0;
6313
6516
  }
6314
6517
  function setHostObjectMember(value, key, entry) {
6315
6518
  const state = guestObjects.get(value);
@@ -6322,7 +6525,106 @@ function setHostObjectMember(value, key, entry) {
6322
6525
  function getHostObjectKeys(value) {
6323
6526
  const state = guestObjects.get(value);
6324
6527
  state.controller.assertActive();
6325
- return [...state.properties.keys(), ...state.methods.keys()];
6528
+ const length = state.indexed === void 0 ? 0 : indexedLength(state);
6529
+ const names = state.named === void 0 || state.named.enumerable === false ? [] : namedKeys(state).filter(
6530
+ (key) => !state.properties.has(key) && !state.methods.has(key) && !(state.indexed !== void 0 && (key === "length" || canonicalIndex(key) !== void 0))
6531
+ );
6532
+ const size = length + state.properties.size + state.methods.size + names.length;
6533
+ state.controller.checkLength(size);
6534
+ state.controller.chargeWork(size + 1);
6535
+ return [
6536
+ ...Array.from({ length }, (_entry, index) => String(index)),
6537
+ ...state.properties.keys(),
6538
+ ...state.methods.keys(),
6539
+ ...names
6540
+ ];
6541
+ }
6542
+ function hasHostObjectMember(value, key, enumerableOnly = false) {
6543
+ const state = guestObjects.get(value);
6544
+ state.controller.assertActive();
6545
+ state.controller.chargeWork();
6546
+ if (state.indexed !== void 0) {
6547
+ if (key === "length") return !enumerableOnly;
6548
+ const index = canonicalIndex(key);
6549
+ if (index !== void 0) return index < state.indexed.maxLength && index < indexedLength(state);
6550
+ }
6551
+ if (state.properties.has(key) || state.methods.has(key)) return true;
6552
+ return state.named !== void 0 && !(enumerableOnly && state.named.enumerable === false) && namedKeys(state).includes(key);
6553
+ }
6554
+ function measureHostObjectData(value) {
6555
+ const state = guestObjects.get(value);
6556
+ let size = state.indexed === void 0 ? 0 : 16;
6557
+ if (state.named !== void 0) size += 24;
6558
+ for (const key of state.properties.keys()) size += key.length + 1;
6559
+ for (const key of state.methods.keys()) size += key.length + 1;
6560
+ return size;
6561
+ }
6562
+ function getHostObjectIterator(value) {
6563
+ const state = guestObjects.get(value);
6564
+ state.controller.assertActive();
6565
+ if (state.indexed === void 0) return void 0;
6566
+ let index = 0;
6567
+ let exhausted = false;
6568
+ return {
6569
+ next: () => {
6570
+ state.controller.assertActive();
6571
+ state.controller.chargeWork();
6572
+ if (exhausted) return { done: true, value: void 0 };
6573
+ if (index >= indexedLength(state)) {
6574
+ exhausted = true;
6575
+ return { done: true, value: void 0 };
6576
+ }
6577
+ const position = index++;
6578
+ return { done: false, value: state.controller.read(() => state.indexed.get(position)) };
6579
+ }
6580
+ };
6581
+ }
6582
+ function indexedLength(state) {
6583
+ state.controller.chargeWork();
6584
+ const length = state.controller.read(state.indexed.length);
6585
+ if (typeof length !== "number" || !Number.isInteger(length) || length < 0 || length > state.indexed.maxLength)
6586
+ throw new RangeError("Indexed length must be a non-negative integer within maxLength.");
6587
+ state.controller.checkLength(length);
6588
+ return length;
6589
+ }
6590
+ function canonicalIndex(key) {
6591
+ const index = Number(key);
6592
+ return Number.isInteger(index) && index >= 0 && index < 4294967295 && String(index) === key ? index : void 0;
6593
+ }
6594
+ function namedKeys(state) {
6595
+ const named = state.named;
6596
+ return state.controller.read(named.keys, (value) => {
6597
+ if (!Array.isArray(value) || types3.isProxy(value))
6598
+ throw new TypeError("Named keys must be a dense own-data array of strings, not a proxy.");
6599
+ const length = Object.getOwnPropertyDescriptor(value, "length").value;
6600
+ if (length > named.maxKeys) throw new RangeError("Named keys exceed maxKeys.");
6601
+ state.controller.checkLength(length);
6602
+ state.controller.chargeWork(length + 1);
6603
+ if (Reflect.ownKeys(value).length !== length + 1)
6604
+ throw new TypeError("Named keys must contain only dense own-data indices and length.");
6605
+ const result = [];
6606
+ const seen = /* @__PURE__ */ new Set();
6607
+ let units = 0;
6608
+ for (let index = 0; index < length; index++) {
6609
+ const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
6610
+ if (descriptor === void 0 || !("value" in descriptor) || typeof descriptor.value !== "string")
6611
+ throw new TypeError(
6612
+ "Named keys require dense own string data, not accessors or sparse arrays."
6613
+ );
6614
+ const key = descriptor.value;
6615
+ units += key.length;
6616
+ if (units > named.maxKeyCodeUnits)
6617
+ throw new RangeError("Named keys exceed maximum UTF-16 code units.");
6618
+ state.controller.chargeWork(key.length);
6619
+ if (seen.has(key)) throw new TypeError("Named keys must be distinct.");
6620
+ if (["constructor", "prototype", "__proto__"].includes(key))
6621
+ throw new TypeError(`Reserved named host member '${key}'.`);
6622
+ seen.add(key);
6623
+ result.push(key);
6624
+ }
6625
+ state.controller.checkTemporaryDataSize(1 + length + units);
6626
+ return result;
6627
+ });
6326
6628
  }
6327
6629
 
6328
6630
  // packages/safe-js/src/interp/values.ts
@@ -6445,7 +6747,7 @@ async function flushPromiseJobs() {
6445
6747
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
6446
6748
 
6447
6749
  // packages/safe-js/src/snapshot/validation.ts
6448
- import { types as types2 } from "node:util";
6750
+ import { types as types4 } from "node:util";
6449
6751
 
6450
6752
  // packages/safe-js/src/interp/arguments.ts
6451
6753
  var sandboxArgumentsBrand = /* @__PURE__ */ Symbol("SandboxArguments");
@@ -6575,6 +6877,8 @@ function graphEntries(value) {
6575
6877
  var guestClosures = /* @__PURE__ */ new WeakSet();
6576
6878
  var functionProperties = /* @__PURE__ */ new WeakMap();
6577
6879
  var prototypes = /* @__PURE__ */ new WeakMap();
6880
+ var intrinsicPrototypes = /* @__PURE__ */ new WeakMap();
6881
+ var intrinsicConstructors = /* @__PURE__ */ new WeakMap();
6578
6882
  var descriptorObjects = /* @__PURE__ */ new WeakSet();
6579
6883
  function registerGuestClosure(closure) {
6580
6884
  guestClosures.add(closure);
@@ -6619,27 +6923,49 @@ function getGuestFunctionProperty(closure, key) {
6619
6923
  }
6620
6924
  return properties === void 0 ? void 0 : Object.getOwnPropertyDescriptor(properties, key)?.value;
6621
6925
  }
6622
- function getSandboxPrototype(value) {
6623
- return prototypes.get(value) ?? null;
6926
+ function installObjectPrototype(budget, prototype, constructor) {
6927
+ prototypes.set(prototype, null);
6928
+ intrinsicPrototypes.set(budget, prototype);
6929
+ const records = [prototype, materializeFunctionProperties(constructor)].map((value) => ({
6930
+ value,
6931
+ descriptors: new Map(Object.entries(Object.getOwnPropertyDescriptors(value)))
6932
+ }));
6933
+ const unchanged = (before, after) => before !== void 0 && after !== void 0 && before.value === after.value && before.writable === after.writable && before.configurable === after.configurable && before.enumerable === after.enumerable;
6934
+ intrinsicConstructors.set(constructor, () => records.every(({ value, descriptors }) => {
6935
+ const current = Object.getOwnPropertyDescriptors(value);
6936
+ return Object.keys(current).length === descriptors.size && Object.keys(current).every((key) => unchanged(descriptors.get(key), current[key]));
6937
+ }));
6938
+ budget.setRetainedValues(prototype, () => records.flatMap(({ value, descriptors }) => Object.entries(Object.getOwnPropertyDescriptors(value)).flatMap(([key, descriptor]) => unchanged(descriptors.get(key), descriptor) ? [] : [key, descriptor.value])));
6939
+ }
6940
+ function releaseObjectPrototype(budget) {
6941
+ const prototype = intrinsicPrototypes.get(budget);
6942
+ if (prototype !== void 0) budget.setRetainedValues(prototype, void 0);
6943
+ intrinsicPrototypes.delete(budget);
6944
+ }
6945
+ function getSandboxPrototype(value, budget) {
6946
+ if (prototypes.has(value)) return prototypes.get(value) ?? null;
6947
+ return budget !== void 0 && isPrototypeRecord(value) ? intrinsicPrototypes.get(budget) ?? null : null;
6624
6948
  }
6625
6949
  function setSandboxPrototype(value, prototype, budget) {
6950
+ if (budget !== void 0 && intrinsicPrototypes.get(budget) === value && prototype !== null) {
6951
+ throw new TypeError("Object.prototype has an immutable null prototype.");
6952
+ }
6626
6953
  if (!isPrototypeRecord(value) || prototype !== null && !isPrototypeRecord(prototype)) {
6627
6954
  throw new TypeError(
6628
6955
  "Prototype links require ordinary sandbox objects; callable and exotic prototype chains are not supported."
6629
6956
  );
6630
6957
  }
6631
- if (getSandboxPrototype(value) === prototype) return;
6958
+ if (prototypes.has(value) && getSandboxPrototype(value, budget) === prototype) return;
6632
6959
  if (!Object.isExtensible(isGuestClosure(value) ? materializeFunctionProperties(value) : value)) {
6633
6960
  throw new TypeError("Cannot change the prototype of a non-extensible object.");
6634
6961
  }
6635
6962
  let depth = 0;
6636
- for (let current = prototype; current !== null; current = getSandboxPrototype(current)) {
6963
+ for (let current = prototype; current !== null; current = getSandboxPrototype(current, budget)) {
6637
6964
  budget?.visitNode();
6638
6965
  assertSandboxDataDepth(depth++);
6639
6966
  if (current === value) throw new TypeError("Cyclic prototype value.");
6640
6967
  }
6641
- if (prototype === null) prototypes.delete(value);
6642
- else prototypes.set(value, prototype);
6968
+ prototypes.set(value, prototype);
6643
6969
  }
6644
6970
  function isPrototypeRecord(value) {
6645
6971
  if (isGuestHostObject(value)) return false;
@@ -6655,6 +6981,8 @@ function hasManagedDescriptors(value) {
6655
6981
  return descriptorObjects.has(value);
6656
6982
  }
6657
6983
  function hasGuestObjectState(value) {
6984
+ const intrinsicUnchanged = intrinsicConstructors.get(value);
6985
+ if (intrinsicUnchanged !== void 0) return !intrinsicUnchanged();
6658
6986
  if (isLiveCapability(value)) return true;
6659
6987
  if (functionProperties.has(value) || prototypes.has(value)) return true;
6660
6988
  return descriptorObjects.has(value) && Object.values(Object.getOwnPropertyDescriptors(value)).some(
@@ -6821,7 +7149,7 @@ function serializeDumpValue(value, path, state) {
6821
7149
  if (hasGuestObjectState(value)) {
6822
7150
  throw new TypeError("Guest function properties and prototype links cannot be serialized.");
6823
7151
  }
6824
- if (isFloat32Array(value)) return serializeHeapReference(value, path, state);
7152
+ if (isSandboxDate(value) || isFloat32Array(value)) return serializeHeapReference(value, path, state);
6825
7153
  if (Array.isArray(value)) {
6826
7154
  const reference2 = serializeHeapReference(value, path, state);
6827
7155
  if (reference2 !== void 0) {
@@ -6845,7 +7173,9 @@ function serializeHeapReference(value, path, state) {
6845
7173
  }
6846
7174
  if (!state.serializedHeapIds.has(id)) {
6847
7175
  state.serializedHeapIds.add(id);
6848
- if (isFloat32Array(value)) {
7176
+ if (isSandboxDate(value)) {
7177
+ state.heap[String(id)] = { kind: "date", time: serializedDateTime(value) };
7178
+ } else if (isFloat32Array(value)) {
6849
7179
  const storage = encodeFloat32Storage(value, id, state.float32Buffers, (id2) => ({
6850
7180
  kind: "ref",
6851
7181
  id: id2
@@ -6902,7 +7232,7 @@ function indexHeapContainers(snapshot) {
6902
7232
  const heapIds = /* @__PURE__ */ new WeakMap();
6903
7233
  let nextId = 1;
6904
7234
  for (const [value, stat2] of stats.entries()) {
6905
- if (stat2.count > 1 || stat2.cyclic || isFloat32Array(value) || Array.isArray(value) && requiresArrayEntries(value) || isSandboxArguments(value) || sandboxErrorTypes.has(value)) {
7235
+ if (stat2.count > 1 || stat2.cyclic || isSandboxDate(value) || isFloat32Array(value) || Array.isArray(value) && requiresArrayEntries(value) || isSandboxArguments(value) || sandboxErrorTypes.has(value)) {
6906
7236
  heapIds.set(value, nextId);
6907
7237
  nextId += 1;
6908
7238
  }
@@ -6913,7 +7243,7 @@ function collectContainerStats(value, stats, ancestors) {
6913
7243
  if (value === null || typeof value !== "object") {
6914
7244
  return;
6915
7245
  }
6916
- if (!Array.isArray(value) && !isPlainObject(value) && !isFloat32Array(value)) {
7246
+ if (!Array.isArray(value) && !isPlainObject(value) && !isFloat32Array(value) && !isSandboxDate(value)) {
6917
7247
  return;
6918
7248
  }
6919
7249
  let stat2 = stats.get(value);
@@ -7049,6 +7379,10 @@ function validateDumpHeap(root, state) {
7049
7379
  addUnique(heapIds, id, path);
7050
7380
  const entry = requireRecord(value, path);
7051
7381
  validateErrorType(entry, path);
7382
+ if (entry.kind === "date") {
7383
+ validateDateRecord(entry, path);
7384
+ continue;
7385
+ }
7052
7386
  if (entry.kind === "float32array") {
7053
7387
  validateFloat32Storage(entry);
7054
7388
  requireRecord(entry.entries, `${path}.entries`);
@@ -7206,6 +7540,14 @@ function validateGeneratorShape(record2, path, state) {
7206
7540
  }
7207
7541
  });
7208
7542
  }
7543
+ function validateDateRecord(record2, path) {
7544
+ if (Object.keys(record2).length !== 2) fail("invalidValue", path, "invalid Date fields");
7545
+ try {
7546
+ restoreDateTime(record2.time);
7547
+ } catch {
7548
+ fail("invalidValue", `${path}.time`, "invalid Date epoch");
7549
+ }
7550
+ }
7209
7551
  function validateArrayHeap(record2, path, state) {
7210
7552
  if (Object.hasOwn(record2, "items")) {
7211
7553
  requireArray(record2.items, `${path}.items`, state);
@@ -7289,7 +7631,7 @@ function validateGenericValue(value, path, depth, state) {
7289
7631
  if (typeof value === "object" && value !== null && hasGuestObjectState(value)) {
7290
7632
  fail("invalidState", path, "guest function properties, prototype links and custom descriptors cannot be restored");
7291
7633
  }
7292
- if (state.dataPropertiesOnly && types2.isProxy(value)) {
7634
+ if (state.dataPropertiesOnly && types4.isProxy(value)) {
7293
7635
  fail("invalidType", path, "proxy objects are not snapshot data");
7294
7636
  }
7295
7637
  if (depth > state.limits.maxDepth)
@@ -8223,6 +8565,7 @@ function assertSnapshotInactive(snapshot) {
8223
8565
 
8224
8566
  // packages/safe-js/src/interp/iteration.ts
8225
8567
  function getSandboxIterator(value) {
8568
+ if (isGuestHostObject(value)) return getHostObjectIterator(value);
8226
8569
  if (isFloat32Array(value)) {
8227
8570
  return syncIterator(Float32Array.prototype.values.call(value));
8228
8571
  }
@@ -9347,6 +9690,7 @@ function createSandboxClosure(input) {
9347
9690
  if (input.sandbox === true) {
9348
9691
  Object.defineProperty(closure, "sandbox", { value: true });
9349
9692
  }
9693
+ if (input.generator === true) Object.defineProperty(closure, "generator", { value: true });
9350
9694
  if (input.length !== void 0) {
9351
9695
  Object.defineProperty(closure, "length", { value: input.length });
9352
9696
  }
@@ -9379,7 +9723,13 @@ function createSandboxClosure(input) {
9379
9723
  return Object.freeze(closure);
9380
9724
  }
9381
9725
  function ownEnumerableSandboxEntries(value) {
9382
- if (isGuestHostObject(value)) return getHostObjectKeys(value).map((key) => [key, getHostObjectMember(value, key)]);
9726
+ if (isGuestHostObject(value)) {
9727
+ const entries = [];
9728
+ for (const key of getHostObjectKeys(value)) {
9729
+ if (hasHostObjectMember(value, key, true)) entries.push([key, getHostObjectMember(value, key)]);
9730
+ }
9731
+ return entries;
9732
+ }
9383
9733
  if (value === null || value === void 0) throw new TypeError("Cannot convert undefined or null to object.");
9384
9734
  if (isGuestClosure(value)) return Object.entries(value.properties ?? {});
9385
9735
  if (isSandboxClosure(value) || isSandboxGenerator(value) || isSandboxMap(value) || isSandboxSet(value) || isSandboxPromise(value) || isSandboxRegex(value)) return [];
@@ -9532,8 +9882,12 @@ function measureSandboxData(values, options = {}) {
9532
9882
  assertSandboxDataDepth(depth);
9533
9883
  seen.add(value);
9534
9884
  usage += 1;
9885
+ if (isSandboxDate(value)) {
9886
+ usage += 8;
9887
+ return;
9888
+ }
9535
9889
  if (isGuestHostObject(value)) {
9536
- for (const key of getHostObjectKeys(value)) usage += key.length + 1;
9890
+ usage += measureHostObjectData(value);
9537
9891
  return;
9538
9892
  }
9539
9893
  const prototype = getSandboxPrototype(value);
@@ -9630,7 +9984,7 @@ function measureSandboxData(values, options = {}) {
9630
9984
  function reconcileCompiledValues(budget, values, compilation, parent, escaping = []) {
9631
9985
  while (parent?.closed) parent = parent.parent;
9632
9986
  const included = /* @__PURE__ */ new Set();
9633
- const usage = measureSandboxData(values, { compileTickets: included });
9987
+ const usage = measureSandboxData([...values, ...budget.retainedValues()], { compileTickets: included });
9634
9988
  const kept = /* @__PURE__ */ new Set();
9635
9989
  if (parent !== void 0) measureSandboxData(escaping, { compileTickets: kept });
9636
9990
  const transferred = /* @__PURE__ */ new Set();
@@ -9726,6 +10080,13 @@ function copyToSandbox(value, state, path = "<root>", cloneSandboxCollections =
9726
10080
  }
9727
10081
  return sandboxPromise;
9728
10082
  }
10083
+ if (nodeTypes.isDate(value)) {
10084
+ const existing = state.seen.get(value);
10085
+ if (existing !== void 0) return existing;
10086
+ const copy = copyNativeDate(value);
10087
+ state.seen.set(value, copy);
10088
+ return copy;
10089
+ }
9729
10090
  if (isFloat32Array(value)) {
9730
10091
  const existing = state.seen.get(value);
9731
10092
  if (existing !== void 0) return existing;
@@ -9885,6 +10246,13 @@ function copyFromSandbox(value, state, path = "<root>", options, depth = 0) {
9885
10246
  if (!Object.isExtensible(value)) Object.preventExtensions(copy);
9886
10247
  return copy;
9887
10248
  }
10249
+ if (isSandboxDate(value)) {
10250
+ const existing = state.seen.get(value);
10251
+ if (existing !== void 0) return existing;
10252
+ const copy = exportDate(value);
10253
+ state.seen.set(value, copy);
10254
+ return copy;
10255
+ }
9888
10256
  if (isSandboxClosure(value)) {
9889
10257
  if (options.wrapClosure === void 0) {
9890
10258
  throw new TypeError(
@@ -10199,6 +10567,8 @@ function encodeReplayData(value, options = {}) {
10199
10567
  id: capabilityId,
10200
10568
  properties: child(entry.properties, "properties")
10201
10569
  };
10570
+ } else if (isSandboxDate(entry)) {
10571
+ nodes[id] = { kind: "date", time: serializedDateTime(entry) };
10202
10572
  } else if (isFloat32Array(entry)) {
10203
10573
  const storage = encodeFloat32Storage(entry, id, float32Buffers, (id2) => ({
10204
10574
  tag: "ref",
@@ -10349,6 +10719,12 @@ function decodeReplayData(input, options = {}, parent) {
10349
10719
  options.onCapabilityRestored?.(capability, copy);
10350
10720
  return copy;
10351
10721
  }
10722
+ if (kind === "date") {
10723
+ if (Object.keys(node).length !== 2) throw new TypeError("Invalid serialized Date fields.");
10724
+ const result3 = restoreDateTime(own(node, "time"));
10725
+ restored.set(id, result3);
10726
+ return result3;
10727
+ }
10352
10728
  if (kind === "float32array") {
10353
10729
  if (typeof node.extensible !== "boolean")
10354
10730
  throw new TypeError("Invalid Float32Array extensibility.");
@@ -11039,6 +11415,8 @@ function normalize(value, seen) {
11039
11415
  if (seen.has(value)) throw new TypeError("Host call arguments cannot contain cycles.");
11040
11416
  seen.add(value);
11041
11417
  try {
11418
+ const date = copyNativeDate(value);
11419
+ if (date !== void 0) return Object.assign(/* @__PURE__ */ Object.create(null), { $type: "date", time: serializedDateTime(date) });
11042
11420
  if (isFloat32Array(value)) {
11043
11421
  const storage = float32Storage(value);
11044
11422
  const properties = /* @__PURE__ */ Object.create(null);
@@ -11994,6 +12372,7 @@ var KNOWN_RUNTIME_GLOBALS = [
11994
12372
  "AggregateError",
11995
12373
  "Array",
11996
12374
  "Boolean",
12375
+ "Date",
11997
12376
  "Error",
11998
12377
  "Infinity",
11999
12378
  "isFinite",
@@ -17158,9 +17537,9 @@ var ASFloatingPromiseScanner = class {
17158
17537
  isPromiseFactoryCall(node) {
17159
17538
  return this.isPromiseStaticMethodCall(node, PROMISE_FACTORIES);
17160
17539
  }
17161
- isPromiseStaticMethodCall(node, methodNames) {
17540
+ isPromiseStaticMethodCall(node, methodNames2) {
17162
17541
  const member = node.callee.type === "MemberExpression" ? node.callee : void 0;
17163
- return member !== void 0 && !member.computed && member.object.type === "Identifier" && member.object.name === "Promise" && member.property.type === "Identifier" && methodNames.has(member.property.name);
17542
+ return member !== void 0 && !member.computed && member.object.type === "Identifier" && member.object.name === "Promise" && member.property.type === "Identifier" && methodNames2.has(member.property.name);
17164
17543
  }
17165
17544
  isPromiseChainCall(node) {
17166
17545
  const member = node.callee.type === "MemberExpression" ? node.callee : void 0;
@@ -22749,6 +23128,86 @@ function hoistVarDeclarations(node, scope) {
22749
23128
  }
22750
23129
  }
22751
23130
 
23131
+ // packages/safe-js/src/interp/string-coercion.ts
23132
+ function sandboxString(value, budget, context, joining = /* @__PURE__ */ new Set()) {
23133
+ if (value === null || typeof value !== "object") {
23134
+ if (typeof value === "function") throw new TypeError("Expected a sandbox value.");
23135
+ return budget.allocateString(String(value));
23136
+ }
23137
+ return stringifyObject(value, budget, context, joining);
23138
+ }
23139
+ async function stringifyObject(value, budget, context, joining) {
23140
+ const leaveCall = budget.enterCall();
23141
+ try {
23142
+ budget.visitNode();
23143
+ for (const name of ["toString", "valueOf"]) {
23144
+ const descriptor = Object.getOwnPropertyDescriptor(value, name);
23145
+ let result;
23146
+ if (descriptor === void 0) {
23147
+ if (name === "valueOf") continue;
23148
+ result = await defaultToString(value, budget, context, joining);
23149
+ } else {
23150
+ const hook = ownDataValue(value, name);
23151
+ if (!isSandboxClosure(hook)) continue;
23152
+ if (context?.invokeClosure === void 0) {
23153
+ throw new TypeError("String hooks require a sandbox call context.");
23154
+ }
23155
+ result = await context.invokeClosure(hook, [], value);
23156
+ }
23157
+ if (result === null || typeof result !== "object") {
23158
+ return sandboxString(result, budget, context, joining);
23159
+ }
23160
+ }
23161
+ throw new TypeError("Cannot convert object to primitive value");
23162
+ } finally {
23163
+ leaveCall();
23164
+ }
23165
+ }
23166
+ async function defaultToString(value, budget, context, joining) {
23167
+ if (isSandboxDate(value)) return budget.allocateString(dateString(value));
23168
+ if (Array.isArray(value) || isFloat32Array(value)) {
23169
+ if (Object.hasOwn(value, "join")) {
23170
+ const join = ownDataValue(value, "join");
23171
+ if (!isSandboxClosure(join))
23172
+ return isFloat32Array(value) ? "[object Float32Array]" : "[object Array]";
23173
+ if (context?.invokeClosure === void 0) {
23174
+ throw new TypeError("String hooks require a sandbox call context.");
23175
+ }
23176
+ return context.invokeClosure(join, [], value);
23177
+ }
23178
+ if (joining.has(value)) return "";
23179
+ joining.add(value);
23180
+ try {
23181
+ const length = isFloat32Array(value) ? float32Storage(value).length : value.length;
23182
+ let text = "";
23183
+ for (let index = 0; index < length; index++) {
23184
+ budget.visitNode();
23185
+ const element = ownDataValue(value, String(index));
23186
+ const part = element === null || element === void 0 ? "" : await sandboxString(element, budget, context, joining);
23187
+ text = budget.allocateString(text + (index === 0 ? "" : ",") + part);
23188
+ }
23189
+ return text;
23190
+ } finally {
23191
+ joining.delete(value);
23192
+ }
23193
+ }
23194
+ if (sandboxErrorTypes.has(value)) {
23195
+ const nameValue = ownDataValue(value, "name");
23196
+ const name = nameValue === void 0 ? "Error" : await sandboxString(nameValue, budget, context, joining);
23197
+ const messageValue = ownDataValue(value, "message");
23198
+ const message = messageValue === void 0 ? "" : await sandboxString(messageValue, budget, context, joining);
23199
+ return name === "" ? message : message === "" ? name : `${name}: ${message}`;
23200
+ }
23201
+ return isSandboxPromise(value) ? "[object Promise]" : "[object Object]";
23202
+ }
23203
+ function ownDataValue(value, name) {
23204
+ const descriptor = Object.getOwnPropertyDescriptor(value, name);
23205
+ if (descriptor !== void 0 && !Object.hasOwn(descriptor, "value")) {
23206
+ throw new TypeError("String conversion requires sandbox data properties.");
23207
+ }
23208
+ return descriptor?.value;
23209
+ }
23210
+
22752
23211
  // packages/safe-js/src/interp/methods/array.ts
22753
23212
  var activeArrayCallbacks = /* @__PURE__ */ new WeakMap();
22754
23213
  var arrayMethodNames = /* @__PURE__ */ new Set([
@@ -24798,6 +25257,101 @@ function relativeIndex(value, length, fallback) {
24798
25257
  return integer < 0 ? Math.max(length + integer, 0) : Math.min(integer, length);
24799
25258
  }
24800
25259
 
25260
+ // packages/safe-js/src/interp/globals/date.ts
25261
+ var intrinsics = /* @__PURE__ */ new WeakMap();
25262
+ var constructors2 = /* @__PURE__ */ new WeakSet();
25263
+ function createDateGlobal(options) {
25264
+ const validateClockTime = (value) => {
25265
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || Math.abs(value) > 864e13)
25266
+ throw new TypeError("Date clock must return a finite integer epoch within the Date range.");
25267
+ return value;
25268
+ };
25269
+ const readNow = declareHostOperation(
25270
+ () => {
25271
+ options.budget.visitNode();
25272
+ const value = options.clock?.now === void 0 ? Date.now() : options.clock.now();
25273
+ return validateClockTime(value);
25274
+ },
25275
+ "re-issue",
25276
+ {
25277
+ onReplay: (_args, outcome) => {
25278
+ if (outcome.status === "fulfilled") {
25279
+ const time = validateClockTime(outcome.value);
25280
+ options.clock?.restore?.({ next: time + 1 });
25281
+ }
25282
+ }
25283
+ }
25284
+ );
25285
+ const now = wrapCallerInjectedBindings({ now: readNow }, { ...options, moduleId: "<Date>" }).now;
25286
+ const prototype = createSandboxDate(NaN);
25287
+ const constructor = createSandboxClosure({
25288
+ sandbox: true,
25289
+ name: "Date",
25290
+ length: 7,
25291
+ call: async (_args, context) => options.budget.allocateString(
25292
+ dateString(createSandboxDate(Number(await now.call([], context))))
25293
+ ),
25294
+ construct: async (args, context) => {
25295
+ let time;
25296
+ if (args.length === 0) time = Number(await now.call([], context));
25297
+ else if (args.length > 1) time = dateFromParts(args, false);
25298
+ else if (isSandboxDate(args[0])) time = dateTime(args[0]);
25299
+ else if (typeof args[0] === "string") time = parseDate(args[0], options.budget);
25300
+ else time = dateNumber(args[0]);
25301
+ options.budget.chargeDataUsage(9);
25302
+ return createSandboxDate(time);
25303
+ },
25304
+ properties: {
25305
+ now,
25306
+ prototype,
25307
+ parse: createSandboxClosure({
25308
+ sandbox: true,
25309
+ name: "parse",
25310
+ length: 1,
25311
+ call: ([value]) => parseDate(value, options.budget)
25312
+ }),
25313
+ UTC: createSandboxClosure({
25314
+ sandbox: true,
25315
+ name: "UTC",
25316
+ length: 7,
25317
+ call: (args) => dateFromParts(args, true)
25318
+ })
25319
+ }
25320
+ });
25321
+ const methods = /* @__PURE__ */ new Map();
25322
+ for (const [name, method] of dateMethods)
25323
+ methods.set(
25324
+ name,
25325
+ createSandboxClosure({
25326
+ sandbox: true,
25327
+ name,
25328
+ length: method.length,
25329
+ call: (args, context) => {
25330
+ const receiver = context?.thisValue;
25331
+ if (!isSandboxDate(receiver))
25332
+ throw new TypeError(`Date#${name} requires a Date receiver.`);
25333
+ options.budget.visitNode();
25334
+ const value = method.invoke(receiver, args);
25335
+ return typeof value === "string" ? options.budget.allocateString(value) : value;
25336
+ }
25337
+ })
25338
+ );
25339
+ constructors2.add(constructor);
25340
+ intrinsics.set(options.compileOwner ?? options.budget, { constructor, prototype, methods });
25341
+ return constructor;
25342
+ }
25343
+ function isDateConstructor(value) {
25344
+ return typeof value === "object" && value !== null && constructors2.has(value);
25345
+ }
25346
+ function getDateMember(property, budget, owner) {
25347
+ const state = intrinsics.get(owner ?? budget);
25348
+ return property === "constructor" ? state?.constructor : state?.methods.get(String(property));
25349
+ }
25350
+ function getDatePrototype(value, budget, owner) {
25351
+ const prototype = intrinsics.get(owner ?? budget)?.prototype;
25352
+ return prototype === value ? null : prototype ?? null;
25353
+ }
25354
+
24801
25355
  // packages/safe-js/src/interp/scope.ts
24802
25356
  var uninitialized = /* @__PURE__ */ Symbol("uninitialized");
24803
25357
  var Scope = class _Scope {
@@ -25347,6 +25901,9 @@ async function evaluateObjectExpression(node, context) {
25347
25901
  return value;
25348
25902
  }
25349
25903
  if (isObjectPrototypeSetterProperty(property, key.value)) {
25904
+ if (value.value === null || typeof value.value === "object") {
25905
+ setSandboxPrototype(object, value.value, context.budget);
25906
+ }
25350
25907
  continue;
25351
25908
  }
25352
25909
  defineSandboxProperty(object, String(key.value), value.value);
@@ -25468,7 +26025,11 @@ async function evaluateBinaryExpression(node, context) {
25468
26025
  if (right.kind !== "normal") {
25469
26026
  return right;
25470
26027
  }
25471
- const value = applyBinaryOperator(node, left.value, right.value, context);
26028
+ const value = node.operator === "in" && isGuestHostObject(right.value) ? hasHostObjectMember(right.value, await sandboxString(left.value, context.budget, {
26029
+ stack: context.callStack,
26030
+ thisValue: void 0,
26031
+ invokeClosure: (closure, args, thisValue) => invokeSandboxClosure(closure, args, context, context.callStack, void 0, thisValue)
26032
+ })) : applyBinaryOperator(node, left.value, right.value, context);
25472
26033
  return {
25473
26034
  kind: "normal",
25474
26035
  hasValue: true,
@@ -26151,7 +26712,7 @@ function forInKeys(object, budget) {
26151
26712
  const keys = [];
26152
26713
  const seen = /* @__PURE__ */ new Set();
26153
26714
  let depth = 0;
26154
- for (let current = object; current !== null; current = getSandboxPrototype(current)) {
26715
+ for (let current = object; current !== null; current = getSandboxPrototype(current, budget)) {
26155
26716
  if (depth > 0) budget.visitNode();
26156
26717
  assertSandboxDataDepth(depth++);
26157
26718
  const properties = isGuestClosure(current) ? materializeFunctionProperties(current) : isSandboxClosure(current) ? current.properties ?? {} : current;
@@ -26165,9 +26726,9 @@ function forInKeys(object, budget) {
26165
26726
  return keys;
26166
26727
  }
26167
26728
  function hasForInProperty(object, key, budget) {
26168
- if (isGuestHostObject(object)) return getHostObjectKeys(object).includes(key);
26729
+ if (isGuestHostObject(object)) return hasHostObjectMember(object, key, true);
26169
26730
  let depth = 0;
26170
- for (let current = object; current !== null; current = getSandboxPrototype(current)) {
26731
+ for (let current = object; current !== null; current = getSandboxPrototype(current, budget)) {
26171
26732
  if (depth > 0) budget.visitNode();
26172
26733
  assertSandboxDataDepth(depth++);
26173
26734
  const properties = isGuestClosure(current) ? materializeFunctionProperties(current) : isSandboxClosure(current) ? current.properties ?? {} : current;
@@ -26662,6 +27223,7 @@ function getPropertyValue(target, property, context) {
26662
27223
  if (typeof target === "number") return getNumberMember(target, property, context.budget);
26663
27224
  if (typeof target === "boolean") return void 0;
26664
27225
  if (isFloat32Array(target)) return getFloat32Member(target, property, context.budget);
27226
+ if (isSandboxDate(target)) return getDateMember(property, context.budget, context.compilation?.owner);
26665
27227
  if (isSandboxMap(target)) return getMapMember(target, property, createMapMethodOptions(context));
26666
27228
  if (isSandboxSet(target)) return getSetMember(target, property, createSetMethodOptions(context));
26667
27229
  if (isSandboxGenerator(target)) return getGeneratorMember(target, property, context.budget);
@@ -26898,6 +27460,9 @@ async function evaluateMemberCallExpression(node, context) {
26898
27460
  context
26899
27461
  );
26900
27462
  }
27463
+ if (isSandboxDate(member.object)) {
27464
+ return evaluateResolvedCallExpression(node, getDateMember(member.property, context.budget, context.compilation?.owner), context, member.object);
27465
+ }
26901
27466
  if (isFloat32Array(member.object)) {
26902
27467
  return evaluateResolvedCallExpression(
26903
27468
  node,
@@ -27150,6 +27715,7 @@ function applyBinaryOperator(node, left, right, context) {
27150
27715
  return true;
27151
27716
  }
27152
27717
  if (isFloat32ArrayConstructor(right)) return isFloat32Array(left);
27718
+ if (isDateConstructor(right)) return isSandboxDate(left) && getDatePrototype(left, context.budget, context.compilation?.owner) !== null;
27153
27719
  if (isSandboxSetConstructor(right) && isSandboxSet(left)) {
27154
27720
  return true;
27155
27721
  }
@@ -27163,7 +27729,7 @@ function applyBinaryOperator(node, left, right, context) {
27163
27729
  throw new TypeError("Function has a non-object prototype in instanceof check.");
27164
27730
  }
27165
27731
  let depth = 0;
27166
- for (let current = getSandboxPrototype(left); current !== null; current = getSandboxPrototype(current)) {
27732
+ for (let current = getSandboxPrototype(left, context.budget); current !== null; current = getSandboxPrototype(current, context.budget)) {
27167
27733
  context.budget.visitNode();
27168
27734
  assertSandboxDataDepth(depth++);
27169
27735
  if (current === prototype) return true;
@@ -27213,8 +27779,8 @@ function applyAdditionOperator(left, right, context) {
27213
27779
  return toNumber(leftPrimitive) + toNumber(rightPrimitive);
27214
27780
  }
27215
27781
  function compareRelational(left, right, operator) {
27216
- const leftPrimitive = toPrimitive(left);
27217
- const rightPrimitive = toPrimitive(right);
27782
+ const leftPrimitive = isSandboxDate(left) ? dateTime(left) : toPrimitive(left);
27783
+ const rightPrimitive = isSandboxDate(right) ? dateTime(right) : toPrimitive(right);
27218
27784
  if (typeof leftPrimitive === "string" && typeof rightPrimitive === "string") {
27219
27785
  switch (operator) {
27220
27786
  case "<":
@@ -27297,6 +27863,7 @@ function toPrimitive(value) {
27297
27863
  return toString(value);
27298
27864
  }
27299
27865
  async function toNumericPrimitive(value, context) {
27866
+ if (isSandboxDate(value)) return dateTime(value);
27300
27867
  if (isPrimitiveCoercionType(getCoercionType(value))) {
27301
27868
  return value;
27302
27869
  }
@@ -27326,6 +27893,7 @@ async function toNumericPrimitive(value, context) {
27326
27893
  return toString(value);
27327
27894
  }
27328
27895
  function toNumber(value) {
27896
+ if (isSandboxDate(value)) return dateTime(value);
27329
27897
  if (typeof value === "number") {
27330
27898
  return value;
27331
27899
  }
@@ -27344,6 +27912,7 @@ function toNumber(value) {
27344
27912
  return toNumber(toPrimitive(value));
27345
27913
  }
27346
27914
  function toString(value) {
27915
+ if (isSandboxDate(value)) return dateString(value);
27347
27916
  if (Array.isArray(value)) {
27348
27917
  return value.map((entry) => entry === null || entry === void 0 ? "" : toString(entry)).join(",");
27349
27918
  }
@@ -27374,7 +27943,7 @@ function getMemberValue(target, property, context) {
27374
27943
  return getPropertyValue(current, property, context);
27375
27944
  }
27376
27945
  if (Object.hasOwn(current, String(property))) return current[String(property)];
27377
- current = getSandboxPrototype(current);
27946
+ current = getSandboxPrototype(current, context.budget);
27378
27947
  if (current !== null) {
27379
27948
  context.budget.visitNode();
27380
27949
  assertSandboxDataDepth(++depth);
@@ -27389,6 +27958,7 @@ function getArrayMemberValue(target, property, context) {
27389
27958
  return getArrayMember(target, property, createArrayMethodOptions(context));
27390
27959
  }
27391
27960
  function setSandboxProperty(target, property, value, budget) {
27961
+ if (isSandboxDate(target)) throw new TypeError("Date own properties are not supported.");
27392
27962
  if (isGuestHostObject(target)) {
27393
27963
  setHostObjectMember(target, String(property), value);
27394
27964
  return;
@@ -27423,7 +27993,7 @@ function setSandboxProperty(target, property, value, budget) {
27423
27993
  } else {
27424
27994
  if (typeof prototypeOwner === "object" && prototypeOwner !== null) {
27425
27995
  let depth = 0;
27426
- for (let prototype = getSandboxPrototype(prototypeOwner); prototype !== null; prototype = getSandboxPrototype(prototype)) {
27996
+ for (let prototype = getSandboxPrototype(prototypeOwner, budget); prototype !== null; prototype = getSandboxPrototype(prototype, budget)) {
27427
27997
  budget.visitNode();
27428
27998
  assertSandboxDataDepth(depth++);
27429
27999
  const properties = isSandboxClosure(prototype) ? prototype.properties : prototype;
@@ -27617,6 +28187,13 @@ async function evaluateObjectSpread(node, context) {
27617
28187
  value: []
27618
28188
  };
27619
28189
  }
28190
+ if (isGuestHostObject(value.value)) {
28191
+ const entries = [];
28192
+ for (const key of getHostObjectKeys(value.value)) {
28193
+ if (hasHostObjectMember(value.value, key, true)) entries.push([key, getHostObjectMember(value.value, key)]);
28194
+ }
28195
+ return { ok: true, value: entries };
28196
+ }
27620
28197
  if (isSandboxClosure(value.value) && !isGuestClosure(value.value) || isSandboxPromise(value.value)) {
27621
28198
  throw new TypeError(
27622
28199
  `Cannot spread ${describeObjectSpreadValue(value.value)} into object literal.`
@@ -27799,6 +28376,7 @@ function createInterpretedClosure(node, context, evaluateNode2) {
27799
28376
  function createGeneratorClosure(node, context, evaluateNode2) {
27800
28377
  return createSandboxClosure({
27801
28378
  guest: true,
28379
+ generator: true,
27802
28380
  sandbox: true,
27803
28381
  length: getFunctionLength(node.params),
27804
28382
  ...node.id === void 0 ? {} : { name: node.id.name },
@@ -28043,7 +28621,7 @@ function wrapCallerInjectedFunction(name, value, options, state) {
28043
28621
  seen: /* @__PURE__ */ new WeakMap(),
28044
28622
  restored: []
28045
28623
  };
28046
- const hostArgs = deepCopyFromSandbox([...args], {
28624
+ const copyArguments = (values) => deepCopyFromSandbox([...values], {
28047
28625
  compilation,
28048
28626
  unwrapHostObject: options.realm === void 0 ? void 0 : (object) => exportHostCapability(object, options.realm.owner),
28049
28627
  wrapClosure: (closure) => options.realm?.wrapCallback(closure) ?? wrapSandboxClosureForHost(
@@ -28054,13 +28632,21 @@ function wrapCallerInjectedFunction(name, value, options, state) {
28054
28632
  callbacks
28055
28633
  )
28056
28634
  });
28635
+ const captured = options.realm?.captureArguments(callable, args, copyArguments);
28636
+ const hostArgs = captured?.args ?? copyArguments(args);
28057
28637
  const hostCalls = options.hostCalls;
28058
28638
  const operation = options.operation ?? bindingName;
28059
28639
  const moduleId = options.moduleId ?? "<bindings>";
28060
28640
  const policy = readHostOperationPolicy(value) ?? readRegisteredPendingHostCallPolicy(moduleId, operation) ?? "re-issue";
28061
28641
  if (hostCalls === void 0) {
28062
28642
  if (options.realm !== void 0) {
28063
- const result = options.realm.invoke(callable, () => Reflect.apply(callable, void 0, hostArgs));
28643
+ let result;
28644
+ try {
28645
+ result = options.realm.invoke(callable, () => Reflect.apply(callable, void 0, hostArgs));
28646
+ } catch (error) {
28647
+ captured.rollback();
28648
+ throw error;
28649
+ }
28064
28650
  if (options.realm.awaitResult(callable)) {
28065
28651
  return Promise.resolve(result).then((value2) => copyHostResultToSandbox(value2, stackFrames, options));
28066
28652
  }
@@ -28648,6 +29234,14 @@ function copyHostValueToSandbox(value, stackFrames, options, state, path) {
28648
29234
  state
28649
29235
  );
28650
29236
  }
29237
+ const date = copyNativeDate(value);
29238
+ if (date !== void 0) {
29239
+ const existing = state.seen.get(value);
29240
+ if (existing !== void 0) return existing;
29241
+ budget.chargeDataUsage(9);
29242
+ state.seen.set(value, date);
29243
+ return date;
29244
+ }
28651
29245
  if (isFloat32Array(value)) {
28652
29246
  const existing = state.seen.get(value);
28653
29247
  if (existing !== void 0) return existing;
@@ -29049,7 +29643,7 @@ function createReplayableRandom(options = {}) {
29049
29643
 
29050
29644
  // packages/safe-js/src/realm.ts
29051
29645
  import { AsyncLocalStorage as AsyncLocalStorage6 } from "node:async_hooks";
29052
- import { types as types3 } from "node:util";
29646
+ import { types as types5 } from "node:util";
29053
29647
 
29054
29648
  // packages/safe-js/src/interp/globals/console-json.ts
29055
29649
  function createConsoleJsonGlobals(options) {
@@ -29163,7 +29757,9 @@ function toJsonParseText(input) {
29163
29757
  }
29164
29758
  async function stringifyProperty(key, holder, state, indent = "") {
29165
29759
  let value = getOwnDataValue(holder, key);
29166
- if (isStringifyContainer(value)) {
29760
+ if (isSandboxDate(value)) {
29761
+ value = dateMethods.get("toJSON").invoke(value, []);
29762
+ } else if (isStringifyContainer(value)) {
29167
29763
  const toJSON = getOwnDataValue(value, "toJSON");
29168
29764
  if (isSandboxClosure(toJSON)) {
29169
29765
  value = await callStringifyClosure(toJSON, [key], value, state);
@@ -29198,7 +29794,7 @@ async function stringifyValue(value, state, indent) {
29198
29794
  return stringifyArray(value, state, indent);
29199
29795
  }
29200
29796
  if (isStringifyObject(value)) {
29201
- return stringifyObject(value, state, indent);
29797
+ return stringifyObject2(value, state, indent);
29202
29798
  }
29203
29799
  return void 0;
29204
29800
  }
@@ -29224,7 +29820,7 @@ ${indent}]`;
29224
29820
  leaveStringifyObject(value, state);
29225
29821
  }
29226
29822
  }
29227
- async function stringifyObject(value, state, indent) {
29823
+ async function stringifyObject2(value, state, indent) {
29228
29824
  enterStringifyObject(value, state);
29229
29825
  try {
29230
29826
  const nextIndent = indent + state.gap;
@@ -29439,89 +30035,138 @@ function assertStructuredCloneable(value, seen) {
29439
30035
  }
29440
30036
  }
29441
30037
 
29442
- // packages/safe-js/src/interp/string-coercion.ts
29443
- function sandboxString(value, budget, context, joining = /* @__PURE__ */ new Set()) {
29444
- if (value === null || typeof value !== "object") {
29445
- if (typeof value === "function") throw new TypeError("Expected a sandbox value.");
29446
- return budget.allocateString(String(value));
29447
- }
29448
- return stringifyObject2(value, budget, context, joining);
29449
- }
29450
- async function stringifyObject2(value, budget, context, joining) {
29451
- const leaveCall = budget.enterCall();
29452
- try {
29453
- budget.visitNode();
29454
- for (const name of ["toString", "valueOf"]) {
29455
- const descriptor = Object.getOwnPropertyDescriptor(value, name);
29456
- let result;
29457
- if (descriptor === void 0) {
29458
- if (name === "valueOf") continue;
29459
- result = await defaultToString(value, budget, context, joining);
29460
- } else {
29461
- const hook = ownDataValue(value, name);
29462
- if (!isSandboxClosure(hook)) continue;
29463
- if (context?.invokeClosure === void 0) {
29464
- throw new TypeError("String hooks require a sandbox call context.");
29465
- }
29466
- result = await context.invokeClosure(hook, [], value);
30038
+ // packages/safe-js/src/interp/globals/object.ts
30039
+ function createObjectGlobal(methods, budget) {
30040
+ const construct = ([value]) => {
30041
+ if (value === null || value === void 0) {
30042
+ budget.chargeDataUsage(1);
30043
+ return /* @__PURE__ */ Object.create(null);
30044
+ }
30045
+ if (typeof value !== "object") throw new TypeError("Object primitive boxing is not supported.");
30046
+ return value;
30047
+ };
30048
+ const constructor = createSandboxClosure({
30049
+ guest: true,
30050
+ sandbox: true,
30051
+ name: "Object",
30052
+ length: 1,
30053
+ call: construct,
30054
+ construct
30055
+ });
30056
+ const properties = materializeFunctionProperties(constructor);
30057
+ const prototype = properties.prototype;
30058
+ Object.defineProperty(properties, "prototype", { writable: false });
30059
+ for (const [name, method] of Object.entries(methods)) {
30060
+ Object.defineProperty(properties, name, { value: method, writable: true, configurable: true });
30061
+ }
30062
+ const prototypeMethods = {
30063
+ toString: createSandboxClosure({
30064
+ sandbox: true,
30065
+ name: "toString",
30066
+ length: 0,
30067
+ call: (_args, context) => budget.allocateString(`[object ${typeTag(context?.thisValue)}]`)
30068
+ }),
30069
+ valueOf: createSandboxClosure({
30070
+ sandbox: true,
30071
+ name: "valueOf",
30072
+ length: 0,
30073
+ call: (_args, context) => {
30074
+ const value = requireReceiver(context?.thisValue);
30075
+ if (typeof value !== "object")
30076
+ throw new TypeError("Object primitive boxing is not supported.");
30077
+ return value;
29467
30078
  }
29468
- if (result === null || typeof result !== "object") {
29469
- return sandboxString(result, budget, context, joining);
30079
+ }),
30080
+ hasOwnProperty: createSandboxClosure({
30081
+ sandbox: true,
30082
+ name: "hasOwnProperty",
30083
+ length: 1,
30084
+ call: async ([key], context) => hasOwnSandboxProperty(
30085
+ requireReceiver(context?.thisValue),
30086
+ await sandboxString(key, budget, context),
30087
+ false
30088
+ )
30089
+ }),
30090
+ propertyIsEnumerable: createSandboxClosure({
30091
+ sandbox: true,
30092
+ name: "propertyIsEnumerable",
30093
+ length: 1,
30094
+ call: async ([key], context) => hasOwnSandboxProperty(
30095
+ requireReceiver(context?.thisValue),
30096
+ await sandboxString(key, budget, context),
30097
+ true
30098
+ )
30099
+ }),
30100
+ isPrototypeOf: createSandboxClosure({
30101
+ sandbox: true,
30102
+ name: "isPrototypeOf",
30103
+ length: 1,
30104
+ call: ([value], context) => {
30105
+ if (typeof value !== "object" || value === null) return false;
30106
+ const receiver = requireReceiver(context?.thisValue);
30107
+ let depth = 0;
30108
+ for (let current = getSandboxPrototype(value, budget); current !== null; current = getSandboxPrototype(current, budget)) {
30109
+ budget.visitNode();
30110
+ assertSandboxDataDepth(depth++);
30111
+ if (current === receiver) return true;
30112
+ }
30113
+ return false;
29470
30114
  }
29471
- }
29472
- throw new TypeError("Cannot convert object to primitive value");
29473
- } finally {
29474
- leaveCall();
30115
+ })
30116
+ };
30117
+ for (const [name, method] of Object.entries(prototypeMethods)) {
30118
+ Object.defineProperty(prototype, name, { value: method, writable: true, configurable: true });
29475
30119
  }
30120
+ markDescriptorObject(prototype);
30121
+ installObjectPrototype(budget, prototype, constructor);
30122
+ return constructor;
29476
30123
  }
29477
- async function defaultToString(value, budget, context, joining) {
29478
- if (Array.isArray(value) || isFloat32Array(value)) {
29479
- if (Object.hasOwn(value, "join")) {
29480
- const join = ownDataValue(value, "join");
29481
- if (!isSandboxClosure(join))
29482
- return isFloat32Array(value) ? "[object Float32Array]" : "[object Array]";
29483
- if (context?.invokeClosure === void 0) {
29484
- throw new TypeError("String hooks require a sandbox call context.");
29485
- }
29486
- return context.invokeClosure(join, [], value);
29487
- }
29488
- if (joining.has(value)) return "";
29489
- joining.add(value);
29490
- try {
29491
- const length = isFloat32Array(value) ? float32Storage(value).length : value.length;
29492
- let text = "";
29493
- for (let index = 0; index < length; index++) {
29494
- budget.visitNode();
29495
- const element = ownDataValue(value, String(index));
29496
- const part = element === null || element === void 0 ? "" : await sandboxString(element, budget, context, joining);
29497
- text = budget.allocateString(text + (index === 0 ? "" : ",") + part);
29498
- }
29499
- return text;
29500
- } finally {
29501
- joining.delete(value);
29502
- }
29503
- }
29504
- if (sandboxErrorTypes.has(value)) {
29505
- const nameValue = ownDataValue(value, "name");
29506
- const name = nameValue === void 0 ? "Error" : await sandboxString(nameValue, budget, context, joining);
29507
- const messageValue = ownDataValue(value, "message");
29508
- const message = messageValue === void 0 ? "" : await sandboxString(messageValue, budget, context, joining);
29509
- return name === "" ? message : message === "" ? name : `${name}: ${message}`;
29510
- }
29511
- return isSandboxPromise(value) ? "[object Promise]" : "[object Object]";
30124
+ function requireReceiver(value) {
30125
+ if (value === null || value === void 0)
30126
+ throw new TypeError("Object method requires a non-null receiver.");
30127
+ return value;
29512
30128
  }
29513
- function ownDataValue(value, name) {
29514
- const descriptor = Object.getOwnPropertyDescriptor(value, name);
29515
- if (descriptor !== void 0 && !Object.hasOwn(descriptor, "value")) {
29516
- throw new TypeError("String conversion requires sandbox data properties.");
29517
- }
29518
- return descriptor?.value;
30129
+ function hasOwnSandboxProperty(value, key, enumerable) {
30130
+ requireReceiver(value);
30131
+ if (isGuestHostObject(value)) return hasHostObjectMember(value, key, enumerable);
30132
+ let properties;
30133
+ if (isGuestClosure(value)) properties = materializeFunctionProperties(value);
30134
+ else if (isSandboxClosure(value)) {
30135
+ if (key === "length" || key === "name") return !enumerable;
30136
+ properties = value.properties ?? /* @__PURE__ */ Object.create(null);
30137
+ } else if (isSandboxMap(value) || isSandboxSet(value) || isSandboxPromise(value) || isSandboxGenerator(value))
30138
+ return false;
30139
+ else if (isSandboxRegex(value)) return key === "lastIndex" && !enumerable;
30140
+ else properties = Object(value);
30141
+ const descriptor = Object.getOwnPropertyDescriptor(properties, key);
30142
+ return descriptor !== void 0 && (!enumerable || descriptor.enumerable === true);
30143
+ }
30144
+ function typeTag(value) {
30145
+ if (value === void 0) return "Undefined";
30146
+ if (value === null) return "Null";
30147
+ if (typeof value === "string") return "String";
30148
+ if (typeof value === "number") return "Number";
30149
+ if (typeof value === "boolean") return "Boolean";
30150
+ if (isSandboxClosure(value)) {
30151
+ while (value.boundTarget !== void 0) value = value.boundTarget;
30152
+ return value.generator ? "GeneratorFunction" : value.async ? "AsyncFunction" : "Function";
30153
+ }
30154
+ if (Array.isArray(value)) return "Array";
30155
+ if (isSandboxDate(value)) return "Date";
30156
+ if (isSandboxErrorConstructorInstance(value, "Error")) return "Error";
30157
+ if (isSandboxRegex(value)) return "RegExp";
30158
+ if (isSandboxMap(value)) return "Map";
30159
+ if (isSandboxSet(value)) return "Set";
30160
+ if (isSandboxPromise(value)) return "Promise";
30161
+ if (isSandboxGenerator(value)) return "Generator";
30162
+ if (isFloat32Array(value)) return "Float32Array";
30163
+ return "Object";
29519
30164
  }
29520
30165
 
29521
30166
  // packages/safe-js/src/interp/globals/object-array.ts
29522
30167
  function createObjectArrayGlobals(options) {
29523
30168
  return {
29524
- Object: {
30169
+ Object: createObjectGlobal({
29525
30170
  keys: createSandboxClosure({
29526
30171
  sandbox: true,
29527
30172
  call: ([value]) => budgetSandboxValue2(getOwnEnumerableKeys(value), options.budget),
@@ -29539,7 +30184,11 @@ function createObjectArrayGlobals(options) {
29539
30184
  }),
29540
30185
  hasOwn: createSandboxClosure({
29541
30186
  sandbox: true,
29542
- call: ([value, key]) => Reflect.apply(Object.hasOwn, Object, [isSandboxClosure(value) ? objectProperties(value) : value, key]),
30187
+ call: ([value, key], context) => {
30188
+ if (value === null || value === void 0) throw new TypeError("Cannot convert undefined or null to object.");
30189
+ const name = sandboxString(key, options.budget, context);
30190
+ return typeof name === "string" ? hasOwnSandboxProperty(value, name, false) : name.then((property) => hasOwnSandboxProperty(value, property, false));
30191
+ },
29543
30192
  name: "hasOwn"
29544
30193
  }),
29545
30194
  getOwnPropertyDescriptor: createSandboxClosure({
@@ -29578,8 +30227,9 @@ function createObjectArrayGlobals(options) {
29578
30227
  getPrototypeOf: createSandboxClosure({
29579
30228
  sandbox: true,
29580
30229
  call: ([value]) => {
30230
+ if (isSandboxDate(value)) return getDatePrototype(value, options.budget, options.compileOwner);
29581
30231
  objectProperties(value);
29582
- return getSandboxPrototype(value);
30232
+ return getSandboxPrototype(value, options.budget);
29583
30233
  },
29584
30234
  name: "getPrototypeOf"
29585
30235
  }),
@@ -29637,6 +30287,7 @@ function createObjectArrayGlobals(options) {
29637
30287
  freeze: createSandboxClosure({
29638
30288
  sandbox: true,
29639
30289
  call: ([value]) => {
30290
+ if (isGuestHostObject(value)) throw new TypeError("Live host objects cannot be frozen.");
29640
30291
  if (typeof value === "object" && value !== null) {
29641
30292
  Object.freeze(isGuestClosure(value) ? materializeFunctionProperties(value) : value);
29642
30293
  }
@@ -29654,7 +30305,7 @@ function createObjectArrayGlobals(options) {
29654
30305
  call: ([target, ...sources]) => assignSandboxValues(target, sources, options.budget),
29655
30306
  name: "assign"
29656
30307
  })
29657
- },
30308
+ }, options.budget),
29658
30309
  Array: createSandboxClosure({
29659
30310
  sandbox: true,
29660
30311
  call: (args) => createArrayFromConstructorArgs(args, options.budget),
@@ -29702,7 +30353,7 @@ function createObjectArrayGlobals(options) {
29702
30353
  }),
29703
30354
  Number: createSandboxClosure({
29704
30355
  sandbox: true,
29705
- call: ([value]) => Number(value),
30356
+ call: ([value]) => isSandboxDate(value) ? dateTime(value) : Number(value),
29706
30357
  name: "Number",
29707
30358
  properties: {
29708
30359
  isFinite: createSandboxClosure({
@@ -29802,6 +30453,10 @@ function assignSandboxValues(target, sources, budget) {
29802
30453
  return target;
29803
30454
  }
29804
30455
  function objectProperties(value, mutable = false) {
30456
+ if (isSandboxDate(value)) {
30457
+ if (mutable) throw new TypeError("Date own properties and prototypes are not supported.");
30458
+ return value;
30459
+ }
29805
30460
  if (isGuestHostObject(value)) throw new TypeError("Live host object descriptors are not supported.");
29806
30461
  if (isGuestClosure(value)) return materializeFunctionProperties(value);
29807
30462
  if (isSandboxClosure(value)) {
@@ -29847,6 +30502,21 @@ function isAssignableSandboxTarget(value) {
29847
30502
  async function arrayFromSandboxValues(args, budget) {
29848
30503
  const [items, mapFn, thisValue] = args;
29849
30504
  const iterator = getSandboxIterator(items);
30505
+ if (isGuestHostObject(items) && iterator !== void 0) {
30506
+ if (mapFn !== void 0 && !isSandboxClosure(mapFn))
30507
+ throw new TypeError("Array.from mapping callback must be a function.");
30508
+ const values2 = [];
30509
+ while (true) {
30510
+ const next = await iterator.next();
30511
+ if (next.done) break;
30512
+ budget.allocateArrayLength(values2.length + 1);
30513
+ const value = mapFn === void 0 ? next.value : await mapFn.call([next.value, values2.length], { stack: [], thisValue });
30514
+ if (isSandboxPromise(value) && value.synchronousPrefix !== void 0)
30515
+ await value.synchronousPrefix;
30516
+ values2.push(value);
30517
+ }
30518
+ return allocateProducedSandboxValue(values2, budget);
30519
+ }
29850
30520
  const values = iterator === void 0 ? Reflect.apply(Array.from, Array, [items]) : await collectIteratorValues(iterator);
29851
30521
  if (mapFn === void 0 || !isSandboxClosure(mapFn)) {
29852
30522
  if (mapFn !== void 0) {
@@ -29923,6 +30593,7 @@ function createBuiltinBindings(options) {
29923
30593
  ...createConsoleJsonGlobals(options),
29924
30594
  ...createCollectionGlobals(options),
29925
30595
  Float32Array: createFloat32ArrayGlobal(options.budget),
30596
+ Date: createDateGlobal(options),
29926
30597
  ...createErrorGlobals(options),
29927
30598
  ...createMathGlobals({ random: options.random }),
29928
30599
  ...createObjectArrayGlobals(options),
@@ -30095,6 +30766,7 @@ var RealmState = class {
30095
30766
  extensions: 32,
30096
30767
  hostObjects: 1024,
30097
30768
  callbacks: 1024,
30769
+ guestReferences: 1024,
30098
30770
  cleanups: 1024,
30099
30771
  nestedEvaluations: 16
30100
30772
  };
@@ -30103,7 +30775,7 @@ var RealmState = class {
30103
30775
  throw new TypeError("Realm limits must be positive safe integers with supported names.");
30104
30776
  this.limits[name] = Number(value);
30105
30777
  }
30106
- if (options.extensions !== void 0 && (!Array.isArray(options.extensions) || types3.isProxy(options.extensions)))
30778
+ if (options.extensions !== void 0 && (!Array.isArray(options.extensions) || types5.isProxy(options.extensions)))
30107
30779
  throw new TypeError("Extensions must be a registration array.");
30108
30780
  const registrations = options.extensions ?? [];
30109
30781
  const extensions = [];
@@ -30131,6 +30803,7 @@ var RealmState = class {
30131
30803
  owner: this,
30132
30804
  assertActive: this.assertOpen,
30133
30805
  wrapCallback: this.wrapCallback,
30806
+ captureArguments: this.captureArguments,
30134
30807
  invoke: this.invokeHost,
30135
30808
  awaitResult: (operation) => this.nestedOperations.has(operation)
30136
30809
  };
@@ -30139,6 +30812,7 @@ var RealmState = class {
30139
30812
  budget: this.budget,
30140
30813
  compileOwner: this.lease.owner,
30141
30814
  sink: options.sink,
30815
+ clock: options.clock,
30142
30816
  random: createReplayableRandom({ seed: options.randomSeed }).next
30143
30817
  });
30144
30818
  const names = /* @__PURE__ */ new Set();
@@ -30170,9 +30844,10 @@ var RealmState = class {
30170
30844
  }
30171
30845
  options.signal?.addEventListener("abort", this.abort, { once: true });
30172
30846
  if (options.signal?.aborted) this.abort();
30173
- this.budget.setRetainedValues(this, this.retainedCallbacks);
30847
+ this.budget.setRetainedValues(this, this.retainedRoots);
30174
30848
  this.tracker.onFatalRejection((error) => this.poison(error));
30175
30849
  } catch (error) {
30850
+ releaseObjectPrototype(this.budget);
30176
30851
  this.compilation.dispose();
30177
30852
  this.lease.release();
30178
30853
  throw error;
@@ -30194,6 +30869,8 @@ var RealmState = class {
30194
30869
  pendingCallbacks = /* @__PURE__ */ new Set();
30195
30870
  callbackCache = /* @__PURE__ */ new WeakMap();
30196
30871
  hostObjects = /* @__PURE__ */ new Set();
30872
+ guestReferences = /* @__PURE__ */ new Map();
30873
+ retainedOperations = /* @__PURE__ */ new WeakMap();
30197
30874
  nestedOperations = /* @__PURE__ */ new WeakMap();
30198
30875
  convertedModules = /* @__PURE__ */ new Map();
30199
30876
  nativeConversions = { seen: /* @__PURE__ */ new WeakMap() };
@@ -30213,10 +30890,56 @@ var RealmState = class {
30213
30890
  signal: this.controller.signal,
30214
30891
  realm: this.bridge
30215
30892
  });
30216
- retainedCallbacks = () => [
30893
+ retainedRoots = () => [
30217
30894
  ...this.callbacks.values(),
30218
- ...Array.from(this.pendingCallbacks, (pending) => pending.closure)
30895
+ ...Array.from(this.pendingCallbacks, (pending) => pending.closure),
30896
+ ...this.guestReferences.values()
30219
30897
  ];
30898
+ captureArguments = (operation, args, copy) => {
30899
+ const from = this.retainedOperations.get(operation)?.from ?? args.length;
30900
+ const values = copy(args.slice(0, from));
30901
+ const captured = [];
30902
+ const rollback = () => {
30903
+ for (const reference of captured) {
30904
+ revokeGuestReference(reference, this);
30905
+ this.guestReferences.delete(reference);
30906
+ }
30907
+ };
30908
+ try {
30909
+ for (const value of args.slice(from)) {
30910
+ this.checkCollection(
30911
+ this.guestReferences.size + 1,
30912
+ this.limits.guestReferences,
30913
+ "guest reference"
30914
+ );
30915
+ const root = [value];
30916
+ const reference = createGuestReference(root, this, this.assertOpen);
30917
+ this.guestReferences.set(reference, root);
30918
+ captured.push(reference);
30919
+ values.push(reference);
30920
+ }
30921
+ if (captured.length > 0)
30922
+ this.budget.reconcileDataUsage(
30923
+ measureSandboxData([...this.scope?.retainedValues() ?? [], ...this.retainedRoots()])
30924
+ );
30925
+ return { args: values, rollback };
30926
+ } catch (error) {
30927
+ rollback();
30928
+ if (error instanceof SandboxError) this.poison(error);
30929
+ throw error;
30930
+ }
30931
+ };
30932
+ releaseGuestReference = (reference) => {
30933
+ readGuestReference(reference, this);
30934
+ revokeGuestReference(reference, this);
30935
+ this.guestReferences.delete(reference);
30936
+ if (this.active === void 0)
30937
+ reconcileCompiledValues(
30938
+ this.budget,
30939
+ [...this.scope?.retainedValues() ?? [], ...this.retainedRoots()],
30940
+ this.compilation
30941
+ );
30942
+ };
30220
30943
  assertOpen = () => {
30221
30944
  if (this.failure !== void 0) throw this.failure.reason;
30222
30945
  if (this.closed) throw new Error("SafeJS realm is closed; capabilities are revoked.");
@@ -30272,7 +30995,7 @@ var RealmState = class {
30272
30995
  return this.phase.run(phase, () => {
30273
30996
  try {
30274
30997
  const result = call();
30275
- if (types3.isPromise(result) || phase.pending.size > 0 || phase.failure !== void 0) {
30998
+ if (types5.isPromise(result) || phase.pending.size > 0 || phase.failure !== void 0) {
30276
30999
  return Promise.resolve(result).then(
30277
31000
  async (value) => {
30278
31001
  await Promise.allSettled(phase.pending);
@@ -30327,17 +31050,26 @@ var RealmState = class {
30327
31050
  owner: this,
30328
31051
  assertActive: this.assertOpen,
30329
31052
  chargeWork: this.chargeWork,
30330
- read: (operation) => {
31053
+ checkLength: (length) => this.budget.allocateArrayLength(length),
31054
+ checkTemporaryDataSize: (size) => {
31055
+ const temporary = {};
31056
+ try {
31057
+ this.budget.setRetainedDataUsage(temporary, size);
31058
+ } finally {
31059
+ this.budget.setRetainedDataUsage(temporary, 0);
31060
+ }
31061
+ },
31062
+ read: (operation, validate) => {
30331
31063
  const value = this.invokeHost(operation, operation);
30332
- if (types3.isPromise(value)) {
31064
+ if (types5.isPromise(value)) {
30333
31065
  void Promise.resolve(value).catch(() => void 0);
30334
31066
  throw new TypeError("Live property getters must be synchronous.");
30335
31067
  }
30336
- return this.importValue(value);
31068
+ return this.importValue(validate === void 0 ? value : validate(value));
30337
31069
  },
30338
31070
  write: (operation, value) => {
30339
31071
  const result = this.invokeHost(operation, () => operation(this.exportValue(value)));
30340
- if (types3.isPromise(result)) {
31072
+ if (types5.isPromise(result)) {
30341
31073
  void Promise.resolve(result).catch(() => void 0);
30342
31074
  throw new TypeError("Live property setters must be synchronous.");
30343
31075
  }
@@ -30384,7 +31116,7 @@ var RealmState = class {
30384
31116
  });
30385
31117
  try {
30386
31118
  this.budget.reconcileDataUsage(
30387
- measureSandboxData([...this.scope?.retainedValues() ?? [], ...this.retainedCallbacks()])
31119
+ measureSandboxData([...this.scope?.retainedValues() ?? [], ...this.retainedRoots()])
30388
31120
  );
30389
31121
  } catch (error) {
30390
31122
  this.poison(error);
@@ -30399,7 +31131,7 @@ var RealmState = class {
30399
31131
  if (this.active === void 0)
30400
31132
  reconcileCompiledValues(
30401
31133
  this.budget,
30402
- [...this.scope?.retainedValues() ?? [], ...this.retainedCallbacks()],
31134
+ [...this.scope?.retainedValues() ?? [], ...this.retainedRoots()],
30403
31135
  this.compilation
30404
31136
  );
30405
31137
  };
@@ -30458,7 +31190,7 @@ var RealmState = class {
30458
31190
  if (!this.closed && this.active === void 0)
30459
31191
  reconcileCompiledValues(
30460
31192
  this.budget,
30461
- [...this.scope?.retainedValues() ?? [], ...this.retainedCallbacks()],
31193
+ [...this.scope?.retainedValues() ?? [], ...this.retainedRoots()],
30462
31194
  this.compilation
30463
31195
  );
30464
31196
  }
@@ -30475,6 +31207,23 @@ var RealmState = class {
30475
31207
  createHostObject: this.createHostObject,
30476
31208
  invokeCallback: this.invokeCallback,
30477
31209
  releaseCallback: this.releaseCallback,
31210
+ releaseGuestReference: this.releaseGuestReference,
31211
+ retainGuestArguments: (operation, from) => {
31212
+ this.assertOpen();
31213
+ if (!extension.manifest.capabilities?.includes("guest:retain"))
31214
+ throw new TypeError("Retaining arguments requires the guest:retain grant.");
31215
+ if (typeof operation !== "function")
31216
+ throw new TypeError("Retained operation must be a function.");
31217
+ if (!Number.isSafeInteger(from) || from < 0)
31218
+ throw new TypeError("Argument index must be a non-negative safe integer.");
31219
+ if (this.scope !== void 0)
31220
+ throw new TypeError("Retained operations must be registered during setup.");
31221
+ const previous = this.retainedOperations.get(operation);
31222
+ if (previous !== void 0 && (previous.extension !== extension || previous.from !== from))
31223
+ throw new TypeError("Conflicting retained operation declaration.");
31224
+ this.retainedOperations.set(operation, { extension, from });
31225
+ return operation;
31226
+ },
30478
31227
  nestedOperation: (operation) => {
30479
31228
  this.assertOpen();
30480
31229
  if (!extension.manifest.capabilities?.includes("source:nested"))
@@ -30513,7 +31262,7 @@ var RealmState = class {
30513
31262
  }
30514
31263
  });
30515
31264
  const output = getExtensionSetup(extension)(context);
30516
- if (types3.isPromise(output)) {
31265
+ if (types5.isPromise(output)) {
30517
31266
  void Promise.resolve(output).catch(() => void 0);
30518
31267
  throw new TypeError("Extension setup must be synchronous.");
30519
31268
  }
@@ -30637,7 +31386,7 @@ var RealmState = class {
30637
31386
  if (!this.closed)
30638
31387
  reconcileCompiledValues(
30639
31388
  this.budget,
30640
- [...this.scope?.retainedValues() ?? [], ...this.retainedCallbacks()],
31389
+ [...this.scope?.retainedValues() ?? [], ...this.retainedRoots()],
30641
31390
  this.compilation
30642
31391
  );
30643
31392
  return result;
@@ -30671,7 +31420,10 @@ var RealmState = class {
30671
31420
  this.callbacks.clear();
30672
31421
  for (const object of this.hostObjects) revokeHostObject(object, this);
30673
31422
  this.hostObjects.clear();
31423
+ for (const reference of this.guestReferences.keys()) revokeGuestReference(reference, this);
31424
+ this.guestReferences.clear();
30674
31425
  this.budget.setRetainedValues(this, void 0);
31426
+ releaseObjectPrototype(this.budget);
30675
31427
  this.disposal = (async () => {
30676
31428
  const errors = [];
30677
31429
  for (const cleanup of this.cleanups.splice(0).reverse()) {
@@ -30698,7 +31450,7 @@ var RealmState = class {
30698
31450
  };
30699
31451
  function readModules(input) {
30700
31452
  const entries = (value, label) => {
30701
- if (types3.isMap(value) && !types3.isProxy(value)) {
31453
+ if (types5.isMap(value) && !types5.isProxy(value)) {
30702
31454
  const result = [...Map.prototype.entries.call(value)];
30703
31455
  if (result.length > 4096 || result.some(([key]) => typeof key !== "string" || key.length === 0))
30704
31456
  throw new TypeError(`${label} requires bounded string keys.`);
@@ -30726,6 +31478,7 @@ function createRealm(options = {}) {
30726
31478
  evaluate: state.evaluate,
30727
31479
  invokeCallback: state.invokeCallback,
30728
31480
  releaseCallback: state.releaseCallback,
31481
+ releaseGuestReference: state.releaseGuestReference,
30729
31482
  close: state.close
30730
31483
  });
30731
31484
  }
@@ -30771,6 +31524,7 @@ function readRealmOptions(value, oneShot = false) {
30771
31524
  "signal",
30772
31525
  "sink",
30773
31526
  "randomSeed",
31527
+ "clock",
30774
31528
  "limits"
30775
31529
  ]);
30776
31530
  for (const [key, entry] of Object.entries(options)) {
@@ -31417,7 +32171,7 @@ function run(source, options = {}) {
31417
32171
  lifecycle
31418
32172
  })
31419
32173
  );
31420
- const builtinBindings = createBuiltinBindings({ compileOwner: operation.owner, budget, hostCalls, sink: options.sink, random: random?.generator.next });
32174
+ const builtinBindings = createBuiltinBindings({ compileOwner: operation.owner, budget, hostCalls, sink: options.sink, random: random?.generator.next, clock: options.clock });
31421
32175
  const importMeta = convertInitialInput(
31422
32176
  () => deepCopyToSandbox(options.importMeta ?? {})
31423
32177
  );
@@ -31678,6 +32432,7 @@ function run(source, options = {}) {
31678
32432
  }
31679
32433
  });
31680
32434
  } finally {
32435
+ releaseObjectPrototype(budget);
31681
32436
  compilation.dispose();
31682
32437
  operation.release();
31683
32438
  }
@@ -31920,4 +32675,4 @@ export {
31920
32675
  FileSnapshotBackend,
31921
32676
  run
31922
32677
  };
31923
- //# sourceMappingURL=chunk-2M6MNQBY.js.map
32678
+ //# sourceMappingURL=chunk-MO3YD4ID.js.map