Skip to content

Commit 5c3ade4

Browse files
src: add setTitle() as alternative to direct assignment
Implement process.setTitle(title) as a new function-based API for setting the process title, complementing the existing process.title property assignment pattern Fixes: #62797 Signed-off-by: Jonathan Lopes <jonathan15989@protonmail.com>
1 parent bee1087 commit 5c3ade4

File tree

7 files changed

+85
-2
lines changed

7 files changed

+85
-2
lines changed

doc/api/process.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4308,6 +4308,32 @@ Assigning a value to `process.title` might not result in an accurate label
43084308
within process manager applications such as macOS Activity Monitor or Windows
43094309
Services Manager.
43104310
4311+
## `process.setTitle(title)`
4312+
4313+
<!-- YAML
4314+
added: REPLACEME
4315+
-->
4316+
4317+
* `title` {string}
4318+
4319+
Sets the process title. This is equivalent to assigning a string to
4320+
[`process.title`][]. See [`process.title`][] for restrictions and platform
4321+
limitations.
4322+
4323+
```mjs
4324+
import { setTitle } from 'node:process';
4325+
4326+
setTitle('my-service');
4327+
```
4328+
4329+
```cjs
4330+
const { setTitle } = require('node:process');
4331+
4332+
setTitle('my-service');
4333+
```
4334+
4335+
This function is not supported in [`Worker`][] threads.
4336+
43114337
## `process.traceDeprecation`
43124338
43134339
<!-- YAML
@@ -4627,6 +4653,7 @@ cases:
46274653
[`process.hrtime.bigint()`]: #processhrtimebigint
46284654
[`process.kill()`]: #processkillpid-signal
46294655
[`process.setUncaughtExceptionCaptureCallback()`]: #processsetuncaughtexceptioncapturecallbackfn
4656+
[`process.title`]: #processtitle
46304657
[`promise.catch()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch
46314658
[`queueMicrotask()`]: globals.md#queuemicrotaskcallback
46324659
[`readable.read()`]: stream.md#readablereadsize

lib/internal/bootstrap/switches/does_not_own_process_state.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const { unavailable } = require('internal/process/worker_thread_only');
77

88
process.abort = unavailable('process.abort()');
99
process.chdir = unavailable('process.chdir()');
10+
process.setTitle = unavailable('process.setTitle()');
1011
process.umask = wrappedUmask;
1112
process.cwd = rawMethods.cwd;
1213

lib/internal/bootstrap/switches/does_own_process_state.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ process.abort = rawMethods.abort;
1414
process.umask = wrappedUmask;
1515
process.chdir = wrappedChdir;
1616
process.cwd = wrappedCwd;
17+
process.setTitle = wrappedSetTitle;
1718

1819
if (credentials.implementsPosixCredentials) {
1920
const wrapped = wrapPosixCredentialSetters(credentials);
@@ -142,3 +143,8 @@ function wrappedCwd() {
142143
cachedCwd = rawMethods.cwd();
143144
return cachedCwd;
144145
}
146+
147+
function wrappedSetTitle(title) {
148+
validateString(title, 'title');
149+
rawMethods.setTitle(title);
150+
}

src/node_process_methods.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,16 @@ static void Chdir(const FunctionCallbackInfo<Value>& args) {
100100
}
101101
}
102102

103+
static void SetTitle(const FunctionCallbackInfo<Value>& args) {
104+
Environment* env = Environment::GetCurrent(args);
105+
CHECK(env->owns_process_state());
106+
107+
CHECK_EQ(args.Length(), 1);
108+
CHECK(args[0]->IsString());
109+
Utf8Value title(env->isolate(), args[0]);
110+
uv_set_process_title(*title);
111+
}
112+
103113
inline Local<ArrayBuffer> get_fields_array_buffer(
104114
const FunctionCallbackInfo<Value>& args,
105115
size_t index,
@@ -771,6 +781,7 @@ static void CreatePerIsolateProperties(IsolateData* isolate_data,
771781
SetMethod(isolate, target, "abort", Abort);
772782
SetMethod(isolate, target, "causeSegfault", CauseSegfault);
773783
SetMethod(isolate, target, "chdir", Chdir);
784+
SetMethod(isolate, target, "setTitle", SetTitle);
774785

775786
SetMethod(isolate, target, "umask", Umask);
776787
SetMethod(isolate, target, "memoryUsage", MemoryUsage);
@@ -819,6 +830,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
819830
registry->Register(Abort);
820831
registry->Register(CauseSegfault);
821832
registry->Register(Chdir);
833+
registry->Register(SetTitle);
822834

823835
registry->Register(Umask);
824836
registry->Register(RawDebug);
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { isIBMi, isSunOS, isWindows, skip } from '../common/index.mjs';
2+
import assert from 'node:assert';
3+
import process, { setTitle } from 'node:process';
4+
import { isMainThread } from 'node:worker_threads';
5+
import { describe, it } from 'node:test';
6+
7+
// FIXME add sunos support
8+
if (isSunOS || isIBMi || isWindows) {
9+
skip(`Unsupported platform [${process.platform}]`);
10+
}
11+
12+
if (!isMainThread) {
13+
skip('Setting the process title from Workers is not supported');
14+
}
15+
16+
describe('ESM named import setTitle', () => {
17+
it('sets process title through node:process', () => {
18+
const title = String(process.pid);
19+
20+
setTitle(title);
21+
assert.strictEqual(process.title, title);
22+
23+
assert.throws(() => setTitle(1), {
24+
code: 'ERR_INVALID_ARG_TYPE',
25+
});
26+
});
27+
});

test/parallel/test-setproctitle.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,26 @@ if (!isMainThread) {
1515
const assert = require('assert');
1616
const { exec, execSync } = require('child_process');
1717
const path = require('path');
18+
const { setTitle } = require('node:process');
1819

1920
// The title shouldn't be too long; libuv's uv_set_process_title() out of
2021
// security considerations no longer overwrites envp, only argv, so the
2122
// maximum title length is possibly quite short.
2223
let title = String(process.pid);
2324

2425
assert.notStrictEqual(process.title, title);
25-
process.title = title;
26+
setTitle(title);
2627
assert.strictEqual(process.title, title);
2728

29+
assert.throws(() => setTitle(1), {
30+
code: 'ERR_INVALID_ARG_TYPE',
31+
});
32+
33+
const legacyTitle = `${title}-legacy`;
34+
process.title = legacyTitle;
35+
assert.strictEqual(process.title, legacyTitle);
36+
title = legacyTitle;
37+
2838
try {
2939
execSync('command -v ps');
3040
} catch (err) {

test/parallel/test-worker-unsupported-things.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ if (!process.env.HAS_STARTED_WORKER) {
3434
});
3535
}
3636

37-
const stubs = ['abort', 'chdir', 'send', 'disconnect'];
37+
const stubs = ['abort', 'chdir', 'setTitle', 'send', 'disconnect'];
3838

3939
if (!common.isWindows) {
4040
stubs.push('setuid', 'seteuid', 'setgid',

0 commit comments

Comments
 (0)