sandboxedjs 0.1.1 → 0.1.3

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
@@ -1,4 +1,5 @@
1
1
  import { Nodepod, DependencyInstaller } from '@scelar/nodepod/headless';
2
+ import { parse as parse$1 } from 'acorn';
2
3
 
3
4
  var __defProp = Object.defineProperty;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -4039,6 +4040,294 @@ var init_builtins = __esm({
4039
4040
  }
4040
4041
  });
4041
4042
 
4043
+ // src/util/binary.ts
4044
+ var isNode = typeof process !== "undefined" && process.versions != null && process.versions.node != null;
4045
+ async function nodeBuiltin(name) {
4046
+ const specifier = `node:${name}`;
4047
+ return await import(
4048
+ /* @vite-ignore */
4049
+ /* webpackIgnore: true */
4050
+ specifier
4051
+ );
4052
+ }
4053
+ var zlibPromise = null;
4054
+ function nodeZlib() {
4055
+ zlibPromise ??= nodeBuiltin("zlib");
4056
+ return zlibPromise;
4057
+ }
4058
+ async function throughStream(data, stream) {
4059
+ const source = new Blob([data]).stream();
4060
+ const piped = source.pipeThrough(stream);
4061
+ return new Uint8Array(await new Response(piped).arrayBuffer());
4062
+ }
4063
+ async function gzip(data) {
4064
+ if (isNode) return new Uint8Array((await nodeZlib()).gzipSync(data));
4065
+ return throughStream(data, new CompressionStream("gzip"));
4066
+ }
4067
+ async function gunzip(data) {
4068
+ if (isNode) return new Uint8Array((await nodeZlib()).gunzipSync(data));
4069
+ return throughStream(data, new DecompressionStream("gzip"));
4070
+ }
4071
+ async function deflate(data) {
4072
+ if (isNode) return new Uint8Array((await nodeZlib()).deflateSync(data));
4073
+ return throughStream(data, new CompressionStream("deflate"));
4074
+ }
4075
+ async function inflate(data) {
4076
+ if (isNode) return new Uint8Array((await nodeZlib()).inflateSync(data));
4077
+ return throughStream(data, new DecompressionStream("deflate"));
4078
+ }
4079
+ async function inflateRaw(data) {
4080
+ if (isNode) return new Uint8Array((await nodeZlib()).inflateRawSync(data));
4081
+ return throughStream(data, new DecompressionStream("deflate-raw"));
4082
+ }
4083
+ var cryptoPromise = null;
4084
+ function nodeCrypto() {
4085
+ cryptoPromise ??= nodeBuiltin("crypto");
4086
+ return cryptoPromise;
4087
+ }
4088
+ var SUBTLE_NAMES = {
4089
+ sha1: "SHA-1",
4090
+ sha256: "SHA-256",
4091
+ sha384: "SHA-384",
4092
+ sha512: "SHA-512"
4093
+ };
4094
+ var UnsupportedAlgorithmError = class extends Error {
4095
+ constructor(algorithm) {
4096
+ super(`${algorithm} is not available in this environment`);
4097
+ this.name = "UnsupportedAlgorithmError";
4098
+ }
4099
+ };
4100
+ async function digestHex(algorithm, data) {
4101
+ if (isNode) {
4102
+ const { createHash } = await nodeCrypto();
4103
+ return createHash(algorithm).update(data).digest("hex");
4104
+ }
4105
+ if (algorithm === "md5") return md5Hex(data);
4106
+ const name = SUBTLE_NAMES[algorithm];
4107
+ if (!name) throw new UnsupportedAlgorithmError(algorithm);
4108
+ const buffer = await crypto.subtle.digest(name, data);
4109
+ return toHex(new Uint8Array(buffer));
4110
+ }
4111
+ async function randomUuid() {
4112
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") return crypto.randomUUID();
4113
+ const { randomUUID } = await nodeCrypto();
4114
+ return randomUUID();
4115
+ }
4116
+ function toHex(bytes) {
4117
+ let out = "";
4118
+ for (const byte of bytes) out += byte.toString(16).padStart(2, "0");
4119
+ return out;
4120
+ }
4121
+ function md5Hex(input) {
4122
+ const S = [
4123
+ 7,
4124
+ 12,
4125
+ 17,
4126
+ 22,
4127
+ 7,
4128
+ 12,
4129
+ 17,
4130
+ 22,
4131
+ 7,
4132
+ 12,
4133
+ 17,
4134
+ 22,
4135
+ 7,
4136
+ 12,
4137
+ 17,
4138
+ 22,
4139
+ 5,
4140
+ 9,
4141
+ 14,
4142
+ 20,
4143
+ 5,
4144
+ 9,
4145
+ 14,
4146
+ 20,
4147
+ 5,
4148
+ 9,
4149
+ 14,
4150
+ 20,
4151
+ 5,
4152
+ 9,
4153
+ 14,
4154
+ 20,
4155
+ 4,
4156
+ 11,
4157
+ 16,
4158
+ 23,
4159
+ 4,
4160
+ 11,
4161
+ 16,
4162
+ 23,
4163
+ 4,
4164
+ 11,
4165
+ 16,
4166
+ 23,
4167
+ 4,
4168
+ 11,
4169
+ 16,
4170
+ 23,
4171
+ 6,
4172
+ 10,
4173
+ 15,
4174
+ 21,
4175
+ 6,
4176
+ 10,
4177
+ 15,
4178
+ 21,
4179
+ 6,
4180
+ 10,
4181
+ 15,
4182
+ 21,
4183
+ 6,
4184
+ 10,
4185
+ 15,
4186
+ 21
4187
+ ];
4188
+ const K = new Uint32Array(64);
4189
+ for (let i = 0; i < 64; i++) K[i] = Math.floor(Math.abs(Math.sin(i + 1)) * 2 ** 32);
4190
+ const bitLength = input.length * 8;
4191
+ const padded = new Uint8Array(((input.length + 8 >> 6) + 1) * 64);
4192
+ padded.set(input);
4193
+ padded[input.length] = 128;
4194
+ const view = new DataView(padded.buffer);
4195
+ view.setUint32(padded.length - 8, bitLength >>> 0, true);
4196
+ view.setUint32(padded.length - 4, Math.floor(bitLength / 2 ** 32), true);
4197
+ let a0 = 1732584193;
4198
+ let b0 = 4023233417;
4199
+ let c0 = 2562383102;
4200
+ let d0 = 271733878;
4201
+ for (let chunk = 0; chunk < padded.length; chunk += 64) {
4202
+ const M = new Uint32Array(16);
4203
+ for (let i = 0; i < 16; i++) M[i] = view.getUint32(chunk + i * 4, true);
4204
+ let [a, b, c, d] = [a0, b0, c0, d0];
4205
+ for (let i = 0; i < 64; i++) {
4206
+ let f;
4207
+ let g;
4208
+ if (i < 16) {
4209
+ f = b & c | ~b & d;
4210
+ g = i;
4211
+ } else if (i < 32) {
4212
+ f = d & b | ~d & c;
4213
+ g = (5 * i + 1) % 16;
4214
+ } else if (i < 48) {
4215
+ f = b ^ c ^ d;
4216
+ g = (3 * i + 5) % 16;
4217
+ } else {
4218
+ f = c ^ (b | ~d);
4219
+ g = 7 * i % 16;
4220
+ }
4221
+ const tmp = d;
4222
+ d = c;
4223
+ c = b;
4224
+ const sum = a + f + K[i] + M[g] >>> 0;
4225
+ b = b + (sum << S[i] | sum >>> 32 - S[i]) >>> 0;
4226
+ a = tmp;
4227
+ }
4228
+ a0 = a0 + a >>> 0;
4229
+ b0 = b0 + b >>> 0;
4230
+ c0 = c0 + c >>> 0;
4231
+ d0 = d0 + d >>> 0;
4232
+ }
4233
+ const out = new Uint8Array(16);
4234
+ new DataView(out.buffer).setUint32(0, a0, true);
4235
+ new DataView(out.buffer).setUint32(4, b0, true);
4236
+ new DataView(out.buffer).setUint32(8, c0, true);
4237
+ new DataView(out.buffer).setUint32(12, d0, true);
4238
+ return toHex(out);
4239
+ }
4240
+
4241
+ // src/runtime/esbuild-host.ts
4242
+ var INITIALIZE_CALLS = /\.initialize\(\s*\{\s*wasmURL:[^}]*\}\s*\)/g;
4243
+ var installed = null;
4244
+ function installEsbuildRuntime() {
4245
+ installed ??= install().catch((error) => {
4246
+ if (process.env.SANDBOXEDJS_DEBUG) {
4247
+ console.error("[sandboxedjs] esbuild runtime unavailable:", error);
4248
+ }
4249
+ });
4250
+ return installed;
4251
+ }
4252
+ async function install() {
4253
+ const workerPath = await buildPatchedWorker();
4254
+ if (!workerPath) return;
4255
+ const { createNodeHost, setRuntimeHost } = await import('@scelar/nodepod/headless');
4256
+ setRuntimeHost(createNodeHost({ workerPath }));
4257
+ }
4258
+ async function buildPatchedWorker() {
4259
+ const { createRequire } = await nodeBuiltin("module");
4260
+ const fs = await nodeBuiltin("fs/promises");
4261
+ const os = await nodeBuiltin("os");
4262
+ const path = await nodeBuiltin("path");
4263
+ const url = await nodeBuiltin("url");
4264
+ const crypto2 = await nodeBuiltin("crypto");
4265
+ const require2 = createRequire(path.join(process.cwd(), "index.js"));
4266
+ let workerPath;
4267
+ let wasmPath;
4268
+ let browserEntry;
4269
+ try {
4270
+ workerPath = path.join(
4271
+ path.dirname(require2.resolve("@scelar/nodepod/headless")),
4272
+ "__worker__.js"
4273
+ );
4274
+ const esbuildRoot = path.dirname(require2.resolve("esbuild-wasm/package.json"));
4275
+ wasmPath = path.join(esbuildRoot, "esbuild.wasm");
4276
+ browserEntry = path.join(esbuildRoot, "esm", "browser.min.js");
4277
+ } catch {
4278
+ return null;
4279
+ }
4280
+ const [source, wasmStat] = await Promise.all([
4281
+ fs.readFile(workerPath, "utf8"),
4282
+ fs.stat(wasmPath)
4283
+ ]);
4284
+ if (!INITIALIZE_CALLS.test(source)) {
4285
+ return null;
4286
+ }
4287
+ INITIALIZE_CALLS.lastIndex = 0;
4288
+ const WASM_URL = /`https:\/\/esm\.sh\/esbuild-wasm@\$\{[A-Za-z0-9_$]+\}\/esbuild\.wasm`/g;
4289
+ const MODULE_URL = /`https:\/\/esm\.sh\/esbuild-wasm@\$\{[A-Za-z0-9_$]+\}`/g;
4290
+ const initCall = `.initialize(await __sandboxedjsEsbuildInit(${JSON.stringify(wasmPath)}, ${JSON.stringify(url.pathToFileURL(wasmPath).href)}))`;
4291
+ const patched = [
4292
+ // The helper is needed by the bundle itself and again inside the nested
4293
+ // worker it builds from a template, which is a separate script.
4294
+ INIT_HELPER,
4295
+ source.replace(WASM_URL, JSON.stringify(url.pathToFileURL(wasmPath).href)).replace(MODULE_URL, JSON.stringify(url.pathToFileURL(browserEntry).href)).replace(INITIALIZE_CALLS, initCall).replace("function ensureEsbuild() {", `${INIT_HELPER}
4296
+
4297
+ function ensureEsbuild() {`)
4298
+ ].join("\n");
4299
+ const fingerprint = crypto2.createHash("sha256").update(`${source.length}:${wasmStat.size}:${patched.length}`).digest("hex").slice(0, 16);
4300
+ const cached = path.join(os.tmpdir(), `sandboxedjs-worker-${fingerprint}.js`);
4301
+ try {
4302
+ await fs.access(cached);
4303
+ } catch {
4304
+ const staging = `${cached}.${process.pid}.tmp`;
4305
+ await fs.writeFile(staging, patched, "utf8");
4306
+ await fs.rename(staging, cached);
4307
+ }
4308
+ return cached;
4309
+ }
4310
+ var INIT_HELPER = `let __sandboxedjsWasmUrl = null;
4311
+ async function __sandboxedjsEsbuildInit(wasmPath, wasmUrl) {
4312
+ // esbuild-wasm is a browser build: it resolves its wasm against document
4313
+ // location. There is no document here, and a bare origin is enough.
4314
+ if (typeof globalThis.location === "undefined") {
4315
+ globalThis.location = { href: "file:///", origin: "null", protocol: "file:" };
4316
+ }
4317
+ // esbuild-wasm fetches its wasm, and fetch cannot read a file: URL, so the
4318
+ // bytes are inlined as a data: URL instead \u2014 the one scheme both the ESM
4319
+ // loader and fetch accept. Built once and reused; it is ~15MB of base64.
4320
+ // Handing over a pre-compiled WebAssembly.Module instead does not work: the
4321
+ // Go glue supplies its own import object and rejects a foreign module.
4322
+ try {
4323
+ if (__sandboxedjsWasmUrl === null && typeof require === "function") {
4324
+ const bytes = require("node:fs").readFileSync(wasmPath);
4325
+ __sandboxedjsWasmUrl = "data:application/wasm;base64," + bytes.toString("base64");
4326
+ }
4327
+ } catch (err) { /* fall back to the file URL below */ }
4328
+ return { wasmURL: __sandboxedjsWasmUrl || wasmUrl, worker: false };
4329
+ }`;
4330
+
4042
4331
  // src/fs/vfs.ts
