Skip to content

Commit

Permalink
src,worker: add isInternalWorker
Browse files Browse the repository at this point in the history
PR-URL: #56469
Reviewed-By: Jacob Smith <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Bryan English <[email protected]>
  • Loading branch information
Ceres6 authored Jan 14, 2025
1 parent fc11189 commit 732744c
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 4 deletions.
38 changes: 38 additions & 0 deletions doc/api/worker_threads.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,44 @@ if (isMainThread) {
}
```

## `worker.isInternalThread`

<!-- YAML
added: REPLACEME
-->

* {boolean}

Is `true` if this code is running inside of an internal [`Worker`][] thread (e.g the loader thread).

```bash
node --experimental-loader ./loader.js main.js
```

```cjs
// loader.js
const { isInternalThread } = require('node:worker_threads');
console.log(isInternalThread); // true
```

```mjs
// loader.js
import { isInternalThread } from 'node:worker_threads';
console.log(isInternalThread); // true
```

```cjs
// main.js
const { isInternalThread } = require('node:worker_threads');
console.log(isInternalThread); // false
```

```mjs
// main.js
import { isInternalThread } from 'node:worker_threads';
console.log(isInternalThread); // false
```

## `worker.isMainThread`

<!-- YAML
Expand Down
2 changes: 2 additions & 0 deletions lib/internal/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ const {
const {
ownsProcessState,
isMainThread,
isInternalThread,
resourceLimits: resourceLimitsRaw,
threadId,
Worker: WorkerImpl,
Expand Down Expand Up @@ -538,6 +539,7 @@ module.exports = {
ownsProcessState,
kIsOnline,
isMainThread,
isInternalThread,
SHARE_ENV,
resourceLimits:
!isMainThread ? makeResourceLimits(resourceLimitsRaw) : {},
Expand Down
2 changes: 2 additions & 0 deletions lib/worker_threads.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const {
isInternalThread,
isMainThread,
SHARE_ENV,
resourceLimits,
Expand Down Expand Up @@ -29,6 +30,7 @@ const {
} = require('internal/buffer');

module.exports = {
isInternalThread,
isMainThread,
MessagePort,
MessageChannel,
Expand Down
19 changes: 16 additions & 3 deletions src/node_worker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ Worker::Worker(Environment* env,
std::shared_ptr<PerIsolateOptions> per_isolate_opts,
std::vector<std::string>&& exec_argv,
std::shared_ptr<KVStore> env_vars,
const SnapshotData* snapshot_data)
const SnapshotData* snapshot_data,
const bool is_internal)
: AsyncWrap(env, wrap, AsyncWrap::PROVIDER_WORKER),
per_isolate_opts_(per_isolate_opts),
exec_argv_(exec_argv),
Expand All @@ -63,7 +64,8 @@ Worker::Worker(Environment* env,
name_(name),
env_vars_(env_vars),
embedder_preload_(env->embedder_preload()),
snapshot_data_(snapshot_data) {
snapshot_data_(snapshot_data),
is_internal_(is_internal) {
Debug(this, "Creating new worker instance with thread id %llu",
thread_id_.id);

Expand Down Expand Up @@ -687,7 +689,8 @@ void Worker::New(const FunctionCallbackInfo<Value>& args) {
per_isolate_opts,
std::move(exec_argv_out),
env_vars,
snapshot_data);
snapshot_data,
is_internal);

CHECK(args[3]->IsFloat64Array());
Local<Float64Array> limit_info = args[3].As<Float64Array>();
Expand Down Expand Up @@ -1030,6 +1033,16 @@ void CreateWorkerPerContextProperties(Local<Object> target,
Boolean::New(isolate, env->is_main_thread()))
.Check();

Worker* worker = env->isolate_data()->worker_context();
bool is_internal = worker != nullptr && worker->is_internal();

// Set the is_internal property
target
->Set(env->context(),
FIXED_ONE_BYTE_STRING(isolate, "isInternalThread"),
Boolean::New(isolate, is_internal))
.Check();

target
->Set(env->context(),
FIXED_ONE_BYTE_STRING(isolate, "ownsProcessState"),
Expand Down
5 changes: 4 additions & 1 deletion src/node_worker.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ class Worker : public AsyncWrap {
std::shared_ptr<PerIsolateOptions> per_isolate_opts,
std::vector<std::string>&& exec_argv,
std::shared_ptr<KVStore> env_vars,
const SnapshotData* snapshot_data);
const SnapshotData* snapshot_data,
const bool is_internal);
~Worker() override;

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

bool is_stopped() const;
const SnapshotData* snapshot_data() const { return snapshot_data_; }
bool is_internal() const { return is_internal_; }

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

const SnapshotData* snapshot_data_ = nullptr;
const bool is_internal_;
friend class WorkerThreadData;
};

Expand Down
3 changes: 3 additions & 0 deletions test/fixtures/loader-is-internal-thread.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const { isInternalThread } = require('node:worker_threads');

console.log(`isInternalThread: ${isInternalThread}`);
3 changes: 3 additions & 0 deletions test/fixtures/worker-is-internal-thread.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const { isInternalThread, parentPort } = require('node:worker_threads');

parentPort.postMessage(`isInternalThread: ${isInternalThread}`);
36 changes: 36 additions & 0 deletions test/parallel/test-is-internal-thread.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { spawnPromisified } from '../common/index.mjs';
import * as fixtures from '../common/fixtures.mjs';
import assert from 'node:assert';
import { execPath } from 'node:process';
import { describe, it } from 'node:test';
import { isInternalThread, Worker } from 'node:worker_threads';
import * as common from '../common/index.mjs';

describe('worker_threads.isInternalThread', { concurrency: !process.env.TEST_PARALLEL }, () => {
it('should be true inside the loader thread', async () => {
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
'--no-warnings',
'--experimental-loader',
fixtures.fileURL('loader-is-internal-thread.js'),
'--eval',
'setTimeout(() => {},99)',
]);

assert.strictEqual(stderr, '');
assert.match(stdout, /isInternalThread: true/);
assert.strictEqual(code, 0);
assert.strictEqual(signal, null);
});

it('should be false inside the main thread', async () => {
assert.strictEqual(isInternalThread, false);
});

it('should be false inside a regular worker thread', async () => {
const worker = new Worker(fixtures.path('worker-is-internal-thread.js'));

worker.on('message', common.mustCall((message) => {
assert.strictEqual(message, 'isInternalThread: false');
}));
});
});

1 comment on commit 732744c

@Babiel09
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Congratulations!

Please sign in to comment.