sandboxedjs 0.2.5 → 0.2.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 CHANGED
@@ -605,32 +605,32 @@ var init_variables = __esm({
605
605
  return this.find(name) !== void 0;
606
606
  }
607
607
  get(name) {
608
- const found = this.find(name);
609
- if (!found) return void 0;
610
- if (found.entry.array) return found.entry.array[0] ?? "";
611
- return found.entry.value;
608
+ const found2 = this.find(name);
609
+ if (!found2) return void 0;
610
+ if (found2.entry.array) return found2.entry.array[0] ?? "";
611
+ return found2.entry.value;
612
612
  }
613
613
  entry(name) {
614
614
  return this.find(name)?.entry;
615
615
  }
616
616
  getArray(name) {
617
- const found = this.find(name);
618
- if (!found) return void 0;
619
- return found.entry.array ?? [found.entry.value];
617
+ const found2 = this.find(name);
618
+ if (!found2) return void 0;
619
+ return found2.entry.array ?? [found2.entry.value];
620
620
  }
621
621
  isArray(name) {
622
622
  return this.find(name)?.entry.array !== void 0;
623
623
  }
624
624
  set(name, value, attrs = {}) {
625
- const found = this.find(name);
626
- if (found?.entry.readonly) throw new ReadonlyVariableError(name);
625
+ const found2 = this.find(name);
626
+ if (found2?.entry.readonly) throw new ReadonlyVariableError(name);
627
627
  let next = value;
628
- if (found?.entry.upper || attrs.upper) next = next.toUpperCase();
629
- if (found?.entry.lower || attrs.lower) next = next.toLowerCase();
630
- if (found) {
631
- found.entry.value = next;
632
- delete found.entry.array;
633
- Object.assign(found.entry, attrs);
628
+ if (found2?.entry.upper || attrs.upper) next = next.toUpperCase();
629
+ if (found2?.entry.lower || attrs.lower) next = next.toLowerCase();
630
+ if (found2) {
631
+ found2.entry.value = next;
632
+ delete found2.entry.array;
633
+ Object.assign(found2.entry, attrs);
634
634
  } else {
635
635
  this.scopes[this.scopes.length - 1].set(name, { value: next, ...attrs });
636
636
  }
@@ -640,28 +640,28 @@ var init_variables = __esm({
640
640
  this.scopes[this.scopes.length - 1].set(name, { value, ...attrs });
641
641
  }
642
642
  setArray(name, values, attrs = {}) {
643
- const found = this.find(name);
644
- if (found?.entry.readonly) throw new ReadonlyVariableError(name);
645
- if (found) {
646
- found.entry.array = values.slice();
647
- found.entry.value = values[0] ?? "";
648
- Object.assign(found.entry, attrs);
643
+ const found2 = this.find(name);
644
+ if (found2?.entry.readonly) throw new ReadonlyVariableError(name);
645
+ if (found2) {
646
+ found2.entry.array = values.slice();
647
+ found2.entry.value = values[0] ?? "";
648
+ Object.assign(found2.entry, attrs);
649
649
  } else {
650
650
  this.scopes[this.scopes.length - 1].set(name, { value: values[0] ?? "", array: values.slice(), ...attrs });
651
651
  }
652
652
  }
653
653
  setIndex(name, index, value) {
654
- const found = this.find(name);
655
- if (found?.entry.readonly) throw new ReadonlyVariableError(name);
656
- const arr = found?.entry.array ?? (found ? [found.entry.value] : []);
654
+ const found2 = this.find(name);
655
+ if (found2?.entry.readonly) throw new ReadonlyVariableError(name);
656
+ const arr = found2?.entry.array ?? (found2 ? [found2.entry.value] : []);
657
657
  while (arr.length < index) arr.push("");
658
658
  arr[index] = value;
659
659
  this.setArray(name, arr);
660
660
  }
661
661
  append(name, value) {
662
- const found = this.find(name);
663
- if (found?.entry.array) {
664
- this.setArray(name, [...found.entry.array, value]);
662
+ const found2 = this.find(name);
663
+ if (found2?.entry.array) {
664
+ this.setArray(name, [...found2.entry.array, value]);
665
665
  return;
666
666
  }
667
667
  this.set(name, (this.get(name) ?? "") + value);
@@ -678,13 +678,13 @@ var init_variables = __esm({
678
678
  return false;
679
679
  }
680
680
  export(name, exported = true) {
681
- const found = this.find(name);
682
- if (found) found.entry.exported = exported;
681
+ const found2 = this.find(name);
682
+ if (found2) found2.entry.exported = exported;
683
683
  else this.scopes[this.scopes.length - 1].set(name, { value: "", exported });
684
684
  }
685
685
  markReadonly(name) {
686
- const found = this.find(name);
687
- if (found) found.entry.readonly = true;
686
+ const found2 = this.find(name);
687
+ if (found2) found2.entry.readonly = true;
688
688
  else this.scopes[this.scopes.length - 1].set(name, { value: "", readonly: true });
689
689
  }
690
690
  names() {
@@ -2930,8 +2930,8 @@ async function builtinSource({ shell, argv, io }) {
2930
2930
  }
2931
2931
  let path = resolve(shell.cwd, target);
2932
2932
  if (!target.includes("/")) {
2933
- const found = shell.kernel.which(target, shell.cwd, shell.vars.environment(), shell.cred);
2934
- if (found) path = found;
2933
+ const found2 = shell.kernel.which(target, shell.cwd, shell.vars.environment(), shell.cred);
2934
+ if (found2) path = found2;
2935
2935
  }
2936
2936
  let text2;
2937
2937
  try {
@@ -3565,32 +3565,32 @@ function builtinType({ shell, argv, io }) {
3565
3565
  const names = args.filter((a) => !a.startsWith("-"));
3566
3566
  let status = 0;
3567
3567
  for (const name of names) {
3568
- const found = [];
3568
+ const found2 = [];
3569
3569
  if (shell.aliases.has(name)) {
3570
- if (typeOnly) found.push("alias");
3571
- else if (!pathOnly) found.push(`${name} is aliased to \`${shell.aliases.get(name)}'`);
3570
+ if (typeOnly) found2.push("alias");
3571
+ else if (!pathOnly) found2.push(`${name} is aliased to \`${shell.aliases.get(name)}'`);
3572
3572
  }
3573
3573
  if (shell.functions.has(name)) {
3574
- if (typeOnly) found.push("function");
3575
- else if (!pathOnly) found.push(`${name} is a function`);
3574
+ if (typeOnly) found2.push("function");
3575
+ else if (!pathOnly) found2.push(`${name} is a function`);
3576
3576
  }
3577
3577
  if (isBuiltinName(name)) {
3578
- if (typeOnly) found.push("builtin");
3579
- else if (!pathOnly) found.push(`${name} is a shell builtin`);
3578
+ if (typeOnly) found2.push("builtin");
3579
+ else if (!pathOnly) found2.push(`${name} is a shell builtin`);
3580
3580
  }
3581
3581
  const path = shell.kernel.which(name, shell.cwd, shell.vars.environment(), shell.cred);
3582
3582
  if (path) {
3583
- if (typeOnly) found.push("file");
3584
- else if (pathOnly) found.push(path);
3585
- else found.push(`${name} is ${path}`);
3583
+ if (typeOnly) found2.push("file");
3584
+ else if (pathOnly) found2.push(path);
3585
+ else found2.push(`${name} is ${path}`);
3586
3586
  }
3587
- if (found.length === 0) {
3587
+ if (found2.length === 0) {
3588
3588
  if (!pathOnly && !typeOnly) io.stderr.write(`type: ${name}: not found
3589
3589
  `);
3590
3590
  status = 1;
3591
3591
  continue;
3592
3592
  }
3593
- for (const line of all ? found : [found[0]]) io.stdout.write(line + "\n");
3593
+ for (const line of all ? found2 : [found2[0]]) io.stdout.write(line + "\n");
3594
3594
  }
3595
3595
  return status;
3596
3596
  }
@@ -5947,9 +5947,9 @@ function parseArgs(argv, specs, opts = {}) {
5947
5947
  const resolveLong = (name) => {
5948
5948
  const exact = byLong.get(name);
5949
5949
  if (exact) return exact;
5950
- const candidates = [...byLong.keys()].filter((k) => k.startsWith(name));
5951
- if (candidates.length === 1) return byLong.get(candidates[0]);
5952
- if (candidates.length > 1) throw new UsageError(`option '--${name}' is ambiguous`);
5950
+ const candidates2 = [...byLong.keys()].filter((k) => k.startsWith(name));
5951
+ if (candidates2.length === 1) return byLong.get(candidates2[0]);
5952
+ if (candidates2.length > 1) throw new UsageError(`option '--${name}' is ambiguous`);
5953
5953
  return void 0;
5954
5954
  };
5955
5955
  for (; i < argv.length; i++) {
@@ -6468,19 +6468,19 @@ var WasiHost = class {
6468
6468
  }
6469
6469
  // ── descriptors ──────────────────────────────────────────────────────────
6470
6470
  get(fd) {
6471
- const found = this.fds.get(fd);
6472
- if (!found) throw new WasiError(WASI_EBADF);
6473
- return found;
6471
+ const found2 = this.fds.get(fd);
6472
+ if (!found2) throw new WasiError(WASI_EBADF);
6473
+ return found2;
6474
6474
  }
6475
6475
  dir(fd) {
6476
- const found = this.get(fd);
6477
- if (found.kind !== "dir") throw new WasiError(WASI_ENOTDIR);
6478
- return found;
6476
+ const found2 = this.get(fd);
6477
+ if (found2.kind !== "dir") throw new WasiError(WASI_ENOTDIR);
6478
+ return found2;
6479
6479
  }
6480
6480
  file(fd) {
6481
- const found = this.get(fd);
6482
- if (found.kind !== "file") throw new WasiError(WASI_EBADF);
6483
- return found;
6481
+ const found2 = this.get(fd);
6482
+ if (found2.kind !== "file") throw new WasiError(WASI_EBADF);
6483
+ return found2;
6484
6484
  }
6485
6485
  /**
6486
6486
  * Resolve a guest path against a directory descriptor.
@@ -7425,13 +7425,13 @@ var Kernel = class {
7425
7425
  * Find `name` the way `execvp` does. Returns null when nothing matches.
7426
7426
  */
7427
7427
  resolveExecutable(name, cwd, env2, cred = ROOT_CRED) {
7428
- const candidates = [];
7428
+ const candidates2 = [];
7429
7429
  if (name.includes("/")) {
7430
- candidates.push(resolve(cwd, name));
7430
+ candidates2.push(resolve(cwd, name));
7431
7431
  } else {
7432
- for (const dir3 of this.pathDirs(env2)) candidates.push(join(dir3, name));
7432
+ for (const dir3 of this.pathDirs(env2)) candidates2.push(join(dir3, name));
7433
7433
  }
7434
- for (const candidate of candidates) {
7434
+ for (const candidate of candidates2) {
7435
7435
  let real;
7436
7436
  try {
7437
7437
  real = this.vfs.realpath(candidate, cred);
@@ -8407,10 +8407,50 @@ function isBrowser() {
8407
8407
  }
8408
8408
  function browserBlocked(hostname, message) {
8409
8409
  return new Error(
8410
- `${message} \u2014 the request to ${hostname} was blocked by the browser. A page can only read a response from a host that sends CORS headers, and most APIs send none. Give the container a proxy that makes the request for it \u2014 network: { proxy }, and \`npx sandboxedjs-egress\` is one \u2014 or run the container on a server.`
8410
+ `${message} \u2014 the request to ${hostname} was blocked by the browser. A page can only read a response from a host that sends CORS headers, and most APIs send none. The container looks for a proxy to make the request for it and found none: mount \`handleEgressRequest\` from "sandboxedjs/egress" at /__sandboxedjs__/egress on this origin, or run \`npx sandboxedjs-egress\`, and it is used without further configuration (network: { proxy } names one somewhere else) \u2014 or run the container on a server.`
8411
8411
  );
8412
8412
  }
8413
8413
 
8414
+ // src/net/discover-egress.ts
8415
+ var EGRESS_PATH = "/__sandboxedjs__/egress";
8416
+ var EGRESS_MARKER = { sandboxedjs: "egress", protocol: 1 };
8417
+ var CLI_PORT = 4181;
8418
+ var found = null;
8419
+ var PROBE_TIMEOUT_MS = 1500;
8420
+ async function isEgress(url, fetchImpl) {
8421
+ const control = new AbortController();
8422
+ const timer = setTimeout(() => control.abort(), PROBE_TIMEOUT_MS);
8423
+ try {
8424
+ const answer = await fetchImpl(url, { method: "GET", signal: control.signal });
8425
+ if (!answer.ok) return false;
8426
+ const payload = await answer.json();
8427
+ return payload?.sandboxedjs === EGRESS_MARKER.sandboxedjs;
8428
+ } catch {
8429
+ return false;
8430
+ } finally {
8431
+ clearTimeout(timer);
8432
+ }
8433
+ }
8434
+ function candidates() {
8435
+ const origin = globalThis.location?.origin;
8436
+ const list = [];
8437
+ if (origin && /^https?:/.test(origin)) list.push(`${origin}${EGRESS_PATH}`);
8438
+ list.push(`http://127.0.0.1:${CLI_PORT}/`);
8439
+ return list;
8440
+ }
8441
+ async function discoverEgress(fetchImpl = fetch) {
8442
+ if (!isBrowser()) return null;
8443
+ if (!found) {
8444
+ found = (async () => {
8445
+ for (const candidate of candidates()) {
8446
+ if (await isEgress(candidate, fetchImpl)) return candidate;
8447
+ }
8448
+ return null;
8449
+ })();
8450
+ }
8451
+ return await found;
8452
+ }
8453
+
8414
8454
  // src/net/policy.ts
8415
8455
  function isLoopbackHostname(hostname) {
8416
8456
  const host2 = hostname.replace(/^\[|\]$/g, "").toLowerCase();
@@ -8453,7 +8493,8 @@ function policedFetch(policy, fetchImpl) {
8453
8493
  if (!outboundAllowed(policy, url)) {
8454
8494
  throw Object.assign(new TypeError("fetch failed"), { cause: outboundBlockedError(url) });
8455
8495
  }
8456
- if (policy.proxy) return await fetchThroughProxy(policy.proxy, fetchImpl, input, init);
8496
+ const proxy = policy.proxy ?? await discoverEgress(fetchImpl);
8497
+ if (proxy) return await fetchThroughProxy(proxy, fetchImpl, input, init);
8457
8498
  try {
8458
8499
  return await fetchImpl(input, init);
8459
8500
  } catch (error) {
@@ -8989,7 +9030,7 @@ var Lexer = class _Lexer {
8989
9030
  const quoted = /['"\\]/.test(rawTag);
8990
9031
  const tag2 = rawTag.replace(/['"\\]/g, "");
8991
9032
  const lines = [];
8992
- let found = false;
9033
+ let found2 = false;
8993
9034
  while (this.pos < this.src.length) {
8994
9035
  let eol = this.src.indexOf("\n", this.pos);
8995
9036
  if (eol < 0) eol = this.src.length;
@@ -8997,13 +9038,13 @@ var Lexer = class _Lexer {
8997
9038
  this.pos = eol + 1;
8998
9039
  const compare = stripTabs ? rawLine.replace(/^\t+/, "") : rawLine;
8999
9040
  if (compare === tag2) {
9000
- found = true;
9041
+ found2 = true;
9001
9042
  break;
9002
9043
  }
9003
9044
  lines.push(stripTabs ? rawLine.replace(/^\t+/, "") : rawLine);
9004
9045
  if (eol >= this.src.length) break;
9005
9046
  }
9006
- if (!found) {
9047
+ if (!found2) {
9007
9048
  throw new IncompleteInputError(`here-document delimited by end-of-file (wanted \`${tag2}')`, opToken.pos);
9008
9049
  }
9009
9050
  opToken.heredoc = { tag: tag2, stripTabs, quoted, body: lines.length ? lines.join("\n") + "\n" : "" };
@@ -14458,8 +14499,8 @@ var Interpreter = class {
14458
14499
  for (let i = this.locals.length - 1; i >= 0; i--) {
14459
14500
  const scope = this.locals[i];
14460
14501
  if (scope.has(name)) {
14461
- const found = scope.get(name);
14462
- return found instanceof Map ? Value.uninitialized : found;
14502
+ const found2 = scope.get(name);
14503
+ return found2 instanceof Map ? Value.uninitialized : found2;
14463
14504
  }
14464
14505
  }
14465
14506
  if (name === "NF") {
@@ -14491,8 +14532,8 @@ var Interpreter = class {
14491
14532
  for (let i = this.locals.length - 1; i >= 0; i--) {
14492
14533
  const scope = this.locals[i];
14493
14534
  if (scope.has(name)) {
14494
- const found = scope.get(name);
14495
- if (found instanceof Map) return found;
14535
+ const found2 = scope.get(name);
14536
+ if (found2 instanceof Map) return found2;
14496
14537
  const created = /* @__PURE__ */ new Map();
14497
14538
  scope.set(name, created);
14498
14539
  return created;
@@ -17570,7 +17611,7 @@ async function performRequest(ctx, url, init) {
17570
17611
  `outbound network access to ${url.hostname} is disabled for this container (enable with network: { allowOutbound: true })`
17571
17612
  );
17572
17613
  }
17573
- const proxy = ctx.kernel.net.proxy;
17614
+ const proxy = ctx.kernel.net.proxy ?? await discoverEgress();
17574
17615
  if (proxy) {
17575
17616
  const result = await proxyExchange(proxy, {
17576
17617
  url: url.toString(),
@@ -18541,14 +18582,14 @@ var apropos = defineCommand({
18541
18582
  return 1;
18542
18583
  }
18543
18584
  const patterns = ctx.args.map((a) => new RegExp(a, "i"));
18544
- let found = 0;
18585
+ let found2 = 0;
18545
18586
  for (const command of ctx.kernel.commands.all()) {
18546
18587
  const haystack = `${command.name} ${command.summary ?? ""}`;
18547
18588
  if (!patterns.some((p) => p.test(haystack))) continue;
18548
- found++;
18589
+ found2++;
18549
18590
  ctx.line(`${command.name} (1)${" ".repeat(Math.max(1, 16 - command.name.length))}- ${command.summary ?? ""}`);
18550
18591
  }
18551
- if (found === 0) {
18592
+ if (found2 === 0) {
18552
18593
  ctx.line(`${ctx.args.join(" ")}: nothing appropriate.`);
18553
18594
  return 1;
18554
18595
  }
@@ -19572,8 +19613,8 @@ ${prelude}${preloadRequires(preloads)}${source}
19572
19613
  }
19573
19614
  function resolveScript(ctx, operand) {
19574
19615
  const base2 = ctx.path(operand);
19575
- const candidates = [base2, `${base2}.js`, `${base2}.mjs`, `${base2}.cjs`, `${base2}.json`];
19576
- for (const candidate of candidates) {
19616
+ const candidates2 = [base2, `${base2}.js`, `${base2}.mjs`, `${base2}.cjs`, `${base2}.json`];
19617
+ for (const candidate of candidates2) {
19577
19618
  try {
19578
19619
  const st = ctx.vfs.stat(candidate, { cred: ctx.cred });
19579
19620
  if (st.isFile()) return ctx.vfs.realpath(candidate, ctx.cred);
@@ -21040,7 +21081,7 @@ var wheels_default = {
21040
21081
 
21041
21082
  // package.json
21042
21083
  var package_default = {
21043
- version: "0.2.5"};
21084
+ version: "0.2.7"};
21044
21085
 
21045
21086
  // src/python/extension-abi.ts
21046
21087
  var EXTENSION_ABI = {
@@ -22705,8 +22746,12 @@ function createHostAbiServer(proc) {
22705
22746
  }
22706
22747
  case Op.resolve: {
22707
22748
  const sockets = proc.sockets;
22749
+ const name = r.string();
22750
+ if (/^(\d{1,3}\.){3}\d{1,3}$/.test(name)) {
22751
+ return { status: 0, payload: new Writer().string(name).finish() };
22752
+ }
22708
22753
  if (!sockets?.outbound) throw new PosixError(Errno.ENOSYS);
22709
- const address = sockets.outbound.resolve(r.string());
22754
+ const address = sockets.outbound.resolve(name);
22710
22755
  return { status: 0, payload: new Writer().string(address).finish() };
22711
22756
  }
22712
22757
  case Op.send: {
@@ -23908,7 +23953,7 @@ function explain(name, constraints, chosenVersion, available2 = []) {
23908
23953
  return lines;
23909
23954
  }
23910
23955
  async function fetchCandidates(client, name, allowSourceBuilds, prebuilt, rejected = { versions: /* @__PURE__ */ new Set(), sourceAvailable: false }) {
23911
- const candidates = [];
23956
+ const candidates2 = [];
23912
23957
  if (prebuilt) assertIndexUsable(prebuilt);
23913
23958
  for (const wheel of prebuilt?.wheels ?? []) {
23914
23959
  if (normalize2(wheel.name) !== normalize2(name)) continue;
@@ -23917,7 +23962,7 @@ async function fetchCandidates(client, name, allowSourceBuilds, prebuilt, reject
23917
23962
  `${wheel.filename} in the wheel index was built for ABI ${wheel.abiId}, but this runtime implements ${EXTENSION_ABI.abiId}; rebuild it`
23918
23963
  );
23919
23964
  }
23920
- candidates.push({
23965
+ candidates2.push({
23921
23966
  name: normalize2(wheel.name),
23922
23967
  version: wheel.version,
23923
23968
  kind: "sbx-wasm",
@@ -23928,13 +23973,13 @@ async function fetchCandidates(client, name, allowSourceBuilds, prebuilt, reject
23928
23973
  indexedRequires: wheel.requires
23929
23974
  });
23930
23975
  }
23931
- candidates.push(...builtinCandidates(normalize2(name)));
23932
- if (isBuiltinOnly(normalize2(name))) return candidates;
23976
+ candidates2.push(...builtinCandidates(normalize2(name)));
23977
+ if (isBuiltinOnly(normalize2(name))) return candidates2;
23933
23978
  let index;
23934
23979
  try {
23935
23980
  index = await client.json(`https://pypi.org/pypi/${name}/json`, { timeoutMs: 3e4 });
23936
23981
  } catch (error) {
23937
- if (candidates.length > 0) return candidates;
23982
+ if (candidates2.length > 0) return candidates2;
23938
23983
  throw error;
23939
23984
  }
23940
23985
  for (const [version, files] of Object.entries(index.releases ?? {})) {
@@ -23947,7 +23992,7 @@ async function fetchCandidates(client, name, allowSourceBuilds, prebuilt, reject
23947
23992
  rejected.versions.add(version);
23948
23993
  continue;
23949
23994
  }
23950
- candidates.push({
23995
+ candidates2.push({
23951
23996
  name: normalize2(name),
23952
23997
  version,
23953
23998
  kind,
@@ -23958,7 +24003,7 @@ async function fetchCandidates(client, name, allowSourceBuilds, prebuilt, reject
23958
24003
  });
23959
24004
  }
23960
24005
  }
23961
- return candidates;
24006
+ return candidates2;
23962
24007
  }
23963
24008
  function newest(versions) {
23964
24009
  return versions.reduce((a, b) => compareVersions(b, a, ">") ? b : a);
@@ -24255,17 +24300,17 @@ function createProcessService(ctx) {
24255
24300
  return proc.pid;
24256
24301
  },
24257
24302
  async wait(pid, options) {
24258
- const candidates = pid > 0 ? [children.get(pid)].filter((p) => p !== void 0) : [...children.values()];
24259
- if (candidates.length === 0) throw new PosixError(Errno.ECHILD);
24303
+ const candidates2 = pid > 0 ? [children.get(pid)].filter((p) => p !== void 0) : [...children.values()];
24304
+ if (candidates2.length === 0) throw new PosixError(Errno.ECHILD);
24260
24305
  const reap = (proc) => {
24261
24306
  children.delete(proc.pid);
24262
24307
  return { pid: proc.pid, status: waitStatus(proc) };
24263
24308
  };
24264
- const done = candidates.find(exited);
24309
+ const done = candidates2.find(exited);
24265
24310
  if (done) return reap(done);
24266
24311
  if (options & WNOHANG) return { pid: 0, status: 0 };
24267
- await Promise.race(candidates.map((proc) => proc.wait()));
24268
- const finished = candidates.find(exited);
24312
+ await Promise.race(candidates2.map((proc) => proc.wait()));
24313
+ const finished = candidates2.find(exited);
24269
24314
  if (!finished) throw new PosixError(Errno.ECHILD);
24270
24315
  return reap(finished);
24271
24316
  },
@@ -24833,6 +24878,77 @@ if os.environ.get("SBX_OUTBOUND_SOCKETS") == "1":
24833
24878
  sys.meta_path.insert(0, _SbxTruststoreHook())
24834
24879
 
24835
24880
 
24881
+ # Literal addresses are answered here rather than through the host.
24882
+ #
24883
+ # The container's resolver is a host call, and a container with no outbound
24884
+ # sockets configured has no resolver to call: it answers ENOSYS. That is the
24885
+ # right answer for a name, but the egress hop below dials 127.0.0.1, and
24886
+ # http.client calls getaddrinfo even for an address that needs no resolving --
24887
+ # so every request through the egress died with "Function not implemented"
24888
+ # before it reached the endpoint. A numeric address (and loopback by its usual
24889
+ # names) is now formed here, which is what a resolver would have returned.
24890
+ def _sbx_local_addresses():
24891
+ import socket as _socket_module
24892
+ import _socket as _socket_native
24893
+
24894
+ # The native entry point, not socket.getaddrinfo: the stdlib wrapper
24895
+ # delegates to _socket, so wrapping the wrapper and replacing _socket with
24896
+ # the wrapper makes the two call each other forever.
24897
+ _real_getaddrinfo = _socket_native.getaddrinfo
24898
+
24899
+ _literals = {"localhost": "127.0.0.1", "localhost.localdomain": "127.0.0.1",
24900
+ "ip6-localhost": "127.0.0.1"}
24901
+
24902
+ def _literal(host):
24903
+ """The address host already is, or None when it needs a resolver."""
24904
+ if isinstance(host, (bytes, bytearray)):
24905
+ host = bytes(host).decode("ascii", "replace")
24906
+ if host is None:
24907
+ return None
24908
+ host = _literals.get(host.lower(), host)
24909
+ parts = host.split(".")
24910
+ if len(parts) != 4:
24911
+ return None
24912
+ for part in parts:
24913
+ if not part.isdigit() or len(part) > 3 or int(part) > 255:
24914
+ return None
24915
+ return host
24916
+
24917
+ def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
24918
+ address = _literal(host)
24919
+ if address is None:
24920
+ return _real_getaddrinfo(host, port, family, type, proto, flags)
24921
+ if isinstance(port, (bytes, bytearray)):
24922
+ port = bytes(port).decode("ascii", "replace")
24923
+ if isinstance(port, str):
24924
+ port = int(port) if port.isdigit() else _socket_module.getservbyname(port)
24925
+ if port is None:
24926
+ port = 0
24927
+ if family not in (0, _socket_module.AF_UNSPEC, _socket_module.AF_INET):
24928
+ raise _socket_module.gaierror(
24929
+ _socket_module.EAI_FAMILY, "only AF_INET is supported in this container"
24930
+ )
24931
+ kind = type or _socket_module.SOCK_STREAM
24932
+ protocol = proto or (_socket_module.IPPROTO_TCP
24933
+ if kind == _socket_module.SOCK_STREAM else 0)
24934
+ return [(_socket_module.AF_INET, kind, protocol, "", (address, int(port)))]
24935
+
24936
+ def gethostbyname(host):
24937
+ return getaddrinfo(host, 0)[0][4][0]
24938
+
24939
+ def gethostbyname_ex(host):
24940
+ return (host, [], [gethostbyname(host)])
24941
+
24942
+ _socket_module.getaddrinfo = getaddrinfo
24943
+ _socket_module.gethostbyname = gethostbyname
24944
+ _socket_module.gethostbyname_ex = gethostbyname_ex
24945
+ _socket_native.getaddrinfo = getaddrinfo
24946
+ _socket_native.gethostbyname = gethostbyname
24947
+ _socket_native.gethostbyname_ex = gethostbyname_ex
24948
+
24949
+
24950
+ _sbx_local_addresses()
24951
+
24836
24952
  _egress = None if os.environ.get("SBX_OUTBOUND_SOCKETS") == "1" else os.environ.get("SBX_HTTP_EGRESS")
24837
24953
  if _egress:
24838
24954
  import http.client
@@ -26422,9 +26538,9 @@ function resolveVersion(metadata, range) {
26422
26538
  const tag2 = metadata["dist-tags"]?.[range];
26423
26539
  if (tag2) return tag2;
26424
26540
  if (valid(range) && metadata.versions[range]) return range;
26425
- const found = maxSatisfying(Object.keys(metadata.versions), range === "latest" ? "*" : range, { includePrerelease: false });
26426
- if (!found) throw new Error(`No matching version found for ${metadata.name}@${range}`);
26427
- return found;
26541
+ const found2 = maxSatisfying(Object.keys(metadata.versions), range === "latest" ? "*" : range, { includePrerelease: false });
26542
+ if (!found2) throw new Error(`No matching version found for ${metadata.name}@${range}`);
26543
+ return found2;
26428
26544
  }
26429
26545
  function verifyIntegrity(data, integrity, shasum, identity) {
26430
26546
  if (integrity) {
@@ -26886,23 +27002,23 @@ var npm = defineCommand({
26886
27002
  case "uninstall":
26887
27003
  case "remove":
26888
27004
  case "rm": {
26889
- const found = readManifest(ctx, root);
27005
+ const found2 = readManifest(ctx, root);
26890
27006
  for (const name of rest.filter((a) => !a.startsWith("-"))) {
26891
27007
  const target = join(root, "node_modules", name);
26892
27008
  if (ctx.vfs.lexists(target)) ctx.vfs.rmrf(target, ctx.cred);
26893
- if (found) {
26894
- delete found.manifest.dependencies?.[name];
26895
- delete found.manifest.devDependencies?.[name];
27009
+ if (found2) {
27010
+ delete found2.manifest.dependencies?.[name];
27011
+ delete found2.manifest.devDependencies?.[name];
26896
27012
  }
26897
27013
  ctx.line(`removed ${name}`);
26898
27014
  }
26899
- if (found) writeManifest(ctx, found.path, found.manifest);
27015
+ if (found2) writeManifest(ctx, found2.path, found2.manifest);
26900
27016
  return 0;
26901
27017
  }
26902
27018
  case "ls":
26903
27019
  case "list": {
26904
- const found = readManifest(ctx, root);
26905
- ctx.line(`${found?.manifest.name ?? basename(root)}@${found?.manifest.version ?? "1.0.0"} ${root}`);
27020
+ const found2 = readManifest(ctx, root);
27021
+ ctx.line(`${found2?.manifest.name ?? basename(root)}@${found2?.manifest.version ?? "1.0.0"} ${root}`);
26906
27022
  const modules = join(root, "node_modules");
26907
27023
  if (!ctx.vfs.lexists(modules)) return 0;
26908
27024
  const names = ctx.vfs.readdir(modules, ctx.cred).filter((n) => !n.startsWith("."));
@@ -26924,29 +27040,29 @@ var npm = defineCommand({
26924
27040
  case "build": {
26925
27041
  const scriptName = subcommand === "run" || subcommand === "run-script" ? rest[0] : subcommand;
26926
27042
  const scriptArgs = subcommand === "run" || subcommand === "run-script" ? rest.slice(1) : rest;
26927
- const found = readManifest(ctx, root);
26928
- if (!found) return ctx.fail("could not read package.json", 1);
27043
+ const found2 = readManifest(ctx, root);
27044
+ if (!found2) return ctx.fail("could not read package.json", 1);
26929
27045
  if (scriptName === void 0) {
26930
- ctx.line("Lifecycle scripts included in " + (found.manifest.name ?? "app") + ":");
26931
- for (const [name, body] of Object.entries(found.manifest.scripts ?? {})) {
27046
+ ctx.line("Lifecycle scripts included in " + (found2.manifest.name ?? "app") + ":");
27047
+ for (const [name, body] of Object.entries(found2.manifest.scripts ?? {})) {
26932
27048
  ctx.line(` ${name}`);
26933
27049
  ctx.line(` ${body}`);
26934
27050
  }
26935
27051
  return 0;
26936
27052
  }
26937
- const script = found.manifest.scripts?.[scriptName];
27053
+ const script = found2.manifest.scripts?.[scriptName];
26938
27054
  if (script === void 0) {
26939
- if (scriptName === "start" && found.manifest.main) {
26940
- return await runScript(ctx, root, `node ${found.manifest.main}`, scriptArgs, found.manifest);
27055
+ if (scriptName === "start" && found2.manifest.main) {
27056
+ return await runScript(ctx, root, `node ${found2.manifest.main}`, scriptArgs, found2.manifest);
26941
27057
  }
26942
27058
  ctx.warn(`Missing script: "${scriptName}"`);
26943
27059
  return 1;
26944
27060
  }
26945
27061
  ctx.line("");
26946
- ctx.line(`> ${found.manifest.name ?? "app"}@${found.manifest.version ?? "1.0.0"} ${scriptName}`);
27062
+ ctx.line(`> ${found2.manifest.name ?? "app"}@${found2.manifest.version ?? "1.0.0"} ${scriptName}`);
26947
27063
  ctx.line(`> ${script}`);
26948
27064
  ctx.line("");
26949
- return await runScript(ctx, root, script, scriptArgs, found.manifest);
27065
+ return await runScript(ctx, root, script, scriptArgs, found2.manifest);
26950
27066
  }
26951
27067
  case "exec":
26952
27068
  return await runScript(ctx, root, rest.join(" "), [], readManifest(ctx, root)?.manifest ?? {});
@@ -29382,23 +29498,23 @@ var CommonJsEngine = class {
29382
29498
  const builtin = this.builtin(specifier);
29383
29499
  if (builtin.found) return specifier;
29384
29500
  if (specifier.startsWith("#")) {
29385
- const found = this.resolveImports(specifier, importer, kind);
29386
- if (found) return found;
29501
+ const found2 = this.resolveImports(specifier, importer, kind);
29502
+ if (found2) return found2;
29387
29503
  throw this.moduleNotFound(specifier, importer);
29388
29504
  }
29389
29505
  const baseDir = dirname(importer);
29390
29506
  if (specifier.startsWith("/") || specifier.startsWith("./") || specifier.startsWith("../")) {
29391
29507
  const resolved = specifier.startsWith("/") ? clean(specifier) : resolve(baseDir, specifier);
29392
- const found = this.resolvePath(resolved, kind);
29393
- if (found) return found;
29508
+ const found2 = this.resolvePath(resolved, kind);
29509
+ if (found2) return found2;
29394
29510
  } else {
29395
29511
  const aliased = this.aliasFor(specifier);
29396
29512
  if (aliased) {
29397
29513
  const substituted = this.resolvePackage(aliased, baseDir, kind);
29398
29514
  if (substituted) return substituted;
29399
29515
  }
29400
- const found = this.resolvePackage(specifier, baseDir, kind);
29401
- if (found) return found;
29516
+ const found2 = this.resolvePackage(specifier, baseDir, kind);
29517
+ if (found2) return found2;
29402
29518
  }
29403
29519
  throw this.moduleNotFound(specifier, importer);
29404
29520
  }
@@ -29564,8 +29680,8 @@ ${code}
29564
29680
  continue;
29565
29681
  }
29566
29682
  for (const target of targets ?? []) {
29567
- const found = this.resolvePath(resolve(root, target), kind);
29568
- if (found) return found;
29683
+ const found2 = this.resolvePath(resolve(root, target), kind);
29684
+ if (found2) return found2;
29569
29685
  }
29570
29686
  }
29571
29687
  return null;
@@ -29574,8 +29690,8 @@ ${code}
29574
29690
  for (const field of ENTRY_FIELDS[kind]) {
29575
29691
  const value = manifest?.[field];
29576
29692
  if (typeof value === "string") {
29577
- const found = this.resolvePath(resolve(root, value), kind);
29578
- if (found) return found;
29693
+ const found2 = this.resolvePath(resolve(root, value), kind);
29694
+ if (found2) return found2;
29579
29695
  }
29580
29696
  }
29581
29697
  return this.resolveIndex(root);
@@ -29598,8 +29714,8 @@ ${code}
29598
29714
  continue;
29599
29715
  }
29600
29716
  for (const target of targets ?? []) {
29601
- const found = target.startsWith(".") ? this.resolvePath(resolve(root, target), kind) : this.resolvePackage(target, root, kind);
29602
- if (found) return found;
29717
+ const found2 = target.startsWith(".") ? this.resolvePath(resolve(root, target), kind) : this.resolvePackage(target, root, kind);
29718
+ if (found2) return found2;
29603
29719
  }
29604
29720
  }
29605
29721
  return null;
@@ -36233,12 +36349,12 @@ async function loadNodeRolldownMemfsBinding() {
36233
36349
  function resolveWorkerPath(node2) {
36234
36350
  const { dirname: dirname3, existsSync, fileURLToPath: fileURLToPath2, join: join3 } = node2;
36235
36351
  const here = dirname3(fileURLToPath2(import.meta.url));
36236
- const candidates = [
36352
+ const candidates2 = [
36237
36353
  join3(here, WORKER_FILE),
36238
36354
  /* src/tools → dist, for a checkout that has been built. */
36239
36355
  join3(here, "..", "..", "dist", WORKER_FILE)
36240
36356
  ];
36241
- return candidates.find((candidate) => existsSync(candidate)) ?? null;
36357
+ return candidates2.find((candidate) => existsSync(candidate)) ?? null;
36242
36358
  }
36243
36359
  function resolveSubpath(node2, require2, packageName, subpath) {
36244
36360
  const { dirname: dirname3, join: join3, pathToFileURL: pathToFileURL2, readFileSync } = node2;
@@ -38592,17 +38708,17 @@ var Terminal = class {
38592
38708
  const match2 = /(\S*)$/.exec(left);
38593
38709
  const word = match2?.[1] ?? "";
38594
38710
  const isFirstWord = left.slice(0, left.length - word.length).trim() === "";
38595
- const candidates = isFirstWord && !word.includes("/") ? this.completeCommand(word) : this.completePath(word);
38596
- if (candidates.length === 0) return;
38597
- if (candidates.length === 1) {
38598
- const completion = candidates[0];
38711
+ const candidates2 = isFirstWord && !word.includes("/") ? this.completeCommand(word) : this.completePath(word);
38712
+ if (candidates2.length === 0) return;
38713
+ if (candidates2.length === 1) {
38714
+ const completion = candidates2[0];
38599
38715
  const suffix = completion.slice(word.length);
38600
38716
  this.buffer = this.buffer.slice(0, this.cursor) + suffix + this.buffer.slice(this.cursor);
38601
38717
  this.cursor += suffix.length;
38602
38718
  this.redraw();
38603
38719
  return;
38604
38720
  }
38605
- const common = longestCommonPrefix(candidates);
38721
+ const common = longestCommonPrefix(candidates2);
38606
38722
  if (common.length > word.length) {
38607
38723
  const suffix = common.slice(word.length);
38608
38724
  this.buffer = this.buffer.slice(0, this.cursor) + suffix + this.buffer.slice(this.cursor);
@@ -38610,7 +38726,7 @@ var Terminal = class {
38610
38726
  this.redraw();
38611
38727
  return;
38612
38728
  }
38613
- this.write("\r\n" + formatColumns(candidates, this.columns) + "\r\n");
38729
+ this.write("\r\n" + formatColumns(candidates2, this.columns) + "\r\n");
38614
38730
  this.redraw();
38615
38731
  }
38616
38732
  completeCommand(word) {