4043
4332
  init_errno();
4044
4333
  init_path();
@@ -15131,206 +15420,6 @@ var commands5 = [grep, find, xargs, diff, cmp];
15131
15420
  // src/bin/archive.ts
15132
15421
  init_mode();
15133
15422
  init_path();
15134
-
15135
- // src/util/binary.ts
15136
- var isNode = typeof process !== "undefined" && process.versions != null && process.versions.node != null;
15137
- async function nodeBuiltin(name) {
15138
- const specifier = `node:${name}`;
15139
- return await import(
15140
- /* @vite-ignore */
15141
- /* webpackIgnore: true */
15142
- specifier
15143
- );
15144
- }
15145
- var zlibPromise = null;
15146
- function nodeZlib() {
15147
- zlibPromise ??= nodeBuiltin("zlib");
15148
- return zlibPromise;
15149
- }
15150
- async function throughStream(data, stream) {
15151
- const source = new Blob([data]).stream();
15152
- const piped = source.pipeThrough(stream);
15153
- return new Uint8Array(await new Response(piped).arrayBuffer());
15154
- }
15155
- async function gzip(data) {
15156
- if (isNode) return new Uint8Array((await nodeZlib()).gzipSync(data));
15157
- return throughStream(data, new CompressionStream("gzip"));
15158
- }
15159
- async function gunzip(data) {
15160
- if (isNode) return new Uint8Array((await nodeZlib()).gunzipSync(data));
15161
- return throughStream(data, new DecompressionStream("gzip"));
15162
- }
15163
- async function deflate(data) {
15164
- if (isNode) return new Uint8Array((await nodeZlib()).deflateSync(data));
15165
- return throughStream(data, new CompressionStream("deflate"));
15166
- }
15167
- async function inflate(data) {
15168
- if (isNode) return new Uint8Array((await nodeZlib()).inflateSync(data));
15169
- return throughStream(data, new DecompressionStream("deflate"));
15170
- }
15171
- async function inflateRaw(data) {
15172
- if (isNode) return new Uint8Array((await nodeZlib()).inflateRawSync(data));
15173
- return throughStream(data, new DecompressionStream("deflate-raw"));
15174
- }
15175
- var cryptoPromise = null;
15176
- function nodeCrypto() {
15177
- cryptoPromise ??= nodeBuiltin("crypto");
15178
- return cryptoPromise;
15179
- }
15180
- var SUBTLE_NAMES = {
15181
- sha1: "SHA-1",
15182
- sha256: "SHA-256",
15183
- sha384: "SHA-384",
15184
- sha512: "SHA-512"
15185
- };
15186
- var UnsupportedAlgorithmError = class extends Error {
15187
- constructor(algorithm) {
15188
- super(`${algorithm} is not available in this environment`);
15189
- this.name = "UnsupportedAlgorithmError";
15190
- }
15191
- };
15192
- async function digestHex(algorithm, data) {
15193
- if (isNode) {
15194
- const { createHash } = await nodeCrypto();
15195
- return createHash(algorithm).update(data).digest("hex");
15196
- }
15197
- if (algorithm === "md5") return md5Hex(data);
15198
- const name = SUBTLE_NAMES[algorithm];
15199
- if (!name) throw new UnsupportedAlgorithmError(algorithm);
15200
- const buffer = await crypto.subtle.digest(name, data);
15201
- return toHex(new Uint8Array(buffer));
15202
- }
15203
- async function randomUuid() {
15204
- if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") return crypto.randomUUID();
15205
- const { randomUUID } = await nodeCrypto();
15206
- return randomUUID();
15207
- }
15208
- function toHex(bytes) {
15209
- let out = "";
15210
- for (const byte of bytes) out += byte.toString(16).padStart(2, "0");
15211
- return out;
15212
- }
15213
- function md5Hex(input) {
15214
- const S = [
15215
- 7,
15216
- 12,
15217
- 17,
15218
- 22,
15219
- 7,
15220
- 12,
15221
- 17,
15222
- 22,
15223
- 7,
15224
- 12,
15225
- 17,
15226
- 22,
15227
- 7,
15228
- 12,
15229
- 17,
15230
- 22,
15231
- 5,
15232
- 9,
15233
- 14,
15234
- 20,
15235
- 5,
15236
- 9,
15237
- 14,
15238
- 20,
15239
- 5,
15240
- 9,
15241
- 14,
15242
- 20,
15243
- 5,
15244
- 9,
15245
- 14,
15246
- 20,
15247
- 4,
15248
- 11,
15249
- 16,
15250
- 23,
15251
- 4,
15252
- 11,
15253
- 16,
15254
- 23,
15255
- 4,
15256
- 11,
15257
- 16,
15258
- 23,
15259
- 4,
15260
- 11,
15261
- 16,
15262
- 23,
15263
- 6,
15264
- 10,
15265
- 15,
15266
- 21,
15267
- 6,
15268
- 10,
15269
- 15,
15270
- 21,
15271
- 6,
15272
- 10,
15273
- 15,
15274
- 21,
15275
- 6,
15276
- 10,
15277
- 15,
15278
- 21
15279
- ];
15280
- const K = new Uint32Array(64);
15281
- for (let i = 0; i < 64; i++) K[i] = Math.floor(Math.abs(Math.sin(i + 1)) * 2 ** 32);
15282
- const bitLength = input.length * 8;
15283
- const padded = new Uint8Array(((input.length + 8 >> 6) + 1) * 64);
15284
- padded.set(input);
15285
- padded[input.length] = 128;
15286
- const view = new DataView(padded.buffer);
15287
- view.setUint32(padded.length - 8, bitLength >>> 0, true);
15288
- view.setUint32(padded.length - 4, Math.floor(bitLength / 2 ** 32), true);
15289
- let a0 = 1732584193;
15290
- let b0 = 4023233417;
15291
- let c0 = 2562383102;
15292
- let d0 = 271733878;
15293
- for (let chunk = 0; chunk < padded.length; chunk += 64) {
15294
- const M = new Uint32Array(16);
15295
- for (let i = 0; i < 16; i++) M[i] = view.getUint32(chunk + i * 4, true);
15296
- let [a, b, c, d] = [a0, b0, c0, d0];
15297
- for (let i = 0; i < 64; i++) {
15298
- let f;
15299
- let g;
15300
- if (i < 16) {
15301
- f = b & c | ~b & d;
15302
- g = i;
15303
- } else if (i < 32) {
15304
- f = d & b | ~d & c;
15305
- g = (5 * i + 1) % 16;
15306
- } else if (i < 48) {
15307
- f = b ^ c ^ d;
15308
- g = (3 * i + 5) % 16;
15309
- } else {
15310
- f = c ^ (b | ~d);
15311
- g = 7 * i % 16;
15312
- }
15313
- const tmp = d;
15314
- d = c;
15315
- c = b;
15316
- const sum = a + f + K[i] + M[g] >>> 0;
15317
- b = b + (sum << S[i] | sum >>> 32 - S[i]) >>> 0;
15318
- a = tmp;
15319
- }
15320
- a0 = a0 + a >>> 0;
15321
- b0 = b0 + b >>> 0;
15322
- c0 = c0 + c >>> 0;
15323
- d0 = d0 + d >>> 0;
15324
- }
15325
- const out = new Uint8Array(16);
15326
- new DataView(out.buffer).setUint32(0, a0, true);
15327
- new DataView(out.buffer).setUint32(4, b0, true);
15328
- new DataView(out.buffer).setUint32(8, c0, true);
15329
- new DataView(out.buffer).setUint32(12, d0, true);
15330
- return toHex(out);
15331
- }
15332
-
15333
- // src/bin/archive.ts
15334
15423
  var BLOCK = 512;
