poe-code 14.0.5 → 14.0.7
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/dist/index.js +1604 -255
- package/dist/index.js.map +4 -4
- package/dist/metafile.json +1 -1
- package/package.json +1 -1
- package/packages/safe-js/dist/chunks/{chunk-B7H4ZL65.js → chunk-BWVASPJX.js} +2099 -783
- package/packages/safe-js/dist/chunks/chunk-BWVASPJX.js.map +7 -0
- package/packages/safe-js/dist/chunks/{chunk-7B7BKWVF.js → chunk-ETKM3KPA.js} +2 -2
- package/packages/safe-js/dist/cli.js +2 -2
- package/packages/safe-js/dist/core.d.ts +3 -0
- package/packages/safe-js/dist/core.js +5 -1
- package/packages/safe-js/dist/extensions.d.ts +44 -0
- package/packages/safe-js/dist/extensions.js +83 -0
- package/packages/safe-js/dist/index.d.ts +4 -1
- package/packages/safe-js/dist/index.js +6 -2
- package/packages/safe-js/dist/index.js.map +2 -2
- package/packages/safe-js/dist/interp/async.d.ts +1 -0
- package/packages/safe-js/dist/interp/date.d.ts +19 -0
- package/packages/safe-js/dist/interp/date.js +129 -0
- package/packages/safe-js/dist/interp/globals/console-json.js +5 -1
- package/packages/safe-js/dist/interp/globals/date.d.ts +10 -0
- package/packages/safe-js/dist/interp/globals/date.js +95 -0
- package/packages/safe-js/dist/interp/globals/object-array.d.ts +2 -1
- package/packages/safe-js/dist/interp/globals/object-array.js +15 -1
- package/packages/safe-js/dist/interp/globals.d.ts +34 -0
- package/packages/safe-js/dist/interp/globals.js +24 -0
- package/packages/safe-js/dist/interp/host-bridge.d.ts +18 -1
- package/packages/safe-js/dist/interp/host-bridge.js +39 -5
- package/packages/safe-js/dist/interp/host-call.js +4 -0
- package/packages/safe-js/dist/interp/host-capabilities.d.ts +50 -0
- package/packages/safe-js/dist/interp/host-capabilities.js +151 -0
- package/packages/safe-js/dist/interp/interpreter.d.ts +4 -0
- package/packages/safe-js/dist/interp/interpreter.js +41 -6
- package/packages/safe-js/dist/interp/object-model.js +7 -0
- package/packages/safe-js/dist/interp/string-coercion.js +3 -0
- package/packages/safe-js/dist/interp/values.d.ts +2 -1
- package/packages/safe-js/dist/interp/values.js +36 -0
- package/packages/safe-js/dist/lint/rules/known-globals.d.ts +1 -1
- package/packages/safe-js/dist/lint/rules/known-globals.js +1 -0
- package/packages/safe-js/dist/modules/registry.d.ts +3 -1
- package/packages/safe-js/dist/modules/registry.js +2 -1
- package/packages/safe-js/dist/parse/parser.js +4 -2
- package/packages/safe-js/dist/realm.d.ts +46 -0
- package/packages/safe-js/dist/realm.js +779 -0
- package/packages/safe-js/dist/run.d.ts +7 -1
- package/packages/safe-js/dist/run.js +6 -35
- package/packages/safe-js/dist/snapshot/dump-format.js +8 -3
- package/packages/safe-js/dist/snapshot/replay-data.d.ts +4 -1
- package/packages/safe-js/dist/snapshot/replay-data.js +11 -0
- package/packages/safe-js/dist/snapshot/restore.js +6 -0
- package/packages/safe-js/dist/snapshot/serialize.d.ts +5 -2
- package/packages/safe-js/dist/snapshot/serialize.js +8 -2
- package/packages/safe-js/dist/snapshot/validation.js +18 -1
- package/packages/safe-js/dist/chunks/chunk-B7H4ZL65.js.map +0 -7
- /package/packages/safe-js/dist/chunks/{chunk-7B7BKWVF.js.map → chunk-ETKM3KPA.js.map} +0 -0
|
@@ -4263,8 +4263,9 @@ var Parser = class {
|
|
|
4263
4263
|
}
|
|
4264
4264
|
break;
|
|
4265
4265
|
}
|
|
4266
|
-
this.
|
|
4267
|
-
|
|
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: {
|
|
@@ -5922,6 +5923,87 @@ function matchingOpeningPunctuator(value) {
|
|
|
5922
5923
|
return "{";
|
|
5923
5924
|
}
|
|
5924
5925
|
|
|
5926
|
+
// packages/safe-js/src/extensions.ts
|
|
5927
|
+
import { types } from "node:util";
|
|
5928
|
+
var definitions = /* @__PURE__ */ new WeakMap();
|
|
5929
|
+
function readDataRecord(value, label) {
|
|
5930
|
+
if (typeof value !== "object" || value === null || types.isProxy(value)) {
|
|
5931
|
+
throw new TypeError(`${label} must be a plain data record.`);
|
|
5932
|
+
}
|
|
5933
|
+
const prototype = Object.getPrototypeOf(value);
|
|
5934
|
+
if (prototype !== null && prototype !== Object.prototype) {
|
|
5935
|
+
throw new TypeError(`${label} must be a plain data record.`);
|
|
5936
|
+
}
|
|
5937
|
+
const keys = Reflect.ownKeys(value);
|
|
5938
|
+
if (keys.length > 4096) throw new RangeError(`${label} has too many fields.`);
|
|
5939
|
+
const result = /* @__PURE__ */ Object.create(null);
|
|
5940
|
+
for (const key of keys) {
|
|
5941
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
5942
|
+
if (typeof key !== "string" || !("value" in descriptor)) {
|
|
5943
|
+
throw new TypeError(`${label} requires string-keyed data properties, not accessors.`);
|
|
5944
|
+
}
|
|
5945
|
+
result[key] = descriptor.value;
|
|
5946
|
+
}
|
|
5947
|
+
return result;
|
|
5948
|
+
}
|
|
5949
|
+
function readStringList(value, label) {
|
|
5950
|
+
if (!Array.isArray(value) || types.isProxy(value) || value.length > 4096) {
|
|
5951
|
+
throw new TypeError(`${label} must be a bounded string array.`);
|
|
5952
|
+
}
|
|
5953
|
+
const result = [];
|
|
5954
|
+
for (let index = 0; index < value.length; index++) {
|
|
5955
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
|
|
5956
|
+
if (descriptor === void 0 || !("value" in descriptor) || typeof descriptor.value !== "string" || descriptor.value.length === 0) {
|
|
5957
|
+
throw new TypeError(`${label} requires nonempty string data properties.`);
|
|
5958
|
+
}
|
|
5959
|
+
if (result.includes(descriptor.value))
|
|
5960
|
+
throw new TypeError(`${label} contains a duplicate name.`);
|
|
5961
|
+
result.push(descriptor.value);
|
|
5962
|
+
}
|
|
5963
|
+
if (Reflect.ownKeys(value).length !== result.length + 1)
|
|
5964
|
+
throw new TypeError(`${label} has unexpected fields.`);
|
|
5965
|
+
return Object.freeze(result);
|
|
5966
|
+
}
|
|
5967
|
+
function defineExtension(definition) {
|
|
5968
|
+
const input = readDataRecord(definition, "Extension definition");
|
|
5969
|
+
if (Object.keys(input).some((key) => key !== "manifest" && key !== "setup"))
|
|
5970
|
+
throw new TypeError("Unknown extension definition field.");
|
|
5971
|
+
if (typeof input.setup !== "function") throw new TypeError("Extension setup must be a function.");
|
|
5972
|
+
if (types.isAsyncFunction(input.setup))
|
|
5973
|
+
throw new TypeError("Extension setup must be synchronous.");
|
|
5974
|
+
const manifest = readDataRecord(input.manifest, "Extension manifest");
|
|
5975
|
+
if (Object.keys(manifest).some(
|
|
5976
|
+
(key) => !["version", "name", "capabilities", "globals", "modules"].includes(key)
|
|
5977
|
+
))
|
|
5978
|
+
throw new TypeError("Unknown extension manifest field.");
|
|
5979
|
+
if (manifest.version !== 1) throw new TypeError("Unsupported extension manifest version.");
|
|
5980
|
+
if (typeof manifest.name !== "string" || manifest.name.length === 0 || manifest.name.length > 256)
|
|
5981
|
+
throw new TypeError("Extension name must be a nonempty bounded string.");
|
|
5982
|
+
const modules = /* @__PURE__ */ Object.create(null);
|
|
5983
|
+
for (const [name, exports] of Object.entries(
|
|
5984
|
+
readDataRecord(manifest.modules ?? {}, "Extension modules")
|
|
5985
|
+
)) {
|
|
5986
|
+
if (name.length === 0) throw new TypeError("Module names must be nonempty.");
|
|
5987
|
+
modules[name] = readStringList(exports, `Module '${name}' exports`);
|
|
5988
|
+
}
|
|
5989
|
+
const extension = Object.freeze({
|
|
5990
|
+
manifest: Object.freeze({
|
|
5991
|
+
version: 1,
|
|
5992
|
+
name: manifest.name,
|
|
5993
|
+
capabilities: readStringList(manifest.capabilities ?? [], "Extension capabilities"),
|
|
5994
|
+
globals: readStringList(manifest.globals ?? [], "Extension globals"),
|
|
5995
|
+
modules: Object.freeze(modules)
|
|
5996
|
+
})
|
|
5997
|
+
});
|
|
5998
|
+
definitions.set(extension, input.setup);
|
|
5999
|
+
return extension;
|
|
6000
|
+
}
|
|
6001
|
+
function getExtensionSetup(extension) {
|
|
6002
|
+
const setup = definitions.get(extension);
|
|
6003
|
+
if (setup === void 0) throw new TypeError("Extensions must be created by defineExtension.");
|
|
6004
|
+
return setup;
|
|
6005
|
+
}
|
|
6006
|
+
|
|
5925
6007
|
// packages/safe-js/src/observability/otel.ts
|
|
5926
6008
|
var noopOtelSink = {
|
|
5927
6009
|
startSpan: () => noopOtelSpan,
|
|
@@ -6126,6 +6208,266 @@ function copyFloat32Storage(value, state) {
|
|
|
6126
6208
|
return new Float32Array(buffer, storage.byteOffset, storage.length);
|
|
6127
6209
|
}
|
|
6128
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
|
+
|
|
6333
|
+
// packages/safe-js/src/interp/host-capabilities.ts
|
|
6334
|
+
var hostObjects = /* @__PURE__ */ new WeakMap();
|
|
6335
|
+
var guestObjects = /* @__PURE__ */ new WeakMap();
|
|
6336
|
+
var guestCallbacks = /* @__PURE__ */ new WeakMap();
|
|
6337
|
+
var guestReferences = /* @__PURE__ */ new WeakMap();
|
|
6338
|
+
function createGuestReference(root, owner, assertActive) {
|
|
6339
|
+
const reference = Object.freeze(/* @__PURE__ */ Object.create(null));
|
|
6340
|
+
guestReferences.set(reference, { root, owner, assertActive });
|
|
6341
|
+
return reference;
|
|
6342
|
+
}
|
|
6343
|
+
function readGuestReference(reference, owner) {
|
|
6344
|
+
const state = typeof reference === "object" && reference !== null ? guestReferences.get(reference) : void 0;
|
|
6345
|
+
if (state === void 0 || state.owner !== owner)
|
|
6346
|
+
throw new TypeError("Foreign or invalid guest reference.");
|
|
6347
|
+
state.assertActive();
|
|
6348
|
+
if (state.root === void 0) throw new TypeError("Guest reference is revoked.");
|
|
6349
|
+
return state.root[0];
|
|
6350
|
+
}
|
|
6351
|
+
function revokeGuestReference(reference, owner) {
|
|
6352
|
+
const state = guestReferences.get(reference);
|
|
6353
|
+
if (state === void 0 || state.owner !== owner) throw new TypeError("Foreign guest reference.");
|
|
6354
|
+
state.root = void 0;
|
|
6355
|
+
}
|
|
6356
|
+
function createLiveHostObject(definition, controller) {
|
|
6357
|
+
const input = readDataRecord(definition, "Host object definition");
|
|
6358
|
+
if (Object.keys(input).some((key) => key !== "properties" && key !== "methods"))
|
|
6359
|
+
throw new TypeError("Unknown host object definition field.");
|
|
6360
|
+
const properties = /* @__PURE__ */ new Map();
|
|
6361
|
+
for (const [name, inputProperty] of Object.entries(
|
|
6362
|
+
readDataRecord(input.properties ?? {}, "Host properties")
|
|
6363
|
+
)) {
|
|
6364
|
+
const property = readDataRecord(inputProperty, `Host property '${name}'`);
|
|
6365
|
+
if (Object.keys(property).some((key) => key !== "get" && key !== "set"))
|
|
6366
|
+
throw new TypeError("Unknown host property field.");
|
|
6367
|
+
if (property.get !== void 0 && typeof property.get !== "function" || property.set !== void 0 && typeof property.set !== "function")
|
|
6368
|
+
throw new TypeError("Host property operations must be functions.");
|
|
6369
|
+
properties.set(name, property);
|
|
6370
|
+
}
|
|
6371
|
+
const operations = readDataRecord(input.methods ?? {}, "Host methods");
|
|
6372
|
+
for (const [name, operation] of Object.entries(operations)) {
|
|
6373
|
+
if (typeof operation !== "function") throw new TypeError("Host methods must be functions.");
|
|
6374
|
+
if (properties.has(name)) throw new TypeError(`Conflicting host member '${name}'.`);
|
|
6375
|
+
}
|
|
6376
|
+
for (const name of [...properties.keys(), ...Object.keys(operations)]) {
|
|
6377
|
+
if (["constructor", "prototype", "__proto__"].includes(name))
|
|
6378
|
+
throw new TypeError(`Reserved host member '${name}'.`);
|
|
6379
|
+
}
|
|
6380
|
+
controller.assertActive();
|
|
6381
|
+
controller.chargeWork(properties.size + Object.keys(operations).length + 1);
|
|
6382
|
+
const host = Object.freeze(/* @__PURE__ */ Object.create(null));
|
|
6383
|
+
const guest = Object.freeze(/* @__PURE__ */ Object.create(null));
|
|
6384
|
+
const methods = new Map(
|
|
6385
|
+
Object.entries(operations).map(([name, operation]) => [
|
|
6386
|
+
name,
|
|
6387
|
+
controller.method(operation)
|
|
6388
|
+
])
|
|
6389
|
+
);
|
|
6390
|
+
const state = { host, guest, controller, properties, methods };
|
|
6391
|
+
hostObjects.set(host, state);
|
|
6392
|
+
guestObjects.set(guest, state);
|
|
6393
|
+
return host;
|
|
6394
|
+
}
|
|
6395
|
+
function isGuestHostObject(value) {
|
|
6396
|
+
return typeof value === "object" && value !== null && guestObjects.has(value);
|
|
6397
|
+
}
|
|
6398
|
+
function isLiveCapability(value) {
|
|
6399
|
+
return (typeof value === "object" && value !== null || typeof value === "function") && (hostObjects.has(value) || guestObjects.has(value) || guestCallbacks.has(value) || guestReferences.has(value));
|
|
6400
|
+
}
|
|
6401
|
+
function importHostCapability(value, owner) {
|
|
6402
|
+
if (guestReferences.has(value)) return readGuestReference(value, owner);
|
|
6403
|
+
const object = hostObjects.get(value);
|
|
6404
|
+
if (object !== void 0) {
|
|
6405
|
+
if (object.controller.owner !== owner) throw new TypeError("Foreign realm host capability.");
|
|
6406
|
+
object.controller.assertActive();
|
|
6407
|
+
return object.guest;
|
|
6408
|
+
}
|
|
6409
|
+
const callback = guestCallbacks.get(value);
|
|
6410
|
+
if (callback !== void 0) {
|
|
6411
|
+
if (callback.owner !== owner) throw new TypeError("Foreign realm guest callback.");
|
|
6412
|
+
callback.assertActive();
|
|
6413
|
+
if (callback.closure === void 0) throw new TypeError("Guest callback is revoked.");
|
|
6414
|
+
return callback.closure;
|
|
6415
|
+
}
|
|
6416
|
+
throw new TypeError("Unsupported live capability conversion.");
|
|
6417
|
+
}
|
|
6418
|
+
function exportHostCapability(value, owner) {
|
|
6419
|
+
const state = guestObjects.get(value);
|
|
6420
|
+
if (state === void 0 || state.controller.owner !== owner)
|
|
6421
|
+
throw new TypeError("Foreign realm host capability.");
|
|
6422
|
+
state.controller.assertActive();
|
|
6423
|
+
return state.host;
|
|
6424
|
+
}
|
|
6425
|
+
function registerGuestCallback(callback, state) {
|
|
6426
|
+
guestCallbacks.set(callback, state);
|
|
6427
|
+
}
|
|
6428
|
+
function readGuestCallback(callback, owner) {
|
|
6429
|
+
const state = typeof callback === "function" ? guestCallbacks.get(callback) : void 0;
|
|
6430
|
+
if (state === void 0 || state.owner !== owner)
|
|
6431
|
+
throw new TypeError("Foreign or invalid guest callback.");
|
|
6432
|
+
state.assertActive();
|
|
6433
|
+
if (state.closure === void 0) throw new TypeError("Guest callback is revoked.");
|
|
6434
|
+
return state.closure;
|
|
6435
|
+
}
|
|
6436
|
+
function revokeGuestCallback(callback, owner) {
|
|
6437
|
+
const state = guestCallbacks.get(callback);
|
|
6438
|
+
if (state === void 0 || state.owner !== owner) throw new TypeError("Foreign guest callback.");
|
|
6439
|
+
state.closure = void 0;
|
|
6440
|
+
}
|
|
6441
|
+
function revokeHostObject(value, owner) {
|
|
6442
|
+
const state = hostObjects.get(value);
|
|
6443
|
+
if (state === void 0 || state.controller.owner !== owner)
|
|
6444
|
+
throw new TypeError("Foreign host object.");
|
|
6445
|
+
state.properties.clear();
|
|
6446
|
+
state.methods.clear();
|
|
6447
|
+
}
|
|
6448
|
+
function getHostObjectMember(value, key) {
|
|
6449
|
+
const state = guestObjects.get(value);
|
|
6450
|
+
state.controller.assertActive();
|
|
6451
|
+
state.controller.chargeWork();
|
|
6452
|
+
const property = state.properties.get(key);
|
|
6453
|
+
if (property !== void 0)
|
|
6454
|
+
return property.get === void 0 ? void 0 : state.controller.read(property.get);
|
|
6455
|
+
return state.methods.get(key);
|
|
6456
|
+
}
|
|
6457
|
+
function setHostObjectMember(value, key, entry) {
|
|
6458
|
+
const state = guestObjects.get(value);
|
|
6459
|
+
state.controller.assertActive();
|
|
6460
|
+
state.controller.chargeWork();
|
|
6461
|
+
const property = state.properties.get(key);
|
|
6462
|
+
if (property?.set === void 0) throw new TypeError(`Host property '${key}' is not writable.`);
|
|
6463
|
+
state.controller.write(property.set, entry);
|
|
6464
|
+
}
|
|
6465
|
+
function getHostObjectKeys(value) {
|
|
6466
|
+
const state = guestObjects.get(value);
|
|
6467
|
+
state.controller.assertActive();
|
|
6468
|
+
return [...state.properties.keys(), ...state.methods.keys()];
|
|
6469
|
+
}
|
|
6470
|
+
|
|
6129
6471
|
// packages/safe-js/src/interp/values.ts
|
|
6130
6472
|
import { types as nodeTypes } from "node:util";
|
|
6131
6473
|
|
|
@@ -6246,7 +6588,7 @@ async function flushPromiseJobs() {
|
|
|
6246
6588
|
import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
|
|
6247
6589
|
|
|
6248
6590
|
// packages/safe-js/src/snapshot/validation.ts
|
|
6249
|
-
import { types } from "node:util";
|
|
6591
|
+
import { types as types3 } from "node:util";
|
|
6250
6592
|
|
|
6251
6593
|
// packages/safe-js/src/interp/arguments.ts
|
|
6252
6594
|
var sandboxArgumentsBrand = /* @__PURE__ */ Symbol("SandboxArguments");
|
|
@@ -6443,6 +6785,7 @@ function setSandboxPrototype(value, prototype, budget) {
|
|
|
6443
6785
|
else prototypes.set(value, prototype);
|
|
6444
6786
|
}
|
|
6445
6787
|
function isPrototypeRecord(value) {
|
|
6788
|
+
if (isGuestHostObject(value)) return false;
|
|
6446
6789
|
if (isSandboxClosure(value) || isSandboxGenerator(value) || isSandboxMap(value) || isSandboxPromise(value) || isSandboxRegex(value) || isSandboxSet(value))
|
|
6447
6790
|
return false;
|
|
6448
6791
|
const prototype = Object.getPrototypeOf(value);
|
|
@@ -6455,6 +6798,7 @@ function hasManagedDescriptors(value) {
|
|
|
6455
6798
|
return descriptorObjects.has(value);
|
|
6456
6799
|
}
|
|
6457
6800
|
function hasGuestObjectState(value) {
|
|
6801
|
+
if (isLiveCapability(value)) return true;
|
|
6458
6802
|
if (functionProperties.has(value) || prototypes.has(value)) return true;
|
|
6459
6803
|
return descriptorObjects.has(value) && Object.values(Object.getOwnPropertyDescriptors(value)).some(
|
|
6460
6804
|
(descriptor) => !descriptor.enumerable || !descriptor.configurable || !descriptor.writable
|
|
@@ -6620,7 +6964,7 @@ function serializeDumpValue(value, path, state) {
|
|
|
6620
6964
|
if (hasGuestObjectState(value)) {
|
|
6621
6965
|
throw new TypeError("Guest function properties and prototype links cannot be serialized.");
|
|
6622
6966
|
}
|
|
6623
|
-
if (isFloat32Array(value)) return serializeHeapReference(value, path, state);
|
|
6967
|
+
if (isSandboxDate(value) || isFloat32Array(value)) return serializeHeapReference(value, path, state);
|
|
6624
6968
|
if (Array.isArray(value)) {
|
|
6625
6969
|
const reference2 = serializeHeapReference(value, path, state);
|
|
6626
6970
|
if (reference2 !== void 0) {
|
|
@@ -6644,7 +6988,9 @@ function serializeHeapReference(value, path, state) {
|
|
|
6644
6988
|
}
|
|
6645
6989
|
if (!state.serializedHeapIds.has(id)) {
|
|
6646
6990
|
state.serializedHeapIds.add(id);
|
|
6647
|
-
if (
|
|
6991
|
+
if (isSandboxDate(value)) {
|
|
6992
|
+
state.heap[String(id)] = { kind: "date", time: serializedDateTime(value) };
|
|
6993
|
+
} else if (isFloat32Array(value)) {
|
|
6648
6994
|
const storage = encodeFloat32Storage(value, id, state.float32Buffers, (id2) => ({
|
|
6649
6995
|
kind: "ref",
|
|
6650
6996
|
id: id2
|
|
@@ -6701,7 +7047,7 @@ function indexHeapContainers(snapshot) {
|
|
|
6701
7047
|
const heapIds = /* @__PURE__ */ new WeakMap();
|
|
6702
7048
|
let nextId = 1;
|
|
6703
7049
|
for (const [value, stat2] of stats.entries()) {
|
|
6704
|
-
if (stat2.count > 1 || stat2.cyclic || isFloat32Array(value) || Array.isArray(value) && requiresArrayEntries(value) || isSandboxArguments(value) || sandboxErrorTypes.has(value)) {
|
|
7050
|
+
if (stat2.count > 1 || stat2.cyclic || isSandboxDate(value) || isFloat32Array(value) || Array.isArray(value) && requiresArrayEntries(value) || isSandboxArguments(value) || sandboxErrorTypes.has(value)) {
|
|
6705
7051
|
heapIds.set(value, nextId);
|
|
6706
7052
|
nextId += 1;
|
|
6707
7053
|
}
|
|
@@ -6712,7 +7058,7 @@ function collectContainerStats(value, stats, ancestors) {
|
|
|
6712
7058
|
if (value === null || typeof value !== "object") {
|
|
6713
7059
|
return;
|
|
6714
7060
|
}
|
|
6715
|
-
if (!Array.isArray(value) && !isPlainObject(value) && !isFloat32Array(value)) {
|
|
7061
|
+
if (!Array.isArray(value) && !isPlainObject(value) && !isFloat32Array(value) && !isSandboxDate(value)) {
|
|
6716
7062
|
return;
|
|
6717
7063
|
}
|
|
6718
7064
|
let stat2 = stats.get(value);
|
|
@@ -6848,6 +7194,10 @@ function validateDumpHeap(root, state) {
|
|
|
6848
7194
|
addUnique(heapIds, id, path);
|
|
6849
7195
|
const entry = requireRecord(value, path);
|
|
6850
7196
|
validateErrorType(entry, path);
|
|
7197
|
+
if (entry.kind === "date") {
|
|
7198
|
+
validateDateRecord(entry, path);
|
|
7199
|
+
continue;
|
|
7200
|
+
}
|
|
6851
7201
|
if (entry.kind === "float32array") {
|
|
6852
7202
|
validateFloat32Storage(entry);
|
|
6853
7203
|
requireRecord(entry.entries, `${path}.entries`);
|
|
@@ -7005,6 +7355,14 @@ function validateGeneratorShape(record2, path, state) {
|
|
|
7005
7355
|
}
|
|
7006
7356
|
});
|
|
7007
7357
|
}
|
|
7358
|
+
function validateDateRecord(record2, path) {
|
|
7359
|
+
if (Object.keys(record2).length !== 2) fail("invalidValue", path, "invalid Date fields");
|
|
7360
|
+
try {
|
|
7361
|
+
restoreDateTime(record2.time);
|
|
7362
|
+
} catch {
|
|
7363
|
+
fail("invalidValue", `${path}.time`, "invalid Date epoch");
|
|
7364
|
+
}
|
|
7365
|
+
}
|
|
7008
7366
|
function validateArrayHeap(record2, path, state) {
|
|
7009
7367
|
if (Object.hasOwn(record2, "items")) {
|
|
7010
7368
|
requireArray(record2.items, `${path}.items`, state);
|
|
@@ -7088,7 +7446,7 @@ function validateGenericValue(value, path, depth, state) {
|
|
|
7088
7446
|
if (typeof value === "object" && value !== null && hasGuestObjectState(value)) {
|
|
7089
7447
|
fail("invalidState", path, "guest function properties, prototype links and custom descriptors cannot be restored");
|
|
7090
7448
|
}
|
|
7091
|
-
if (state.dataPropertiesOnly &&
|
|
7449
|
+
if (state.dataPropertiesOnly && types3.isProxy(value)) {
|
|
7092
7450
|
fail("invalidType", path, "proxy objects are not snapshot data");
|
|
7093
7451
|
}
|
|
7094
7452
|
if (depth > state.limits.maxDepth)
|
|
@@ -9178,6 +9536,7 @@ function createSandboxClosure(input) {
|
|
|
9178
9536
|
return Object.freeze(closure);
|
|
9179
9537
|
}
|
|
9180
9538
|
function ownEnumerableSandboxEntries(value) {
|
|
9539
|
+
if (isGuestHostObject(value)) return getHostObjectKeys(value).map((key) => [key, getHostObjectMember(value, key)]);
|
|
9181
9540
|
if (value === null || value === void 0) throw new TypeError("Cannot convert undefined or null to object.");
|
|
9182
9541
|
if (isGuestClosure(value)) return Object.entries(value.properties ?? {});
|
|
9183
9542
|
if (isSandboxClosure(value) || isSandboxGenerator(value) || isSandboxMap(value) || isSandboxSet(value) || isSandboxPromise(value) || isSandboxRegex(value)) return [];
|
|
@@ -9330,6 +9689,14 @@ function measureSandboxData(values, options = {}) {
|
|
|
9330
9689
|
assertSandboxDataDepth(depth);
|
|
9331
9690
|
seen.add(value);
|
|
9332
9691
|
usage += 1;
|
|
9692
|
+
if (isSandboxDate(value)) {
|
|
9693
|
+
usage += 8;
|
|
9694
|
+
return;
|
|
9695
|
+
}
|
|
9696
|
+
if (isGuestHostObject(value)) {
|
|
9697
|
+
for (const key of getHostObjectKeys(value)) usage += key.length + 1;
|
|
9698
|
+
return;
|
|
9699
|
+
}
|
|
9333
9700
|
const prototype = getSandboxPrototype(value);
|
|
9334
9701
|
if (prototype !== null) visit(prototype, depth + 1);
|
|
9335
9702
|
if (isFloat32Array(value)) {
|
|
@@ -9472,6 +9839,7 @@ function copyToSandbox(value, state, path = "<root>", cloneSandboxCollections =
|
|
|
9472
9839
|
if (isSandboxPrimitive(value)) {
|
|
9473
9840
|
return value;
|
|
9474
9841
|
}
|
|
9842
|
+
if (isLiveCapability(value)) throw new TypeError("Live capabilities require their owning realm bridge.");
|
|
9475
9843
|
if (isSandboxClosure(value) || isSandboxGenerator(value) || isSandboxRegex(value) || isSandboxPromise(value)) {
|
|
9476
9844
|
return value;
|
|
9477
9845
|
}
|
|
@@ -9519,6 +9887,13 @@ function copyToSandbox(value, state, path = "<root>", cloneSandboxCollections =
|
|
|
9519
9887
|
}
|
|
9520
9888
|
return sandboxPromise;
|
|
9521
9889
|
}
|
|
9890
|
+
if (nodeTypes.isDate(value)) {
|
|
9891
|
+
const existing = state.seen.get(value);
|
|
9892
|
+
if (existing !== void 0) return existing;
|
|
9893
|
+
const copy = copyNativeDate(value);
|
|
9894
|
+
state.seen.set(value, copy);
|
|
9895
|
+
return copy;
|
|
9896
|
+
}
|
|
9522
9897
|
if (isFloat32Array(value)) {
|
|
9523
9898
|
const existing = state.seen.get(value);
|
|
9524
9899
|
if (existing !== void 0) return existing;
|
|
@@ -9635,6 +10010,10 @@ function copyFromSandbox(value, state, path = "<root>", options, depth = 0) {
|
|
|
9635
10010
|
if (isSandboxPrimitive(value)) {
|
|
9636
10011
|
return value;
|
|
9637
10012
|
}
|
|
10013
|
+
if (isGuestHostObject(value)) {
|
|
10014
|
+
if (options.unwrapHostObject === void 0) throw new TypeError("Live capabilities require their owning realm bridge.");
|
|
10015
|
+
return options.unwrapHostObject(value);
|
|
10016
|
+
}
|
|
9638
10017
|
if (nodeTypes.isProxy(value)) throw new TypeError("Unsupported proxy sandbox value.");
|
|
9639
10018
|
if (!isSandboxClosure(value) && hasGuestObjectState(value)) {
|
|
9640
10019
|
throw new TypeError("Guest prototype links and custom descriptors cannot be copied as data.");
|
|
@@ -9674,6 +10053,13 @@ function copyFromSandbox(value, state, path = "<root>", options, depth = 0) {
|
|
|
9674
10053
|
if (!Object.isExtensible(value)) Object.preventExtensions(copy);
|
|
9675
10054
|
return copy;
|
|
9676
10055
|
}
|
|
10056
|
+
if (isSandboxDate(value)) {
|
|
10057
|
+
const existing = state.seen.get(value);
|
|
10058
|
+
if (existing !== void 0) return existing;
|
|
10059
|
+
const copy = exportDate(value);
|
|
10060
|
+
state.seen.set(value, copy);
|
|
10061
|
+
return copy;
|
|
10062
|
+
}
|
|
9677
10063
|
if (isSandboxClosure(value)) {
|
|
9678
10064
|
if (options.wrapClosure === void 0) {
|
|
9679
10065
|
throw new TypeError(
|
|
@@ -9988,6 +10374,8 @@ function encodeReplayData(value, options = {}) {
|
|
|
9988
10374
|
id: capabilityId,
|
|
9989
10375
|
properties: child(entry.properties, "properties")
|
|
9990
10376
|
};
|
|
10377
|
+
} else if (isSandboxDate(entry)) {
|
|
10378
|
+
nodes[id] = { kind: "date", time: serializedDateTime(entry) };
|
|
9991
10379
|
} else if (isFloat32Array(entry)) {
|
|
9992
10380
|
const storage = encodeFloat32Storage(entry, id, float32Buffers, (id2) => ({
|
|
9993
10381
|
tag: "ref",
|
|
@@ -10138,6 +10526,12 @@ function decodeReplayData(input, options = {}, parent) {
|
|
|
10138
10526
|
options.onCapabilityRestored?.(capability, copy);
|
|
10139
10527
|
return copy;
|
|
10140
10528
|
}
|
|
10529
|
+
if (kind === "date") {
|
|
10530
|
+
if (Object.keys(node).length !== 2) throw new TypeError("Invalid serialized Date fields.");
|
|
10531
|
+
const result3 = restoreDateTime(own(node, "time"));
|
|
10532
|
+
restored.set(id, result3);
|
|
10533
|
+
return result3;
|
|
10534
|
+
}
|
|
10141
10535
|
if (kind === "float32array") {
|
|
10142
10536
|
if (typeof node.extensible !== "boolean")
|
|
10143
10537
|
throw new TypeError("Invalid Float32Array extensibility.");
|
|
@@ -10828,6 +11222,8 @@ function normalize(value, seen) {
|
|
|
10828
11222
|
if (seen.has(value)) throw new TypeError("Host call arguments cannot contain cycles.");
|
|
10829
11223
|
seen.add(value);
|
|
10830
11224
|
try {
|
|
11225
|
+
const date = copyNativeDate(value);
|
|
11226
|
+
if (date !== void 0) return Object.assign(/* @__PURE__ */ Object.create(null), { $type: "date", time: serializedDateTime(date) });
|
|
10831
11227
|
if (isFloat32Array(value)) {
|
|
10832
11228
|
const storage = float32Storage(value);
|
|
10833
11229
|
const properties = /* @__PURE__ */ Object.create(null);
|
|
@@ -11783,6 +12179,7 @@ var KNOWN_RUNTIME_GLOBALS = [
|
|
|
11783
12179
|
"AggregateError",
|
|
11784
12180
|
"Array",
|
|
11785
12181
|
"Boolean",
|
|
12182
|
+
"Date",
|
|
11786
12183
|
"Error",
|
|
11787
12184
|
"Infinity",
|
|
11788
12185
|
"isFinite",
|
|
@@ -16947,9 +17344,9 @@ var ASFloatingPromiseScanner = class {
|
|
|
16947
17344
|
isPromiseFactoryCall(node) {
|
|
16948
17345
|
return this.isPromiseStaticMethodCall(node, PROMISE_FACTORIES);
|
|
16949
17346
|
}
|
|
16950
|
-
isPromiseStaticMethodCall(node,
|
|
17347
|
+
isPromiseStaticMethodCall(node, methodNames2) {
|
|
16951
17348
|
const member = node.callee.type === "MemberExpression" ? node.callee : void 0;
|
|
16952
|
-
return member !== void 0 && !member.computed && member.object.type === "Identifier" && member.object.name === "Promise" && member.property.type === "Identifier" &&
|
|
17349
|
+
return member !== void 0 && !member.computed && member.object.type === "Identifier" && member.object.name === "Promise" && member.property.type === "Identifier" && methodNames2.has(member.property.name);
|
|
16953
17350
|
}
|
|
16954
17351
|
isPromiseChainCall(node) {
|
|
16955
17352
|
const member = node.callee.type === "MemberExpression" ? node.callee : void 0;
|
|
@@ -22240,128 +22637,6 @@ function hasOnlyRegexLiteralDiagnostics(diagnostics) {
|
|
|
22240
22637
|
);
|
|
22241
22638
|
}
|
|
22242
22639
|
|
|
22243
|
-
// packages/safe-js/src/random.ts
|
|
22244
|
-
import { randomInt } from "node:crypto";
|
|
22245
|
-
|
|
22246
|
-
// packages/safe-js/src/interp/globals/math.ts
|
|
22247
|
-
var mathMethods = {
|
|
22248
|
-
abs: Math.abs,
|
|
22249
|
-
acos: Math.acos,
|
|
22250
|
-
acosh: Math.acosh,
|
|
22251
|
-
asin: Math.asin,
|
|
22252
|
-
asinh: Math.asinh,
|
|
22253
|
-
atan: Math.atan,
|
|
22254
|
-
atan2: Math.atan2,
|
|
22255
|
-
atanh: Math.atanh,
|
|
22256
|
-
ceil: Math.ceil,
|
|
22257
|
-
cbrt: Math.cbrt,
|
|
22258
|
-
clz32: Math.clz32,
|
|
22259
|
-
cos: Math.cos,
|
|
22260
|
-
cosh: Math.cosh,
|
|
22261
|
-
exp: Math.exp,
|
|
22262
|
-
expm1: Math.expm1,
|
|
22263
|
-
floor: Math.floor,
|
|
22264
|
-
f16round,
|
|
22265
|
-
fround: Math.fround,
|
|
22266
|
-
hypot: Math.hypot,
|
|
22267
|
-
imul: Math.imul,
|
|
22268
|
-
log: Math.log,
|
|
22269
|
-
log1p: Math.log1p,
|
|
22270
|
-
log10: Math.log10,
|
|
22271
|
-
log2: Math.log2,
|
|
22272
|
-
max: Math.max,
|
|
22273
|
-
min: Math.min,
|
|
22274
|
-
pow: Math.pow,
|
|
22275
|
-
round: Math.round,
|
|
22276
|
-
sign: Math.sign,
|
|
22277
|
-
sin: Math.sin,
|
|
22278
|
-
sinh: Math.sinh,
|
|
22279
|
-
sqrt: Math.sqrt,
|
|
22280
|
-
tan: Math.tan,
|
|
22281
|
-
tanh: Math.tanh,
|
|
22282
|
-
trunc: Math.trunc
|
|
22283
|
-
};
|
|
22284
|
-
function f16round(value) {
|
|
22285
|
-
const number = +value;
|
|
22286
|
-
if (!Number.isFinite(number) || number === 0) {
|
|
22287
|
-
return number;
|
|
22288
|
-
}
|
|
22289
|
-
const magnitude = Math.abs(number);
|
|
22290
|
-
if (magnitude >= 65520) {
|
|
22291
|
-
return number < 0 ? -Infinity : Infinity;
|
|
22292
|
-
}
|
|
22293
|
-
let quantum = 2 ** -24;
|
|
22294
|
-
let boundary = 2 ** -13;
|
|
22295
|
-
for (let exponent = -13; exponent <= 15 && magnitude >= boundary; exponent += 1) {
|
|
22296
|
-
quantum *= 2;
|
|
22297
|
-
boundary *= 2;
|
|
22298
|
-
}
|
|
22299
|
-
const scaled = magnitude / quantum;
|
|
22300
|
-
const lower = Math.floor(scaled);
|
|
22301
|
-
const remainder = scaled - lower;
|
|
22302
|
-
const rounded = (remainder > 0.5 || remainder === 0.5 && lower % 2 !== 0 ? lower + 1 : lower) * quantum;
|
|
22303
|
-
return number < 0 ? -rounded : rounded;
|
|
22304
|
-
}
|
|
22305
|
-
function createMathGlobals(options = {}) {
|
|
22306
|
-
const random = options.random ?? Math.random;
|
|
22307
|
-
const mathObject = {
|
|
22308
|
-
E: Math.E,
|
|
22309
|
-
LN2: Math.LN2,
|
|
22310
|
-
LN10: Math.LN10,
|
|
22311
|
-
LOG2E: Math.LOG2E,
|
|
22312
|
-
LOG10E: Math.LOG10E,
|
|
22313
|
-
PI: Math.PI,
|
|
22314
|
-
SQRT1_2: Math.SQRT1_2,
|
|
22315
|
-
SQRT2: Math.SQRT2,
|
|
22316
|
-
random: createSandboxClosure({ sandbox: true, call: () => random(), name: "random" })
|
|
22317
|
-
};
|
|
22318
|
-
for (const [name, method] of Object.entries(mathMethods)) {
|
|
22319
|
-
mathObject[name] = createSandboxClosure({
|
|
22320
|
-
sandbox: true,
|
|
22321
|
-
call: (args) => Reflect.apply(method, Math, args),
|
|
22322
|
-
name
|
|
22323
|
-
});
|
|
22324
|
-
}
|
|
22325
|
-
return {
|
|
22326
|
-
Infinity: Infinity,
|
|
22327
|
-
Math: mathObject,
|
|
22328
|
-
NaN: Number.NaN
|
|
22329
|
-
};
|
|
22330
|
-
}
|
|
22331
|
-
function createSeededRandom(seed) {
|
|
22332
|
-
let state = normalizeSeed(seed);
|
|
22333
|
-
return {
|
|
22334
|
-
next: () => {
|
|
22335
|
-
state = Math.imul(state, 1664525) + 1013904223 >>> 0;
|
|
22336
|
-
return state / 4294967296;
|
|
22337
|
-
},
|
|
22338
|
-
snapshot: () => state,
|
|
22339
|
-
restore: (nextState) => {
|
|
22340
|
-
state = normalizeSeed(nextState);
|
|
22341
|
-
}
|
|
22342
|
-
};
|
|
22343
|
-
}
|
|
22344
|
-
function normalizeSeed(seed) {
|
|
22345
|
-
if (!Number.isFinite(seed)) {
|
|
22346
|
-
throw new TypeError("Seeded random requires a finite numeric seed.");
|
|
22347
|
-
}
|
|
22348
|
-
return Math.trunc(seed) >>> 0;
|
|
22349
|
-
}
|
|
22350
|
-
|
|
22351
|
-
// packages/safe-js/src/random.ts
|
|
22352
|
-
function createReplayableRandom(options = {}) {
|
|
22353
|
-
const snapshot = options.snapshot;
|
|
22354
|
-
const saved = snapshot?.random;
|
|
22355
|
-
let initialState = options.seed;
|
|
22356
|
-
if (saved !== void 0) {
|
|
22357
|
-
const hasLoopState = typeof snapshot?.loopIterations === "object" && snapshot.loopIterations !== null && Object.keys(snapshot.loopIterations).length > 0;
|
|
22358
|
-
const replaysFromStart = snapshot?.replay !== void 0 || Array.isArray(snapshot?.pendingAwaits) && snapshot.pendingAwaits.length > 0 && !hasLoopState;
|
|
22359
|
-
initialState = replaysFromStart ? saved.initialState ?? saved.seed : saved.resumeState ?? saved.state;
|
|
22360
|
-
}
|
|
22361
|
-
const generator = createSeededRandom(initialState ?? randomInt(4294967296));
|
|
22362
|
-
return { seed: saved?.seed ?? generator.snapshot(), ...generator };
|
|
22363
|
-
}
|
|
22364
|
-
|
|
22365
22640
|
// packages/safe-js/src/interp/generator.ts
|
|
22366
22641
|
function createGeneratorChannel(body) {
|
|
22367
22642
|
let state = "unstarted";
|
|
@@ -24709,6 +24984,101 @@ function relativeIndex(value, length, fallback) {
|
|
|
24709
24984
|
return integer < 0 ? Math.max(length + integer, 0) : Math.min(integer, length);
|
|
24710
24985
|
}
|
|
24711
24986
|
|
|
24987
|
+
// packages/safe-js/src/interp/globals/date.ts
|
|
24988
|
+
var intrinsics = /* @__PURE__ */ new WeakMap();
|
|
24989
|
+
var constructors2 = /* @__PURE__ */ new WeakSet();
|
|
24990
|
+
function createDateGlobal(options) {
|
|
24991
|
+
const validateClockTime = (value) => {
|
|
24992
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || Math.abs(value) > 864e13)
|
|
24993
|
+
throw new TypeError("Date clock must return a finite integer epoch within the Date range.");
|
|
24994
|
+
return value;
|
|
24995
|
+
};
|
|
24996
|
+
const readNow = declareHostOperation(
|
|
24997
|
+
() => {
|
|
24998
|
+
options.budget.visitNode();
|
|
24999
|
+
const value = options.clock?.now === void 0 ? Date.now() : options.clock.now();
|
|
25000
|
+
return validateClockTime(value);
|
|
25001
|
+
},
|
|
25002
|
+
"re-issue",
|
|
25003
|
+
{
|
|
25004
|
+
onReplay: (_args, outcome) => {
|
|
25005
|
+
if (outcome.status === "fulfilled") {
|
|
25006
|
+
const time = validateClockTime(outcome.value);
|
|
25007
|
+
options.clock?.restore?.({ next: time + 1 });
|
|
25008
|
+
}
|
|
25009
|
+
}
|
|
25010
|
+
}
|
|
25011
|
+
);
|
|
25012
|
+
const now = wrapCallerInjectedBindings({ now: readNow }, { ...options, moduleId: "<Date>" }).now;
|
|
25013
|
+
const prototype = createSandboxDate(NaN);
|
|
25014
|
+
const constructor = createSandboxClosure({
|
|
25015
|
+
sandbox: true,
|
|
25016
|
+
name: "Date",
|
|
25017
|
+
length: 7,
|
|
25018
|
+
call: async (_args, context) => options.budget.allocateString(
|
|
25019
|
+
dateString(createSandboxDate(Number(await now.call([], context))))
|
|
25020
|
+
),
|
|
25021
|
+
construct: async (args, context) => {
|
|
25022
|
+
let time;
|
|
25023
|
+
if (args.length === 0) time = Number(await now.call([], context));
|
|
25024
|
+
else if (args.length > 1) time = dateFromParts(args, false);
|
|
25025
|
+
else if (isSandboxDate(args[0])) time = dateTime(args[0]);
|
|
25026
|
+
else if (typeof args[0] === "string") time = parseDate(args[0], options.budget);
|
|
25027
|
+
else time = dateNumber(args[0]);
|
|
25028
|
+
options.budget.chargeDataUsage(9);
|
|
25029
|
+
return createSandboxDate(time);
|
|
25030
|
+
},
|
|
25031
|
+
properties: {
|
|
25032
|
+
now,
|
|
25033
|
+
prototype,
|
|
25034
|
+
parse: createSandboxClosure({
|
|
25035
|
+
sandbox: true,
|
|
25036
|
+
name: "parse",
|
|
25037
|
+
length: 1,
|
|
25038
|
+
call: ([value]) => parseDate(value, options.budget)
|
|
25039
|
+
}),
|
|
25040
|
+
UTC: createSandboxClosure({
|
|
25041
|
+
sandbox: true,
|
|
25042
|
+
name: "UTC",
|
|
25043
|
+
length: 7,
|
|
25044
|
+
call: (args) => dateFromParts(args, true)
|
|
25045
|
+
})
|
|
25046
|
+
}
|
|
25047
|
+
});
|
|
25048
|
+
const methods = /* @__PURE__ */ new Map();
|
|
25049
|
+
for (const [name, method] of dateMethods)
|
|
25050
|
+
methods.set(
|
|
25051
|
+
name,
|
|
25052
|
+
createSandboxClosure({
|
|
25053
|
+
sandbox: true,
|
|
25054
|
+
name,
|
|
25055
|
+
length: method.length,
|
|
25056
|
+
call: (args, context) => {
|
|
25057
|
+
const receiver = context?.thisValue;
|
|
25058
|
+
if (!isSandboxDate(receiver))
|
|
25059
|
+
throw new TypeError(`Date#${name} requires a Date receiver.`);
|
|
25060
|
+
options.budget.visitNode();
|
|
25061
|
+
const value = method.invoke(receiver, args);
|
|
25062
|
+
return typeof value === "string" ? options.budget.allocateString(value) : value;
|
|
25063
|
+
}
|
|
25064
|
+
})
|
|
25065
|
+
);
|
|
25066
|
+
constructors2.add(constructor);
|
|
25067
|
+
intrinsics.set(options.compileOwner ?? options.budget, { constructor, prototype, methods });
|
|
25068
|
+
return constructor;
|
|
25069
|
+
}
|
|
25070
|
+
function isDateConstructor(value) {
|
|
25071
|
+
return typeof value === "object" && value !== null && constructors2.has(value);
|
|
25072
|
+
}
|
|
25073
|
+
function getDateMember(property, budget, owner) {
|
|
25074
|
+
const state = intrinsics.get(owner ?? budget);
|
|
25075
|
+
return property === "constructor" ? state?.constructor : state?.methods.get(String(property));
|
|
25076
|
+
}
|
|
25077
|
+
function getDatePrototype(value, budget, owner) {
|
|
25078
|
+
const prototype = intrinsics.get(owner ?? budget)?.prototype;
|
|
25079
|
+
return prototype === value ? null : prototype ?? null;
|
|
25080
|
+
}
|
|
25081
|
+
|
|
24712
25082
|
// packages/safe-js/src/interp/scope.ts
|
|
24713
25083
|
var uninitialized = /* @__PURE__ */ Symbol("uninitialized");
|
|
24714
25084
|
var Scope = class _Scope {
|
|
@@ -25003,9 +25373,10 @@ async function interpret(node, options = {}) {
|
|
|
25003
25373
|
peakDataSize: { enumerable: false, value: 0, writable: true }
|
|
25004
25374
|
});
|
|
25005
25375
|
const activeLoopIterations = /* @__PURE__ */ new Map();
|
|
25006
|
-
const jobs = new SandboxJobQueue();
|
|
25376
|
+
const jobs = options.jobs ?? new SandboxJobQueue();
|
|
25007
25377
|
hoistVarDeclarations(node, scope);
|
|
25008
25378
|
const context = {
|
|
25379
|
+
assertActive: options.assertActive,
|
|
25009
25380
|
compilation,
|
|
25010
25381
|
budget,
|
|
25011
25382
|
callStack: [],
|
|
@@ -25028,9 +25399,9 @@ async function interpret(node, options = {}) {
|
|
|
25028
25399
|
};
|
|
25029
25400
|
const evaluation = await withCancellationSignal(
|
|
25030
25401
|
options.signal,
|
|
25031
|
-
() => jobs.run(() => evaluateNode(node, context))
|
|
25402
|
+
() => options.nested ? runAsyncPrefix(() => evaluateNode(node, context)) : jobs.run(() => evaluateNode(node, context))
|
|
25032
25403
|
);
|
|
25033
|
-
await jobs.drain();
|
|
25404
|
+
if (!options.nested) await jobs.drain();
|
|
25034
25405
|
const snapshot = scope.snapshot();
|
|
25035
25406
|
reconcileDataBudget(
|
|
25036
25407
|
budget,
|
|
@@ -25085,6 +25456,7 @@ async function interpret(node, options = {}) {
|
|
|
25085
25456
|
}
|
|
25086
25457
|
}
|
|
25087
25458
|
async function evaluateNode(node, context) {
|
|
25459
|
+
context.assertActive?.();
|
|
25088
25460
|
const replayWait = promiseReplayContext.getStore()?.beforeNode(node.nodeId);
|
|
25089
25461
|
if (replayWait !== void 0) await suspendJob(replayWait);
|
|
25090
25462
|
assertPromiseExecutionAllowed();
|
|
@@ -26056,6 +26428,7 @@ function forInObject(value) {
|
|
|
26056
26428
|
return void 0;
|
|
26057
26429
|
}
|
|
26058
26430
|
function forInKeys(object, budget) {
|
|
26431
|
+
if (isGuestHostObject(object)) return getHostObjectKeys(object);
|
|
26059
26432
|
const keys = [];
|
|
26060
26433
|
const seen = /* @__PURE__ */ new Set();
|
|
26061
26434
|
let depth = 0;
|
|
@@ -26073,6 +26446,7 @@ function forInKeys(object, budget) {
|
|
|
26073
26446
|
return keys;
|
|
26074
26447
|
}
|
|
26075
26448
|
function hasForInProperty(object, key, budget) {
|
|
26449
|
+
if (isGuestHostObject(object)) return getHostObjectKeys(object).includes(key);
|
|
26076
26450
|
let depth = 0;
|
|
26077
26451
|
for (let current = object; current !== null; current = getSandboxPrototype(current)) {
|
|
26078
26452
|
if (depth > 0) budget.visitNode();
|
|
@@ -26564,10 +26938,12 @@ async function evaluateMemberExpression(node, context) {
|
|
|
26564
26938
|
};
|
|
26565
26939
|
}
|
|
26566
26940
|
function getPropertyValue(target, property, context) {
|
|
26941
|
+
if (isGuestHostObject(target)) return getHostObjectMember(target, String(property));
|
|
26567
26942
|
if (typeof target === "string") return getStringMember(target, property, context.budget);
|
|
26568
26943
|
if (typeof target === "number") return getNumberMember(target, property, context.budget);
|
|
26569
26944
|
if (typeof target === "boolean") return void 0;
|
|
26570
26945
|
if (isFloat32Array(target)) return getFloat32Member(target, property, context.budget);
|
|
26946
|
+
if (isSandboxDate(target)) return getDateMember(property, context.budget, context.compilation?.owner);
|
|
26571
26947
|
if (isSandboxMap(target)) return getMapMember(target, property, createMapMethodOptions(context));
|
|
26572
26948
|
if (isSandboxSet(target)) return getSetMember(target, property, createSetMethodOptions(context));
|
|
26573
26949
|
if (isSandboxGenerator(target)) return getGeneratorMember(target, property, context.budget);
|
|
@@ -26804,6 +27180,9 @@ async function evaluateMemberCallExpression(node, context) {
|
|
|
26804
27180
|
context
|
|
26805
27181
|
);
|
|
26806
27182
|
}
|
|
27183
|
+
if (isSandboxDate(member.object)) {
|
|
27184
|
+
return evaluateResolvedCallExpression(node, getDateMember(member.property, context.budget, context.compilation?.owner), context, member.object);
|
|
27185
|
+
}
|
|
26807
27186
|
if (isFloat32Array(member.object)) {
|
|
26808
27187
|
return evaluateResolvedCallExpression(
|
|
26809
27188
|
node,
|
|
@@ -27056,6 +27435,7 @@ function applyBinaryOperator(node, left, right, context) {
|
|
|
27056
27435
|
return true;
|
|
27057
27436
|
}
|
|
27058
27437
|
if (isFloat32ArrayConstructor(right)) return isFloat32Array(left);
|
|
27438
|
+
if (isDateConstructor(right)) return isSandboxDate(left) && getDatePrototype(left, context.budget, context.compilation?.owner) !== null;
|
|
27059
27439
|
if (isSandboxSetConstructor(right) && isSandboxSet(left)) {
|
|
27060
27440
|
return true;
|
|
27061
27441
|
}
|
|
@@ -27119,8 +27499,8 @@ function applyAdditionOperator(left, right, context) {
|
|
|
27119
27499
|
return toNumber(leftPrimitive) + toNumber(rightPrimitive);
|
|
27120
27500
|
}
|
|
27121
27501
|
function compareRelational(left, right, operator) {
|
|
27122
|
-
const leftPrimitive = toPrimitive(left);
|
|
27123
|
-
const rightPrimitive = toPrimitive(right);
|
|
27502
|
+
const leftPrimitive = isSandboxDate(left) ? dateTime(left) : toPrimitive(left);
|
|
27503
|
+
const rightPrimitive = isSandboxDate(right) ? dateTime(right) : toPrimitive(right);
|
|
27124
27504
|
if (typeof leftPrimitive === "string" && typeof rightPrimitive === "string") {
|
|
27125
27505
|
switch (operator) {
|
|
27126
27506
|
case "<":
|
|
@@ -27203,6 +27583,7 @@ function toPrimitive(value) {
|
|
|
27203
27583
|
return toString(value);
|
|
27204
27584
|
}
|
|
27205
27585
|
async function toNumericPrimitive(value, context) {
|
|
27586
|
+
if (isSandboxDate(value)) return dateTime(value);
|
|
27206
27587
|
if (isPrimitiveCoercionType(getCoercionType(value))) {
|
|
27207
27588
|
return value;
|
|
27208
27589
|
}
|
|
@@ -27232,6 +27613,7 @@ async function toNumericPrimitive(value, context) {
|
|
|
27232
27613
|
return toString(value);
|
|
27233
27614
|
}
|
|
27234
27615
|
function toNumber(value) {
|
|
27616
|
+
if (isSandboxDate(value)) return dateTime(value);
|
|
27235
27617
|
if (typeof value === "number") {
|
|
27236
27618
|
return value;
|
|
27237
27619
|
}
|
|
@@ -27250,6 +27632,7 @@ function toNumber(value) {
|
|
|
27250
27632
|
return toNumber(toPrimitive(value));
|
|
27251
27633
|
}
|
|
27252
27634
|
function toString(value) {
|
|
27635
|
+
if (isSandboxDate(value)) return dateString(value);
|
|
27253
27636
|
if (Array.isArray(value)) {
|
|
27254
27637
|
return value.map((entry) => entry === null || entry === void 0 ? "" : toString(entry)).join(",");
|
|
27255
27638
|
}
|
|
@@ -27270,6 +27653,7 @@ function isPlainSandboxObject(value) {
|
|
|
27270
27653
|
return typeof value === "object" && value !== null && !Array.isArray(value) && !isSandboxClosure(value) && !isSandboxMap(value) && !isSandboxSet(value) && !isSandboxPromise(value) && !isSandboxRegex(value);
|
|
27271
27654
|
}
|
|
27272
27655
|
function getMemberValue(target, property, context) {
|
|
27656
|
+
if (isGuestHostObject(target)) return getHostObjectMember(target, String(property));
|
|
27273
27657
|
let current = target;
|
|
27274
27658
|
let depth = 0;
|
|
27275
27659
|
while (typeof current === "object" && current !== null) {
|
|
@@ -27294,6 +27678,11 @@ function getArrayMemberValue(target, property, context) {
|
|
|
27294
27678
|
return getArrayMember(target, property, createArrayMethodOptions(context));
|
|
27295
27679
|
}
|
|
27296
27680
|
function setSandboxProperty(target, property, value, budget) {
|
|
27681
|
+
if (isSandboxDate(target)) throw new TypeError("Date own properties are not supported.");
|
|
27682
|
+
if (isGuestHostObject(target)) {
|
|
27683
|
+
setHostObjectMember(target, String(property), value);
|
|
27684
|
+
return;
|
|
27685
|
+
}
|
|
27297
27686
|
const prototypeOwner = target;
|
|
27298
27687
|
if (isGuestClosure(target)) target = materializeFunctionProperties(target);
|
|
27299
27688
|
if (isFloat32Array(target)) {
|
|
@@ -27338,6 +27727,7 @@ function setSandboxProperty(target, property, value, budget) {
|
|
|
27338
27727
|
}
|
|
27339
27728
|
}
|
|
27340
27729
|
function deleteSandboxProperty(target, property) {
|
|
27730
|
+
if (isGuestHostObject(target)) throw new TypeError("Live host properties cannot be deleted.");
|
|
27341
27731
|
if (isGuestClosure(target)) target = materializeFunctionProperties(target);
|
|
27342
27732
|
if (Array.isArray(target)) {
|
|
27343
27733
|
assertCollectionMutable(target);
|
|
@@ -27903,7 +28293,7 @@ function wrapCallerInjectedBindings(bindings, options) {
|
|
|
27903
28293
|
const copied = Object.fromEntries(
|
|
27904
28294
|
Object.entries(bindings).map(([name, value]) => [
|
|
27905
28295
|
name,
|
|
27906
|
-
typeof value === "function" ? wrapCallerInjectedFunction(name, value, { ...options, capabilityPath: [name] }, state) : copyHostValueToSandbox(
|
|
28296
|
+
typeof value === "function" && !isLiveCapability(value) ? wrapCallerInjectedFunction(name, value, { ...options, capabilityPath: [name] }, state) : copyHostValueToSandbox(
|
|
27907
28297
|
value,
|
|
27908
28298
|
[],
|
|
27909
28299
|
{ ...options, operation: name, capabilityPath: [name] },
|
|
@@ -27924,9 +28314,10 @@ function wrapCallerInjectedFunction(name, value, options, state) {
|
|
|
27924
28314
|
const bindingName = name === "default" && value.name.length > 0 ? value.name : name;
|
|
27925
28315
|
const callable = value;
|
|
27926
28316
|
return createSandboxClosure({
|
|
27927
|
-
...isAsyncFunction(callable) ? { async: true } : {},
|
|
28317
|
+
...isAsyncFunction(callable) && !options.realm?.awaitResult(callable) ? { async: true } : {},
|
|
27928
28318
|
cancellationSignal: options.signal,
|
|
27929
28319
|
call: (args, context) => {
|
|
28320
|
+
options.realm?.assertActive();
|
|
27930
28321
|
const operationLease = options.budget.acquireCompileOwner(false, options.compileOwner);
|
|
27931
28322
|
const compilation = new CompileScope(operationLease.owner);
|
|
27932
28323
|
try {
|
|
@@ -27942,9 +28333,10 @@ function wrapCallerInjectedFunction(name, value, options, state) {
|
|
|
27942
28333
|
seen: /* @__PURE__ */ new WeakMap(),
|
|
27943
28334
|
restored: []
|
|
27944
28335
|
};
|
|
27945
|
-
const
|
|
28336
|
+
const copyArguments = (values) => deepCopyFromSandbox([...values], {
|
|
27946
28337
|
compilation,
|
|
27947
|
-
|
|
28338
|
+
unwrapHostObject: options.realm === void 0 ? void 0 : (object) => exportHostCapability(object, options.realm.owner),
|
|
28339
|
+
wrapClosure: (closure) => options.realm?.wrapCallback(closure) ?? wrapSandboxClosureForHost(
|
|
27948
28340
|
closure,
|
|
27949
28341
|
stackFrames,
|
|
27950
28342
|
options.budget,
|
|
@@ -27952,11 +28344,26 @@ function wrapCallerInjectedFunction(name, value, options, state) {
|
|
|
27952
28344
|
callbacks
|
|
27953
28345
|
)
|
|
27954
28346
|
});
|
|
28347
|
+
const captured = options.realm?.captureArguments(callable, args, copyArguments);
|
|
28348
|
+
const hostArgs = captured?.args ?? copyArguments(args);
|
|
27955
28349
|
const hostCalls = options.hostCalls;
|
|
27956
28350
|
const operation = options.operation ?? bindingName;
|
|
27957
28351
|
const moduleId = options.moduleId ?? "<bindings>";
|
|
27958
28352
|
const policy = readHostOperationPolicy(value) ?? readRegisteredPendingHostCallPolicy(moduleId, operation) ?? "re-issue";
|
|
27959
28353
|
if (hostCalls === void 0) {
|
|
28354
|
+
if (options.realm !== void 0) {
|
|
28355
|
+
let result;
|
|
28356
|
+
try {
|
|
28357
|
+
result = options.realm.invoke(callable, () => Reflect.apply(callable, void 0, hostArgs));
|
|
28358
|
+
} catch (error) {
|
|
28359
|
+
captured.rollback();
|
|
28360
|
+
throw error;
|
|
28361
|
+
}
|
|
28362
|
+
if (options.realm.awaitResult(callable)) {
|
|
28363
|
+
return Promise.resolve(result).then((value2) => copyHostResultToSandbox(value2, stackFrames, options));
|
|
28364
|
+
}
|
|
28365
|
+
return copyHostResultToSandbox(result, stackFrames, options);
|
|
28366
|
+
}
|
|
27960
28367
|
return copyHostResultToSandbox(
|
|
27961
28368
|
invokeHostCallback(() => Reflect.apply(callable, void 0, hostArgs), options),
|
|
27962
28369
|
stackFrames,
|
|
@@ -28494,6 +28901,10 @@ function wrapHostPromiseWithSignal(promise, signal) {
|
|
|
28494
28901
|
}
|
|
28495
28902
|
function copyHostValueToSandbox(value, stackFrames, options, state, path) {
|
|
28496
28903
|
const { budget } = options;
|
|
28904
|
+
if (isLiveCapability(value)) {
|
|
28905
|
+
if (options.realm === void 0 || options.errorData || options.hostCalls !== void 0) throw new TypeError("Live capabilities are not portable replay or error data.");
|
|
28906
|
+
return importHostCapability(value, options.realm.owner);
|
|
28907
|
+
}
|
|
28497
28908
|
if (value === null || value === void 0 || typeof value === "number" || typeof value === "boolean") {
|
|
28498
28909
|
return value;
|
|
28499
28910
|
}
|
|
@@ -28535,6 +28946,14 @@ function copyHostValueToSandbox(value, stackFrames, options, state, path) {
|
|
|
28535
28946
|
state
|
|
28536
28947
|
);
|
|
28537
28948
|
}
|
|
28949
|
+
const date = copyNativeDate(value);
|
|
28950
|
+
if (date !== void 0) {
|
|
28951
|
+
const existing = state.seen.get(value);
|
|
28952
|
+
if (existing !== void 0) return existing;
|
|
28953
|
+
budget.chargeDataUsage(9);
|
|
28954
|
+
state.seen.set(value, date);
|
|
28955
|
+
return date;
|
|
28956
|
+
}
|
|
28538
28957
|
if (isFloat32Array(value)) {
|
|
28539
28958
|
const existing = state.seen.get(value);
|
|
28540
28959
|
if (existing !== void 0) return existing;
|
|
@@ -28812,386 +29231,131 @@ function describeValue2(value) {
|
|
|
28812
29231
|
return typeof value;
|
|
28813
29232
|
}
|
|
28814
29233
|
|
|
28815
|
-
// packages/safe-js/src/
|
|
28816
|
-
|
|
28817
|
-
|
|
28818
|
-
|
|
28819
|
-
|
|
28820
|
-
|
|
28821
|
-
|
|
28822
|
-
|
|
28823
|
-
|
|
28824
|
-
|
|
28825
|
-
|
|
28826
|
-
|
|
28827
|
-
|
|
28828
|
-
|
|
28829
|
-
|
|
28830
|
-
|
|
28831
|
-
|
|
28832
|
-
|
|
28833
|
-
|
|
28834
|
-
|
|
28835
|
-
|
|
28836
|
-
|
|
28837
|
-
|
|
28838
|
-
|
|
28839
|
-
|
|
28840
|
-
|
|
28841
|
-
|
|
28842
|
-
|
|
28843
|
-
|
|
28844
|
-
|
|
28845
|
-
|
|
28846
|
-
|
|
28847
|
-
|
|
28848
|
-
|
|
28849
|
-
|
|
28850
|
-
|
|
28851
|
-
|
|
28852
|
-
|
|
28853
|
-
|
|
28854
|
-
|
|
28855
|
-
|
|
28856
|
-
|
|
28857
|
-
|
|
28858
|
-
|
|
28859
|
-
|
|
28860
|
-
settlePendingSnapshot(createSnapshot());
|
|
28861
|
-
},
|
|
28862
|
-
requestCurrentSnapshot(options = {}) {
|
|
28863
|
-
assertDumpAllowed(options);
|
|
28864
|
-
if (failed !== void 0) {
|
|
28865
|
-
return Promise.reject(failed.error);
|
|
28866
|
-
}
|
|
28867
|
-
if (latestSnapshot !== void 0 || latestSnapshotFactory !== void 0) {
|
|
28868
|
-
try {
|
|
28869
|
-
return Promise.resolve(serializeRunSnapshot(latestSnapshot ?? latestSnapshotFactory()));
|
|
28870
|
-
} catch (error) {
|
|
28871
|
-
return Promise.reject(error);
|
|
28872
|
-
}
|
|
28873
|
-
}
|
|
28874
|
-
return this.requestSnapshot(options);
|
|
28875
|
-
},
|
|
28876
|
-
requestSnapshot(options = {}) {
|
|
28877
|
-
assertDumpAllowed(options);
|
|
28878
|
-
if (failed !== void 0) {
|
|
28879
|
-
if ((options.onFailure === "checkpoint" || options.onFailure === void 0 && isDataBudgetError(failed.error)) && finalSnapshot !== void 0) {
|
|
28880
|
-
try {
|
|
28881
|
-
return Promise.resolve(serializeRunSnapshot(finalSnapshot));
|
|
28882
|
-
} catch (error) {
|
|
28883
|
-
return Promise.reject(error);
|
|
28884
|
-
}
|
|
28885
|
-
}
|
|
28886
|
-
return Promise.reject(failed.error);
|
|
28887
|
-
}
|
|
28888
|
-
if (finished) {
|
|
28889
|
-
if (finalSnapshot === void 0) {
|
|
28890
|
-
throw new Error("Run completed without producing a snapshot.");
|
|
28891
|
-
}
|
|
28892
|
-
try {
|
|
28893
|
-
const serializedSnapshot = serializeRunSnapshot(finalSnapshot);
|
|
28894
|
-
return Promise.resolve(serializedSnapshot);
|
|
28895
|
-
} catch (error) {
|
|
28896
|
-
return Promise.reject(error);
|
|
28897
|
-
}
|
|
28898
|
-
}
|
|
28899
|
-
if (options.mode === "replay" && (latestSnapshot !== void 0 || latestSnapshotFactory !== void 0)) {
|
|
28900
|
-
return this.requestCurrentSnapshot(options);
|
|
28901
|
-
}
|
|
28902
|
-
if (pendingRequest !== void 0) {
|
|
28903
|
-
return pendingRequest.promise;
|
|
28904
|
-
}
|
|
28905
|
-
let resolveSnapshot = () => void 0;
|
|
28906
|
-
let rejectSnapshot = () => void 0;
|
|
28907
|
-
const promise = new Promise((resolve, reject) => {
|
|
28908
|
-
resolveSnapshot = resolve;
|
|
28909
|
-
rejectSnapshot = reject;
|
|
28910
|
-
});
|
|
28911
|
-
pendingRequest = {
|
|
28912
|
-
promise,
|
|
28913
|
-
reject: rejectSnapshot,
|
|
28914
|
-
resolve: resolveSnapshot
|
|
28915
|
-
};
|
|
28916
|
-
return promise;
|
|
28917
|
-
}
|
|
28918
|
-
};
|
|
28919
|
-
function assertDumpAllowed(options) {
|
|
28920
|
-
if ((lifecycle?.hostCallbackDepth ?? 0) > 0 && (options.mode !== "replay" || lifecycle?.hostCallbackContext.getStore() === true)) {
|
|
28921
|
-
throw new SandboxError("reentry");
|
|
28922
|
-
}
|
|
28923
|
-
}
|
|
28924
|
-
function settlePendingSnapshot(snapshot) {
|
|
28925
|
-
try {
|
|
28926
|
-
settlePendingRequest(serializeRunSnapshot(snapshot));
|
|
28927
|
-
} catch (error) {
|
|
28928
|
-
pendingRequest?.reject(error);
|
|
28929
|
-
pendingRequest = void 0;
|
|
28930
|
-
}
|
|
28931
|
-
}
|
|
28932
|
-
function settlePendingRequest(snapshot) {
|
|
28933
|
-
if (pendingRequest === void 0) {
|
|
28934
|
-
return;
|
|
28935
|
-
}
|
|
28936
|
-
pendingRequest.resolve(snapshot);
|
|
28937
|
-
pendingRequest = void 0;
|
|
29234
|
+
// packages/safe-js/src/random.ts
|
|
29235
|
+
import { randomInt } from "node:crypto";
|
|
29236
|
+
|
|
29237
|
+
// packages/safe-js/src/interp/globals/math.ts
|
|
29238
|
+
var mathMethods = {
|
|
29239
|
+
abs: Math.abs,
|
|
29240
|
+
acos: Math.acos,
|
|
29241
|
+
acosh: Math.acosh,
|
|
29242
|
+
asin: Math.asin,
|
|
29243
|
+
asinh: Math.asinh,
|
|
29244
|
+
atan: Math.atan,
|
|
29245
|
+
atan2: Math.atan2,
|
|
29246
|
+
atanh: Math.atanh,
|
|
29247
|
+
ceil: Math.ceil,
|
|
29248
|
+
cbrt: Math.cbrt,
|
|
29249
|
+
clz32: Math.clz32,
|
|
29250
|
+
cos: Math.cos,
|
|
29251
|
+
cosh: Math.cosh,
|
|
29252
|
+
exp: Math.exp,
|
|
29253
|
+
expm1: Math.expm1,
|
|
29254
|
+
floor: Math.floor,
|
|
29255
|
+
f16round,
|
|
29256
|
+
fround: Math.fround,
|
|
29257
|
+
hypot: Math.hypot,
|
|
29258
|
+
imul: Math.imul,
|
|
29259
|
+
log: Math.log,
|
|
29260
|
+
log1p: Math.log1p,
|
|
29261
|
+
log10: Math.log10,
|
|
29262
|
+
log2: Math.log2,
|
|
29263
|
+
max: Math.max,
|
|
29264
|
+
min: Math.min,
|
|
29265
|
+
pow: Math.pow,
|
|
29266
|
+
round: Math.round,
|
|
29267
|
+
sign: Math.sign,
|
|
29268
|
+
sin: Math.sin,
|
|
29269
|
+
sinh: Math.sinh,
|
|
29270
|
+
sqrt: Math.sqrt,
|
|
29271
|
+
tan: Math.tan,
|
|
29272
|
+
tanh: Math.tanh,
|
|
29273
|
+
trunc: Math.trunc
|
|
29274
|
+
};
|
|
29275
|
+
function f16round(value) {
|
|
29276
|
+
const number = +value;
|
|
29277
|
+
if (!Number.isFinite(number) || number === 0) {
|
|
29278
|
+
return number;
|
|
28938
29279
|
}
|
|
28939
|
-
|
|
28940
|
-
|
|
28941
|
-
|
|
28942
|
-
}
|
|
28943
|
-
function dump(result, options = {}) {
|
|
28944
|
-
const controller = readDumpController(result);
|
|
28945
|
-
if (controller !== void 0) {
|
|
28946
|
-
return controller.requestSnapshot(options);
|
|
29280
|
+
const magnitude = Math.abs(number);
|
|
29281
|
+
if (magnitude >= 65520) {
|
|
29282
|
+
return number < 0 ? -Infinity : Infinity;
|
|
28947
29283
|
}
|
|
28948
|
-
|
|
28949
|
-
|
|
28950
|
-
|
|
28951
|
-
|
|
28952
|
-
|
|
28953
|
-
}
|
|
29284
|
+
let quantum = 2 ** -24;
|
|
29285
|
+
let boundary = 2 ** -13;
|
|
29286
|
+
for (let exponent = -13; exponent <= 15 && magnitude >= boundary; exponent += 1) {
|
|
29287
|
+
quantum *= 2;
|
|
29288
|
+
boundary *= 2;
|
|
28954
29289
|
}
|
|
28955
|
-
|
|
28956
|
-
|
|
28957
|
-
|
|
28958
|
-
|
|
28959
|
-
|
|
28960
|
-
});
|
|
29290
|
+
const scaled = magnitude / quantum;
|
|
29291
|
+
const lower = Math.floor(scaled);
|
|
29292
|
+
const remainder = scaled - lower;
|
|
29293
|
+
const rounded = (remainder > 0.5 || remainder === 0.5 && lower % 2 !== 0 ? lower + 1 : lower) * quantum;
|
|
29294
|
+
return number < 0 ? -rounded : rounded;
|
|
28961
29295
|
}
|
|
28962
|
-
function
|
|
28963
|
-
const
|
|
28964
|
-
|
|
28965
|
-
|
|
29296
|
+
function createMathGlobals(options = {}) {
|
|
29297
|
+
const random = options.random ?? Math.random;
|
|
29298
|
+
const mathObject = {
|
|
29299
|
+
E: Math.E,
|
|
29300
|
+
LN2: Math.LN2,
|
|
29301
|
+
LN10: Math.LN10,
|
|
29302
|
+
LOG2E: Math.LOG2E,
|
|
29303
|
+
LOG10E: Math.LOG10E,
|
|
29304
|
+
PI: Math.PI,
|
|
29305
|
+
SQRT1_2: Math.SQRT1_2,
|
|
29306
|
+
SQRT2: Math.SQRT2,
|
|
29307
|
+
random: createSandboxClosure({ sandbox: true, call: () => random(), name: "random" })
|
|
29308
|
+
};
|
|
29309
|
+
for (const [name, method] of Object.entries(mathMethods)) {
|
|
29310
|
+
mathObject[name] = createSandboxClosure({
|
|
29311
|
+
sandbox: true,
|
|
29312
|
+
call: (args) => Reflect.apply(method, Math, args),
|
|
29313
|
+
name
|
|
29314
|
+
});
|
|
28966
29315
|
}
|
|
28967
|
-
return
|
|
28968
|
-
|
|
28969
|
-
|
|
28970
|
-
|
|
29316
|
+
return {
|
|
29317
|
+
Infinity: Infinity,
|
|
29318
|
+
Math: mathObject,
|
|
29319
|
+
NaN: Number.NaN
|
|
29320
|
+
};
|
|
28971
29321
|
}
|
|
28972
|
-
function
|
|
28973
|
-
|
|
29322
|
+
function createSeededRandom(seed) {
|
|
29323
|
+
let state = normalizeSeed(seed);
|
|
29324
|
+
return {
|
|
29325
|
+
next: () => {
|
|
29326
|
+
state = Math.imul(state, 1664525) + 1013904223 >>> 0;
|
|
29327
|
+
return state / 4294967296;
|
|
29328
|
+
},
|
|
29329
|
+
snapshot: () => state,
|
|
29330
|
+
restore: (nextState) => {
|
|
29331
|
+
state = normalizeSeed(nextState);
|
|
29332
|
+
}
|
|
29333
|
+
};
|
|
28974
29334
|
}
|
|
28975
|
-
function
|
|
28976
|
-
if (
|
|
28977
|
-
|
|
29335
|
+
function normalizeSeed(seed) {
|
|
29336
|
+
if (!Number.isFinite(seed)) {
|
|
29337
|
+
throw new TypeError("Seeded random requires a finite numeric seed.");
|
|
28978
29338
|
}
|
|
28979
|
-
return
|
|
29339
|
+
return Math.trunc(seed) >>> 0;
|
|
28980
29340
|
}
|
|
28981
29341
|
|
|
28982
|
-
// packages/safe-js/src/
|
|
28983
|
-
function
|
|
28984
|
-
|
|
28985
|
-
|
|
29342
|
+
// packages/safe-js/src/random.ts
|
|
29343
|
+
function createReplayableRandom(options = {}) {
|
|
29344
|
+
const snapshot = options.snapshot;
|
|
29345
|
+
const saved = snapshot?.random;
|
|
29346
|
+
let initialState = options.seed;
|
|
29347
|
+
if (saved !== void 0) {
|
|
29348
|
+
const hasLoopState = typeof snapshot?.loopIterations === "object" && snapshot.loopIterations !== null && Object.keys(snapshot.loopIterations).length > 0;
|
|
29349
|
+
const replaysFromStart = snapshot?.replay !== void 0 || Array.isArray(snapshot?.pendingAwaits) && snapshot.pendingAwaits.length > 0 && !hasLoopState;
|
|
29350
|
+
initialState = replaysFromStart ? saved.initialState ?? saved.seed : saved.resumeState ?? saved.state;
|
|
28986
29351
|
}
|
|
28987
|
-
const
|
|
28988
|
-
return
|
|
28989
|
-
}
|
|
28990
|
-
function hasOwnErrorCode(error, code) {
|
|
28991
|
-
return getOwnErrorCode(error) === code;
|
|
29352
|
+
const generator = createSeededRandom(initialState ?? randomInt(4294967296));
|
|
29353
|
+
return { seed: saved?.seed ?? generator.snapshot(), ...generator };
|
|
28992
29354
|
}
|
|
28993
29355
|
|
|
28994
|
-
// packages/safe-js/src/
|
|
28995
|
-
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
28996
|
-
import { readFile, rename, stat, unlink, writeFile } from "node:fs/promises";
|
|
28997
|
-
import { dirname } from "node:path";
|
|
28998
|
-
var DEFAULT_WRITE_MAX_ATTEMPTS = 3;
|
|
28999
|
-
var DEFAULT_WRITE_RETRY_DELAY_MS = 100;
|
|
29000
|
-
var LOCKED_FILE_ERROR_CODES = /* @__PURE__ */ new Set(["EACCES", "EBUSY", "EPERM"]);
|
|
29001
|
-
var pendingOperations = /* @__PURE__ */ new Map();
|
|
29002
|
-
var FileSnapshotBackend = class {
|
|
29003
|
-
constructor(path, options = {}) {
|
|
29004
|
-
this.path = path;
|
|
29005
|
-
this.#writeMaxAttempts = options.writeMaxAttempts ?? DEFAULT_WRITE_MAX_ATTEMPTS;
|
|
29006
|
-
this.#writeRetryDelayMs = options.writeRetryDelayMs ?? DEFAULT_WRITE_RETRY_DELAY_MS;
|
|
29007
|
-
}
|
|
29008
|
-
path;
|
|
29009
|
-
#writeMaxAttempts;
|
|
29010
|
-
#writeRetryDelayMs;
|
|
29011
|
-
async read() {
|
|
29012
|
-
try {
|
|
29013
|
-
return JSON.parse(await readFile(this.path, "utf8"));
|
|
29014
|
-
} catch (error) {
|
|
29015
|
-
if (hasErrorCode(error, "ENOENT")) {
|
|
29016
|
-
return void 0;
|
|
29017
|
-
}
|
|
29018
|
-
if (error instanceof SyntaxError) {
|
|
29019
|
-
throw new Error(`Failed to parse snapshot at ${this.path}: ${error.message}`);
|
|
29020
|
-
}
|
|
29021
|
-
throw error;
|
|
29022
|
-
}
|
|
29023
|
-
}
|
|
29024
|
-
async write(snapshot) {
|
|
29025
|
-
await enqueueOperation(
|
|
29026
|
-
this.path,
|
|
29027
|
-
() => writeSnapshotAtomically(this.path, snapshot, {
|
|
29028
|
-
maxAttempts: this.#writeMaxAttempts,
|
|
29029
|
-
retryDelayMs: this.#writeRetryDelayMs
|
|
29030
|
-
})
|
|
29031
|
-
);
|
|
29032
|
-
}
|
|
29033
|
-
async remove() {
|
|
29034
|
-
await enqueueOperation(this.path, async () => {
|
|
29035
|
-
try {
|
|
29036
|
-
await unlink(this.path);
|
|
29037
|
-
} catch (error) {
|
|
29038
|
-
if (!hasErrorCode(error, "ENOENT")) {
|
|
29039
|
-
throw error;
|
|
29040
|
-
}
|
|
29041
|
-
}
|
|
29042
|
-
});
|
|
29043
|
-
}
|
|
29044
|
-
};
|
|
29045
|
-
async function writeSnapshotAtomically(snapshotPath, snapshot, options) {
|
|
29046
|
-
const parentPath = dirname(snapshotPath);
|
|
29047
|
-
const contents = serializeSafeJSSnapshot(snapshot);
|
|
29048
|
-
await assertParentDirectoryExists(snapshotPath, parentPath);
|
|
29049
|
-
for (let attempt = 1; attempt <= options.maxAttempts; attempt += 1) {
|
|
29050
|
-
try {
|
|
29051
|
-
const temporaryPath = `${snapshotPath}.${randomUUID2()}.tmp`;
|
|
29052
|
-
await writeSnapshotOnce(temporaryPath, snapshotPath, contents);
|
|
29053
|
-
return;
|
|
29054
|
-
} catch (error) {
|
|
29055
|
-
if (hasErrorCode(error, "EEXIST")) {
|
|
29056
|
-
if (attempt === options.maxAttempts) {
|
|
29057
|
-
throw new Error(
|
|
29058
|
-
`Failed to write snapshot at ${snapshotPath} after ${options.maxAttempts} attempts: temporary path already exists`,
|
|
29059
|
-
{
|
|
29060
|
-
cause: error
|
|
29061
|
-
}
|
|
29062
|
-
);
|
|
29063
|
-
}
|
|
29064
|
-
continue;
|
|
29065
|
-
}
|
|
29066
|
-
if (!isLockedFileError(error)) {
|
|
29067
|
-
throw error;
|
|
29068
|
-
}
|
|
29069
|
-
if (attempt === options.maxAttempts) {
|
|
29070
|
-
throw new Error(
|
|
29071
|
-
`Failed to write snapshot at ${snapshotPath} after ${options.maxAttempts} attempts: file is locked (${getOwnErrorCode(error)})`,
|
|
29072
|
-
{
|
|
29073
|
-
cause: error
|
|
29074
|
-
}
|
|
29075
|
-
);
|
|
29076
|
-
}
|
|
29077
|
-
await delay(options.retryDelayMs);
|
|
29078
|
-
}
|
|
29079
|
-
}
|
|
29080
|
-
}
|
|
29081
|
-
async function assertParentDirectoryExists(snapshotPath, parentPath) {
|
|
29082
|
-
try {
|
|
29083
|
-
const parent = await stat(parentPath);
|
|
29084
|
-
if (!parent.isDirectory()) {
|
|
29085
|
-
throw new Error(
|
|
29086
|
-
`Cannot write snapshot at ${snapshotPath}: parent path ${parentPath} is not a directory`
|
|
29087
|
-
);
|
|
29088
|
-
}
|
|
29089
|
-
} catch (error) {
|
|
29090
|
-
if (hasErrorCode(error, "ENOENT")) {
|
|
29091
|
-
throw new Error(
|
|
29092
|
-
`Cannot write snapshot at ${snapshotPath}: parent directory ${parentPath} does not exist`,
|
|
29093
|
-
{
|
|
29094
|
-
cause: error
|
|
29095
|
-
}
|
|
29096
|
-
);
|
|
29097
|
-
}
|
|
29098
|
-
throw error;
|
|
29099
|
-
}
|
|
29100
|
-
}
|
|
29101
|
-
async function writeSnapshotOnce(temporaryPath, snapshotPath, contents) {
|
|
29102
|
-
let temporaryCreated = false;
|
|
29103
|
-
let renamed = false;
|
|
29104
|
-
try {
|
|
29105
|
-
try {
|
|
29106
|
-
await writeFile(temporaryPath, contents, { encoding: "utf8", flag: "wx" });
|
|
29107
|
-
temporaryCreated = true;
|
|
29108
|
-
} catch (error) {
|
|
29109
|
-
if (!hasErrorCode(error, "EEXIST")) {
|
|
29110
|
-
await removeTemporarySnapshot(temporaryPath).catch(() => void 0);
|
|
29111
|
-
}
|
|
29112
|
-
throw error;
|
|
29113
|
-
}
|
|
29114
|
-
await rename(temporaryPath, snapshotPath);
|
|
29115
|
-
renamed = true;
|
|
29116
|
-
} finally {
|
|
29117
|
-
if (temporaryCreated && !renamed) {
|
|
29118
|
-
await removeTemporarySnapshot(temporaryPath).catch(() => void 0);
|
|
29119
|
-
}
|
|
29120
|
-
}
|
|
29121
|
-
}
|
|
29122
|
-
async function enqueueOperation(path, operation) {
|
|
29123
|
-
const previous = pendingOperations.get(path) ?? Promise.resolve();
|
|
29124
|
-
const pending = previous.catch(() => void 0).then(operation);
|
|
29125
|
-
const queued = pending.catch(() => void 0);
|
|
29126
|
-
pendingOperations.set(path, queued);
|
|
29127
|
-
try {
|
|
29128
|
-
await pending;
|
|
29129
|
-
} finally {
|
|
29130
|
-
if (pendingOperations.get(path) === queued) {
|
|
29131
|
-
pendingOperations.delete(path);
|
|
29132
|
-
}
|
|
29133
|
-
}
|
|
29134
|
-
}
|
|
29135
|
-
async function removeTemporarySnapshot(temporaryPath) {
|
|
29136
|
-
try {
|
|
29137
|
-
await unlink(temporaryPath);
|
|
29138
|
-
} catch (error) {
|
|
29139
|
-
if (!hasErrorCode(error, "ENOENT")) {
|
|
29140
|
-
throw error;
|
|
29141
|
-
}
|
|
29142
|
-
}
|
|
29143
|
-
}
|
|
29144
|
-
async function delay(ms) {
|
|
29145
|
-
if (ms === 0) {
|
|
29146
|
-
return;
|
|
29147
|
-
}
|
|
29148
|
-
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
29149
|
-
}
|
|
29150
|
-
function hasErrorCode(error, code) {
|
|
29151
|
-
return hasOwnErrorCode(error, code);
|
|
29152
|
-
}
|
|
29153
|
-
function isLockedFileError(error) {
|
|
29154
|
-
const code = getOwnErrorCode(error);
|
|
29155
|
-
return code !== void 0 && LOCKED_FILE_ERROR_CODES.has(code);
|
|
29156
|
-
}
|
|
29157
|
-
|
|
29158
|
-
// packages/safe-js/src/run.ts
|
|
29356
|
+
// packages/safe-js/src/realm.ts
|
|
29159
29357
|
import { AsyncLocalStorage as AsyncLocalStorage6 } from "node:async_hooks";
|
|
29160
|
-
|
|
29161
|
-
// packages/safe-js/src/interp/resources.ts
|
|
29162
|
-
import { AsyncLocalStorage as AsyncLocalStorage5 } from "node:async_hooks";
|
|
29163
|
-
var runResources = new AsyncLocalStorage5();
|
|
29164
|
-
async function withRunResources(signal, execute) {
|
|
29165
|
-
const controller = new AbortController();
|
|
29166
|
-
const cancel = () => controller.abort(signal?.reason);
|
|
29167
|
-
const cleanups = /* @__PURE__ */ new Set();
|
|
29168
|
-
const resources = {
|
|
29169
|
-
signal: controller.signal,
|
|
29170
|
-
add(close) {
|
|
29171
|
-
cleanups.add(close);
|
|
29172
|
-
}
|
|
29173
|
-
};
|
|
29174
|
-
signal?.addEventListener("abort", cancel, { once: true });
|
|
29175
|
-
if (signal?.aborted) cancel();
|
|
29176
|
-
let result;
|
|
29177
|
-
let failure;
|
|
29178
|
-
let errors = [];
|
|
29179
|
-
try {
|
|
29180
|
-
result = await runResources.run(resources, execute);
|
|
29181
|
-
} catch (error) {
|
|
29182
|
-
failure = { reason: error };
|
|
29183
|
-
} finally {
|
|
29184
|
-
signal?.removeEventListener("abort", cancel);
|
|
29185
|
-
controller.abort(new Error("SafeJS run finished."));
|
|
29186
|
-
const outcomes = await Promise.allSettled(
|
|
29187
|
-
[...cleanups].map((close) => Promise.resolve().then(close))
|
|
29188
|
-
);
|
|
29189
|
-
errors = outcomes.flatMap((outcome) => outcome.status === "rejected" ? [outcome.reason] : []);
|
|
29190
|
-
}
|
|
29191
|
-
if (failure !== void 0) throw failure.reason;
|
|
29192
|
-
if (errors.length > 0) throw new AggregateError(errors, "SafeJS resource cleanup failed.");
|
|
29193
|
-
return result;
|
|
29194
|
-
}
|
|
29358
|
+
import { types as types4 } from "node:util";
|
|
29195
29359
|
|
|
29196
29360
|
// packages/safe-js/src/interp/globals/console-json.ts
|
|
29197
29361
|
function createConsoleJsonGlobals(options) {
|
|
@@ -29305,7 +29469,9 @@ function toJsonParseText(input) {
|
|
|
29305
29469
|
}
|
|
29306
29470
|
async function stringifyProperty(key, holder, state, indent = "") {
|
|
29307
29471
|
let value = getOwnDataValue(holder, key);
|
|
29308
|
-
if (
|
|
29472
|
+
if (isSandboxDate(value)) {
|
|
29473
|
+
value = dateMethods.get("toJSON").invoke(value, []);
|
|
29474
|
+
} else if (isStringifyContainer(value)) {
|
|
29309
29475
|
const toJSON = getOwnDataValue(value, "toJSON");
|
|
29310
29476
|
if (isSandboxClosure(toJSON)) {
|
|
29311
29477
|
value = await callStringifyClosure(toJSON, [key], value, state);
|
|
@@ -29617,6 +29783,7 @@ async function stringifyObject2(value, budget, context, joining) {
|
|
|
29617
29783
|
}
|
|
29618
29784
|
}
|
|
29619
29785
|
async function defaultToString(value, budget, context, joining) {
|
|
29786
|
+
if (isSandboxDate(value)) return budget.allocateString(dateString(value));
|
|
29620
29787
|
if (Array.isArray(value) || isFloat32Array(value)) {
|
|
29621
29788
|
if (Object.hasOwn(value, "join")) {
|
|
29622
29789
|
const join = ownDataValue(value, "join");
|
|
@@ -29720,6 +29887,7 @@ function createObjectArrayGlobals(options) {
|
|
|
29720
29887
|
getPrototypeOf: createSandboxClosure({
|
|
29721
29888
|
sandbox: true,
|
|
29722
29889
|
call: ([value]) => {
|
|
29890
|
+
if (isSandboxDate(value)) return getDatePrototype(value, options.budget, options.compileOwner);
|
|
29723
29891
|
objectProperties(value);
|
|
29724
29892
|
return getSandboxPrototype(value);
|
|
29725
29893
|
},
|
|
@@ -29844,7 +30012,7 @@ function createObjectArrayGlobals(options) {
|
|
|
29844
30012
|
}),
|
|
29845
30013
|
Number: createSandboxClosure({
|
|
29846
30014
|
sandbox: true,
|
|
29847
|
-
call: ([value]) => Number(value),
|
|
30015
|
+
call: ([value]) => isSandboxDate(value) ? dateTime(value) : Number(value),
|
|
29848
30016
|
name: "Number",
|
|
29849
30017
|
properties: {
|
|
29850
30018
|
isFinite: createSandboxClosure({
|
|
@@ -29886,295 +30054,1465 @@ function createObjectArrayGlobals(options) {
|
|
|
29886
30054
|
NEGATIVE_INFINITY: Number.NEGATIVE_INFINITY,
|
|
29887
30055
|
POSITIVE_INFINITY: Number.POSITIVE_INFINITY
|
|
29888
30056
|
}
|
|
29889
|
-
}),
|
|
29890
|
-
Boolean: createSandboxClosure({
|
|
29891
|
-
sandbox: true,
|
|
29892
|
-
call: ([value]) => Boolean(value),
|
|
29893
|
-
name: "Boolean"
|
|
29894
|
-
})
|
|
29895
|
-
};
|
|
29896
|
-
}
|
|
29897
|
-
async function objectFromSandboxEntries(iterator, budget) {
|
|
29898
|
-
const object = /* @__PURE__ */ Object.create(null);
|
|
29899
|
-
try {
|
|
29900
|
-
while (true) {
|
|
29901
|
-
const result = await iterator.next();
|
|
29902
|
-
if (typeof result !== "object" && typeof result !== "function" || result === null) {
|
|
29903
|
-
throw new TypeError("Iterator result must be an object.");
|
|
30057
|
+
}),
|
|
30058
|
+
Boolean: createSandboxClosure({
|
|
30059
|
+
sandbox: true,
|
|
30060
|
+
call: ([value]) => Boolean(value),
|
|
30061
|
+
name: "Boolean"
|
|
30062
|
+
})
|
|
30063
|
+
};
|
|
30064
|
+
}
|
|
30065
|
+
async function objectFromSandboxEntries(iterator, budget) {
|
|
30066
|
+
const object = /* @__PURE__ */ Object.create(null);
|
|
30067
|
+
try {
|
|
30068
|
+
while (true) {
|
|
30069
|
+
const result = await iterator.next();
|
|
30070
|
+
if (typeof result !== "object" && typeof result !== "function" || result === null) {
|
|
30071
|
+
throw new TypeError("Iterator result must be an object.");
|
|
30072
|
+
}
|
|
30073
|
+
if (result.done) break;
|
|
30074
|
+
const entry = result.value;
|
|
30075
|
+
if (typeof entry !== "object" && typeof entry !== "function" || entry === null) {
|
|
30076
|
+
throw new TypeError("Object.fromEntries requires entry objects.");
|
|
30077
|
+
}
|
|
30078
|
+
const key = entry[0];
|
|
30079
|
+
const value = entry[1];
|
|
30080
|
+
Object.defineProperty(object, key, {
|
|
30081
|
+
configurable: true,
|
|
30082
|
+
enumerable: true,
|
|
30083
|
+
value,
|
|
30084
|
+
writable: true
|
|
30085
|
+
});
|
|
30086
|
+
}
|
|
30087
|
+
} catch (error) {
|
|
30088
|
+
try {
|
|
30089
|
+
await iterator.return?.();
|
|
30090
|
+
} catch {
|
|
30091
|
+
throw error;
|
|
30092
|
+
}
|
|
30093
|
+
throw error;
|
|
30094
|
+
}
|
|
30095
|
+
return allocateProducedSandboxValue(object, budget);
|
|
30096
|
+
}
|
|
30097
|
+
function assignSandboxValues(target, sources, budget) {
|
|
30098
|
+
if (target === null || target === void 0) {
|
|
30099
|
+
throw new TypeError("Object.assign(target, ...sources) requires a non-null target.");
|
|
30100
|
+
}
|
|
30101
|
+
if (!isGuestClosure(target) && !isAssignableSandboxTarget(target)) {
|
|
30102
|
+
throw new TypeError("Object.assign(target, ...sources) requires an object or array target.");
|
|
30103
|
+
}
|
|
30104
|
+
for (const source of sources) {
|
|
30105
|
+
if (source === null || source === void 0) {
|
|
30106
|
+
continue;
|
|
30107
|
+
}
|
|
30108
|
+
for (const [key, value] of ownEnumerableSandboxEntries(source)) {
|
|
30109
|
+
setSandboxProperty(target, key, value, budget);
|
|
30110
|
+
}
|
|
30111
|
+
}
|
|
30112
|
+
return target;
|
|
30113
|
+
}
|
|
30114
|
+
function objectProperties(value, mutable = false) {
|
|
30115
|
+
if (isSandboxDate(value)) {
|
|
30116
|
+
if (mutable) throw new TypeError("Date own properties and prototypes are not supported.");
|
|
30117
|
+
return value;
|
|
30118
|
+
}
|
|
30119
|
+
if (isGuestHostObject(value)) throw new TypeError("Live host object descriptors are not supported.");
|
|
30120
|
+
if (isGuestClosure(value)) return materializeFunctionProperties(value);
|
|
30121
|
+
if (isSandboxClosure(value)) {
|
|
30122
|
+
if (mutable) throw new TypeError("Host function properties are read only.");
|
|
30123
|
+
return value.properties ?? /* @__PURE__ */ Object.create(null);
|
|
30124
|
+
}
|
|
30125
|
+
if (!isAssignableSandboxTarget(value)) throw new TypeError("Expected a sandbox object or function.");
|
|
30126
|
+
return value;
|
|
30127
|
+
}
|
|
30128
|
+
function dataDescriptor(input) {
|
|
30129
|
+
const source = objectProperties(input);
|
|
30130
|
+
const descriptor = {};
|
|
30131
|
+
for (const field of ["get", "set", "value", "writable", "enumerable", "configurable"]) {
|
|
30132
|
+
const entry = Object.getOwnPropertyDescriptor(source, field);
|
|
30133
|
+
if (entry === void 0) continue;
|
|
30134
|
+
if (!("value" in entry) || field === "get" || field === "set") {
|
|
30135
|
+
throw new TypeError("Only data property descriptors are supported.");
|
|
30136
|
+
}
|
|
30137
|
+
if (field === "value") descriptor.value = entry.value;
|
|
30138
|
+
else descriptor[field] = Boolean(entry.value);
|
|
30139
|
+
}
|
|
30140
|
+
return descriptor;
|
|
30141
|
+
}
|
|
30142
|
+
function defineDataProperty2(target, key, descriptor, budget) {
|
|
30143
|
+
budget.visitNode();
|
|
30144
|
+
if (isFloat32Array(target)) throw new TypeError("Typed array property descriptors are not supported.");
|
|
30145
|
+
const properties = objectProperties(target, true);
|
|
30146
|
+
if (Array.isArray(properties)) {
|
|
30147
|
+
if (key === "length" && "value" in descriptor) budget.allocateArrayLength(Number(descriptor.value));
|
|
30148
|
+
else {
|
|
30149
|
+
const index = Number(key);
|
|
30150
|
+
if (Number.isInteger(index) && index >= 0 && index < 4294967295 && String(index) === key) {
|
|
30151
|
+
budget.allocateArrayLength(index + 1);
|
|
30152
|
+
}
|
|
30153
|
+
}
|
|
30154
|
+
}
|
|
30155
|
+
Object.defineProperty(properties, key, descriptor);
|
|
30156
|
+
markDescriptorObject(properties);
|
|
30157
|
+
}
|
|
30158
|
+
function isAssignableSandboxTarget(value) {
|
|
30159
|
+
return typeof value === "object" && value !== null && !isSandboxClosure(value) && !isSandboxGenerator(value) && !isSandboxMap(value) && !isSandboxSet(value) && !isSandboxPromise(value) && !isSandboxRegex(value);
|
|
30160
|
+
}
|
|
30161
|
+
async function arrayFromSandboxValues(args, budget) {
|
|
30162
|
+
const [items, mapFn, thisValue] = args;
|
|
30163
|
+
const iterator = getSandboxIterator(items);
|
|
30164
|
+
const values = iterator === void 0 ? Reflect.apply(Array.from, Array, [items]) : await collectIteratorValues(iterator);
|
|
30165
|
+
if (mapFn === void 0 || !isSandboxClosure(mapFn)) {
|
|
30166
|
+
if (mapFn !== void 0) {
|
|
30167
|
+
throw new TypeError("Array.from mapping callback must be a function.");
|
|
30168
|
+
}
|
|
30169
|
+
return budgetSandboxValue2(values, budget);
|
|
30170
|
+
}
|
|
30171
|
+
const mappedValues = [];
|
|
30172
|
+
for (const [index, value] of values.entries()) {
|
|
30173
|
+
const result = await mapFn.call([value, index], { stack: [], thisValue });
|
|
30174
|
+
if (isSandboxPromise(result) && result.synchronousPrefix !== void 0) {
|
|
30175
|
+
await result.synchronousPrefix;
|
|
30176
|
+
}
|
|
30177
|
+
mappedValues.push(result);
|
|
30178
|
+
}
|
|
30179
|
+
return budgetSandboxValue2(mappedValues, budget);
|
|
30180
|
+
}
|
|
30181
|
+
function createArrayFromConstructorArgs(args, budget) {
|
|
30182
|
+
if (args.length !== 1) {
|
|
30183
|
+
return budgetSandboxValue2(Reflect.apply(Array, Array, [...args]), budget);
|
|
30184
|
+
}
|
|
30185
|
+
const [lengthOrValue] = args;
|
|
30186
|
+
if (typeof lengthOrValue !== "number") {
|
|
30187
|
+
return budgetSandboxValue2([lengthOrValue], budget);
|
|
30188
|
+
}
|
|
30189
|
+
if (!Number.isInteger(lengthOrValue) || lengthOrValue < 0 || lengthOrValue > 4294967295) {
|
|
30190
|
+
throw new RangeError("Invalid array length.");
|
|
30191
|
+
}
|
|
30192
|
+
budget.allocateArrayLength(lengthOrValue);
|
|
30193
|
+
return new Array(lengthOrValue);
|
|
30194
|
+
}
|
|
30195
|
+
async function collectIteratorValues(iterator) {
|
|
30196
|
+
const values = [];
|
|
30197
|
+
while (true) {
|
|
30198
|
+
const result = await iterator.next();
|
|
30199
|
+
if (result.done) return values;
|
|
30200
|
+
values.push(result.value);
|
|
30201
|
+
}
|
|
30202
|
+
}
|
|
30203
|
+
function getOwnEnumerableKeys(value) {
|
|
30204
|
+
if (isGuestHostObject(value)) return getHostObjectKeys(value);
|
|
30205
|
+
return ownEnumerableSandboxEntries(value).map(([key]) => key);
|
|
30206
|
+
}
|
|
30207
|
+
function getOwnEnumerableValues(value) {
|
|
30208
|
+
return ownEnumerableSandboxEntries(value).map(([, entryValue]) => entryValue);
|
|
30209
|
+
}
|
|
30210
|
+
function budgetSandboxValue2(value, budget) {
|
|
30211
|
+
const sandboxValue = deepCopyToSandbox(value);
|
|
30212
|
+
return allocateProducedSandboxValue(sandboxValue, budget);
|
|
30213
|
+
}
|
|
30214
|
+
function stringRaw(args, budget) {
|
|
30215
|
+
const [template, ...substitutions] = args;
|
|
30216
|
+
const raw = getTemplateRawParts(template);
|
|
30217
|
+
let result = "";
|
|
30218
|
+
for (let index = 0; index < raw.length; index += 1) {
|
|
30219
|
+
result += String(raw[index]);
|
|
30220
|
+
if (index < raw.length - 1 && index < substitutions.length) {
|
|
30221
|
+
result += String(substitutions[index]);
|
|
30222
|
+
}
|
|
30223
|
+
}
|
|
30224
|
+
return budget.allocateString(result);
|
|
30225
|
+
}
|
|
30226
|
+
function getTemplateRawParts(template) {
|
|
30227
|
+
const raw = typeof template === "object" && template !== null ? template.raw : void 0;
|
|
30228
|
+
if (typeof template !== "object" || template === null || isSandboxClosure(template) || isSandboxPromise(template) || !Array.isArray(raw)) {
|
|
30229
|
+
throw new TypeError("String.raw requires a raw strings array.");
|
|
30230
|
+
}
|
|
30231
|
+
return raw;
|
|
30232
|
+
}
|
|
30233
|
+
|
|
30234
|
+
// packages/safe-js/src/interp/globals.ts
|
|
30235
|
+
function createBuiltinBindings(options) {
|
|
30236
|
+
return {
|
|
30237
|
+
...createConsoleJsonGlobals(options),
|
|
30238
|
+
...createCollectionGlobals(options),
|
|
30239
|
+
Float32Array: createFloat32ArrayGlobal(options.budget),
|
|
30240
|
+
Date: createDateGlobal(options),
|
|
30241
|
+
...createErrorGlobals(options),
|
|
30242
|
+
...createMathGlobals({ random: options.random }),
|
|
30243
|
+
...createObjectArrayGlobals(options),
|
|
30244
|
+
...createMiscGlobals(options),
|
|
30245
|
+
...createPromiseGlobals(options),
|
|
30246
|
+
...createRegexGlobals(options.compileOwner)
|
|
30247
|
+
};
|
|
30248
|
+
}
|
|
30249
|
+
|
|
30250
|
+
// packages/safe-js/src/interp/resources.ts
|
|
30251
|
+
import { AsyncLocalStorage as AsyncLocalStorage5 } from "node:async_hooks";
|
|
30252
|
+
var runResources = new AsyncLocalStorage5();
|
|
30253
|
+
async function withRunResources(signal, execute) {
|
|
30254
|
+
const controller = new AbortController();
|
|
30255
|
+
const cancel = () => controller.abort(signal?.reason);
|
|
30256
|
+
const cleanups = /* @__PURE__ */ new Set();
|
|
30257
|
+
const resources = {
|
|
30258
|
+
signal: controller.signal,
|
|
30259
|
+
add(close) {
|
|
30260
|
+
cleanups.add(close);
|
|
30261
|
+
}
|
|
30262
|
+
};
|
|
30263
|
+
signal?.addEventListener("abort", cancel, { once: true });
|
|
30264
|
+
if (signal?.aborted) cancel();
|
|
30265
|
+
let result;
|
|
30266
|
+
let failure;
|
|
30267
|
+
let errors = [];
|
|
30268
|
+
try {
|
|
30269
|
+
result = await runResources.run(resources, execute);
|
|
30270
|
+
} catch (error) {
|
|
30271
|
+
failure = { reason: error };
|
|
30272
|
+
} finally {
|
|
30273
|
+
signal?.removeEventListener("abort", cancel);
|
|
30274
|
+
controller.abort(new Error("SafeJS run finished."));
|
|
30275
|
+
const outcomes = await Promise.allSettled(
|
|
30276
|
+
[...cleanups].map((close) => Promise.resolve().then(close))
|
|
30277
|
+
);
|
|
30278
|
+
errors = outcomes.flatMap((outcome) => outcome.status === "rejected" ? [outcome.reason] : []);
|
|
30279
|
+
}
|
|
30280
|
+
if (failure !== void 0) throw failure.reason;
|
|
30281
|
+
if (errors.length > 0) throw new AggregateError(errors, "SafeJS resource cleanup failed.");
|
|
30282
|
+
return result;
|
|
30283
|
+
}
|
|
30284
|
+
|
|
30285
|
+
// packages/safe-js/src/modules/registry.ts
|
|
30286
|
+
function createUnknownModuleMessage2(moduleName, moduleNames) {
|
|
30287
|
+
if (moduleNames.length === 0) {
|
|
30288
|
+
return `Unknown module '${moduleName}'. No modules are registered.`;
|
|
30289
|
+
}
|
|
30290
|
+
return `Unknown module '${moduleName}'. Available modules: ${moduleNames.join(", ")}.`;
|
|
30291
|
+
}
|
|
30292
|
+
function createUnknownExportMessage2(moduleName, exportName, availableExports) {
|
|
30293
|
+
if (availableExports.length === 0) {
|
|
30294
|
+
return `Module '${moduleName}' does not export '${exportName}'. The module exports nothing.`;
|
|
30295
|
+
}
|
|
30296
|
+
return `Module '${moduleName}' does not export '${exportName}'. Available exports: ${availableExports.join(", ")}.`;
|
|
30297
|
+
}
|
|
30298
|
+
function resolveModuleImports(module, modules, options) {
|
|
30299
|
+
const registry = normalizeModuleRegistry(modules);
|
|
30300
|
+
const bindings = createBindingRecord();
|
|
30301
|
+
const wrappedModules = options.wrappedModules ?? /* @__PURE__ */ new Map();
|
|
30302
|
+
for (const statement of module.body) {
|
|
30303
|
+
if (statement.type !== "ImportDeclaration") {
|
|
30304
|
+
continue;
|
|
30305
|
+
}
|
|
30306
|
+
bindImportDeclaration(statement, registry, wrappedModules, bindings, options);
|
|
30307
|
+
}
|
|
30308
|
+
return bindings;
|
|
30309
|
+
}
|
|
30310
|
+
function bindImportDeclaration(declaration, registry, wrappedModules, bindings, options) {
|
|
30311
|
+
const moduleName = declaration.source.value;
|
|
30312
|
+
const moduleExports = registry.get(moduleName);
|
|
30313
|
+
if (moduleExports === void 0) {
|
|
30314
|
+
if (options.allowMissing) return;
|
|
30315
|
+
throw createModuleImportError(
|
|
30316
|
+
createUnknownModuleMessage2(moduleName, [...registry.keys()]),
|
|
30317
|
+
declaration.source.span
|
|
30318
|
+
);
|
|
30319
|
+
}
|
|
30320
|
+
const wrappedExports = wrappedModules.get(moduleName) ?? createBindingRecord(
|
|
30321
|
+
wrapCancelableBindings(
|
|
30322
|
+
wrapCallerInjectedBindings(Object.fromEntries(moduleExports), {
|
|
30323
|
+
realm: options.realm,
|
|
30324
|
+
budget: options.budget,
|
|
30325
|
+
compileOwner: options.compileOwner,
|
|
30326
|
+
hostCalls: options.hostCalls,
|
|
30327
|
+
moduleId: moduleName,
|
|
30328
|
+
signal: options.signal
|
|
30329
|
+
}),
|
|
30330
|
+
options.signal
|
|
30331
|
+
)
|
|
30332
|
+
);
|
|
30333
|
+
wrappedModules.set(moduleName, wrappedExports);
|
|
30334
|
+
for (const specifier of declaration.specifiers) {
|
|
30335
|
+
const localName = specifier.local.name;
|
|
30336
|
+
if (Object.hasOwn(bindings, localName)) {
|
|
30337
|
+
throw createModuleImportError(
|
|
30338
|
+
`Cannot redeclare imported binding '${localName}'.`,
|
|
30339
|
+
specifier.local.span
|
|
30340
|
+
);
|
|
30341
|
+
}
|
|
30342
|
+
if (options.allowMissing && specifier.type !== "ImportNamespaceSpecifier") {
|
|
30343
|
+
const exportName = specifier.type === "ImportDefaultSpecifier" ? "default" : specifier.imported.name;
|
|
30344
|
+
if (!Object.hasOwn(wrappedExports, exportName)) continue;
|
|
30345
|
+
}
|
|
30346
|
+
bindings[localName] = resolveImportSpecifier(moduleName, specifier, wrappedExports);
|
|
30347
|
+
}
|
|
30348
|
+
}
|
|
30349
|
+
function resolveImportSpecifier(moduleName, specifier, wrappedExports) {
|
|
30350
|
+
if (specifier.type === "ImportNamespaceSpecifier") {
|
|
30351
|
+
return wrappedExports;
|
|
30352
|
+
}
|
|
30353
|
+
const exportName = specifier.type === "ImportDefaultSpecifier" ? "default" : specifier.imported.name;
|
|
30354
|
+
const exportedValue = wrappedExports[exportName];
|
|
30355
|
+
if (exportedValue !== void 0 || Object.hasOwn(wrappedExports, exportName)) {
|
|
30356
|
+
return exportedValue;
|
|
30357
|
+
}
|
|
30358
|
+
throw createModuleImportError(
|
|
30359
|
+
createUnknownExportMessage2(moduleName, exportName, Object.keys(wrappedExports).sort()),
|
|
30360
|
+
specifier.span
|
|
30361
|
+
);
|
|
30362
|
+
}
|
|
30363
|
+
function createModuleImportError(message, span) {
|
|
30364
|
+
const error = new Error(message);
|
|
30365
|
+
attachErrorSpan(error, span);
|
|
30366
|
+
return error;
|
|
30367
|
+
}
|
|
30368
|
+
function normalizeModuleRegistry(modules) {
|
|
30369
|
+
if (modules === void 0) {
|
|
30370
|
+
return /* @__PURE__ */ new Map();
|
|
30371
|
+
}
|
|
30372
|
+
const entries = modules instanceof Map ? [...modules.entries()] : Object.entries(modules);
|
|
30373
|
+
const registry = new Map(
|
|
30374
|
+
entries.map(
|
|
30375
|
+
([moduleName, moduleExports]) => [moduleName, normalizeModuleExports(moduleExports)]
|
|
30376
|
+
).sort(([left], [right]) => left.localeCompare(right))
|
|
30377
|
+
);
|
|
30378
|
+
registerModuleHostOperationPolicies(registry);
|
|
30379
|
+
return registry;
|
|
30380
|
+
}
|
|
30381
|
+
function registerModuleHostOperationPolicies(registry) {
|
|
30382
|
+
for (const [moduleId, moduleExports] of registry) {
|
|
30383
|
+
for (const [operation, value] of moduleExports) {
|
|
30384
|
+
if (typeof value !== "function") {
|
|
30385
|
+
continue;
|
|
30386
|
+
}
|
|
30387
|
+
const policy = readHostOperationPolicy(value);
|
|
30388
|
+
if (policy !== void 0) {
|
|
30389
|
+
registerPendingHostCallPolicy({ moduleId, operation, policy });
|
|
30390
|
+
}
|
|
30391
|
+
}
|
|
30392
|
+
}
|
|
30393
|
+
}
|
|
30394
|
+
function normalizeModuleExports(moduleExports) {
|
|
30395
|
+
const entries = moduleExports instanceof Map ? [...moduleExports.entries()] : Object.entries(moduleExports);
|
|
30396
|
+
return new Map(
|
|
30397
|
+
entries.filter(([exportName]) => exportName.length > 0).sort(([left], [right]) => left.localeCompare(right))
|
|
30398
|
+
);
|
|
30399
|
+
}
|
|
30400
|
+
function createBindingRecord(entries) {
|
|
30401
|
+
return Object.assign(/* @__PURE__ */ Object.create(null), entries);
|
|
30402
|
+
}
|
|
30403
|
+
|
|
30404
|
+
// packages/safe-js/src/realm.ts
|
|
30405
|
+
var RealmState = class {
|
|
30406
|
+
constructor(options) {
|
|
30407
|
+
this.options = options;
|
|
30408
|
+
const limitInput = readDataRecord(options.limits ?? {}, "Realm limits");
|
|
30409
|
+
this.limits = {
|
|
30410
|
+
extensions: 32,
|
|
30411
|
+
hostObjects: 1024,
|
|
30412
|
+
callbacks: 1024,
|
|
30413
|
+
guestReferences: 1024,
|
|
30414
|
+
cleanups: 1024,
|
|
30415
|
+
nestedEvaluations: 16
|
|
30416
|
+
};
|
|
30417
|
+
for (const [name, value] of Object.entries(limitInput)) {
|
|
30418
|
+
if (!Object.hasOwn(this.limits, name) || !Number.isSafeInteger(value) || Number(value) < 1)
|
|
30419
|
+
throw new TypeError("Realm limits must be positive safe integers with supported names.");
|
|
30420
|
+
this.limits[name] = Number(value);
|
|
30421
|
+
}
|
|
30422
|
+
if (options.extensions !== void 0 && (!Array.isArray(options.extensions) || types4.isProxy(options.extensions)))
|
|
30423
|
+
throw new TypeError("Extensions must be a registration array.");
|
|
30424
|
+
const registrations = options.extensions ?? [];
|
|
30425
|
+
const extensions = [];
|
|
30426
|
+
if (registrations.length > this.limits.extensions)
|
|
30427
|
+
throw new RangeError("Realm extension limit exceeded.");
|
|
30428
|
+
for (let index = 0; index < registrations.length; index++) {
|
|
30429
|
+
const descriptor = Object.getOwnPropertyDescriptor(registrations, String(index));
|
|
30430
|
+
if (descriptor === void 0 || !("value" in descriptor))
|
|
30431
|
+
throw new TypeError("Extension registrations require data properties, not accessors.");
|
|
30432
|
+
extensions.push(descriptor.value);
|
|
30433
|
+
}
|
|
30434
|
+
if (Reflect.ownKeys(registrations).length !== extensions.length + 1)
|
|
30435
|
+
throw new TypeError("Extension registrations have unsupported fields.");
|
|
30436
|
+
this.extensions = Object.freeze(extensions);
|
|
30437
|
+
if (this.extensions.length > this.limits.extensions)
|
|
30438
|
+
throw new RangeError("Realm extension limit exceeded.");
|
|
30439
|
+
this.globals = readDataRecord(options.bindings ?? {}, "Realm bindings");
|
|
30440
|
+
this.modules = readModules(options.modules);
|
|
30441
|
+
const grants = new Set(readStringList(options.grants ?? [], "Realm grants"));
|
|
30442
|
+
for (const extension of this.extensions) getExtensionSetup(extension);
|
|
30443
|
+
this.budget = options.budget ?? new Budget({ maxCallDepth: 1e3 });
|
|
30444
|
+
this.lease = this.budget.acquireCompileOwner(true);
|
|
30445
|
+
this.compilation = new CompileScope(this.lease.owner);
|
|
30446
|
+
this.bridge = {
|
|
30447
|
+
owner: this,
|
|
30448
|
+
assertActive: this.assertOpen,
|
|
30449
|
+
wrapCallback: this.wrapCallback,
|
|
30450
|
+
captureArguments: this.captureArguments,
|
|
30451
|
+
invoke: this.invokeHost,
|
|
30452
|
+
awaitResult: (operation) => this.nestedOperations.has(operation)
|
|
30453
|
+
};
|
|
30454
|
+
try {
|
|
30455
|
+
this.builtinBindings = createBuiltinBindings({
|
|
30456
|
+
budget: this.budget,
|
|
30457
|
+
compileOwner: this.lease.owner,
|
|
30458
|
+
sink: options.sink,
|
|
30459
|
+
clock: options.clock,
|
|
30460
|
+
random: createReplayableRandom({ seed: options.randomSeed }).next
|
|
30461
|
+
});
|
|
30462
|
+
const names = /* @__PURE__ */ new Set();
|
|
30463
|
+
const globals = /* @__PURE__ */ new Set([...Object.keys(this.builtinBindings), ...Object.keys(this.globals)]);
|
|
30464
|
+
const modules = new Map(
|
|
30465
|
+
Object.entries(this.modules).map(([name, exports]) => [name, new Set(Object.keys(exports))])
|
|
30466
|
+
);
|
|
30467
|
+
for (const extension of this.extensions) {
|
|
30468
|
+
const manifest = extension.manifest;
|
|
30469
|
+
if (names.has(manifest.name))
|
|
30470
|
+
throw new TypeError(`Duplicate extension '${manifest.name}'.`);
|
|
30471
|
+
names.add(manifest.name);
|
|
30472
|
+
for (const capability of manifest.capabilities ?? []) {
|
|
30473
|
+
if (!grants.has(capability))
|
|
30474
|
+
throw new TypeError(`Missing grant '${capability}' for extension '${manifest.name}'.`);
|
|
30475
|
+
}
|
|
30476
|
+
for (const name of manifest.globals ?? []) {
|
|
30477
|
+
if (globals.has(name)) throw new TypeError(`Conflicting global '${name}'.`);
|
|
30478
|
+
globals.add(name);
|
|
30479
|
+
}
|
|
30480
|
+
for (const [name, exports] of Object.entries(manifest.modules ?? {})) {
|
|
30481
|
+
const occupied = modules.get(name) ?? /* @__PURE__ */ new Set();
|
|
30482
|
+
for (const key of exports) {
|
|
30483
|
+
if (occupied.has(key)) throw new TypeError(`Conflicting export '${name}.${key}'.`);
|
|
30484
|
+
occupied.add(key);
|
|
30485
|
+
}
|
|
30486
|
+
modules.set(name, occupied);
|
|
30487
|
+
}
|
|
30488
|
+
}
|
|
30489
|
+
options.signal?.addEventListener("abort", this.abort, { once: true });
|
|
30490
|
+
if (options.signal?.aborted) this.abort();
|
|
30491
|
+
this.budget.setRetainedValues(this, this.retainedRoots);
|
|
30492
|
+
this.tracker.onFatalRejection((error) => this.poison(error));
|
|
30493
|
+
} catch (error) {
|
|
30494
|
+
this.compilation.dispose();
|
|
30495
|
+
this.lease.release();
|
|
30496
|
+
throw error;
|
|
30497
|
+
}
|
|
30498
|
+
}
|
|
30499
|
+
options;
|
|
30500
|
+
budget;
|
|
30501
|
+
lease;
|
|
30502
|
+
compilation;
|
|
30503
|
+
controller = new AbortController();
|
|
30504
|
+
phase = new AsyncLocalStorage6();
|
|
30505
|
+
queue = new SandboxJobQueue();
|
|
30506
|
+
tracker = createSandboxPromiseRejectionTracker();
|
|
30507
|
+
bridge;
|
|
30508
|
+
limits;
|
|
30509
|
+
extensions;
|
|
30510
|
+
cleanups = [];
|
|
30511
|
+
callbacks = /* @__PURE__ */ new Map();
|
|
30512
|
+
pendingCallbacks = /* @__PURE__ */ new Set();
|
|
30513
|
+
callbackCache = /* @__PURE__ */ new WeakMap();
|
|
30514
|
+
hostObjects = /* @__PURE__ */ new Set();
|
|
30515
|
+
guestReferences = /* @__PURE__ */ new Map();
|
|
30516
|
+
retainedOperations = /* @__PURE__ */ new WeakMap();
|
|
30517
|
+
nestedOperations = /* @__PURE__ */ new WeakMap();
|
|
30518
|
+
convertedModules = /* @__PURE__ */ new Map();
|
|
30519
|
+
nativeConversions = { seen: /* @__PURE__ */ new WeakMap() };
|
|
30520
|
+
modules;
|
|
30521
|
+
globals;
|
|
30522
|
+
builtinBindings;
|
|
30523
|
+
scope;
|
|
30524
|
+
active;
|
|
30525
|
+
disposal;
|
|
30526
|
+
closed = false;
|
|
30527
|
+
initialized = false;
|
|
30528
|
+
nestedDepth = 0;
|
|
30529
|
+
failure;
|
|
30530
|
+
bridgeOptions = () => ({
|
|
30531
|
+
budget: this.budget,
|
|
30532
|
+
compileOwner: this.lease.owner,
|
|
30533
|
+
signal: this.controller.signal,
|
|
30534
|
+
realm: this.bridge
|
|
30535
|
+
});
|
|
30536
|
+
retainedRoots = () => [
|
|
30537
|
+
...this.callbacks.values(),
|
|
30538
|
+
...Array.from(this.pendingCallbacks, (pending) => pending.closure),
|
|
30539
|
+
...this.guestReferences.values()
|
|
30540
|
+
];
|
|
30541
|
+
captureArguments = (operation, args, copy) => {
|
|
30542
|
+
const from = this.retainedOperations.get(operation)?.from ?? args.length;
|
|
30543
|
+
const values = copy(args.slice(0, from));
|
|
30544
|
+
const captured = [];
|
|
30545
|
+
const rollback = () => {
|
|
30546
|
+
for (const reference of captured) {
|
|
30547
|
+
revokeGuestReference(reference, this);
|
|
30548
|
+
this.guestReferences.delete(reference);
|
|
30549
|
+
}
|
|
30550
|
+
};
|
|
30551
|
+
try {
|
|
30552
|
+
for (const value of args.slice(from)) {
|
|
30553
|
+
this.checkCollection(
|
|
30554
|
+
this.guestReferences.size + 1,
|
|
30555
|
+
this.limits.guestReferences,
|
|
30556
|
+
"guest reference"
|
|
30557
|
+
);
|
|
30558
|
+
const root = [value];
|
|
30559
|
+
const reference = createGuestReference(root, this, this.assertOpen);
|
|
30560
|
+
this.guestReferences.set(reference, root);
|
|
30561
|
+
captured.push(reference);
|
|
30562
|
+
values.push(reference);
|
|
30563
|
+
}
|
|
30564
|
+
if (captured.length > 0)
|
|
30565
|
+
this.budget.reconcileDataUsage(
|
|
30566
|
+
measureSandboxData([...this.scope?.retainedValues() ?? [], ...this.retainedRoots()])
|
|
30567
|
+
);
|
|
30568
|
+
return { args: values, rollback };
|
|
30569
|
+
} catch (error) {
|
|
30570
|
+
rollback();
|
|
30571
|
+
if (error instanceof SandboxError) this.poison(error);
|
|
30572
|
+
throw error;
|
|
30573
|
+
}
|
|
30574
|
+
};
|
|
30575
|
+
releaseGuestReference = (reference) => {
|
|
30576
|
+
readGuestReference(reference, this);
|
|
30577
|
+
revokeGuestReference(reference, this);
|
|
30578
|
+
this.guestReferences.delete(reference);
|
|
30579
|
+
if (this.active === void 0)
|
|
30580
|
+
reconcileCompiledValues(
|
|
30581
|
+
this.budget,
|
|
30582
|
+
[...this.scope?.retainedValues() ?? [], ...this.retainedRoots()],
|
|
30583
|
+
this.compilation
|
|
30584
|
+
);
|
|
30585
|
+
};
|
|
30586
|
+
assertOpen = () => {
|
|
30587
|
+
if (this.failure !== void 0) throw this.failure.reason;
|
|
30588
|
+
if (this.closed) throw new Error("SafeJS realm is closed; capabilities are revoked.");
|
|
30589
|
+
this.controller.signal.throwIfAborted();
|
|
30590
|
+
};
|
|
30591
|
+
abort = () => {
|
|
30592
|
+
this.poison(this.options.signal?.reason ?? new SandboxError("aborted"));
|
|
30593
|
+
void this.close().catch(() => void 0);
|
|
30594
|
+
};
|
|
30595
|
+
poison(reason) {
|
|
30596
|
+
this.failure ??= { reason };
|
|
30597
|
+
this.controller.abort(reason);
|
|
30598
|
+
if (this.active === void 0)
|
|
30599
|
+
queueMicrotask(() => {
|
|
30600
|
+
void this.dispose().catch(() => void 0);
|
|
30601
|
+
});
|
|
30602
|
+
}
|
|
30603
|
+
chargeWork = (units = 1) => {
|
|
30604
|
+
this.assertOpen();
|
|
30605
|
+
if (!Number.isSafeInteger(units) || units < 0)
|
|
30606
|
+
throw new TypeError("Work charges must be non-negative safe integers.");
|
|
30607
|
+
try {
|
|
30608
|
+
for (let index = 0; index < units; index++) this.budget.visitNode();
|
|
30609
|
+
} catch (error) {
|
|
30610
|
+
this.poison(error);
|
|
30611
|
+
throw error;
|
|
30612
|
+
}
|
|
30613
|
+
};
|
|
30614
|
+
onCleanup = (cleanup) => {
|
|
30615
|
+
this.assertOpen();
|
|
30616
|
+
if (typeof cleanup !== "function") throw new TypeError("Cleanup must be a function.");
|
|
30617
|
+
this.checkCollection(this.cleanups.length + 1, this.limits.cleanups, "cleanup");
|
|
30618
|
+
this.cleanups.push(cleanup);
|
|
30619
|
+
};
|
|
30620
|
+
checkCollection(count, limit, name) {
|
|
30621
|
+
this.assertOpen();
|
|
30622
|
+
try {
|
|
30623
|
+
this.budget.allocateCollectionEntries(count);
|
|
30624
|
+
} catch (error) {
|
|
30625
|
+
this.poison(error);
|
|
30626
|
+
throw error;
|
|
30627
|
+
}
|
|
30628
|
+
if (count > limit) throw new RangeError(`Realm ${name} limit exceeded.`);
|
|
30629
|
+
}
|
|
30630
|
+
invokeHost = (operation, call) => {
|
|
30631
|
+
this.assertOpen();
|
|
30632
|
+
const phase = {
|
|
30633
|
+
active: true,
|
|
30634
|
+
extension: this.nestedOperations.get(operation),
|
|
30635
|
+
evaluating: false,
|
|
30636
|
+
pending: /* @__PURE__ */ new Set()
|
|
30637
|
+
};
|
|
30638
|
+
return this.phase.run(phase, () => {
|
|
30639
|
+
try {
|
|
30640
|
+
const result = call();
|
|
30641
|
+
if (types4.isPromise(result) || phase.pending.size > 0 || phase.failure !== void 0) {
|
|
30642
|
+
return Promise.resolve(result).then(
|
|
30643
|
+
async (value) => {
|
|
30644
|
+
await Promise.allSettled(phase.pending);
|
|
30645
|
+
if (phase.failure !== void 0) throw phase.failure.reason;
|
|
30646
|
+
this.assertOpen();
|
|
30647
|
+
return value;
|
|
30648
|
+
},
|
|
30649
|
+
async (error) => {
|
|
30650
|
+
if (error instanceof SandboxError || phase.pending.size > 0) this.poison(error);
|
|
30651
|
+
await Promise.allSettled(phase.pending);
|
|
30652
|
+
throw error;
|
|
30653
|
+
}
|
|
30654
|
+
).finally(() => {
|
|
30655
|
+
phase.active = false;
|
|
30656
|
+
});
|
|
30657
|
+
}
|
|
30658
|
+
this.assertOpen();
|
|
30659
|
+
phase.active = false;
|
|
30660
|
+
return result;
|
|
30661
|
+
} catch (error) {
|
|
30662
|
+
phase.active = false;
|
|
30663
|
+
if (error instanceof SandboxError) this.poison(error);
|
|
30664
|
+
if (phase.pending.size > 0) {
|
|
30665
|
+
this.poison(error);
|
|
30666
|
+
return Promise.allSettled(phase.pending).then(() => {
|
|
30667
|
+
throw error;
|
|
30668
|
+
});
|
|
30669
|
+
}
|
|
30670
|
+
throw error;
|
|
30671
|
+
}
|
|
30672
|
+
});
|
|
30673
|
+
};
|
|
30674
|
+
importValue(value) {
|
|
30675
|
+
return copyHostValueToSandbox(
|
|
30676
|
+
value,
|
|
30677
|
+
[],
|
|
30678
|
+
this.bridgeOptions(),
|
|
30679
|
+
{ seen: /* @__PURE__ */ new WeakMap() },
|
|
30680
|
+
"<realm>"
|
|
30681
|
+
);
|
|
30682
|
+
}
|
|
30683
|
+
exportValue(value) {
|
|
30684
|
+
return deepCopyFromSandbox(value, {
|
|
30685
|
+
compilation: this.compilation,
|
|
30686
|
+
wrapClosure: this.wrapCallback,
|
|
30687
|
+
unwrapHostObject: (object) => exportHostCapability(object, this)
|
|
30688
|
+
});
|
|
30689
|
+
}
|
|
30690
|
+
createHostObject = (definition) => {
|
|
30691
|
+
this.checkCollection(this.hostObjects.size + 1, this.limits.hostObjects, "host object");
|
|
30692
|
+
const object = createLiveHostObject(definition, {
|
|
30693
|
+
owner: this,
|
|
30694
|
+
assertActive: this.assertOpen,
|
|
30695
|
+
chargeWork: this.chargeWork,
|
|
30696
|
+
read: (operation) => {
|
|
30697
|
+
const value = this.invokeHost(operation, operation);
|
|
30698
|
+
if (types4.isPromise(value)) {
|
|
30699
|
+
void Promise.resolve(value).catch(() => void 0);
|
|
30700
|
+
throw new TypeError("Live property getters must be synchronous.");
|
|
30701
|
+
}
|
|
30702
|
+
return this.importValue(value);
|
|
30703
|
+
},
|
|
30704
|
+
write: (operation, value) => {
|
|
30705
|
+
const result = this.invokeHost(operation, () => operation(this.exportValue(value)));
|
|
30706
|
+
if (types4.isPromise(result)) {
|
|
30707
|
+
void Promise.resolve(result).catch(() => void 0);
|
|
30708
|
+
throw new TypeError("Live property setters must be synchronous.");
|
|
30709
|
+
}
|
|
30710
|
+
},
|
|
30711
|
+
method: (operation) => {
|
|
30712
|
+
const value = copyHostValueToSandbox(
|
|
30713
|
+
operation,
|
|
30714
|
+
[],
|
|
30715
|
+
this.bridgeOptions(),
|
|
30716
|
+
this.nativeConversions,
|
|
30717
|
+
"<host-method>"
|
|
30718
|
+
);
|
|
30719
|
+
if (!isSandboxClosure(value)) throw new TypeError("Invalid host method.");
|
|
30720
|
+
return value;
|
|
30721
|
+
}
|
|
30722
|
+
});
|
|
30723
|
+
this.hostObjects.add(object);
|
|
30724
|
+
try {
|
|
30725
|
+
this.budget.chargeDataUsage(1);
|
|
30726
|
+
} catch (error) {
|
|
30727
|
+
this.poison(error);
|
|
30728
|
+
throw error;
|
|
30729
|
+
}
|
|
30730
|
+
return object;
|
|
30731
|
+
};
|
|
30732
|
+
wrapCallback = (closure) => {
|
|
30733
|
+
this.assertOpen();
|
|
30734
|
+
const existing = this.callbackCache.get(closure);
|
|
30735
|
+
if (existing !== void 0 && this.callbacks.has(existing)) return existing;
|
|
30736
|
+
this.checkCollection(this.callbacks.size + 1, this.limits.callbacks, "callback");
|
|
30737
|
+
const invokeCallback = this.invokeCallback;
|
|
30738
|
+
const callback = function(...args) {
|
|
30739
|
+
return invokeCallback(callback, { args, thisValue: this });
|
|
30740
|
+
};
|
|
30741
|
+
this.callbacks.set(callback, closure);
|
|
30742
|
+
this.callbackCache.set(closure, callback);
|
|
30743
|
+
registerGuestCallback(callback, {
|
|
30744
|
+
owner: this,
|
|
30745
|
+
closure,
|
|
30746
|
+
assertActive: () => {
|
|
30747
|
+
this.assertOpen();
|
|
30748
|
+
if (!this.callbacks.has(callback)) throw new TypeError("Guest callback is revoked.");
|
|
30749
|
+
}
|
|
30750
|
+
});
|
|
30751
|
+
try {
|
|
30752
|
+
this.budget.reconcileDataUsage(
|
|
30753
|
+
measureSandboxData([...this.scope?.retainedValues() ?? [], ...this.retainedRoots()])
|
|
30754
|
+
);
|
|
30755
|
+
} catch (error) {
|
|
30756
|
+
this.poison(error);
|
|
30757
|
+
throw error;
|
|
30758
|
+
}
|
|
30759
|
+
return callback;
|
|
30760
|
+
};
|
|
30761
|
+
releaseCallback = (callback) => {
|
|
30762
|
+
readGuestCallback(callback, this);
|
|
30763
|
+
revokeGuestCallback(callback, this);
|
|
30764
|
+
this.callbacks.delete(callback);
|
|
30765
|
+
if (this.active === void 0)
|
|
30766
|
+
reconcileCompiledValues(
|
|
30767
|
+
this.budget,
|
|
30768
|
+
[...this.scope?.retainedValues() ?? [], ...this.retainedRoots()],
|
|
30769
|
+
this.compilation
|
|
30770
|
+
);
|
|
30771
|
+
};
|
|
30772
|
+
invokeCallback = async (callback, options = {}) => {
|
|
30773
|
+
if (this.closed || this.failure !== void 0) await this.dispose();
|
|
30774
|
+
this.assertOpen();
|
|
30775
|
+
const closure = readGuestCallback(callback, this);
|
|
30776
|
+
this.checkCollection(this.pendingCallbacks.size + 1, this.limits.callbacks, "pending callback");
|
|
30777
|
+
const record2 = { closure };
|
|
30778
|
+
this.pendingCallbacks.add(record2);
|
|
30779
|
+
const invoke = async () => {
|
|
30780
|
+
this.assertOpen();
|
|
30781
|
+
readGuestCallback(callback, this);
|
|
30782
|
+
const leave = enterRunningState(closure);
|
|
30783
|
+
const leaveCall = this.budget.enterCall();
|
|
30784
|
+
try {
|
|
30785
|
+
const values = this.importValue([
|
|
30786
|
+
options.thisValue,
|
|
30787
|
+
[...options.args ?? []]
|
|
30788
|
+
]);
|
|
30789
|
+
const value = await closure.call(values[1], {
|
|
30790
|
+
thisValue: values[0],
|
|
30791
|
+
compilation: this.compilation,
|
|
30792
|
+
stack: []
|
|
30793
|
+
});
|
|
30794
|
+
const settled = await suspendJob(
|
|
30795
|
+
awaitSandboxValue(value, this.controller.signal, this.budget)
|
|
30796
|
+
);
|
|
30797
|
+
return this.exportValue(settled);
|
|
30798
|
+
} finally {
|
|
30799
|
+
leaveCall();
|
|
30800
|
+
leave();
|
|
30801
|
+
}
|
|
30802
|
+
};
|
|
30803
|
+
try {
|
|
30804
|
+
if (this.active !== void 0) {
|
|
30805
|
+
record2.promise = withSandboxPromiseRejectionTracker(
|
|
30806
|
+
this.tracker,
|
|
30807
|
+
() => runResources.run(
|
|
30808
|
+
{ signal: this.controller.signal, add: this.onCleanup },
|
|
30809
|
+
() => withCancellationSignal(
|
|
30810
|
+
this.controller.signal,
|
|
30811
|
+
() => this.phase.getStore()?.active ? runAsyncPrefix(invoke) : this.queue.run(invoke)
|
|
30812
|
+
)
|
|
30813
|
+
)
|
|
30814
|
+
);
|
|
30815
|
+
} else {
|
|
30816
|
+
record2.promise = this.perform(() => this.queue.run(invoke));
|
|
30817
|
+
}
|
|
30818
|
+
return await record2.promise;
|
|
30819
|
+
} catch (error) {
|
|
30820
|
+
if (error instanceof SandboxError) this.poison(error);
|
|
30821
|
+
throw error;
|
|
30822
|
+
} finally {
|
|
30823
|
+
this.pendingCallbacks.delete(record2);
|
|
30824
|
+
if (!this.closed && this.active === void 0)
|
|
30825
|
+
reconcileCompiledValues(
|
|
30826
|
+
this.budget,
|
|
30827
|
+
[...this.scope?.retainedValues() ?? [], ...this.retainedRoots()],
|
|
30828
|
+
this.compilation
|
|
30829
|
+
);
|
|
30830
|
+
}
|
|
30831
|
+
};
|
|
30832
|
+
initialize() {
|
|
30833
|
+
if (this.initialized) return;
|
|
30834
|
+
this.assertOpen();
|
|
30835
|
+
this.initialized = true;
|
|
30836
|
+
for (const extension of this.extensions) {
|
|
30837
|
+
const context = Object.freeze({
|
|
30838
|
+
signal: this.controller.signal,
|
|
30839
|
+
onCleanup: this.onCleanup,
|
|
30840
|
+
chargeWork: this.chargeWork,
|
|
30841
|
+
createHostObject: this.createHostObject,
|
|
30842
|
+
invokeCallback: this.invokeCallback,
|
|
30843
|
+
releaseCallback: this.releaseCallback,
|
|
30844
|
+
releaseGuestReference: this.releaseGuestReference,
|
|
30845
|
+
retainGuestArguments: (operation, from) => {
|
|
30846
|
+
this.assertOpen();
|
|
30847
|
+
if (!extension.manifest.capabilities?.includes("guest:retain"))
|
|
30848
|
+
throw new TypeError("Retaining arguments requires the guest:retain grant.");
|
|
30849
|
+
if (typeof operation !== "function")
|
|
30850
|
+
throw new TypeError("Retained operation must be a function.");
|
|
30851
|
+
if (!Number.isSafeInteger(from) || from < 0)
|
|
30852
|
+
throw new TypeError("Argument index must be a non-negative safe integer.");
|
|
30853
|
+
if (this.scope !== void 0)
|
|
30854
|
+
throw new TypeError("Retained operations must be registered during setup.");
|
|
30855
|
+
const previous = this.retainedOperations.get(operation);
|
|
30856
|
+
if (previous !== void 0 && (previous.extension !== extension || previous.from !== from))
|
|
30857
|
+
throw new TypeError("Conflicting retained operation declaration.");
|
|
30858
|
+
this.retainedOperations.set(operation, { extension, from });
|
|
30859
|
+
return operation;
|
|
30860
|
+
},
|
|
30861
|
+
nestedOperation: (operation) => {
|
|
30862
|
+
this.assertOpen();
|
|
30863
|
+
if (!extension.manifest.capabilities?.includes("source:nested"))
|
|
30864
|
+
throw new TypeError("Nested source requires the source:nested grant.");
|
|
30865
|
+
if (typeof operation !== "function")
|
|
30866
|
+
throw new TypeError("Nested operation must be a function.");
|
|
30867
|
+
if (this.scope !== void 0)
|
|
30868
|
+
throw new TypeError("Nested operations must be registered during setup.");
|
|
30869
|
+
const owner = this.nestedOperations.get(operation);
|
|
30870
|
+
if (owner !== void 0 && owner !== extension)
|
|
30871
|
+
throw new TypeError("Nested operation already belongs to another extension.");
|
|
30872
|
+
this.nestedOperations.set(operation, extension);
|
|
30873
|
+
return operation;
|
|
30874
|
+
},
|
|
30875
|
+
evaluateNested: (source) => {
|
|
30876
|
+
const phase = this.phase.getStore();
|
|
30877
|
+
if (!extension.manifest.capabilities?.includes("source:nested") || !phase?.active || phase.extension !== extension || phase.evaluating) {
|
|
30878
|
+
const error = new SandboxError("reentry");
|
|
30879
|
+
this.poison(error);
|
|
30880
|
+
const rejected = Promise.reject(error);
|
|
30881
|
+
void rejected.catch(() => void 0);
|
|
30882
|
+
return rejected;
|
|
30883
|
+
}
|
|
30884
|
+
const pending = this.evaluateNested(source, extension);
|
|
30885
|
+
phase.pending.add(pending);
|
|
30886
|
+
void pending.then(
|
|
30887
|
+
() => {
|
|
30888
|
+
phase.pending.delete(pending);
|
|
30889
|
+
},
|
|
30890
|
+
(reason) => {
|
|
30891
|
+
phase.pending.delete(pending);
|
|
30892
|
+
phase.failure ??= { reason };
|
|
30893
|
+
}
|
|
30894
|
+
);
|
|
30895
|
+
return pending;
|
|
30896
|
+
}
|
|
30897
|
+
});
|
|
30898
|
+
const output = getExtensionSetup(extension)(context);
|
|
30899
|
+
if (types4.isPromise(output)) {
|
|
30900
|
+
void Promise.resolve(output).catch(() => void 0);
|
|
30901
|
+
throw new TypeError("Extension setup must be synchronous.");
|
|
30902
|
+
}
|
|
30903
|
+
const exports = readDataRecord(output, "Extension exports");
|
|
30904
|
+
if (Object.keys(exports).some((key) => key !== "globals" && key !== "modules"))
|
|
30905
|
+
throw new TypeError("Unknown extension export field.");
|
|
30906
|
+
const globals = readDataRecord(
|
|
30907
|
+
exports.globals ?? {},
|
|
30908
|
+
"Extension globals"
|
|
30909
|
+
);
|
|
30910
|
+
const modules = readModules(exports.modules);
|
|
30911
|
+
assertNames(Object.keys(globals), extension.manifest.globals ?? [], "global");
|
|
30912
|
+
assertNames(Object.keys(modules), Object.keys(extension.manifest.modules ?? {}), "module");
|
|
30913
|
+
for (const [name, values] of Object.entries(modules)) {
|
|
30914
|
+
assertNames(Object.keys(values), extension.manifest.modules?.[name] ?? [], "module export");
|
|
30915
|
+
this.modules[name] ??= /* @__PURE__ */ Object.create(null);
|
|
30916
|
+
Object.assign(this.modules[name], values);
|
|
30917
|
+
}
|
|
30918
|
+
Object.assign(this.globals, globals);
|
|
30919
|
+
}
|
|
30920
|
+
const bindings = wrapCallerInjectedBindings(this.globals, this.bridgeOptions());
|
|
30921
|
+
this.scope = new Scope(this.builtinBindings, void 0, void 0, { chargeData: false }).child(
|
|
30922
|
+
bindings,
|
|
30923
|
+
{ functionBoundary: true }
|
|
30924
|
+
);
|
|
30925
|
+
}
|
|
30926
|
+
async evaluateRaw(source, filename = "<realm>", nested = false) {
|
|
30927
|
+
this.assertOpen();
|
|
30928
|
+
if (typeof source !== "string") throw new TypeError("Realm source must be a string.");
|
|
30929
|
+
const module = parseExecutableModule(source, filename, this.lease.owner);
|
|
30930
|
+
this.initialize();
|
|
30931
|
+
const imports = resolveModuleImports(module, this.modules, {
|
|
30932
|
+
...this.bridgeOptions(),
|
|
30933
|
+
wrappedModules: this.convertedModules
|
|
30934
|
+
});
|
|
30935
|
+
for (const [name, value] of Object.entries(imports)) {
|
|
30936
|
+
const binding = this.scope.lookup(name);
|
|
30937
|
+
if (!binding.found) this.scope.declare(name, "const", value);
|
|
30938
|
+
else if (binding.value !== value) throw new TypeError(`Conflicting import '${name}'.`);
|
|
30939
|
+
}
|
|
30940
|
+
const result = await interpret(
|
|
30941
|
+
{
|
|
30942
|
+
type: "BlockStatement",
|
|
30943
|
+
body: module.body.filter((statement) => statement.type !== "ImportDeclaration"),
|
|
30944
|
+
span: module.span
|
|
30945
|
+
},
|
|
30946
|
+
{
|
|
30947
|
+
scope: this.scope,
|
|
30948
|
+
useScopeDirectly: true,
|
|
30949
|
+
budget: this.budget,
|
|
30950
|
+
compilation: this.compilation,
|
|
30951
|
+
signal: this.controller.signal,
|
|
30952
|
+
surfaceUnhandledThrows: true,
|
|
30953
|
+
jobs: this.queue,
|
|
30954
|
+
nested,
|
|
30955
|
+
assertActive: this.assertOpen
|
|
30956
|
+
}
|
|
30957
|
+
);
|
|
30958
|
+
this.assertOpen();
|
|
30959
|
+
return result;
|
|
30960
|
+
}
|
|
30961
|
+
evaluateNested = async (source, extension) => {
|
|
30962
|
+
this.assertOpen();
|
|
30963
|
+
const phase = this.phase.getStore();
|
|
30964
|
+
if (!phase?.active || phase.extension !== extension || phase.evaluating || this.active === void 0)
|
|
30965
|
+
throw new SandboxError("reentry");
|
|
30966
|
+
const leave = this.budget.enterCall();
|
|
30967
|
+
phase.evaluating = true;
|
|
30968
|
+
try {
|
|
30969
|
+
if (++this.nestedDepth > this.limits.nestedEvaluations) {
|
|
30970
|
+
const error = new SandboxError({
|
|
30971
|
+
budget: "callDepth",
|
|
30972
|
+
current: this.nestedDepth,
|
|
30973
|
+
limit: this.limits.nestedEvaluations
|
|
30974
|
+
});
|
|
30975
|
+
this.poison(error);
|
|
30976
|
+
throw error;
|
|
30977
|
+
}
|
|
30978
|
+
const result = await this.evaluateRaw(source, "<nested>", true);
|
|
30979
|
+
if (!result.ok) throw new Error(result.error.message);
|
|
30980
|
+
} finally {
|
|
30981
|
+
this.nestedDepth--;
|
|
30982
|
+
phase.evaluating = false;
|
|
30983
|
+
leave();
|
|
30984
|
+
}
|
|
30985
|
+
};
|
|
30986
|
+
evaluate = async (source, options = {}) => this.perform(async () => {
|
|
30987
|
+
const result = await this.evaluateRaw(source, options.filename);
|
|
30988
|
+
if (!result.ok) {
|
|
30989
|
+
await this.dispose();
|
|
30990
|
+
return { ok: false, error: result.error, stats: result.stats };
|
|
30991
|
+
}
|
|
30992
|
+
return { ok: true, returnValue: this.exportValue(result.returnValue), stats: result.stats };
|
|
30993
|
+
});
|
|
30994
|
+
async perform(task) {
|
|
30995
|
+
if (this.closed || this.failure !== void 0) await this.dispose();
|
|
30996
|
+
this.assertOpen();
|
|
30997
|
+
if (this.active !== void 0) throw new SandboxError("reentry");
|
|
30998
|
+
const pending = Promise.resolve().then(
|
|
30999
|
+
() => withSandboxPromiseRejectionTracker(
|
|
31000
|
+
this.tracker,
|
|
31001
|
+
() => runResources.run(
|
|
31002
|
+
{ signal: this.controller.signal, add: this.onCleanup },
|
|
31003
|
+
() => withCancellationSignal(this.controller.signal, task)
|
|
31004
|
+
)
|
|
31005
|
+
)
|
|
31006
|
+
);
|
|
31007
|
+
this.active = pending;
|
|
31008
|
+
try {
|
|
31009
|
+
const result = await pending;
|
|
31010
|
+
await this.queue.drain();
|
|
31011
|
+
const unhandled = await this.tracker.findUnhandledRejection();
|
|
31012
|
+
if (unhandled !== void 0) {
|
|
31013
|
+
const error = new Error(
|
|
31014
|
+
`Unhandled guest promise rejection: ${describeThrownValue(unhandled.reason)}`
|
|
31015
|
+
);
|
|
31016
|
+
error.name = "UnhandledRejectionError";
|
|
31017
|
+
throw error;
|
|
31018
|
+
}
|
|
31019
|
+
if (this.failure !== void 0) throw this.failure.reason;
|
|
31020
|
+
if (!this.closed)
|
|
31021
|
+
reconcileCompiledValues(
|
|
31022
|
+
this.budget,
|
|
31023
|
+
[...this.scope?.retainedValues() ?? [], ...this.retainedRoots()],
|
|
31024
|
+
this.compilation
|
|
31025
|
+
);
|
|
31026
|
+
return result;
|
|
31027
|
+
} catch (error) {
|
|
31028
|
+
this.poison(error);
|
|
31029
|
+
try {
|
|
31030
|
+
await this.dispose();
|
|
31031
|
+
} catch (cleanup) {
|
|
31032
|
+
throw new AggregateError([error, cleanup], "Realm execution and cleanup failed.");
|
|
31033
|
+
}
|
|
31034
|
+
throw error;
|
|
31035
|
+
} finally {
|
|
31036
|
+
this.active = void 0;
|
|
31037
|
+
}
|
|
31038
|
+
}
|
|
31039
|
+
close = () => {
|
|
31040
|
+
this.closed = true;
|
|
31041
|
+
this.controller.abort(new Error("SafeJS realm is closed."));
|
|
31042
|
+
if (this.phase.getStore()?.active) return this.dispose();
|
|
31043
|
+
return Promise.allSettled([
|
|
31044
|
+
this.active,
|
|
31045
|
+
...Array.from(this.pendingCallbacks, (pending) => pending.promise)
|
|
31046
|
+
]).then(() => this.dispose());
|
|
31047
|
+
};
|
|
31048
|
+
dispose() {
|
|
31049
|
+
if (this.disposal !== void 0) return this.disposal;
|
|
31050
|
+
this.closed = true;
|
|
31051
|
+
this.controller.abort(new Error("SafeJS realm is closed."));
|
|
31052
|
+
this.options.signal?.removeEventListener("abort", this.abort);
|
|
31053
|
+
for (const callback of this.callbacks.keys()) revokeGuestCallback(callback, this);
|
|
31054
|
+
this.callbacks.clear();
|
|
31055
|
+
for (const object of this.hostObjects) revokeHostObject(object, this);
|
|
31056
|
+
this.hostObjects.clear();
|
|
31057
|
+
for (const reference of this.guestReferences.keys()) revokeGuestReference(reference, this);
|
|
31058
|
+
this.guestReferences.clear();
|
|
31059
|
+
this.budget.setRetainedValues(this, void 0);
|
|
31060
|
+
this.disposal = (async () => {
|
|
31061
|
+
const errors = [];
|
|
31062
|
+
for (const cleanup of this.cleanups.splice(0).reverse()) {
|
|
31063
|
+
try {
|
|
31064
|
+
await cleanup();
|
|
31065
|
+
} catch (error) {
|
|
31066
|
+
errors.push(error);
|
|
31067
|
+
}
|
|
31068
|
+
}
|
|
31069
|
+
this.scope = void 0;
|
|
31070
|
+
this.convertedModules.clear();
|
|
31071
|
+
for (const key of Object.keys(this.globals)) delete this.globals[key];
|
|
31072
|
+
for (const key of Object.keys(this.modules)) delete this.modules[key];
|
|
31073
|
+
for (const key of Object.keys(this.builtinBindings))
|
|
31074
|
+
Reflect.deleteProperty(this.builtinBindings, key);
|
|
31075
|
+
this.nativeConversions.seen = /* @__PURE__ */ new WeakMap();
|
|
31076
|
+
reconcileCompiledValues(this.budget, [], this.compilation);
|
|
31077
|
+
this.compilation.dispose();
|
|
31078
|
+
this.lease.release();
|
|
31079
|
+
if (errors.length > 0) throw new AggregateError(errors, "Realm cleanup failed.");
|
|
31080
|
+
})();
|
|
31081
|
+
return this.disposal;
|
|
31082
|
+
}
|
|
31083
|
+
};
|
|
31084
|
+
function readModules(input) {
|
|
31085
|
+
const entries = (value, label) => {
|
|
31086
|
+
if (types4.isMap(value) && !types4.isProxy(value)) {
|
|
31087
|
+
const result = [...Map.prototype.entries.call(value)];
|
|
31088
|
+
if (result.length > 4096 || result.some(([key]) => typeof key !== "string" || key.length === 0))
|
|
31089
|
+
throw new TypeError(`${label} requires bounded string keys.`);
|
|
31090
|
+
return result;
|
|
31091
|
+
}
|
|
31092
|
+
return Object.entries(readDataRecord(value, label));
|
|
31093
|
+
};
|
|
31094
|
+
const modules = /* @__PURE__ */ Object.create(null);
|
|
31095
|
+
for (const [name, exports] of entries(input ?? {}, "Module registry")) {
|
|
31096
|
+
const exported = /* @__PURE__ */ Object.create(null);
|
|
31097
|
+
for (const [key, value] of entries(exports, "Module exports"))
|
|
31098
|
+
exported[key] = value;
|
|
31099
|
+
modules[name] = exported;
|
|
31100
|
+
}
|
|
31101
|
+
return modules;
|
|
31102
|
+
}
|
|
31103
|
+
function assertNames(actual, expected, label) {
|
|
31104
|
+
if (actual.length !== expected.length || actual.some((name) => !expected.includes(name)))
|
|
31105
|
+
throw new TypeError(`Extension ${label} names do not match its manifest.`);
|
|
31106
|
+
}
|
|
31107
|
+
function createRealm(options = {}) {
|
|
31108
|
+
const state = new RealmState(readRealmOptions(options));
|
|
31109
|
+
return Object.freeze({
|
|
31110
|
+
extensions: Object.freeze(state.extensions.map((extension) => extension.manifest)),
|
|
31111
|
+
evaluate: state.evaluate,
|
|
31112
|
+
invokeCallback: state.invokeCallback,
|
|
31113
|
+
releaseCallback: state.releaseCallback,
|
|
31114
|
+
releaseGuestReference: state.releaseGuestReference,
|
|
31115
|
+
close: state.close
|
|
31116
|
+
});
|
|
31117
|
+
}
|
|
31118
|
+
async function runWithExtensions(source, options) {
|
|
31119
|
+
if (options.snapshot !== void 0 || options.snapshotBackend !== void 0 || options.snapshotPath !== void 0 || options.entryPointArgs !== void 0)
|
|
31120
|
+
throw new TypeError(
|
|
31121
|
+
"Live extension runs do not support snapshots or entryPointArgs; use a persistent realm."
|
|
31122
|
+
);
|
|
31123
|
+
const state = new RealmState(readRealmOptions(options, true));
|
|
31124
|
+
try {
|
|
31125
|
+
const result = await state.perform(() => state.evaluateRaw(source, options.filename));
|
|
31126
|
+
if (result.ok) encodeReplayData(result.returnValue);
|
|
31127
|
+
return {
|
|
31128
|
+
...result,
|
|
31129
|
+
snapshot: {
|
|
31130
|
+
version: 1,
|
|
31131
|
+
sourceHash: hashSource(source),
|
|
31132
|
+
bindings: {},
|
|
31133
|
+
replayError: "Live realm state cannot be serialized or replayed."
|
|
31134
|
+
}
|
|
31135
|
+
};
|
|
31136
|
+
} catch (error) {
|
|
31137
|
+
if (state.disposal === void 0) {
|
|
31138
|
+
try {
|
|
31139
|
+
await state.close();
|
|
31140
|
+
} catch (cleanupError) {
|
|
31141
|
+
throw new AggregateError([error, cleanupError], "Realm execution and cleanup failed.");
|
|
31142
|
+
}
|
|
31143
|
+
}
|
|
31144
|
+
throw error;
|
|
31145
|
+
} finally {
|
|
31146
|
+
if (state.disposal === void 0) await state.close();
|
|
31147
|
+
}
|
|
31148
|
+
}
|
|
31149
|
+
function readRealmOptions(value, oneShot = false) {
|
|
31150
|
+
const options = readDataRecord(value, "Realm options");
|
|
31151
|
+
const supported = /* @__PURE__ */ new Set([
|
|
31152
|
+
"bindings",
|
|
31153
|
+
"modules",
|
|
31154
|
+
"extensions",
|
|
31155
|
+
"grants",
|
|
31156
|
+
"budget",
|
|
31157
|
+
"signal",
|
|
31158
|
+
"sink",
|
|
31159
|
+
"randomSeed",
|
|
31160
|
+
"clock",
|
|
31161
|
+
"limits"
|
|
31162
|
+
]);
|
|
31163
|
+
for (const [key, entry] of Object.entries(options)) {
|
|
31164
|
+
if (supported.has(key) || oneShot && (key === "filename" || entry === void 0)) continue;
|
|
31165
|
+
throw new TypeError(`Unsupported ${oneShot ? "extension-run" : "realm"} option '${key}'.`);
|
|
31166
|
+
}
|
|
31167
|
+
return options;
|
|
31168
|
+
}
|
|
31169
|
+
|
|
31170
|
+
// packages/safe-js/src/snapshot/dump.ts
|
|
31171
|
+
var RUN_DUMP_CONTROLLER = /* @__PURE__ */ Symbol("SafeJS.run-dump-controller");
|
|
31172
|
+
function attachDumpController(result, controller) {
|
|
31173
|
+
Object.defineProperty(result, RUN_DUMP_CONTROLLER, {
|
|
31174
|
+
configurable: false,
|
|
31175
|
+
enumerable: false,
|
|
31176
|
+
value: controller,
|
|
31177
|
+
writable: false
|
|
31178
|
+
});
|
|
31179
|
+
return result;
|
|
31180
|
+
}
|
|
31181
|
+
function createDumpController(lifecycle) {
|
|
31182
|
+
let finished = false;
|
|
31183
|
+
let failed;
|
|
31184
|
+
let finalSnapshot;
|
|
31185
|
+
let latestSnapshot;
|
|
31186
|
+
let latestSnapshotFactory;
|
|
31187
|
+
let pendingRequest;
|
|
31188
|
+
return {
|
|
31189
|
+
fail(error) {
|
|
31190
|
+
finished = true;
|
|
31191
|
+
failed = {
|
|
31192
|
+
error
|
|
31193
|
+
};
|
|
31194
|
+
if (pendingRequest === void 0) {
|
|
31195
|
+
return;
|
|
31196
|
+
}
|
|
31197
|
+
pendingRequest.reject(error);
|
|
31198
|
+
pendingRequest = void 0;
|
|
31199
|
+
},
|
|
31200
|
+
finalize(snapshot) {
|
|
31201
|
+
finished = true;
|
|
31202
|
+
finalSnapshot = snapshot;
|
|
31203
|
+
latestSnapshot = snapshot;
|
|
31204
|
+
latestSnapshotFactory = void 0;
|
|
31205
|
+
if (pendingRequest !== void 0) {
|
|
31206
|
+
settlePendingSnapshot(snapshot);
|
|
31207
|
+
}
|
|
31208
|
+
},
|
|
31209
|
+
onYield(createSnapshot) {
|
|
31210
|
+
latestSnapshot = void 0;
|
|
31211
|
+
latestSnapshotFactory = createSnapshot;
|
|
31212
|
+
if (pendingRequest === void 0) {
|
|
31213
|
+
return;
|
|
31214
|
+
}
|
|
31215
|
+
settlePendingSnapshot(createSnapshot());
|
|
31216
|
+
},
|
|
31217
|
+
requestCurrentSnapshot(options = {}) {
|
|
31218
|
+
assertDumpAllowed(options);
|
|
31219
|
+
if (failed !== void 0) {
|
|
31220
|
+
return Promise.reject(failed.error);
|
|
29904
31221
|
}
|
|
29905
|
-
if (
|
|
29906
|
-
|
|
29907
|
-
|
|
29908
|
-
|
|
31222
|
+
if (latestSnapshot !== void 0 || latestSnapshotFactory !== void 0) {
|
|
31223
|
+
try {
|
|
31224
|
+
return Promise.resolve(serializeRunSnapshot(latestSnapshot ?? latestSnapshotFactory()));
|
|
31225
|
+
} catch (error) {
|
|
31226
|
+
return Promise.reject(error);
|
|
31227
|
+
}
|
|
29909
31228
|
}
|
|
29910
|
-
|
|
29911
|
-
|
|
29912
|
-
|
|
29913
|
-
|
|
29914
|
-
|
|
29915
|
-
|
|
29916
|
-
|
|
31229
|
+
return this.requestSnapshot(options);
|
|
31230
|
+
},
|
|
31231
|
+
requestSnapshot(options = {}) {
|
|
31232
|
+
assertDumpAllowed(options);
|
|
31233
|
+
if (failed !== void 0) {
|
|
31234
|
+
if ((options.onFailure === "checkpoint" || options.onFailure === void 0 && isDataBudgetError(failed.error)) && finalSnapshot !== void 0) {
|
|
31235
|
+
try {
|
|
31236
|
+
return Promise.resolve(serializeRunSnapshot(finalSnapshot));
|
|
31237
|
+
} catch (error) {
|
|
31238
|
+
return Promise.reject(error);
|
|
31239
|
+
}
|
|
31240
|
+
}
|
|
31241
|
+
return Promise.reject(failed.error);
|
|
31242
|
+
}
|
|
31243
|
+
if (finished) {
|
|
31244
|
+
if (finalSnapshot === void 0) {
|
|
31245
|
+
throw new Error("Run completed without producing a snapshot.");
|
|
31246
|
+
}
|
|
31247
|
+
try {
|
|
31248
|
+
const serializedSnapshot = serializeRunSnapshot(finalSnapshot);
|
|
31249
|
+
return Promise.resolve(serializedSnapshot);
|
|
31250
|
+
} catch (error) {
|
|
31251
|
+
return Promise.reject(error);
|
|
31252
|
+
}
|
|
31253
|
+
}
|
|
31254
|
+
if (options.mode === "replay" && (latestSnapshot !== void 0 || latestSnapshotFactory !== void 0)) {
|
|
31255
|
+
return this.requestCurrentSnapshot(options);
|
|
31256
|
+
}
|
|
31257
|
+
if (pendingRequest !== void 0) {
|
|
31258
|
+
return pendingRequest.promise;
|
|
31259
|
+
}
|
|
31260
|
+
let resolveSnapshot = () => void 0;
|
|
31261
|
+
let rejectSnapshot = () => void 0;
|
|
31262
|
+
const promise = new Promise((resolve, reject) => {
|
|
31263
|
+
resolveSnapshot = resolve;
|
|
31264
|
+
rejectSnapshot = reject;
|
|
29917
31265
|
});
|
|
31266
|
+
pendingRequest = {
|
|
31267
|
+
promise,
|
|
31268
|
+
reject: rejectSnapshot,
|
|
31269
|
+
resolve: resolveSnapshot
|
|
31270
|
+
};
|
|
31271
|
+
return promise;
|
|
29918
31272
|
}
|
|
29919
|
-
}
|
|
29920
|
-
|
|
29921
|
-
|
|
29922
|
-
|
|
29923
|
-
throw error;
|
|
31273
|
+
};
|
|
31274
|
+
function assertDumpAllowed(options) {
|
|
31275
|
+
if ((lifecycle?.hostCallbackDepth ?? 0) > 0 && (options.mode !== "replay" || lifecycle?.hostCallbackContext.getStore() === true)) {
|
|
31276
|
+
throw new SandboxError("reentry");
|
|
29924
31277
|
}
|
|
29925
|
-
throw error;
|
|
29926
|
-
}
|
|
29927
|
-
return allocateProducedSandboxValue(object, budget);
|
|
29928
|
-
}
|
|
29929
|
-
function assignSandboxValues(target, sources, budget) {
|
|
29930
|
-
if (target === null || target === void 0) {
|
|
29931
|
-
throw new TypeError("Object.assign(target, ...sources) requires a non-null target.");
|
|
29932
31278
|
}
|
|
29933
|
-
|
|
29934
|
-
|
|
29935
|
-
|
|
29936
|
-
|
|
29937
|
-
|
|
29938
|
-
|
|
31279
|
+
function settlePendingSnapshot(snapshot) {
|
|
31280
|
+
try {
|
|
31281
|
+
settlePendingRequest(serializeRunSnapshot(snapshot));
|
|
31282
|
+
} catch (error) {
|
|
31283
|
+
pendingRequest?.reject(error);
|
|
31284
|
+
pendingRequest = void 0;
|
|
29939
31285
|
}
|
|
29940
|
-
|
|
29941
|
-
|
|
31286
|
+
}
|
|
31287
|
+
function settlePendingRequest(snapshot) {
|
|
31288
|
+
if (pendingRequest === void 0) {
|
|
31289
|
+
return;
|
|
29942
31290
|
}
|
|
31291
|
+
pendingRequest.resolve(snapshot);
|
|
31292
|
+
pendingRequest = void 0;
|
|
29943
31293
|
}
|
|
29944
|
-
return target;
|
|
29945
31294
|
}
|
|
29946
|
-
function
|
|
29947
|
-
|
|
29948
|
-
if (isSandboxClosure(value)) {
|
|
29949
|
-
if (mutable) throw new TypeError("Host function properties are read only.");
|
|
29950
|
-
return value.properties ?? /* @__PURE__ */ Object.create(null);
|
|
29951
|
-
}
|
|
29952
|
-
if (!isAssignableSandboxTarget(value)) throw new TypeError("Expected a sandbox object or function.");
|
|
29953
|
-
return value;
|
|
31295
|
+
function isDataBudgetError(error) {
|
|
31296
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "budgetExceeded" && "budget" in error && error.budget === "dataSize";
|
|
29954
31297
|
}
|
|
29955
|
-
function
|
|
29956
|
-
const
|
|
29957
|
-
|
|
29958
|
-
|
|
29959
|
-
|
|
29960
|
-
|
|
29961
|
-
|
|
29962
|
-
|
|
31298
|
+
function dump(result, options = {}) {
|
|
31299
|
+
const controller = readDumpController(result);
|
|
31300
|
+
if (controller !== void 0) {
|
|
31301
|
+
return controller.requestSnapshot(options);
|
|
31302
|
+
}
|
|
31303
|
+
if (hasSnapshot(result)) {
|
|
31304
|
+
try {
|
|
31305
|
+
return Promise.resolve(serializeRunSnapshot(result.snapshot));
|
|
31306
|
+
} catch (error) {
|
|
31307
|
+
return Promise.reject(error);
|
|
29963
31308
|
}
|
|
29964
|
-
if (field === "value") descriptor.value = entry.value;
|
|
29965
|
-
else descriptor[field] = Boolean(entry.value);
|
|
29966
31309
|
}
|
|
29967
|
-
return
|
|
29968
|
-
|
|
29969
|
-
|
|
29970
|
-
budget.visitNode();
|
|
29971
|
-
if (isFloat32Array(target)) throw new TypeError("Typed array property descriptors are not supported.");
|
|
29972
|
-
const properties = objectProperties(target, true);
|
|
29973
|
-
if (Array.isArray(properties)) {
|
|
29974
|
-
if (key === "length" && "value" in descriptor) budget.allocateArrayLength(Number(descriptor.value));
|
|
29975
|
-
else {
|
|
29976
|
-
const index = Number(key);
|
|
29977
|
-
if (Number.isInteger(index) && index >= 0 && index < 4294967295 && String(index) === key) {
|
|
29978
|
-
budget.allocateArrayLength(index + 1);
|
|
29979
|
-
}
|
|
31310
|
+
return Promise.resolve(result).then((resolved) => {
|
|
31311
|
+
if (!hasSnapshot(resolved)) {
|
|
31312
|
+
throw new Error("Run completed without producing a snapshot.");
|
|
29980
31313
|
}
|
|
31314
|
+
return serializeRunSnapshot(resolved.snapshot);
|
|
31315
|
+
});
|
|
31316
|
+
}
|
|
31317
|
+
function dumpCurrent(result) {
|
|
31318
|
+
const controller = readDumpController(result);
|
|
31319
|
+
if (controller !== void 0) {
|
|
31320
|
+
return controller.requestCurrentSnapshot();
|
|
29981
31321
|
}
|
|
29982
|
-
|
|
29983
|
-
markDescriptorObject(properties);
|
|
31322
|
+
return dump(result);
|
|
29984
31323
|
}
|
|
29985
|
-
function
|
|
29986
|
-
return
|
|
31324
|
+
function serializeRunSnapshot(snapshot) {
|
|
31325
|
+
return serializeSafeJSSnapshot(snapshot);
|
|
29987
31326
|
}
|
|
29988
|
-
|
|
29989
|
-
|
|
29990
|
-
const iterator = getSandboxIterator(items);
|
|
29991
|
-
const values = iterator === void 0 ? Reflect.apply(Array.from, Array, [items]) : await collectIteratorValues(iterator);
|
|
29992
|
-
if (mapFn === void 0 || !isSandboxClosure(mapFn)) {
|
|
29993
|
-
if (mapFn !== void 0) {
|
|
29994
|
-
throw new TypeError("Array.from mapping callback must be a function.");
|
|
29995
|
-
}
|
|
29996
|
-
return budgetSandboxValue2(values, budget);
|
|
29997
|
-
}
|
|
29998
|
-
const mappedValues = [];
|
|
29999
|
-
for (const [index, value] of values.entries()) {
|
|
30000
|
-
const result = await mapFn.call([value, index], { stack: [], thisValue });
|
|
30001
|
-
if (isSandboxPromise(result) && result.synchronousPrefix !== void 0) {
|
|
30002
|
-
await result.synchronousPrefix;
|
|
30003
|
-
}
|
|
30004
|
-
mappedValues.push(result);
|
|
30005
|
-
}
|
|
30006
|
-
return budgetSandboxValue2(mappedValues, budget);
|
|
31327
|
+
function hasSnapshot(value) {
|
|
31328
|
+
return typeof value === "object" && value !== null && Object.prototype.hasOwnProperty.call(value, "snapshot");
|
|
30007
31329
|
}
|
|
30008
|
-
function
|
|
30009
|
-
if (
|
|
30010
|
-
return
|
|
30011
|
-
}
|
|
30012
|
-
const [lengthOrValue] = args;
|
|
30013
|
-
if (typeof lengthOrValue !== "number") {
|
|
30014
|
-
return budgetSandboxValue2([lengthOrValue], budget);
|
|
30015
|
-
}
|
|
30016
|
-
if (!Number.isInteger(lengthOrValue) || lengthOrValue < 0 || lengthOrValue > 4294967295) {
|
|
30017
|
-
throw new RangeError("Invalid array length.");
|
|
31330
|
+
function readDumpController(value) {
|
|
31331
|
+
if (typeof value !== "object" || value === null) {
|
|
31332
|
+
return void 0;
|
|
30018
31333
|
}
|
|
30019
|
-
|
|
30020
|
-
return new Array(lengthOrValue);
|
|
31334
|
+
return value[RUN_DUMP_CONTROLLER];
|
|
30021
31335
|
}
|
|
30022
|
-
|
|
30023
|
-
|
|
30024
|
-
|
|
30025
|
-
|
|
30026
|
-
|
|
30027
|
-
values.push(result.value);
|
|
31336
|
+
|
|
31337
|
+
// packages/safe-js/src/error-codes.ts
|
|
31338
|
+
function getOwnErrorCode(error) {
|
|
31339
|
+
if (typeof error !== "object" || error === null || !Object.prototype.hasOwnProperty.call(error, "code")) {
|
|
31340
|
+
return void 0;
|
|
30028
31341
|
}
|
|
31342
|
+
const code = error.code;
|
|
31343
|
+
return typeof code === "string" ? code : void 0;
|
|
30029
31344
|
}
|
|
30030
|
-
function
|
|
30031
|
-
return
|
|
30032
|
-
}
|
|
30033
|
-
function getOwnEnumerableValues(value) {
|
|
30034
|
-
return ownEnumerableSandboxEntries(value).map(([, entryValue]) => entryValue);
|
|
30035
|
-
}
|
|
30036
|
-
function budgetSandboxValue2(value, budget) {
|
|
30037
|
-
const sandboxValue = deepCopyToSandbox(value);
|
|
30038
|
-
return allocateProducedSandboxValue(sandboxValue, budget);
|
|
31345
|
+
function hasOwnErrorCode(error, code) {
|
|
31346
|
+
return getOwnErrorCode(error) === code;
|
|
30039
31347
|
}
|
|
30040
|
-
|
|
30041
|
-
|
|
30042
|
-
|
|
30043
|
-
|
|
30044
|
-
|
|
30045
|
-
|
|
30046
|
-
|
|
30047
|
-
|
|
30048
|
-
|
|
31348
|
+
|
|
31349
|
+
// packages/safe-js/src/snapshot/backend.ts
|
|
31350
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
31351
|
+
import { readFile, rename, stat, unlink, writeFile } from "node:fs/promises";
|
|
31352
|
+
import { dirname } from "node:path";
|
|
31353
|
+
var DEFAULT_WRITE_MAX_ATTEMPTS = 3;
|
|
31354
|
+
var DEFAULT_WRITE_RETRY_DELAY_MS = 100;
|
|
31355
|
+
var LOCKED_FILE_ERROR_CODES = /* @__PURE__ */ new Set(["EACCES", "EBUSY", "EPERM"]);
|
|
31356
|
+
var pendingOperations = /* @__PURE__ */ new Map();
|
|
31357
|
+
var FileSnapshotBackend = class {
|
|
31358
|
+
constructor(path, options = {}) {
|
|
31359
|
+
this.path = path;
|
|
31360
|
+
this.#writeMaxAttempts = options.writeMaxAttempts ?? DEFAULT_WRITE_MAX_ATTEMPTS;
|
|
31361
|
+
this.#writeRetryDelayMs = options.writeRetryDelayMs ?? DEFAULT_WRITE_RETRY_DELAY_MS;
|
|
30049
31362
|
}
|
|
30050
|
-
|
|
30051
|
-
|
|
30052
|
-
|
|
30053
|
-
|
|
30054
|
-
|
|
30055
|
-
|
|
31363
|
+
path;
|
|
31364
|
+
#writeMaxAttempts;
|
|
31365
|
+
#writeRetryDelayMs;
|
|
31366
|
+
async read() {
|
|
31367
|
+
try {
|
|
31368
|
+
return JSON.parse(await readFile(this.path, "utf8"));
|
|
31369
|
+
} catch (error) {
|
|
31370
|
+
if (hasErrorCode(error, "ENOENT")) {
|
|
31371
|
+
return void 0;
|
|
31372
|
+
}
|
|
31373
|
+
if (error instanceof SyntaxError) {
|
|
31374
|
+
throw new Error(`Failed to parse snapshot at ${this.path}: ${error.message}`);
|
|
31375
|
+
}
|
|
31376
|
+
throw error;
|
|
31377
|
+
}
|
|
30056
31378
|
}
|
|
30057
|
-
|
|
30058
|
-
|
|
30059
|
-
|
|
30060
|
-
|
|
30061
|
-
|
|
30062
|
-
|
|
30063
|
-
|
|
31379
|
+
async write(snapshot) {
|
|
31380
|
+
await enqueueOperation(
|
|
31381
|
+
this.path,
|
|
31382
|
+
() => writeSnapshotAtomically(this.path, snapshot, {
|
|
31383
|
+
maxAttempts: this.#writeMaxAttempts,
|
|
31384
|
+
retryDelayMs: this.#writeRetryDelayMs
|
|
31385
|
+
})
|
|
31386
|
+
);
|
|
30064
31387
|
}
|
|
30065
|
-
|
|
30066
|
-
|
|
30067
|
-
|
|
30068
|
-
|
|
30069
|
-
|
|
31388
|
+
async remove() {
|
|
31389
|
+
await enqueueOperation(this.path, async () => {
|
|
31390
|
+
try {
|
|
31391
|
+
await unlink(this.path);
|
|
31392
|
+
} catch (error) {
|
|
31393
|
+
if (!hasErrorCode(error, "ENOENT")) {
|
|
31394
|
+
throw error;
|
|
31395
|
+
}
|
|
31396
|
+
}
|
|
31397
|
+
});
|
|
30070
31398
|
}
|
|
30071
|
-
|
|
30072
|
-
|
|
30073
|
-
|
|
30074
|
-
const
|
|
30075
|
-
|
|
30076
|
-
|
|
30077
|
-
|
|
30078
|
-
|
|
30079
|
-
|
|
31399
|
+
};
|
|
31400
|
+
async function writeSnapshotAtomically(snapshotPath, snapshot, options) {
|
|
31401
|
+
const parentPath = dirname(snapshotPath);
|
|
31402
|
+
const contents = serializeSafeJSSnapshot(snapshot);
|
|
31403
|
+
await assertParentDirectoryExists(snapshotPath, parentPath);
|
|
31404
|
+
for (let attempt = 1; attempt <= options.maxAttempts; attempt += 1) {
|
|
31405
|
+
try {
|
|
31406
|
+
const temporaryPath = `${snapshotPath}.${randomUUID2()}.tmp`;
|
|
31407
|
+
await writeSnapshotOnce(temporaryPath, snapshotPath, contents);
|
|
31408
|
+
return;
|
|
31409
|
+
} catch (error) {
|
|
31410
|
+
if (hasErrorCode(error, "EEXIST")) {
|
|
31411
|
+
if (attempt === options.maxAttempts) {
|
|
31412
|
+
throw new Error(
|
|
31413
|
+
`Failed to write snapshot at ${snapshotPath} after ${options.maxAttempts} attempts: temporary path already exists`,
|
|
31414
|
+
{
|
|
31415
|
+
cause: error
|
|
31416
|
+
}
|
|
31417
|
+
);
|
|
31418
|
+
}
|
|
31419
|
+
continue;
|
|
31420
|
+
}
|
|
31421
|
+
if (!isLockedFileError(error)) {
|
|
31422
|
+
throw error;
|
|
31423
|
+
}
|
|
31424
|
+
if (attempt === options.maxAttempts) {
|
|
31425
|
+
throw new Error(
|
|
31426
|
+
`Failed to write snapshot at ${snapshotPath} after ${options.maxAttempts} attempts: file is locked (${getOwnErrorCode(error)})`,
|
|
31427
|
+
{
|
|
31428
|
+
cause: error
|
|
31429
|
+
}
|
|
31430
|
+
);
|
|
31431
|
+
}
|
|
31432
|
+
await delay(options.retryDelayMs);
|
|
30080
31433
|
}
|
|
30081
|
-
bindImportDeclaration(statement, registry, wrappedModules, bindings, options);
|
|
30082
31434
|
}
|
|
30083
|
-
return bindings;
|
|
30084
31435
|
}
|
|
30085
|
-
function
|
|
30086
|
-
|
|
30087
|
-
|
|
30088
|
-
|
|
30089
|
-
|
|
30090
|
-
|
|
30091
|
-
createUnknownModuleMessage2(moduleName, [...registry.keys()]),
|
|
30092
|
-
declaration.source.span
|
|
30093
|
-
);
|
|
30094
|
-
}
|
|
30095
|
-
const wrappedExports = wrappedModules.get(moduleName) ?? createBindingRecord(
|
|
30096
|
-
wrapCancelableBindings(
|
|
30097
|
-
wrapCallerInjectedBindings(Object.fromEntries(moduleExports), {
|
|
30098
|
-
budget: options.budget,
|
|
30099
|
-
compileOwner: options.compileOwner,
|
|
30100
|
-
hostCalls: options.hostCalls,
|
|
30101
|
-
moduleId: moduleName,
|
|
30102
|
-
signal: options.signal
|
|
30103
|
-
}),
|
|
30104
|
-
options.signal
|
|
30105
|
-
)
|
|
30106
|
-
);
|
|
30107
|
-
wrappedModules.set(moduleName, wrappedExports);
|
|
30108
|
-
for (const specifier of declaration.specifiers) {
|
|
30109
|
-
const localName = specifier.local.name;
|
|
30110
|
-
if (Object.hasOwn(bindings, localName)) {
|
|
30111
|
-
throw createModuleImportError(
|
|
30112
|
-
`Cannot redeclare imported binding '${localName}'.`,
|
|
30113
|
-
specifier.local.span
|
|
31436
|
+
async function assertParentDirectoryExists(snapshotPath, parentPath) {
|
|
31437
|
+
try {
|
|
31438
|
+
const parent = await stat(parentPath);
|
|
31439
|
+
if (!parent.isDirectory()) {
|
|
31440
|
+
throw new Error(
|
|
31441
|
+
`Cannot write snapshot at ${snapshotPath}: parent path ${parentPath} is not a directory`
|
|
30114
31442
|
);
|
|
30115
31443
|
}
|
|
30116
|
-
|
|
30117
|
-
|
|
30118
|
-
|
|
31444
|
+
} catch (error) {
|
|
31445
|
+
if (hasErrorCode(error, "ENOENT")) {
|
|
31446
|
+
throw new Error(
|
|
31447
|
+
`Cannot write snapshot at ${snapshotPath}: parent directory ${parentPath} does not exist`,
|
|
31448
|
+
{
|
|
31449
|
+
cause: error
|
|
31450
|
+
}
|
|
31451
|
+
);
|
|
30119
31452
|
}
|
|
30120
|
-
|
|
31453
|
+
throw error;
|
|
30121
31454
|
}
|
|
30122
31455
|
}
|
|
30123
|
-
function
|
|
30124
|
-
|
|
30125
|
-
|
|
30126
|
-
|
|
30127
|
-
|
|
30128
|
-
|
|
30129
|
-
|
|
30130
|
-
|
|
31456
|
+
async function writeSnapshotOnce(temporaryPath, snapshotPath, contents) {
|
|
31457
|
+
let temporaryCreated = false;
|
|
31458
|
+
let renamed = false;
|
|
31459
|
+
try {
|
|
31460
|
+
try {
|
|
31461
|
+
await writeFile(temporaryPath, contents, { encoding: "utf8", flag: "wx" });
|
|
31462
|
+
temporaryCreated = true;
|
|
31463
|
+
} catch (error) {
|
|
31464
|
+
if (!hasErrorCode(error, "EEXIST")) {
|
|
31465
|
+
await removeTemporarySnapshot(temporaryPath).catch(() => void 0);
|
|
31466
|
+
}
|
|
31467
|
+
throw error;
|
|
31468
|
+
}
|
|
31469
|
+
await rename(temporaryPath, snapshotPath);
|
|
31470
|
+
renamed = true;
|
|
31471
|
+
} finally {
|
|
31472
|
+
if (temporaryCreated && !renamed) {
|
|
31473
|
+
await removeTemporarySnapshot(temporaryPath).catch(() => void 0);
|
|
31474
|
+
}
|
|
30131
31475
|
}
|
|
30132
|
-
throw createModuleImportError(
|
|
30133
|
-
createUnknownExportMessage2(moduleName, exportName, Object.keys(wrappedExports).sort()),
|
|
30134
|
-
specifier.span
|
|
30135
|
-
);
|
|
30136
|
-
}
|
|
30137
|
-
function createModuleImportError(message, span) {
|
|
30138
|
-
const error = new Error(message);
|
|
30139
|
-
attachErrorSpan(error, span);
|
|
30140
|
-
return error;
|
|
30141
31476
|
}
|
|
30142
|
-
function
|
|
30143
|
-
|
|
30144
|
-
|
|
31477
|
+
async function enqueueOperation(path, operation) {
|
|
31478
|
+
const previous = pendingOperations.get(path) ?? Promise.resolve();
|
|
31479
|
+
const pending = previous.catch(() => void 0).then(operation);
|
|
31480
|
+
const queued = pending.catch(() => void 0);
|
|
31481
|
+
pendingOperations.set(path, queued);
|
|
31482
|
+
try {
|
|
31483
|
+
await pending;
|
|
31484
|
+
} finally {
|
|
31485
|
+
if (pendingOperations.get(path) === queued) {
|
|
31486
|
+
pendingOperations.delete(path);
|
|
31487
|
+
}
|
|
30145
31488
|
}
|
|
30146
|
-
const entries = modules instanceof Map ? [...modules.entries()] : Object.entries(modules);
|
|
30147
|
-
const registry = new Map(
|
|
30148
|
-
entries.map(
|
|
30149
|
-
([moduleName, moduleExports]) => [moduleName, normalizeModuleExports(moduleExports)]
|
|
30150
|
-
).sort(([left], [right]) => left.localeCompare(right))
|
|
30151
|
-
);
|
|
30152
|
-
registerModuleHostOperationPolicies(registry);
|
|
30153
|
-
return registry;
|
|
30154
31489
|
}
|
|
30155
|
-
function
|
|
30156
|
-
|
|
30157
|
-
|
|
30158
|
-
|
|
30159
|
-
|
|
30160
|
-
|
|
30161
|
-
const policy = readHostOperationPolicy(value);
|
|
30162
|
-
if (policy !== void 0) {
|
|
30163
|
-
registerPendingHostCallPolicy({ moduleId, operation, policy });
|
|
30164
|
-
}
|
|
31490
|
+
async function removeTemporarySnapshot(temporaryPath) {
|
|
31491
|
+
try {
|
|
31492
|
+
await unlink(temporaryPath);
|
|
31493
|
+
} catch (error) {
|
|
31494
|
+
if (!hasErrorCode(error, "ENOENT")) {
|
|
31495
|
+
throw error;
|
|
30165
31496
|
}
|
|
30166
31497
|
}
|
|
30167
31498
|
}
|
|
30168
|
-
function
|
|
30169
|
-
|
|
30170
|
-
|
|
30171
|
-
|
|
30172
|
-
);
|
|
31499
|
+
async function delay(ms) {
|
|
31500
|
+
if (ms === 0) {
|
|
31501
|
+
return;
|
|
31502
|
+
}
|
|
31503
|
+
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
30173
31504
|
}
|
|
30174
|
-
function
|
|
30175
|
-
return
|
|
31505
|
+
function hasErrorCode(error, code) {
|
|
31506
|
+
return hasOwnErrorCode(error, code);
|
|
31507
|
+
}
|
|
31508
|
+
function isLockedFileError(error) {
|
|
31509
|
+
const code = getOwnErrorCode(error);
|
|
31510
|
+
return code !== void 0 && LOCKED_FILE_ERROR_CODES.has(code);
|
|
30176
31511
|
}
|
|
30177
31512
|
|
|
31513
|
+
// packages/safe-js/src/run.ts
|
|
31514
|
+
import { AsyncLocalStorage as AsyncLocalStorage7 } from "node:async_hooks";
|
|
31515
|
+
|
|
30178
31516
|
// packages/safe-js/src/snapshot/scheduler.ts
|
|
30179
31517
|
var DEFAULT_SNAPSHOT_INTERVAL_MS = 3e4;
|
|
30180
31518
|
function createSnapshotScheduler(options) {
|
|
@@ -30397,9 +31735,10 @@ var UnhandledRejectionError = class extends Error {
|
|
|
30397
31735
|
};
|
|
30398
31736
|
var DEFAULT_MAX_CALL_DEPTH = 1e3;
|
|
30399
31737
|
function run(source, options = {}) {
|
|
31738
|
+
if (options.extensions !== void 0) return runWithExtensions(source, options);
|
|
30400
31739
|
const lifecycle = {
|
|
30401
31740
|
hostCallbackDepth: 0,
|
|
30402
|
-
hostCallbackContext: new
|
|
31741
|
+
hostCallbackContext: new AsyncLocalStorage7()
|
|
30403
31742
|
};
|
|
30404
31743
|
const dumpController = createDumpController(lifecycle);
|
|
30405
31744
|
const promiseTracker = createSandboxPromiseRejectionTracker();
|
|
@@ -30465,32 +31804,7 @@ function run(source, options = {}) {
|
|
|
30465
31804
|
lifecycle
|
|
30466
31805
|
})
|
|
30467
31806
|
);
|
|
30468
|
-
const builtinBindings = {
|
|
30469
|
-
...createConsoleJsonGlobals({
|
|
30470
|
-
compileOwner: operation.owner,
|
|
30471
|
-
budget,
|
|
30472
|
-
hostCalls,
|
|
30473
|
-
sink: options.sink
|
|
30474
|
-
}),
|
|
30475
|
-
...createCollectionGlobals({ budget }),
|
|
30476
|
-
Float32Array: createFloat32ArrayGlobal(budget),
|
|
30477
|
-
...createErrorGlobals({
|
|
30478
|
-
budget
|
|
30479
|
-
}),
|
|
30480
|
-
...createMathGlobals({
|
|
30481
|
-
random: random?.generator.next
|
|
30482
|
-
}),
|
|
30483
|
-
...createObjectArrayGlobals({
|
|
30484
|
-
budget
|
|
30485
|
-
}),
|
|
30486
|
-
...createMiscGlobals({
|
|
30487
|
-
budget
|
|
30488
|
-
}),
|
|
30489
|
-
...createPromiseGlobals({
|
|
30490
|
-
budget
|
|
30491
|
-
}),
|
|
30492
|
-
...createRegexGlobals(operation.owner)
|
|
30493
|
-
};
|
|
31807
|
+
const builtinBindings = createBuiltinBindings({ compileOwner: operation.owner, budget, hostCalls, sink: options.sink, random: random?.generator.next, clock: options.clock });
|
|
30494
31808
|
const importMeta = convertInitialInput(
|
|
30495
31809
|
() => deepCopyToSandbox(options.importMeta ?? {})
|
|
30496
31810
|
);
|
|
@@ -30952,6 +32266,7 @@ export {
|
|
|
30952
32266
|
parse,
|
|
30953
32267
|
parseModule,
|
|
30954
32268
|
hashSource,
|
|
32269
|
+
defineExtension,
|
|
30955
32270
|
noopOtelSink,
|
|
30956
32271
|
bindOtelSpan,
|
|
30957
32272
|
activateOtelSpan,
|
|
@@ -30980,10 +32295,11 @@ export {
|
|
|
30980
32295
|
validateSnapshotMigration,
|
|
30981
32296
|
restore,
|
|
30982
32297
|
lint,
|
|
30983
|
-
|
|
32298
|
+
declareHostOperation,
|
|
30984
32299
|
createSeededRandom,
|
|
32300
|
+
runResources,
|
|
30985
32301
|
createReplayableRandom,
|
|
30986
|
-
|
|
32302
|
+
createRealm,
|
|
30987
32303
|
dump,
|
|
30988
32304
|
dumpCurrent,
|
|
30989
32305
|
getOwnErrorCode,
|
|
@@ -30991,4 +32307,4 @@ export {
|
|
|
30991
32307
|
FileSnapshotBackend,
|
|
30992
32308
|
run
|
|
30993
32309
|
};
|
|
30994
|
-
//# sourceMappingURL=chunk-
|
|
32310
|
+
//# sourceMappingURL=chunk-BWVASPJX.js.map
|