Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/jsc/web_worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -976,6 +976,11 @@ impl WebWorker {
unsafe {
let b = &mut (*vm).transpiler;
b.resolver.env_loader = NonNull::new(b.env);
// Match the main thread (run_command.rs): never inline
// `process.env.X` dot-reads as literals — they'd be baked into
// the shared on-disk runtime transpiler cache.
Comment thread
robobun marked this conversation as resolved.
Outdated
b.options.env.behavior =
bun_options_types::schema::api::DotEnvBehavior::LoadAllWithoutInlining;
Comment thread
claude[bot] marked this conversation as resolved.

if let Some(graph) = parent.standalone_module_graph {
(hooks.apply_standalone_runtime_flags)(b, graph);
Expand Down
18 changes: 18 additions & 0 deletions test/cli/run/transpiler-cache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,24 @@ describe("transpiler cache", () => {
expect(b.stdout == "production 5");
expect(newCacheCount()).toBe(0);
});
test("does not inline process.env in Worker threads", () => {
// https://github.com/oven-sh/bun/issues/34210
writeFileSync(
join(temp_dir, "big-env.js"),
dummyFile((50 * 1024 * 1.5) | 0, "1", { code: "process.env.TRANSPILER_CACHE_TEST_ID" }),
);
writeFileSync(join(temp_dir, "worker-entry.js"), `await import("./big-env.js");`);
writeFileSync(join(temp_dir, "worker-main.js"), `new Worker(new URL("./worker-entry.js", import.meta.url));`);

const a = bunRun(join(temp_dir, "worker-main.js"), { ...env, TRANSPILER_CACHE_TEST_ID: "first" });
expect(a.stdout).toBe("first");
expect(newCacheCount()).toBe(1);

// A second process with a different env must not observe the first
// process's value through the shared cache entry.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
const b = bunRun(join(temp_dir, "worker-main.js"), { ...env, TRANSPILER_CACHE_TEST_ID: "second" });
expect(b.stdout).toBe("second");
Comment thread
coderabbitai[bot] marked this conversation as resolved.
});
test("--feature flag invalidates cache", () => {
// feature() can only appear in an if/ternary, so wrap it
const code = `import { feature } from "bun:bundle";\nif (feature("SUPER_SECRET")) console.log("enabled"); else console.log("disabled");`;
Expand Down
36 changes: 36 additions & 0 deletions test/js/node/worker_threads/worker_threads.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1419,6 +1419,42 @@ test("*Internal introspection methods are DontEnum on Worker.prototype", () => {
expect(enumerable).not.toContain("cpuUsageInternal");
});

test("env: {} scrubs the launch environment from the worker's process.env", async () => {
// Spawn so the launch environ we're scrubbing is known and not the test
// runner's own. The worker reads the vars as literal dot accesses, which is
// the form the worker transpiler was previously inlining from the parent's
// env loader even when `env: {}` installed an empty plain object.
await using proc = Bun.spawn({
cmd: [
bunExe(),
"-e",
`const { Worker } = require("node:worker_threads");
const src = \`const { parentPort } = require("node:worker_threads");
parentPort.postMessage({
keys: Object.keys(process.env),
secret: process.env.LAUNCH_SECRET ?? null,
only: process.env.ONLY ?? null,
inSecret: "LAUNCH_SECRET" in process.env,
node_env: process.env.NODE_ENV ?? null,
});\`;
const w = new Worker(src, { eval: true, env: { ONLY: "1" } });
w.once("message", m => { console.log(JSON.stringify(m)); w.terminate(); });`,
],
env: { ...bunEnv, LAUNCH_SECRET: "s3cr3t", NODE_ENV: "production" },
stderr: "pipe",
});
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
expect(stderr).toBe("");
expect(JSON.parse(stdout.trim())).toEqual({
keys: ["ONLY"],
secret: null,
only: "1",
inSecret: false,
node_env: null,
});
expect(exitCode).toBe(0);
});

describe("env: SHARE_ENV shares the spawning thread's env, not a process-wide one", () => {
async function run(mode: string) {
const proc = Bun.spawn({
Expand Down
Loading