Skip to content

Commit 5afffb4

Browse files
Ceres6aduh95
authored andcommitted
src,worker: add isInternalWorker
PR-URL: #56469 Reviewed-By: Jacob Smith <jacob@frende.me> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Bryan English <bryan@bryanenglish.com>
1 parent 46bd4b8 commit 5afffb4

8 files changed

+104
-4
lines changed

doc/api/worker_threads.md

+38
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,44 @@ if (isMainThread) {
100100
}
101101
```
102102

103+
## `worker.isInternalThread`
104+
105+
<!-- YAML
106+
added: REPLACEME
107+
-->
108+
109+
* {boolean}
110+
111+
Is `true` if this code is running inside of an internal [`Worker`][] thread (e.g the loader thread).
112+
113+
```bash
114+
node --experimental-loader ./loader.js main.js
115+
```
116+
117+
```cjs
118+
// loader.js
119+
const { isInternalThread } = require('node:worker_threads');
120+
console.log(isInternalThread); // true
121+
```
122+
123+
```mjs
124+
// loader.js
125+
import { isInternalThread } from 'node:worker_threads';
126+
console.log(isInternalThread); // true
127+
```
128+
129+
```cjs
130+
// main.js
131+
const { isInternalThread } = require('node:worker_threads');
132+
console.log(isInternalThread); // false
133+
```
134+
135+
```mjs
136+
// main.js
137+
import { isInternalThread } from 'node:worker_threads';
138+
console.log(isInternalThread); // false
139+
```
140+
103141
## `worker.isMainThread`
104142

105143
<!-- YAML

lib/internal/worker.js

+2
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ const {
6767
const {
6868
ownsProcessState,
6969
isMainThread,
70+
isInternalThread,
7071
resourceLimits: resourceLimitsRaw,
7172
threadId,
7273
Worker: WorkerImpl,
@@ -538,6 +539,7 @@ module.exports = {
538539
ownsProcessState,
539540
kIsOnline,
540541
isMainThread,
542+
isInternalThread,
541543
SHARE_ENV,
542544
resourceLimits:
543545
!isMainThread ? makeResourceLimits(resourceLimitsRaw) : {},

lib/worker_threads.js

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22

33
const {
4+
isInternalThread,
45
isMainThread,
56
SHARE_ENV,
67
resourceLimits,
@@ -29,6 +30,7 @@ const {
2930
} = require('internal/buffer');
3031

3132
module.exports = {
33+
isInternalThread,
3234
isMainThread,
3335
MessagePort,
3436
MessageChannel,

src/node_worker.cc

+16-3
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ Worker::Worker(Environment* env,
5454
std::shared_ptr<PerIsolateOptions> per_isolate_opts,
5555
std::vector<std::string>&& exec_argv,
5656
std::shared_ptr<KVStore> env_vars,
57-
const SnapshotData* snapshot_data)
57+
const SnapshotData* snapshot_data,
58+
const bool is_internal)
5859
: AsyncWrap(env, wrap, AsyncWrap::PROVIDER_WORKER),
5960
per_isolate_opts_(per_isolate_opts),
6061
exec_argv_(exec_argv),
@@ -63,7 +64,8 @@ Worker::Worker(Environment* env,
6364
name_(name),
6465
env_vars_(env_vars),
6566
embedder_preload_(env->embedder_preload()),
66-
snapshot_data_(snapshot_data) {
67+
snapshot_data_(snapshot_data),
68+
is_internal_(is_internal) {
6769
Debug(this, "Creating new worker instance with thread id %llu",
6870
thread_id_.id);
6971

@@ -685,7 +687,8 @@ void Worker::New(const FunctionCallbackInfo<Value>& args) {
685687
per_isolate_opts,
686688
std::move(exec_argv_out),
687689
env_vars,
688-
snapshot_data);
690+
snapshot_data,
691+
is_internal);
689692

690693
CHECK(args[3]->IsFloat64Array());
691694
Local<Float64Array> limit_info = args[3].As<Float64Array>();
@@ -1028,6 +1031,16 @@ void CreateWorkerPerContextProperties(Local<Object> target,
10281031
Boolean::New(isolate, env->is_main_thread()))
10291032
.Check();
10301033

1034+
Worker* worker = env->isolate_data()->worker_context();
1035+
bool is_internal = worker != nullptr && worker->is_internal();
1036+
1037+
// Set the is_internal property
1038+
target
1039+
->Set(env->context(),
1040+
FIXED_ONE_BYTE_STRING(isolate, "isInternalThread"),
1041+
Boolean::New(isolate, is_internal))
1042+
.Check();
1043+
10311044
target
10321045
->Set(env->context(),
10331046
FIXED_ONE_BYTE_STRING(isolate, "ownsProcessState"),

src/node_worker.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ class Worker : public AsyncWrap {
3434
std::shared_ptr<PerIsolateOptions> per_isolate_opts,
3535
std::vector<std::string>&& exec_argv,
3636
std::shared_ptr<KVStore> env_vars,
37-
const SnapshotData* snapshot_data);
37+
const SnapshotData* snapshot_data,
38+
const bool is_internal);
3839
~Worker() override;
3940

4041
// Run the worker. This is only called from the worker thread.
@@ -60,6 +61,7 @@ class Worker : public AsyncWrap {
6061

6162
bool is_stopped() const;
6263
const SnapshotData* snapshot_data() const { return snapshot_data_; }
64+
bool is_internal() const { return is_internal_; }
6365

6466
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
6567
static void CloneParentEnvVars(
@@ -132,6 +134,7 @@ class Worker : public AsyncWrap {
132134
Environment* env_ = nullptr;
133135

134136
const SnapshotData* snapshot_data_ = nullptr;
137+
const bool is_internal_;
135138
friend class WorkerThreadData;
136139
};
137140

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
const { isInternalThread } = require('node:worker_threads');
2+
3+
console.log(`isInternalThread: ${isInternalThread}`);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
const { isInternalThread, parentPort } = require('node:worker_threads');
2+
3+
parentPort.postMessage(`isInternalThread: ${isInternalThread}`);
+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { spawnPromisified } from '../common/index.mjs';
2+
import * as fixtures from '../common/fixtures.mjs';
3+
import assert from 'node:assert';
4+
import { execPath } from 'node:process';
5+
import { describe, it } from 'node:test';
6+
import { isInternalThread, Worker } from 'node:worker_threads';
7+
import * as common from '../common/index.mjs';
8+
9+
describe('worker_threads.isInternalThread', { concurrency: !process.env.TEST_PARALLEL }, () => {
10+
it('should be true inside the loader thread', async () => {
11+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
12+
'--no-warnings',
13+
'--experimental-loader',
14+
fixtures.fileURL('loader-is-internal-thread.js'),
15+
'--eval',
16+
'setTimeout(() => {},99)',
17+
]);
18+
19+
assert.strictEqual(stderr, '');
20+
assert.match(stdout, /isInternalThread: true/);
21+
assert.strictEqual(code, 0);
22+
assert.strictEqual(signal, null);
23+
});
24+
25+
it('should be false inside the main thread', async () => {
26+
assert.strictEqual(isInternalThread, false);
27+
});
28+
29+
it('should be false inside a regular worker thread', async () => {
30+
const worker = new Worker(fixtures.path('worker-is-internal-thread.js'));
31+
32+
worker.on('message', common.mustCall((message) => {
33+
assert.strictEqual(message, 'isInternalThread: false');
34+
}));
35+
});
36+
});

0 commit comments

Comments
 (0)