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