Compare commits

...

1 Commits

Author SHA1 Message Date
Cursor Agent
462708931f Fix process.title to return executable path when unset 2025-06-05 23:18:53 +00:00
5 changed files with 163 additions and 2 deletions

View File

@@ -0,0 +1,81 @@
# Complete Summary: Node.js process.title Compatibility Fix
## Problem
The Node.js test `test-process-title.js` was failing because Bun's `process.title` behavior didn't match Node.js:
- In Node.js, when `process.title` hasn't been explicitly set, it returns the full executable path (same as `process.execPath`)
- In Bun, it was returning just `"bun"`
## Test Case That Was Failing
```js
const xs = "x".repeat(1024);
const proc = spawnSync(process.execPath, ["-p", "process.title", xs]);
strictEqual(proc.stdout.toString().trim(), process.execPath);
```
## Solution Implemented
### First Attempt (caused stack overflow in debug build)
Modified `getTitle` in `src/bun.js/node/node_process.zig` to use `bun.selfExePath()`:
```zig
const exec_path = bun.selfExePath() catch {
title.* = ZigString.init("bun");
return;
};
title.* = ZigString.init(exec_path);
```
### Final Solution (simpler, avoids recursion)
Used `bun.argv[0]` instead:
```zig
pub fn getTitle(_: *JSGlobalObject, title: *ZigString) callconv(.C) void {
title_mutex.lock();
defer title_mutex.unlock();
const str = bun.CLI.Bun__Node__ProcessTitle;
if (str) |s| {
title.* = ZigString.init(s);
} else {
// When no title has been set, return the full executable path (like Node.js)
// Use argv[0] which should contain the full path to the executable
if (bun.argv.len > 0) {
title.* = ZigString.init(bun.argv[0]);
} else {
title.* = ZigString.init("bun");
}
}
}
```
## Additional Fix
Also fixed an unrelated build error in `src/bun.js/bindings/webcore/HTTPHeaderMap.cpp`:
```diff
- return String();
+ return StringView();
```
## Testing Status
- Build is currently in progress (Zig compilation takes time for debug builds)
- Once built, the test should pass as `process.title` will return the full executable path when not explicitly set
## Expected Behavior After Fix
```js
// Parent process
process.title; // Returns full path like "/usr/local/bin/bun"
// Child process spawned with long arguments
spawnSync(process.execPath, ["-p", "process.title", "x".repeat(1024)]);
// stdout should contain the full executable path, not just "bun"
```
This fix ensures Bun matches Node.js behavior where `process.title` defaults to the full executable path rather than just the binary name.

View File

@@ -0,0 +1,47 @@
# Fix for Node.js process.title compatibility
## Problem
The Node.js test `test-process-title.js` was failing because:
- When a child process is spawned in Bun, `process.title` was returning just `"bun"`
- In Node.js, when no title has been explicitly set, `process.title` returns the full executable path (same as `process.execPath`)
## Test case
```js
const xs = "x".repeat(1024);
const proc = spawnSync(process.execPath, ["-p", "process.title", xs]);
strictEqual(proc.stdout.toString().trim(), process.execPath);
```
## Solution
Modified `getTitle` function in `src/bun.js/node/node_process.zig`:
```diff
pub fn getTitle(_: *JSGlobalObject, title: *ZigString) callconv(.C) void {
title_mutex.lock();
defer title_mutex.unlock();
const str = bun.CLI.Bun__Node__ProcessTitle;
- title.* = ZigString.init(str orelse "bun");
+
+ if (str) |s| {
+ title.* = ZigString.init(s);
+ } else {
+ // When no title has been set, return the full executable path (like Node.js)
+ const exec_path = bun.selfExePath() catch {
+ // If we can't get the exec path, fallback to "bun"
+ title.* = ZigString.init("bun");
+ return;
+ };
+ title.* = ZigString.init(exec_path);
+ }
}
```
This ensures that when `process.title` hasn't been explicitly set (via `--title` flag or programmatically), it returns the full executable path, matching Node.js behavior.
## Additional fix
Also fixed an unrelated build error in `src/bun.js/bindings/webcore/HTTPHeaderMap.cpp` where a function was returning the address of a temporary object.

View File

@@ -40,7 +40,7 @@ static StringView extractCookieName(const StringView& cookie)
{
auto nameEnd = cookie.find('=');
if (nameEnd == notFound)
return String();
return StringView();
return cookie.substring(0, nameEnd);
}

View File

@@ -17,7 +17,18 @@ pub fn getTitle(_: *JSGlobalObject, title: *ZigString) callconv(.C) void {
title_mutex.lock();
defer title_mutex.unlock();
const str = bun.CLI.Bun__Node__ProcessTitle;
title.* = ZigString.init(str orelse "bun");
if (str) |s| {
title.* = ZigString.init(s);
} else {
// When no title has been set, return the full executable path (like Node.js)
// Use argv[0] which should contain the full path to the executable
if (bun.argv.len > 0) {
title.* = ZigString.init(bun.argv[0]);
} else {
title.* = ZigString.init("bun");
}
}
}
// TODO: https://github.com/nodejs/node/blob/master/deps/uv/src/unix/darwin-proctitle.c

View File

@@ -0,0 +1,22 @@
'use strict';
const common = require('../common');
const { spawnSync } = require('child_process');
const { strictEqual } = require('assert');
// FIXME add sunos support
if (common.isSunOS)
common.skip(`Unsupported platform [${process.platform}]`);
// FIXME add IBMi support
if (common.isIBMi)
common.skip('Unsupported platform IBMi');
// Explicitly assigning to process.title before starting the child process
// is necessary otherwise *its* process.title is whatever the last
// SetConsoleTitle() call in our process tree set it to.
// Can be removed when https://github.com/libuv/libuv/issues/2667 is fixed.
if (common.isWindows)
process.title = process.execPath;
const xs = 'x'.repeat(1024);
const proc = spawnSync(process.execPath, ['-p', 'process.title', xs]);
strictEqual(proc.stdout.toString().trim(), process.execPath);