15335
15424
  var encoder4 = new TextEncoder();
15336
15425
  var decoder6 = new TextDecoder();
@@ -16638,7 +16727,7 @@ var watch = defineCommand({
16638
16727
  return 0;
16639
16728
  }
16640
16729
  });
16641
- var install = defineCommand({
16730
+ var install2 = defineCommand({
16642
16731
  name: "install",
16643
16732
  path: "/usr/bin/install",
16644
16733
  summary: "copy files and set attributes",
@@ -16757,7 +16846,7 @@ var commands9 = [
16757
16846
  timeoutCmd,
16758
16847
  nohup,
16759
16848
  watch,
16760
- install,
16849
+ install2,
16761
16850
  niceCmd,
16762
16851
  timeCmd
16763
16852
  ];
@@ -17947,6 +18036,226 @@ async function readZip(data) {
17947
18036
  function pythonCommands() {
17948
18037
  return [python, pip];
17949
18038
  }
18039
+ var DECLARES_EXPORTS = /(?:^|[\s;{)])(?:var|let|const|function|class)\s+exports\b/;
18040
+ var NAME = "exports";
18041
+ function renameShadowedExports(source) {
18042
+ if (!DECLARES_EXPORTS.test(source)) return null;
18043
+ let ast;
18044
+ try {
18045
+ ast = parse$1(source, {
18046
+ ecmaVersion: "latest",
18047
+ sourceType: "module",
18048
+ allowAwaitOutsideFunction: true,
18049
+ allowHashBang: true
18050
+ });
18051
+ } catch {
18052
+ return null;
18053
+ }
18054
+ const body = ast.body;
18055
+ const isModule = body.some(
18056
+ (node2) => node2.type.startsWith("Import") || node2.type.startsWith("Export")
18057
+ );
18058
+ if (!isModule) return null;
18059
+ const programScope = { bindsExports: hoistedNames(body).has(NAME), parent: null };
18060
+ if (!programScope.bindsExports) return null;
18061
+ const targets = [];
18062
+ let bail = false;
18063
+ visit(ast, programScope);
18064
+ if (bail || targets.length === 0) return null;
18065
+ const replacement = freshName(source);
18066
+ let out = source;
18067
+ for (const target of [...targets].sort((a, b) => b.start - a.start)) {
18068
+ const text = target.shorthand ? `${NAME}: ${replacement}` : replacement;
18069
+ out = out.slice(0, target.start) + text + out.slice(target.end);
18070
+ }
18071
+ return out;
18072
+ function visit(node2, scope) {
18073
+ if (bail) return;
18074
+ let childScope = scope;
18075
+ let skip = NOTHING;
18076
+ switch (node2.type) {
18077
+ case "FunctionDeclaration":
18078
+ case "FunctionExpression":
18079
+ case "ArrowFunctionExpression": {
18080
+ const names = /* @__PURE__ */ new Set();
18081
+ for (const param of node2.params ?? []) collectPattern(param, names);
18082
+ if (isExports(node2.id) && node2.type === "FunctionExpression") names.add(NAME);
18083
+ const fnBody = node2.body;
18084
+ if (fnBody?.type === "BlockStatement") {
18085
+ for (const name of hoistedNames(fnBody.body)) names.add(name);
18086
+ }
18087
+ childScope = { bindsExports: names.has(NAME), parent: scope };
18088
+ break;
18089
+ }
18090
+ case "CatchClause": {
18091
+ const names = /* @__PURE__ */ new Set();
18092
+ if (node2.param) collectPattern(node2.param, names);
18093
+ childScope = { bindsExports: names.has(NAME), parent: scope };
18094
+ break;
18095
+ }
18096
+ case "ClassDeclaration":
18097
+ case "ClassExpression":
18098
+ if (isExports(node2.id) && node2.type === "ClassExpression") {
18099
+ childScope = { bindsExports: true, parent: scope };
18100
+ }
18101
+ break;
18102
+ case "BlockStatement":
18103
+ case "StaticBlock":
18104
+ if (node2 !== ast.body) {
18105
+ childScope = {
18106
+ bindsExports: blockNames(node2.body).has(NAME),
18107
+ parent: scope
18108
+ };
18109
+ }
18110
+ break;
18111
+ case "ForStatement":
18112
+ case "ForInStatement":
18113
+ case "ForOfStatement": {
18114
+ const head2 = node2.init ?? node2.left;
18115
+ if (head2?.type === "VariableDeclaration" && head2.kind !== "var") {
18116
+ const names = /* @__PURE__ */ new Set();
18117
+ for (const declarator of head2.declarations) {
18118
+ collectPattern(declarator.id, names);
18119
+ }
18120
+ childScope = { bindsExports: names.has(NAME), parent: scope };
18121
+ }
18122
+ break;
18123
+ }
18124
+ /* `export { exports }` would have to become `exports as exports`, and
18125
+ * `import { exports as x }` names someone else's binding. Neither is
18126
+ * worth handling; refuse rather than rewrite them wrongly. */
18127
+ case "ExportSpecifier":
18128
+ case "ImportSpecifier":
18129
+ if (isExports(node2.local) || isExports(node2.exported) || isExports(node2.imported)) {
18130
+ bail = true;
18131
+ }
18132
+ return;
18133
+ case "Identifier":
18134
+ if (node2.name === NAME && resolvesToProgram(scope)) {
18135
+ targets.push({ start: node2.start, end: node2.end, shorthand: false });
18136
+ }
18137
+ return;
18138
+ // Property positions are names, not references to the binding.
18139
+ case "MemberExpression":
18140
+ case "MethodDefinition":
18141
+ case "PropertyDefinition":
18142
+ skip = node2.computed ? NOTHING : PROPERTY;
18143
+ break;
18144
+ case "Property":
18145
+ if (node2.computed) break;
18146
+ if (node2.shorthand) {
18147
+ const value = node2.value;
18148
+ if (isExports(value) && resolvesToProgram(scope)) {
18149
+ targets.push({ start: value.start, end: value.end, shorthand: true });
18150
+ }
18151
+ return;
18152
+ }
18153
+ skip = PROPERTY;
18154
+ break;
18155
+ case "LabeledStatement":
18156
+ case "BreakStatement":
18157
+ case "ContinueStatement":
18158
+ skip = LABEL;
18159
+ break;
18160
+ }
18161
+ for (const [key, value] of Object.entries(node2)) {
18162
+ if (key === "type" || key === "start" || key === "end" || skip.includes(key)) continue;
18163
+ if (Array.isArray(value)) {
18164
+ for (const item of value) if (isNode2(item)) visit(item, childScope);
18165
+ } else if (isNode2(value)) {
18166
+ visit(value, childScope);
18167
+ }
18168
+ }
18169
+ }
18170
+ }
18171
+ function resolvesToProgram(scope) {
18172
+ for (let current = scope; current; current = current.parent) {
18173
+ if (current.bindsExports) return current.parent === null;
18174
+ }
18175
+ return false;
18176
+ }
18177
+ function hoistedNames(body) {
18178
+ const names = blockNames(body);
18179
+ collectVars(body, names);
18180
+ return names;
18181
+ }
18182
+ function blockNames(body) {
18183
+ const names = /* @__PURE__ */ new Set();
18184
+ for (const node2 of body ?? []) {
18185
+ if (node2.type === "VariableDeclaration" && node2.kind !== "var") {
18186
+ for (const declarator of node2.declarations) {
18187
+ collectPattern(declarator.id, names);
18188
+ }
18189
+ } else if (node2.type === "ClassDeclaration" && isNode2(node2.id)) {
18190
+ names.add(node2.id.name);
18191
+ } else if (node2.type === "FunctionDeclaration" && isNode2(node2.id)) {
18192
+ names.add(node2.id.name);
18193
+ }
18194
+ }
18195
+ return names;
18196
+ }
18197
+ function collectVars(nodes, names) {
18198
+ if (Array.isArray(nodes)) {
18199
+ for (const item of nodes) collectVars(item, names);
18200
+ return;
18201
+ }
18202
+ if (!isNode2(nodes)) return;
18203
+ const node2 = nodes;
18204
+ if (node2.type === "FunctionDeclaration" || node2.type === "FunctionExpression" || node2.type === "ArrowFunctionExpression") {
18205
+ if (isNode2(node2.id)) names.add(node2.id.name);
18206
+ return;
18207
+ }
18208
+ if (node2.type === "VariableDeclaration" && node2.kind === "var") {
18209
+ for (const declarator of node2.declarations) {
18210
+ collectPattern(declarator.id, names);
18211
+ }
18212
+ }
18213
+ for (const [key, value] of Object.entries(node2)) {
18214
+ if (key === "type" || key === "start" || key === "end") continue;
18215
+ collectVars(value, names);
18216
+ }
18217
+ }
18218
+ function collectPattern(node2, names) {
18219
+ if (!isNode2(node2)) return;
18220
+ switch (node2.type) {
18221
+ case "Identifier":
18222
+ names.add(node2.name);
18223
+ return;
18224
+ case "ObjectPattern":
18225
+ for (const property of node2.properties) {
18226
+ collectPattern(property.value ?? property.argument, names);
18227
+ }
18228
+ return;
18229
+ case "ArrayPattern":
18230
+ for (const element of node2.elements) collectPattern(element, names);
18231
+ return;
18232
+ case "AssignmentPattern":
18233
+ collectPattern(node2.left, names);
18234
+ return;
18235
+ case "RestElement":
18236
+ collectPattern(node2.argument, names);
18237
+ return;
18238
+ default:
18239
+ return;
18240
+ }
18241
+ }
18242
+ function isExports(value) {
18243
+ return isNode2(value) && value.type === "Identifier" && value.name === NAME;
18244
+ }
18245
+ function freshName(source) {
18246
+ let name = "__sandboxedjs_exports";
18247
+ let suffix = 0;
18248
+ while (source.includes(name)) name = `__sandboxedjs_exports${++suffix}`;
18249
+ return name;
18250
+ }
18251
+ function isNode2(value) {
18252
+ return typeof value === "object" && value !== null && typeof value.type === "string";
18253
+ }
18254
+ var NOTHING = [];
18255
+ var PROPERTY = ["property", "key"];
18256
+ var LABEL = ["label"];
18257
+
18258
+ // src/pkg/index.ts
17950
18259
  init_path();
17951
18260
  var NPM_VERSION = "10.9.0";
17952
18261
  function readManifest(ctx, dir3) {
@@ -18008,6 +18317,7 @@ async function installPackages(ctx, specs, opts) {
18008
18317
  }
18009
18318
  }
18010
18319
  normalizeBinDirectories(ctx, opts.cwd);
18320
+ normalizeEsmExports(ctx, opts.cwd);
18011
18321
  return 0;
18012
18322
  } catch (e) {
18013
18323
  ctx.warn(`npm error ${e instanceof Error ? e.message : String(e)}`);
@@ -18231,6 +18541,20 @@ function normalizeBinDirectories(ctx, root) {
18231
18541
  if (basename(path) === ".bin" && path !== join(modules, ".bin")) visit(path);
18232
18542
  }
18233
18543
  }
18544
+ function normalizeEsmExports(ctx, root) {
18545
+ const modules = join(root, "node_modules");
18546
+ if (!ctx.vfs.lexists(modules)) return;
18547
+ for (const path of ctx.vfs.walk(modules, { cred: ctx.cred })) {
18548
+ if (!/\.(?:js|mjs)$/.test(path)) continue;
18549
+ try {
18550
+ if (!ctx.vfs.lstat(path).isFile()) continue;
18551
+ const source = ctx.vfs.readText(path, ctx.cred);
18552
+ const repaired = renameShadowedExports(source);
18553
+ if (repaired !== null) ctx.vfs.writeFile(path, repaired, { privileged: true });
18554
+ } catch {
18555
+ }
18556
+ }
18557
+ }
18234
18558
  function printNpmHelp(ctx) {
18235
18559
  ctx.line(`npm <command>`);
18236
18560
  ctx.line("");
@@ -18348,12 +18672,12 @@ unless the container was created with network: { allowOutbound: true }.`,
18348
18672
  }
18349
18673
  ctx.stderr.write(`npx: installing ${packageSpec}...
18350
18674
  `);
18351
- const installed = await installPackages(ctx, [packageSpec], {
18675
+ const installed2 = await installPackages(ctx, [packageSpec], {
18352
18676
  cwd: root,
18353
18677
  save: false,
18354
18678
  quiet: true
18355
18679
  });
18356
- if (installed !== 0) return installed;
18680
+ if (installed2 !== 0) return installed2;
18357
18681
  if (!findLocalBin(ctx, command)) {
18358
18682
  const binaries = packageBinaries(ctx, root, packageName);
18359
18683
  const chosen = binaries.includes(command) ? command : binaries[0];
@@ -18782,6 +19106,7 @@ var Container = class _Container {
18782
19106
  }
18783
19107
  // ── boot ──────────────────────────────────────────────────────────────────
18784
19108
  static async create(opts = {}) {
19109
+ if (!opts.pod) await installEsbuildRuntime();
18785
19110
  const pod = opts.pod ?? await Nodepod.boot({
18786
19111
  headless: true,
18787
19112
  serviceWorker: false,