sandboxedjs 0.1.73 → 0.1.74

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.
@@ -12496,7 +12496,7 @@ var require_object_inspect = __commonJS({
12496
12496
  if (depth >= maxDepth && maxDepth > 0 && typeof obj === "object") {
12497
12497
  return isArray2(obj) ? "[Array]" : "[Object]";
12498
12498
  }
12499
- var indent = getIndent(opts, depth);
12499
+ var indent2 = getIndent(opts, depth);
12500
12500
  if (typeof seen === "undefined") {
12501
12501
  seen = [];
12502
12502
  } else if (indexOf(seen, obj) >= 0) {
@@ -12545,8 +12545,8 @@ var require_object_inspect = __commonJS({
12545
12545
  return "[]";
12546
12546
  }
12547
12547
  var xs = arrObjKeys(obj, inspect2);
12548
- if (indent && !singleLineValues(xs)) {
12549
- return "[" + indentedJoin(xs, indent) + "]";
12548
+ if (indent2 && !singleLineValues(xs)) {
12549
+ return "[" + indentedJoin(xs, indent2) + "]";
12550
12550
  }
12551
12551
  return "[ " + $join.call(xs, ", ") + " ]";
12552
12552
  }
@@ -12574,7 +12574,7 @@ var require_object_inspect = __commonJS({
12574
12574
  mapParts.push(inspect2(key, obj, true) + " => " + inspect2(value, obj));
12575
12575
  });
12576
12576
  }
12577
- return collectionOf("Map", mapSize.call(obj), mapParts, indent);
12577
+ return collectionOf("Map", mapSize.call(obj), mapParts, indent2);
12578
12578
  }
12579
12579
  if (isSet(obj)) {
12580
12580
  var setParts = [];
@@ -12583,7 +12583,7 @@ var require_object_inspect = __commonJS({
12583
12583
  setParts.push(inspect2(value, obj));
12584
12584
  });
12585
12585
  }
12586
- return collectionOf("Set", setSize.call(obj), setParts, indent);
12586
+ return collectionOf("Set", setSize.call(obj), setParts, indent2);
12587
12587
  }
12588
12588
  if (isWeakMap(obj)) {
12589
12589
  return weakCollectionOf("WeakMap");
@@ -12622,8 +12622,8 @@ var require_object_inspect = __commonJS({
12622
12622
  if (ys.length === 0) {
12623
12623
  return tag2 + "{}";
12624
12624
  }
12625
- if (indent) {
12626
- return tag2 + "{" + indentedJoin(ys, indent) + "}";
12625
+ if (indent2) {
12626
+ return tag2 + "{" + indentedJoin(ys, indent2) + "}";
12627
12627
  }
12628
12628
  return tag2 + "{ " + $join.call(ys, ", ") + " }";
12629
12629
  }
@@ -12834,8 +12834,8 @@ var require_object_inspect = __commonJS({
12834
12834
  function weakCollectionOf(type) {
12835
12835
  return type + " { ? }";
12836
12836
  }
12837
- function collectionOf(type, size, entries, indent) {
12838
- var joinedEntries = indent ? indentedJoin(entries, indent) : $join.call(entries, ", ");
12837
+ function collectionOf(type, size, entries, indent2) {
12838
+ var joinedEntries = indent2 ? indentedJoin(entries, indent2) : $join.call(entries, ", ");
12839
12839
  return type + " (" + size + ") {" + joinedEntries + "}";
12840
12840
  }
12841
12841
  function singleLineValues(xs) {
@@ -12860,12 +12860,12 @@ var require_object_inspect = __commonJS({
12860
12860
  prev: $join.call(Array(depth + 1), baseIndent)
12861
12861
  };
12862
12862
  }
12863
- function indentedJoin(xs, indent) {
12863
+ function indentedJoin(xs, indent2) {
12864
12864
  if (xs.length === 0) {
12865
12865
  return "";
12866
12866
  }
12867
- var lineJoiner = "\n" + indent.prev + indent.base;
12868
- return lineJoiner + $join.call(xs, "," + lineJoiner) + "\n" + indent.prev;
12867
+ var lineJoiner = "\n" + indent2.prev + indent2.base;
12868
+ return lineJoiner + $join.call(xs, "," + lineJoiner) + "\n" + indent2.prev;
12869
12869
  }
12870
12870
  function arrObjKeys(obj, inspect2) {
12871
12871
  var isArr = isArray2(obj);
@@ -21669,6 +21669,7 @@ function f(e2, r2, t2) {
21669
21669
 
21670
21670
  // src/node/commonjs-engine.ts
21671
21671
  var EXTENSIONS = [".js", ".mjs", ".cjs", ".json", ".node"];
21672
+ var PREFIX_ONLY_BUILTINS = /* @__PURE__ */ new Set(["test", "test/reporters", "sea", "sqlite"]);
21672
21673
  var CONDITION_SETS = {
21673
21674
  import: [["node", "import", "module", "default"], ["node", "require", "default"], ["default"]],
21674
21675
  require: [["node", "require", "default"], ["node", "import", "module", "default"], ["default"]]
@@ -22008,7 +22009,8 @@ ${code}
22008
22009
  }
22009
22010
  builtin(specifier, importer) {
22010
22011
  const name = specifier.replace(/^node:/, "");
22011
- if (!Object.prototype.hasOwnProperty.call(this.builtins, name)) {
22012
+ const prefixOnly = PREFIX_ONLY_BUILTINS.has(name) && !specifier.startsWith("node:");
22013
+ if (prefixOnly || !Object.prototype.hasOwnProperty.call(this.builtins, name)) {
22012
22014
  return Object.prototype.hasOwnProperty.call(this.overrides, specifier) ? { found: true, value: this.overrides[specifier] } : { found: false, value: void 0 };
22013
22015
  }
22014
22016
  if (name === "module" && importer) {
@@ -27132,6 +27134,79 @@ var url_module_default = urlModule;
27132
27134
  // src/node/virtual-http.ts
27133
27135
  var import_events = __toESM(require_events());
27134
27136
  var import_stream_browserify2 = __toESM(require_stream_browserify());
27137
+
27138
+ // src/net/policy.ts
27139
+ function isLoopbackHostname(hostname) {
27140
+ const host = hostname.replace(/^\[|\]$/g, "").toLowerCase();
27141
+ return host === "localhost" || host === "0.0.0.0" || host === "::1" || host === "::" || host.startsWith("127.") || host.endsWith(".localhost");
27142
+ }
27143
+ function outboundAllowed(policy, url) {
27144
+ if (!policy.allowOutbound) return false;
27145
+ let hostname;
27146
+ try {
27147
+ hostname = new URL(url).hostname;
27148
+ } catch {
27149
+ return false;
27150
+ }
27151
+ if (isLoopbackHostname(hostname)) return false;
27152
+ const hosts = policy.allowedHosts;
27153
+ if (!hosts) return true;
27154
+ return hosts.some((allowed) => hostname === allowed || hostname.endsWith(`.${allowed}`));
27155
+ }
27156
+ function outboundBlockedError(url) {
27157
+ let host = url;
27158
+ try {
27159
+ host = new URL(url).host;
27160
+ } catch {
27161
+ }
27162
+ return Object.assign(
27163
+ new Error(
27164
+ `connect ENETUNREACH ${host}: outbound network access is disabled for this container (allowed by the host with network.allowOutbound and network.allowedHosts)`
27165
+ ),
27166
+ { code: "ENETUNREACH", errno: -101, syscall: "connect", hostname: host }
27167
+ );
27168
+ }
27169
+ function requestUrl(input) {
27170
+ if (typeof input === "string") return input;
27171
+ if (input instanceof URL) return input.href;
27172
+ return input.url;
27173
+ }
27174
+ function policedFetch(policy, fetchImpl) {
27175
+ return (async (input, init) => {
27176
+ const url = requestUrl(input);
27177
+ if (!outboundAllowed(policy, url)) {
27178
+ throw Object.assign(new TypeError("fetch failed"), { cause: outboundBlockedError(url) });
27179
+ }
27180
+ return fetchImpl(input, init);
27181
+ });
27182
+ }
27183
+ function policedWebSocket(Native, policy) {
27184
+ const Base = Native;
27185
+ return class PolicedWebSocket extends Base {
27186
+ constructor(url, protocols) {
27187
+ const href = url instanceof URL ? url.href : String(url);
27188
+ let parsed = null;
27189
+ try {
27190
+ parsed = new URL(href);
27191
+ } catch {
27192
+ }
27193
+ if (parsed && isLoopbackHostname(parsed.hostname)) {
27194
+ throw Object.assign(
27195
+ new Error(
27196
+ `WebSocket to ${parsed.host} is not available from a program inside the container; reach servers in the container over HTTP`
27197
+ ),
27198
+ { code: "ERR_UNSUPPORTED" }
27199
+ );
27200
+ }
27201
+ if (parsed && !outboundAllowed(policy, href.replace(/^ws(s?):/i, "http$1:"))) {
27202
+ throw outboundBlockedError(href);
27203
+ }
27204
+ super(url, protocols);
27205
+ }
27206
+ };
27207
+ }
27208
+
27209
+ // src/node/virtual-http.ts
27135
27210
  var VirtualIncomingMessage = class extends import_stream_browserify2.default.Readable {
27136
27211
  method;
27137
27212
  url;
@@ -27527,21 +27602,23 @@ function resolveTarget(input, overrides, defaultProtocol) {
27527
27602
  };
27528
27603
  }
27529
27604
  function isLoopback(hostname) {
27530
- return hostname === "localhost" || hostname === "0.0.0.0" || hostname === "::1" || hostname === "::" || hostname.startsWith("127.") || hostname.endsWith(".localhost");
27605
+ return isLoopbackHostname(hostname);
27531
27606
  }
27532
27607
  var VirtualClientRequest = class extends import_stream_browserify2.default.Writable {
27533
- constructor(target, router, fetchImpl, trackRequest) {
27608
+ constructor(target, router, fetchImpl, trackRequest, loopback = void 0) {
27534
27609
  super();
27535
27610
  this.target = target;
27536
27611
  this.router = router;
27537
27612
  this.fetchImpl = fetchImpl;
27538
27613
  this.trackRequest = trackRequest;
27614
+ this.loopback = loopback;
27539
27615
  for (const [name, value] of Object.entries(target.headers)) this.setHeader(name, value);
27540
27616
  }
27541
27617
  target;
27542
27618
  router;
27543
27619
  fetchImpl;
27544
27620
  trackRequest;
27621
+ loopback;
27545
27622
  socket = socketStub();
27546
27623
  connection = this.socket;
27547
27624
  chunks = [];
@@ -27655,7 +27732,9 @@ var VirtualClientRequest = class extends import_stream_browserify2.default.Writa
27655
27732
  } catch (error) {
27656
27733
  clearTimeout(this.timer);
27657
27734
  if (this.destroyedByUser) return;
27658
- const failure = error instanceof Error ? error : new Error(String(error));
27735
+ const thrown = error instanceof Error ? error : new Error(String(error));
27736
+ const cause = thrown.cause;
27737
+ const failure = cause instanceof Error && "code" in cause ? cause : thrown;
27659
27738
  if (!("code" in failure)) Object.assign(failure, { code: "ECONNREFUSED" });
27660
27739
  this.emit("error", failure);
27661
27740
  } finally {
@@ -27663,18 +27742,21 @@ var VirtualClientRequest = class extends import_stream_browserify2.default.Writa
27663
27742
  }
27664
27743
  }
27665
27744
  async viaRouter(body) {
27666
- if (!this.router.activePortsIncludes(this.target.port)) {
27745
+ const init = {
27746
+ method: this.target.method,
27747
+ path: this.target.path,
27748
+ headers: this.getHeaders(),
27749
+ body: body.length ? new Uint8Array(body) : null
27750
+ };
27751
+ const local = this.router.activePortsIncludes(this.target.port);
27752
+ const remote = local || !this.loopback ? null : await this.loopback(this.target.port, init);
27753
+ if (!local && !remote) {
27667
27754
  throw Object.assign(
27668
27755
  new Error(`connect ECONNREFUSED ${this.target.hostname}:${this.target.port}`),
27669
27756
  { code: "ECONNREFUSED", errno: -61, syscall: "connect", address: this.target.hostname, port: this.target.port }
27670
27757
  );
27671
27758
  }
27672
- const result = await this.router.request(this.target.port, {
27673
- method: this.target.method,
27674
- path: this.target.path,
27675
- headers: this.getHeaders(),
27676
- body: body.length ? new Uint8Array(body) : null
27677
- });
27759
+ const result = remote ?? await this.router.request(this.target.port, init);
27678
27760
  const body_ = result.body;
27679
27761
  const bytes2 = typeof body_ === "string" ? new TextEncoder().encode(body_) : body_ instanceof ArrayBuffer ? new Uint8Array(body_) : body_ ?? new Uint8Array();
27680
27762
  const status = result.statusCode ?? 200;
@@ -27714,7 +27796,13 @@ function createHttpModule(router, owner, options = {}, defaultProtocol = "http:"
27714
27796
  const request = (input, second, third) => {
27715
27797
  const overrides = second && typeof second === "object" && !(second instanceof Function) ? second : void 0;
27716
27798
  const callback = [second, third].find((value) => typeof value === "function");
27717
- const req = new VirtualClientRequest(resolveTarget(input, overrides, defaultProtocol), router, options.fetch, options.trackRequest);
27799
+ const req = new VirtualClientRequest(
27800
+ resolveTarget(input, overrides, defaultProtocol),
27801
+ router,
27802
+ options.fetch,
27803
+ options.trackRequest,
27804
+ options.loopback
27805
+ );
27718
27806
  if (callback) req.on("response", callback);
27719
27807
  return req;
27720
27808
  };
@@ -27741,6 +27829,62 @@ function createHttpModule(router, owner, options = {}, defaultProtocol = "http:"
27741
27829
  }
27742
27830
  };
27743
27831
  }
27832
+ function createVirtualFetch(router, options = {}) {
27833
+ return (async (input, init) => {
27834
+ const request = new Request(input, init);
27835
+ const url = new URL(request.url);
27836
+ const release = options.trackRequest?.();
27837
+ try {
27838
+ if (!isLoopback(url.hostname)) {
27839
+ if (!options.fetch) {
27840
+ throw Object.assign(new TypeError("fetch failed"), {
27841
+ cause: Object.assign(new Error(`getaddrinfo ENOTFOUND ${url.hostname}`), { code: "ENOTFOUND" })
27842
+ });
27843
+ }
27844
+ return await options.fetch(request);
27845
+ }
27846
+ const port = Number(url.port || (url.protocol === "https:" ? 443 : 80));
27847
+ const headers = {};
27848
+ request.headers.forEach((value, key) => {
27849
+ headers[key] = value;
27850
+ });
27851
+ const bodyless = request.method === "GET" || request.method === "HEAD";
27852
+ const loopbackRequest = {
27853
+ method: request.method,
27854
+ path: `${url.pathname}${url.search}`,
27855
+ headers,
27856
+ body: bodyless ? null : new Uint8Array(await request.arrayBuffer())
27857
+ };
27858
+ const result = router.activePortsIncludes(port) ? await router.request(port, loopbackRequest) : await options.loopback?.(port, loopbackRequest) ?? null;
27859
+ if (!result) {
27860
+ throw Object.assign(new TypeError("fetch failed"), {
27861
+ cause: Object.assign(new Error(`connect ECONNREFUSED ${url.hostname}:${port}`), {
27862
+ code: "ECONNREFUSED",
27863
+ errno: -61,
27864
+ syscall: "connect",
27865
+ address: url.hostname,
27866
+ port
27867
+ })
27868
+ });
27869
+ }
27870
+ const status = result.statusCode ?? 200;
27871
+ const responseHeaders = new Headers();
27872
+ for (const [name, value] of Object.entries(result.headers ?? {})) {
27873
+ for (const part of Array.isArray(value) ? value : [value]) responseHeaders.append(name, String(part));
27874
+ }
27875
+ const raw = result.body;
27876
+ const bytes2 = typeof raw === "string" ? new TextEncoder().encode(raw) : raw instanceof ArrayBuffer ? new Uint8Array(raw) : raw ?? new Uint8Array();
27877
+ const nullBody = status === 204 || status === 205 || status === 304 || request.method === "HEAD";
27878
+ return new Response(nullBody ? null : new Uint8Array(bytes2), {
27879
+ status,
27880
+ statusText: result.statusMessage ?? STATUS_CODES[status] ?? "",
27881
+ headers: responseHeaders
27882
+ });
27883
+ } finally {
27884
+ release?.();
27885
+ }
27886
+ });
27887
+ }
27744
27888
  function validateHeaderName(name) {
27745
27889
  if (!/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/.test(name)) throw Object.assign(new TypeError(`Header name must be a valid HTTP token [${name}]`), { code: "ERR_INVALID_HTTP_TOKEN" });
27746
27890
  }
@@ -27761,6 +27905,492 @@ function socketStub() {
27761
27905
  var METHODS = ["ACL", "BIND", "CHECKOUT", "CONNECT", "COPY", "DELETE", "GET", "HEAD", "LINK", "LOCK", "M-SEARCH", "MERGE", "MKACTIVITY", "MKCALENDAR", "MKCOL", "MOVE", "NOTIFY", "OPTIONS", "PATCH", "POST", "PROPFIND", "PROPPATCH", "PURGE", "PUT", "REBIND", "REPORT", "SEARCH", "SOURCE", "SUBSCRIBE", "TRACE", "UNBIND", "UNLINK", "UNLOCK", "UNSUBSCRIBE"];
27762
27906
  var STATUS_CODES = { 100: "Continue", 200: "OK", 201: "Created", 202: "Accepted", 204: "No Content", 206: "Partial Content", 301: "Moved Permanently", 302: "Found", 304: "Not Modified", 307: "Temporary Redirect", 308: "Permanent Redirect", 400: "Bad Request", 401: "Unauthorized", 403: "Forbidden", 404: "Not Found", 405: "Method Not Allowed", 409: "Conflict", 413: "Payload Too Large", 415: "Unsupported Media Type", 422: "Unprocessable Entity", 429: "Too Many Requests", 500: "Internal Server Error", 501: "Not Implemented", 502: "Bad Gateway", 503: "Service Unavailable" };
27763
27907
 
27908
+ // src/node/test-module.ts
27909
+ function parseArguments(args) {
27910
+ let name = "<anonymous>";
27911
+ let options = {};
27912
+ let fn;
27913
+ for (const arg of args) {
27914
+ if (typeof arg === "string") name = arg;
27915
+ else if (typeof arg === "function") {
27916
+ fn = arg;
27917
+ if (name === "<anonymous>" && arg.name) name = arg.name;
27918
+ } else if (arg && typeof arg === "object") options = arg;
27919
+ }
27920
+ return { name, options, fn };
27921
+ }
27922
+ function errorText(error) {
27923
+ if (error instanceof Error) {
27924
+ const stack = error.stack ?? `${error.name}: ${error.message}`;
27925
+ return stack.includes(error.message) ? stack : `${error.name}: ${error.message}
27926
+ ${stack}`;
27927
+ }
27928
+ return String(error);
27929
+ }
27930
+ function indent(text, spaces) {
27931
+ const pad = " ".repeat(spaces);
27932
+ return text.split("\n").map((line) => line ? pad + line : line).join("\n");
27933
+ }
27934
+ function duration(started) {
27935
+ return (performance.now() - started).toFixed(6).replace(/\.?0+$/, "");
27936
+ }
27937
+ function invoke(host, fn, context, timeout) {
27938
+ const body = new Promise((resolve2, reject) => {
27939
+ if (fn.length >= 2) {
27940
+ let settled = false;
27941
+ const done = (error) => {
27942
+ if (settled) return;
27943
+ settled = true;
27944
+ if (error) reject(error);
27945
+ else resolve2();
27946
+ };
27947
+ try {
27948
+ const returned = fn(context, done);
27949
+ if (returned && typeof returned.then === "function") {
27950
+ reject(new Error("passed a callback but also returned a Promise"));
27951
+ }
27952
+ } catch (error) {
27953
+ done(error);
27954
+ }
27955
+ return;
27956
+ }
27957
+ try {
27958
+ Promise.resolve(fn(context)).then(() => resolve2(), reject);
27959
+ } catch (error) {
27960
+ reject(error);
27961
+ }
27962
+ });
27963
+ if (timeout === void 0 || !Number.isFinite(timeout)) return body;
27964
+ return new Promise((resolve2, reject) => {
27965
+ const timer = host.setTimeout(() => reject(new Error(`test timed out after ${timeout}ms`)), timeout);
27966
+ body.then(
27967
+ () => {
27968
+ host.clearTimeout(timer);
27969
+ resolve2();
27970
+ },
27971
+ (error) => {
27972
+ host.clearTimeout(timer);
27973
+ reject(error);
27974
+ }
27975
+ );
27976
+ });
27977
+ }
27978
+ function createMockTracker() {
27979
+ const restorers = [];
27980
+ const fn = (original = () => void 0, implementation = original) => {
27981
+ let current2 = implementation;
27982
+ const once = /* @__PURE__ */ new Map();
27983
+ const calls = [];
27984
+ const mocked = function(...args) {
27985
+ const index = calls.length;
27986
+ const chosen = once.get(index) ?? current2;
27987
+ once.delete(index);
27988
+ const call = { arguments: args, result: void 0, error: void 0, this: this };
27989
+ calls.push(call);
27990
+ try {
27991
+ call.result = chosen.apply(this, args);
27992
+ return call.result;
27993
+ } catch (error) {
27994
+ call.error = error;
27995
+ throw error;
27996
+ }
27997
+ };
27998
+ Object.defineProperty(mocked, "mock", {
27999
+ value: {
28000
+ calls,
28001
+ callCount: () => calls.length,
28002
+ resetCalls: () => {
28003
+ calls.length = 0;
28004
+ },
28005
+ mockImplementation: (next) => {
28006
+ current2 = next;
28007
+ },
28008
+ mockImplementationOnce: (next, onCall) => {
28009
+ once.set(onCall ?? calls.length, next);
28010
+ },
28011
+ restore: () => {
28012
+ current2 = original;
28013
+ }
28014
+ }
28015
+ });
28016
+ return mocked;
28017
+ };
28018
+ const method = (object, name, implementation) => {
28019
+ const original = object[name];
28020
+ if (typeof original !== "function") {
28021
+ throw new TypeError(`The property '${name}' is not a function and cannot be mocked`);
28022
+ }
28023
+ const mocked = fn(original, implementation ?? original);
28024
+ object[name] = mocked;
28025
+ const restore = () => {
28026
+ object[name] = original;
28027
+ };
28028
+ mocked.mock.restore = restore;
28029
+ restorers.push(restore);
28030
+ return mocked;
28031
+ };
28032
+ return {
28033
+ fn,
28034
+ method,
28035
+ reset: () => {
28036
+ for (const restore of restorers.splice(0)) restore();
28037
+ },
28038
+ restoreAll: () => {
28039
+ for (const restore of restorers.splice(0)) restore();
28040
+ }
28041
+ };
28042
+ }
28043
+ function createTestModule(host) {
28044
+ const root = {
28045
+ kind: "suite",
28046
+ name: "",
28047
+ options: {},
28048
+ parent: null,
28049
+ children: [],
28050
+ hooks: { before: [], after: [], beforeEach: [], afterEach: [] }
28051
+ };
28052
+ let collecting = root;
28053
+ let scheduled = false;
28054
+ let running = null;
28055
+ const mock = createMockTracker();
28056
+ const counts = { tests: 0, suites: 0, pass: 0, fail: 0, cancelled: 0, skipped: 0, todo: 0 };
28057
+ const failures = [];
28058
+ let tapIndex = 0;
28059
+ let onlyWarned = false;
28060
+ const settings = () => host.settings();
28061
+ const tap = () => settings().reporter === "tap";
28062
+ const schedule = () => {
28063
+ if (scheduled) return;
28064
+ scheduled = true;
28065
+ host.setTimeout(() => {
28066
+ running = runAll();
28067
+ }, 0);
28068
+ };
28069
+ const fullName = (node) => {
28070
+ const parts = [];
28071
+ let cursor = node;
28072
+ while (cursor && cursor !== root) {
28073
+ parts.unshift(cursor.name);
28074
+ cursor = cursor.parent;
28075
+ }
28076
+ return parts.join(" ");
28077
+ };
28078
+ const matchesPattern = (name) => {
28079
+ const patterns = settings().namePatterns ?? [];
28080
+ if (patterns.length === 0) return true;
28081
+ return patterns.some((pattern) => {
28082
+ try {
28083
+ return new RegExp(pattern).test(name);
28084
+ } catch {
28085
+ return name.includes(pattern);
28086
+ }
28087
+ });
28088
+ };
28089
+ const hasOnly = (node) => Boolean(node.options.only) || node.kind === "suite" && node.children.some(hasOnly);
28090
+ const report = (depth, outcome, name, started, detail) => {
28091
+ if (tap()) {
28092
+ tapIndex += 1;
28093
+ const ok2 = outcome === "fail" ? "not ok" : "ok";
28094
+ const directive = outcome === "skip" ? " # SKIP" : outcome === "todo" ? " # TODO" : outcome === "cancelled" ? " # CANCELLED" : "";
28095
+ host.write(`${ok2} ${tapIndex} - ${name}${directive}
28096
+ `);
28097
+ host.write(` ---
28098
+ duration_ms: ${duration(started)}
28099
+ `);
28100
+ if (detail) host.write(` error: |-
28101
+ ${indent(detail, 4)}
28102
+ `);
28103
+ host.write(" ...\n");
28104
+ return;
28105
+ }
28106
+ const pad = " ".repeat(depth);
28107
+ const mark = outcome === "pass" ? "\u2714" : outcome === "fail" ? "\u2716" : outcome === "cancelled" ? "\u2716" : "\uFE63";
28108
+ const suffix = outcome === "skip" ? " # SKIP" : outcome === "todo" ? " # TODO" : "";
28109
+ host.write(`${pad}${mark} ${name} (${duration(started)}ms)${suffix}
28110
+ `);
28111
+ if (detail) host.write(`${indent(detail, depth * 2 + 2)}
28112
+ `);
28113
+ };
28114
+ const record = (outcome, name, error) => {
28115
+ counts.tests += 1;
28116
+ if (outcome === "pass") counts.pass += 1;
28117
+ else if (outcome === "fail") {
28118
+ counts.fail += 1;
28119
+ failures.push({ name, error });
28120
+ } else if (outcome === "cancelled") {
28121
+ counts.cancelled += 1;
28122
+ failures.push({ name, error });
28123
+ } else if (outcome === "skip") counts.skipped += 1;
28124
+ else counts.todo += 1;
28125
+ };
28126
+ const ancestors = (suite) => {
28127
+ const chain = [];
28128
+ for (let cursor = suite; cursor; cursor = cursor.parent) chain.unshift(cursor);
28129
+ return chain;
28130
+ };
28131
+ const runTest = async (name, display, options, fn, depth, suite, extraHooks, runOnly) => {
28132
+ const started = performance.now();
28133
+ if (!matchesPattern(display)) return true;
28134
+ if (runOnly && !options.only) return true;
28135
+ if (options.skip) {
28136
+ record("skip", display);
28137
+ report(depth, "skip", name, started);
28138
+ return true;
28139
+ }
28140
+ if (!fn) {
28141
+ const outcome = options.todo ? "todo" : "skip";
28142
+ record(outcome, display);
28143
+ report(depth, outcome, name, started);
28144
+ return true;
28145
+ }
28146
+ const controller = new AbortController();
28147
+ const subtests = [];
28148
+ const ownHooks = { before: [], after: [], beforeEach: [], afterEach: [] };
28149
+ let skipped = false;
28150
+ let todo = options.todo ?? false;
28151
+ const context = {
28152
+ name,
28153
+ fullName: display,
28154
+ signal: controller.signal,
28155
+ mock,
28156
+ test: (...args) => {
28157
+ const sub = parseArguments(args);
28158
+ const promise = runTest(
28159
+ sub.name,
28160
+ `${display} ${sub.name}`,
28161
+ sub.options,
28162
+ sub.fn,
28163
+ depth + 1,
28164
+ suite,
28165
+ ownHooks,
28166
+ false
28167
+ );
28168
+ subtests.push(promise);
28169
+ return promise.then(() => void 0);
28170
+ },
28171
+ skip: (message) => {
28172
+ skipped = message ?? true;
28173
+ },
28174
+ todo: (message) => {
28175
+ todo = message ?? true;
28176
+ },
28177
+ diagnostic: (message) => {
28178
+ host.write(tap() ? `# ${message}
28179
+ ` : `${" ".repeat(depth + 1)}\u2139 ${message}
28180
+ `);
28181
+ },
28182
+ plan: () => {
28183
+ },
28184
+ before: (hook2) => ownHooks.before.push(hook2),
28185
+ after: (hook2) => ownHooks.after.push(hook2),
28186
+ beforeEach: (hook2) => ownHooks.beforeEach.push(hook2),
28187
+ afterEach: (hook2) => ownHooks.afterEach.push(hook2)
28188
+ };
28189
+ let error;
28190
+ try {
28191
+ const chain = ancestors(suite);
28192
+ for (const level of chain) for (const hook2 of level.hooks.beforeEach) await invoke(host, hook2, context, void 0);
28193
+ for (const hook2 of extraHooks.beforeEach) await invoke(host, hook2, context, void 0);
28194
+ await invoke(host, fn, context, options.timeout);
28195
+ const results = await Promise.all(subtests);
28196
+ for (const hook2 of ownHooks.after) await invoke(host, hook2, context, void 0);
28197
+ if (results.includes(false)) error = new Error(`${results.filter((ok2) => !ok2).length} subtest(s) failed`);
28198
+ for (const hook2 of extraHooks.afterEach) await invoke(host, hook2, context, void 0);
28199
+ for (const level of [...chain].reverse()) for (const hook2 of level.hooks.afterEach) await invoke(host, hook2, context, void 0);
28200
+ } catch (caught) {
28201
+ error = caught;
28202
+ } finally {
28203
+ controller.abort();
28204
+ }
28205
+ if (skipped) {
28206
+ record("skip", display);
28207
+ report(depth, "skip", name, started);
28208
+ return true;
28209
+ }
28210
+ if (error !== void 0) {
28211
+ if (todo) {
28212
+ record("todo", display);
28213
+ report(depth, "todo", name, started);
28214
+ return true;
28215
+ }
28216
+ record("fail", display, error);
28217
+ report(depth, "fail", name, started, errorText(error));
28218
+ return false;
28219
+ }
28220
+ record(todo ? "todo" : "pass", display);
28221
+ report(depth, todo ? "todo" : "pass", name, started);
28222
+ return true;
28223
+ };
28224
+ const runSuite = async (suite, depth, runOnly) => {
28225
+ const started = performance.now();
28226
+ const display = fullName(suite);
28227
+ const isRoot = suite === root;
28228
+ if (!isRoot) {
28229
+ counts.suites += 1;
28230
+ if (tap()) host.write(`# Subtest: ${suite.name}
28231
+ `);
28232
+ else host.write(`${" ".repeat(depth)}\u25B6 ${suite.name}
28233
+ `);
28234
+ if (suite.options.skip) {
28235
+ for (const child of suite.children) if (child.kind === "test") record("skip", fullName(child));
28236
+ report(depth, "skip", suite.name, started);
28237
+ return true;
28238
+ }
28239
+ }
28240
+ const context = { name: suite.name, signal: new AbortController().signal };
28241
+ let ok2 = true;
28242
+ try {
28243
+ for (const hook2 of suite.hooks.before) await invoke(host, hook2, context, void 0);
28244
+ } catch (error) {
28245
+ for (const child of suite.children) {
28246
+ if (child.kind === "test") {
28247
+ record("cancelled", fullName(child), error);
28248
+ report(depth + (isRoot ? 0 : 1), "cancelled", child.name, started, errorText(error));
28249
+ }
28250
+ }
28251
+ if (!isRoot) report(depth, "fail", suite.name, started);
28252
+ return false;
28253
+ }
28254
+ const only = runOnly || settings().only === true && suite.children.some(hasOnly);
28255
+ for (const child of suite.children) {
28256
+ const childDepth = depth + (isRoot ? 0 : 1);
28257
+ if (child.kind === "suite") {
28258
+ if (only && !hasOnly(child) && !child.options.only) continue;
28259
+ ok2 = await runSuite(child, childDepth, only && !child.options.only) && ok2;
28260
+ } else {
28261
+ ok2 = await runTest(
28262
+ child.name,
28263
+ fullName(child),
28264
+ child.options,
28265
+ child.fn,
28266
+ childDepth,
28267
+ suite,
28268
+ { before: [], after: [], beforeEach: [], afterEach: [] },
28269
+ only
28270
+ ) && ok2;
28271
+ }
28272
+ }
28273
+ try {
28274
+ for (const hook2 of suite.hooks.after) await invoke(host, hook2, context, void 0);
28275
+ } catch (error) {
28276
+ ok2 = false;
28277
+ failures.push({ name: `${display || "<root>"} (after hook)`, error });
28278
+ host.write(`${indent(`\u2716 after hook failed
28279
+ ${errorText(error)}`, depth * 2)}
28280
+ `);
28281
+ }
28282
+ if (!isRoot) {
28283
+ if (tap()) host.write(`${ok2 ? "ok" : "not ok"} ${++tapIndex} - ${suite.name}
28284
+ `);
28285
+ else host.write(`${" ".repeat(depth)}${ok2 ? "\u25B6" : "\u2716"} ${suite.name} (${duration(started)}ms)
28286
+ `);
28287
+ }
28288
+ return ok2;
28289
+ };
28290
+ const runAll = async () => {
28291
+ const release = host.keepAlive();
28292
+ const started = performance.now();
28293
+ if (tap()) host.write("TAP version 13\n");
28294
+ if (!settings().only && !onlyWarned && root.children.some(hasOnly)) {
28295
+ onlyWarned = true;
28296
+ host.write("\u2139 'only' and 'runOnly' require the --test-only command-line option.\n");
28297
+ }
28298
+ let ok2 = true;
28299
+ try {
28300
+ ok2 = await runSuite(root, 0, false);
28301
+ } catch (error) {
28302
+ ok2 = false;
28303
+ failures.push({ name: "<test runner>", error });
28304
+ }
28305
+ mock.restoreAll();
28306
+ if (tap()) {
28307
+ host.write(`1..${tapIndex}
28308
+ `);
28309
+ for (const [key, value] of Object.entries(counts)) host.write(`# ${key} ${value}
28310
+ `);
28311
+ host.write(`# duration_ms ${duration(started)}
28312
+ `);
28313
+ } else {
28314
+ for (const [key, value] of Object.entries(counts)) host.write(`\u2139 ${key} ${value}
28315
+ `);
28316
+ host.write(`\u2139 duration_ms ${duration(started)}
28317
+ `);
28318
+ if (failures.length > 0) {
28319
+ host.write("\n\u2716 failing tests:\n\n");
28320
+ for (const failure of failures) host.write(`test at ${failure.name}
28321
+ ${indent(errorText(failure.error), 2)}
28322
+
28323
+ `);
28324
+ }
28325
+ }
28326
+ release();
28327
+ host.exit(ok2 && counts.fail === 0 && counts.cancelled === 0 ? 0 : 1);
28328
+ };
28329
+ const declareTest = (extra) => (...args) => {
28330
+ const { name, options, fn } = parseArguments(args);
28331
+ if (running && collecting === root && scheduled) {
28332
+ host.write(`\u2716 test "${name}" was declared after the run started and did not run
28333
+ `);
28334
+ return Promise.resolve();
28335
+ }
28336
+ collecting.children.push({ kind: "test", name, options: { ...options, ...extra }, parent: collecting, fn });
28337
+ schedule();
28338
+ return Promise.resolve();
28339
+ };
28340
+ const declareSuite = (extra) => (...args) => {
28341
+ const { name, options, fn } = parseArguments(args);
28342
+ const suite = {
28343
+ kind: "suite",
28344
+ name,
28345
+ options: { ...options, ...extra },
28346
+ parent: collecting,
28347
+ children: [],
28348
+ hooks: { before: [], after: [], beforeEach: [], afterEach: [] }
28349
+ };
28350
+ collecting.children.push(suite);
28351
+ schedule();
28352
+ const previous = collecting;
28353
+ collecting = suite;
28354
+ try {
28355
+ fn?.({ name, signal: new AbortController().signal });
28356
+ } finally {
28357
+ collecting = previous;
28358
+ }
28359
+ return Promise.resolve();
28360
+ };
28361
+ const withModifiers = (make) => {
28362
+ const base2 = make({});
28363
+ base2.skip = make({ skip: true });
28364
+ base2.todo = make({ todo: true });
28365
+ base2.only = make({ only: true });
28366
+ return base2;
28367
+ };
28368
+ const test = withModifiers(declareTest);
28369
+ const describe2 = withModifiers(declareSuite);
28370
+ const hook = (kind) => (fn) => {
28371
+ collecting.hooks[kind].push(fn);
28372
+ schedule();
28373
+ };
28374
+ Object.assign(test, {
28375
+ test,
28376
+ it: test,
28377
+ describe: describe2,
28378
+ suite: describe2,
28379
+ before: hook("before"),
28380
+ after: hook("after"),
28381
+ beforeEach: hook("beforeEach"),
28382
+ afterEach: hook("afterEach"),
28383
+ mock,
28384
+ run: () => {
28385
+ throw Object.assign(new Error("node:test run() is not available in this container; use `node --test`"), {
28386
+ code: "ERR_FEATURE_UNAVAILABLE_ON_PLATFORM"
28387
+ });
28388
+ }
28389
+ });
28390
+ Object.defineProperty(test, "default", { value: test, enumerable: false });
28391
+ return test;
28392
+ }
28393
+
27764
28394
  // node_modules/@noble/hashes/esm/utils.js
27765
28395
  function isBytes(a) {
27766
28396
  return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
@@ -29618,7 +30248,7 @@ function createCoreModules(options) {
29618
30248
  });
29619
30249
  const stderrWrite = options.stderr ?? (() => {
29620
30250
  });
29621
- const timers = createTrackedTimers();
30251
+ const timers = createTrackedTimers((error) => reportUncaught(error));
29622
30252
  const processObject = Object.assign(new import_events4.default(), import_browser.default, {
29623
30253
  argv: options.argv?.slice() ?? ["/usr/bin/node"],
29624
30254
  argv0: "node",
@@ -29648,16 +30278,65 @@ function createCoreModules(options) {
29648
30278
  uptime: () => performance.now() / 1e3,
29649
30279
  memoryUsage: () => ({ rss: 0, heapTotal: 0, heapUsed: 0, external: 0, arrayBuffers: 0 }),
29650
30280
  cpuUsage: () => ({ user: 0, system: 0 }),
29651
- exit: (code = 0) => {
29652
- exitCode = code;
29653
- processObject.exitCode = code;
29654
- options.onExit?.(code);
30281
+ /* A bare `process.exit()` ends with `process.exitCode`, as in Node. */
30282
+ exit: (code) => {
30283
+ const status = normalizeExitCode(code ?? processObject.exitCode);
30284
+ exitCode = status;
30285
+ processObject.exitCode = status;
30286
+ emitExit(status);
30287
+ options.onExit?.(status);
30288
+ },
30289
+ nextTick: (fn, ...args) => {
30290
+ queueMicrotask(() => {
30291
+ try {
30292
+ fn(...args);
30293
+ } catch (error) {
30294
+ reportUncaught(error);
30295
+ }
30296
+ });
29655
30297
  },
29656
30298
  kill: () => true
29657
30299
  });
30300
+ for (const method of EVENT_EMITTER_METHODS) {
30301
+ const implementation = import_events4.default.prototype[method];
30302
+ if (typeof implementation === "function") processObject[method] = implementation;
30303
+ }
29658
30304
  const tty = options.tty === true;
29659
30305
  processObject.stdout = makeOutputStream(stdoutWrite, 1, tty);
29660
30306
  processObject.stderr = makeOutputStream(stderrWrite, 2, tty);
30307
+ let exiting = false;
30308
+ const emitExit = (status) => {
30309
+ if (exiting) return;
30310
+ exiting = true;
30311
+ try {
30312
+ processObject.emit("exit", status);
30313
+ } catch {
30314
+ }
30315
+ };
30316
+ const reportUncaught = (error, origin = "uncaughtException") => {
30317
+ if (!exiting && processObject.listenerCount(origin) > 0) {
30318
+ try {
30319
+ processObject.emit(origin, error, origin === "uncaughtException" ? origin : void 0);
30320
+ return;
30321
+ } catch (handlerError) {
30322
+ error = handlerError;
30323
+ }
30324
+ }
30325
+ stderrWrite(formatUncaught(error));
30326
+ try {
30327
+ processObject.exit(1);
30328
+ } catch {
30329
+ }
30330
+ };
30331
+ const defer = (fn) => {
30332
+ queueMicrotask(() => {
30333
+ try {
30334
+ fn();
30335
+ } catch (error) {
30336
+ reportUncaught(error);
30337
+ }
30338
+ });
30339
+ };
29661
30340
  const stdin = options.interactiveStdin ? new import_stream_browserify4.default.PassThrough() : new import_stream_browserify4.default.Readable({ read() {
29662
30341
  this.push(null);
29663
30342
  } });
@@ -29677,7 +30356,7 @@ function createCoreModules(options) {
29677
30356
  });
29678
30357
  processObject.stdin = stdin;
29679
30358
  Reflect.deleteProperty(processObject, "browser");
29680
- const fs = createFsModule(volume, () => cwd, options.stdinPath);
30359
+ const fs = createFsModule(volume, () => cwd, options.stdinPath, defer);
29681
30360
  const path = createPathModule(() => cwd);
29682
30361
  const consoleObject = new Console(stdoutWrite, stderrWrite);
29683
30362
  const os = createOsModule();
@@ -29690,20 +30369,24 @@ function createCoreModules(options) {
29690
30369
  }
29691
30370
  };
29692
30371
  let inFlightRequests = 0;
30372
+ const trackRequest = () => {
30373
+ inFlightRequests++;
30374
+ return () => {
30375
+ inFlightRequests--;
30376
+ };
30377
+ };
30378
+ const ambientFetch = options.http?.fetch ?? (typeof globalThis.fetch === "function" ? globalThis.fetch.bind(globalThis) : void 0);
30379
+ const outboundFetch = options.http?.policy && ambientFetch ? policedFetch(options.http.policy, ambientFetch) : ambientFetch;
29693
30380
  const httpOptions = {
29694
- ...options.http?.fetch ? { fetch: options.http.fetch } : {},
29695
- trackRequest: () => {
29696
- inFlightRequests++;
29697
- return () => {
29698
- inFlightRequests--;
29699
- };
29700
- }
30381
+ ...outboundFetch ? { fetch: outboundFetch } : {},
30382
+ ...options.http?.loopback ? { loopback: options.http.loopback } : {},
30383
+ trackRequest
29701
30384
  };
29702
30385
  const http = options.http ? createHttpModule(options.http.router, options.http.owner, httpOptions, "http:") : createUnsupportedModule("http");
29703
30386
  const https = options.http ? createHttpModule(options.http.router, options.http.owner, httpOptions, "https:") : createUnsupportedModule("https");
29704
30387
  const childProcess = options.spawnChild ? createChildProcessModule(options.spawnChild, () => cwd, options.syncSpawn, () => ({ ...processObject.env })) : createUnsupportedModule("child_process");
29705
30388
  const readline = createReadlineModule(() => processObject.stdin, () => processObject.stdout);
29706
- const dns = createDnsModule();
30389
+ const dns = createDnsModule(defer);
29707
30390
  const builtins = {
29708
30391
  assert: assert_module_default,
29709
30392
  "assert/strict": assert_module_default.strict ?? assert_module_default,
@@ -29739,7 +30422,27 @@ function createCoreModules(options) {
29739
30422
  url: url_module_default,
29740
30423
  util: util_module_default,
29741
30424
  "util/types": util_module_default.types ?? {},
29742
- zlib: zlib_module_default
30425
+ zlib: zlib_module_default,
30426
+ test: createTestModule({
30427
+ write: stdoutWrite,
30428
+ setTimeout: (fn, ms) => timers.api.setTimeout(fn, ms),
30429
+ clearTimeout: (handle) => timers.api.clearTimeout(handle),
30430
+ /* A pending interval is what keeps a process alive in this runtime; a test
30431
+ * awaiting nothing but promises would otherwise be judged finished. */
30432
+ keepAlive: () => {
30433
+ const handle = timers.api.setInterval(() => {
30434
+ }, 1 << 30);
30435
+ return () => timers.api.clearInterval(handle);
30436
+ },
30437
+ exit: (code) => {
30438
+ processObject.exitCode = code;
30439
+ try {
30440
+ processObject.exit(code);
30441
+ } catch {
30442
+ }
30443
+ },
30444
+ settings: () => parseTestSettings(env.SANDBOXEDJS_NODE_TEST)
30445
+ })
29743
30446
  };
29744
30447
  for (const name of stubNames) builtins[name] = createUnsupportedModule(name);
29745
30448
  builtins.net = createNetModule();
@@ -29747,8 +30450,26 @@ function createCoreModules(options) {
29747
30450
  Buffer: Buffer2,
29748
30451
  console: consoleObject,
29749
30452
  process: processObject,
29750
- ...timers.api
30453
+ ...timers.api,
30454
+ queueMicrotask: (fn) => queueMicrotask(() => {
30455
+ try {
30456
+ fn();
30457
+ } catch (error) {
30458
+ reportUncaught(error);
30459
+ }
30460
+ })
29751
30461
  };
30462
+ if (options.http) {
30463
+ globals.fetch = createVirtualFetch(options.http.router, {
30464
+ ...outboundFetch ? { fetch: outboundFetch } : {},
30465
+ ...options.http.loopback ? { loopback: options.http.loopback } : {},
30466
+ trackRequest
30467
+ });
30468
+ const NativeWebSocket = globalThis.WebSocket;
30469
+ if (options.http.policy && NativeWebSocket) {
30470
+ globals.WebSocket = policedWebSocket(NativeWebSocket, options.http.policy);
30471
+ }
30472
+ }
29752
30473
  const globalOverlay = new Proxy(globalThis, {
29753
30474
  get: (target, key) => typeof key === "string" && key in globals ? globals[key] : key === "global" || key === "globalThis" ? globalOverlay : Reflect.get(target, key),
29754
30475
  has: (target, key) => typeof key === "string" && key in globals || Reflect.has(target, key)
@@ -29764,6 +30485,10 @@ function createCoreModules(options) {
29764
30485
  /** Client requests sent but not yet read to completion. */
29765
30486
  pendingRequests: () => inFlightRequests,
29766
30487
  cancelTimers: timers.cancelAll,
30488
+ reportUncaught: (error) => reportUncaught(error),
30489
+ reportUnhandledRejection: (reason) => reportUncaught(reason, "unhandledRejection"),
30490
+ exitStatus: () => normalizeExitCode(processObject.exitCode),
30491
+ emitExit,
29767
30492
  writeStdin: (data2) => {
29768
30493
  if (options.interactiveStdin) stdin.write(data2);
29769
30494
  },
@@ -29825,7 +30550,7 @@ function createPathModule(cwd) {
29825
30550
  path.default = path;
29826
30551
  return path;
29827
30552
  }
29828
- function createFsModule(volume, cwd, stdinPath) {
30553
+ function createFsModule(volume, cwd, stdinPath, defer = queueMicrotask) {
29829
30554
  const fds = /* @__PURE__ */ new Map();
29830
30555
  let nextFd = 3;
29831
30556
  if (stdinPath) fds.set(0, { path: stdinPath, position: 0, flags: "r" });
@@ -29865,12 +30590,15 @@ function createFsModule(volume, cwd, stdinPath) {
29865
30590
  volume.rmdirSync(path);
29866
30591
  };
29867
30592
  const callback = (operation, cb) => {
29868
- queueMicrotask(() => {
30593
+ defer(() => {
30594
+ let value;
29869
30595
  try {
29870
- cb(null, operation());
30596
+ value = operation();
29871
30597
  } catch (error) {
29872
30598
  cb(error);
30599
+ return;
29873
30600
  }
30601
+ cb(null, value);
29874
30602
  });
29875
30603
  };
29876
30604
  const fs = {
@@ -30000,7 +30728,7 @@ function createFsModule(volume, cwd, stdinPath) {
30000
30728
  const slice = whole.subarray(start, Math.max(start, end));
30001
30729
  const stream = import_stream_browserify4.default.Readable.from([settings.encoding ? slice.toString(settings.encoding) : slice]);
30002
30730
  Object.assign(stream, { path: target, bytesRead: slice.length, close: () => stream.destroy() });
30003
- queueMicrotask(() => {
30731
+ defer(() => {
30004
30732
  stream.emit("open", 0);
30005
30733
  stream.emit("ready");
30006
30734
  });
@@ -30068,7 +30796,7 @@ function createFsModule(volume, cwd, stdinPath) {
30068
30796
  }
30069
30797
  fs.realpath.native = fs.realpath;
30070
30798
  fs.exists = (path, cb) => {
30071
- queueMicrotask(() => cb(fs.existsSync(path)));
30799
+ defer(() => cb(fs.existsSync(path)));
30072
30800
  };
30073
30801
  fs.promises = {
30074
30802
  ...Object.fromEntries(
@@ -30190,7 +30918,7 @@ var Console = class {
30190
30918
  timeLog = (_label = "default") => {
30191
30919
  };
30192
30920
  };
30193
- function createDnsModule() {
30921
+ function createDnsModule(defer = queueMicrotask) {
30194
30922
  const LOOPBACK = {
30195
30923
  localhost: { address: "127.0.0.1", family: 4 },
30196
30924
  "127.0.0.1": { address: "127.0.0.1", family: 4 },
@@ -30210,7 +30938,7 @@ function createDnsModule() {
30210
30938
  const lookup = (hostname, options, callback) => {
30211
30939
  const done = typeof options === "function" ? options : callback;
30212
30940
  const all = typeof options === "object" && options !== null && options.all;
30213
- queueMicrotask(() => {
30941
+ defer(() => {
30214
30942
  try {
30215
30943
  const entry = lookupSync(hostname);
30216
30944
  done?.(null, all ? [entry] : entry.address, entry.family);
@@ -30368,7 +31096,16 @@ var ERRNO_CONSTANTS = {
30368
31096
  EWOULDBLOCK: 11,
30369
31097
  EXDEV: 18
30370
31098
  };
30371
- function createTrackedTimers() {
31099
+ function createTrackedTimers(onError = (error) => {
31100
+ throw error;
31101
+ }) {
31102
+ const run2 = (fn, args) => {
31103
+ try {
31104
+ fn(...args);
31105
+ } catch (error) {
31106
+ onError(error);
31107
+ }
31108
+ };
30372
31109
  const live = /* @__PURE__ */ new Set();
30373
31110
  const unrefed = /* @__PURE__ */ new Set();
30374
31111
  const states = /* @__PURE__ */ new WeakMap();
@@ -30411,7 +31148,7 @@ function createTrackedTimers() {
30411
31148
  const native = setTimeout(
30412
31149
  (...inner) => {
30413
31150
  complete(handle);
30414
- fn(...inner);
31151
+ run2(fn, inner);
30415
31152
  },
30416
31153
  delay,
30417
31154
  ...args
@@ -30419,14 +31156,14 @@ function createTrackedTimers() {
30419
31156
  handle = track(native);
30420
31157
  return handle;
30421
31158
  };
30422
- const setIntervalTracked = (fn, delay, ...args) => track(setInterval(fn, delay, ...args));
31159
+ const setIntervalTracked = (fn, delay, ...args) => track(setInterval((...inner) => run2(fn, inner), delay, ...args));
30423
31160
  const hostSetImmediate = globalThis.setImmediate;
30424
31161
  const setImmediateTracked = (fn, ...args) => {
30425
31162
  if (!hostSetImmediate) return setTimeoutTracked(fn, 0, ...args);
30426
31163
  let handle;
30427
31164
  const native = hostSetImmediate((...inner) => {
30428
31165
  complete(handle);
30429
- fn(...inner);
31166
+ run2(fn, inner);
30430
31167
  }, ...args);
30431
31168
  handle = track(native);
30432
31169
  return handle;
@@ -30609,6 +31346,43 @@ function createNetModule() {
30609
31346
  isIP: (value) => isIPv4(value) ? 4 : isIPv6(value) ? 6 : 0
30610
31347
  });
30611
31348
  }
31349
+ function parseTestSettings(raw) {
31350
+ if (!raw) return {};
31351
+ try {
31352
+ const parsed = JSON.parse(raw);
31353
+ return parsed && typeof parsed === "object" ? parsed : {};
31354
+ } catch {
31355
+ return {};
31356
+ }
31357
+ }
31358
+ var EVENT_EMITTER_METHODS = [
31359
+ "on",
31360
+ "addListener",
31361
+ "once",
31362
+ "off",
31363
+ "removeListener",
31364
+ "removeAllListeners",
31365
+ "emit",
31366
+ "prependListener",
31367
+ "prependOnceListener",
31368
+ "listeners",
31369
+ "rawListeners",
31370
+ "listenerCount",
31371
+ "eventNames",
31372
+ "setMaxListeners",
31373
+ "getMaxListeners"
31374
+ ];
31375
+ function normalizeExitCode(value) {
31376
+ const code = typeof value === "string" && value.trim() !== "" ? Number(value) : value;
31377
+ return typeof code === "number" && Number.isInteger(code) ? code & 255 : 0;
31378
+ }
31379
+ function formatUncaught(error) {
31380
+ const text = error instanceof Error ? error.stack ?? `${error.name}: ${error.message}` : `Uncaught ${typeof error === "string" ? JSON.stringify(error) : String(error)}`;
31381
+ return `${text}
31382
+
31383
+ Node.js v22.12.0
31384
+ `;
31385
+ }
30612
31386
  var stubNames = ["cluster", "dgram", "diagnostics_channel", "domain", "http2", "inspector", "net", "tls", "v8", "vm", "worker_threads"];
30613
31387
  var builtinNames = [
30614
31388
  "assert",
@@ -30646,6 +31420,7 @@ var builtinNames = [
30646
31420
  "util",
30647
31421
  "util/types",
30648
31422
  "zlib",
31423
+ "test",
30649
31424
  ...stubNames
30650
31425
  ];
30651
31426
 
@@ -30839,7 +31614,13 @@ async function run(port, start) {
30839
31614
  const owner = "worker";
30840
31615
  router.onListen = (listening) => port.postMessage({ type: "listen", port: listening });
30841
31616
  router.onClose = (closed) => port.postMessage({ type: "close-port", port: closed });
30842
- let requestedExit = 0;
31617
+ const pendingLoopback = /* @__PURE__ */ new Map();
31618
+ let nextLoopbackId = 1;
31619
+ const loopback = (targetPort, request) => new Promise((resolve2) => {
31620
+ const id = nextLoopbackId++;
31621
+ pendingLoopback.set(id, resolve2);
31622
+ port.postMessage({ type: "loopback-request", id, port: targetPort, request });
31623
+ });
30843
31624
  let engine;
30844
31625
  let finished = false;
30845
31626
  const core = createCoreModules({
@@ -30850,11 +31631,10 @@ async function run(port, start) {
30850
31631
  stdout: (text) => port.postMessage({ type: "output", text }),
30851
31632
  stderr: (text) => port.postMessage({ type: "error", text }),
30852
31633
  onExit: (code) => {
30853
- requestedExit = code;
30854
31634
  finish(code);
30855
31635
  if (engine?.isEvaluating) throw new ProcessExit(code);
30856
31636
  },
30857
- http: { router, owner },
31637
+ http: { router, owner, loopback, ...start.network ? { policy: start.network } : {} },
30858
31638
  /* Asynchronous children are the host's business: it owns the process table
30859
31639
  * and the PATH. Both forms end up in the same place, one blocking. */
30860
31640
  spawnChild: (config) => hostChildProcess(port, config),
@@ -30864,6 +31644,24 @@ async function run(port, start) {
30864
31644
  ...start.tty ? { tty: true } : {},
30865
31645
  onRawMode: (enabled) => port.postMessage({ type: "rawmode", enabled })
30866
31646
  });
31647
+ const guestGlobals = globalThis;
31648
+ if (typeof core.globals.fetch === "function") guestGlobals.fetch = core.globals.fetch;
31649
+ if (typeof core.globals.WebSocket === "function") guestGlobals.WebSocket = core.globals.WebSocket;
31650
+ if (typeof self !== "undefined" && typeof self.addEventListener === "function") {
31651
+ const scope = self;
31652
+ scope.addEventListener("error", (event) => {
31653
+ event.preventDefault?.();
31654
+ core.reportUncaught(event.error ?? new Error(String(event.message)));
31655
+ });
31656
+ scope.addEventListener("unhandledrejection", (event) => {
31657
+ event.preventDefault?.();
31658
+ core.reportUnhandledRejection(event.reason);
31659
+ });
31660
+ } else {
31661
+ const threadProcess = globalThis.process;
31662
+ threadProcess?.on?.("uncaughtException", (error) => core.reportUncaught(error));
31663
+ threadProcess?.on?.("unhandledRejection", (reason) => core.reportUnhandledRejection(reason));
31664
+ }
30867
31665
  const finish = (code) => {
30868
31666
  if (finished) return;
30869
31667
  finished = true;
@@ -30880,6 +31678,12 @@ async function run(port, start) {
30880
31678
  finish(137);
30881
31679
  }
30882
31680
  if (message?.type === "http-request") void answer(port, router, message);
31681
+ if (message?.type === "loopback-response") {
31682
+ const id = Number(message.id);
31683
+ const settle2 = pendingLoopback.get(id);
31684
+ pendingLoopback.delete(id);
31685
+ settle2?.(message.response ?? null);
31686
+ }
30883
31687
  if (message?.type === "ws-open") openSocket(port, router, message);
30884
31688
  if (message?.type === "ws-data") sockets.get(Number(message.id))?.send(new Uint8Array(message.data));
30885
31689
  if (message?.type === "ws-close") {
@@ -30897,7 +31701,9 @@ async function run(port, start) {
30897
31701
  try {
30898
31702
  await engine.run(start.script);
30899
31703
  await settle(router, owner, core, () => finished);
30900
- finish(requestedExit);
31704
+ const status = core.exitStatus();
31705
+ core.emitExit(status);
31706
+ finish(status);
30901
31707
  } catch (error) {
30902
31708
  if (error instanceof ProcessExit) {
30903
31709
  finish(error.code);