Skip to content

Commit 9f6bc58

Browse files
jasnelltargos
authored andcommittedSep 1, 2021
worker: add setEnvironmentData/getEnvironmentData
These APIs allow arbitrary, cloneable JavaScript values to be set and passed to all new Worker instances spawned from the current context. It is similar to `workerData` except that environment data is set independently of the `new Worker()` constructor, and the the value is passed automatically to all new Workers. This is a *partial* fix of #30992 but does not implement a complete fix. Signed-off-by: James M Snell <[email protected]> PR-URL: #37486 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Gireesh Punathil <[email protected]> Reviewed-By: Darshan Sen <[email protected]>
1 parent fe12cc0 commit 9f6bc58

File tree

5 files changed

+114
-0
lines changed

5 files changed

+114
-0
lines changed
 

‎doc/api/worker_threads.md

+49
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,38 @@ Worker threads inherit non-process-specific options by default. Refer to
6161
[`Worker constructor options`][] to know how to customize worker thread options,
6262
specifically `argv` and `execArgv` options.
6363

64+
## `worker.getEnvironmentData(key)`
65+
<!-- YAML
66+
added: REPLACEME
67+
-->
68+
69+
> Stability: 1 - Experimental
70+
71+
* `key` {any} Any arbitrary, cloneable JavaScript value that can be used as a
72+
{Map} key.
73+
* Returns: {any}
74+
75+
Within a worker thread, `worker.getEnvironmentData()` returns a clone
76+
of data passed to the spawning thread's `worker.setEnvironmentData()`.
77+
Every new `Worker` receives its own copy of the environment data
78+
automatically.
79+
80+
```js
81+
const {
82+
Worker,
83+
isMainThread,
84+
setEnvironmentData,
85+
getEnvironmentData,
86+
} = require('worker_threads');
87+
88+
if (isMainThread) {
89+
setEnvironmentData('Hello', 'World!');
90+
const worker = new Worker(__filename);
91+
} else {
92+
console.log(getEnvironmentData('Hello')); // Prints 'World!'.
93+
}
94+
```
95+
6496
## `worker.isMainThread`
6597
<!-- YAML
6698
added: v10.5.0
@@ -240,6 +272,23 @@ new Worker('process.env.SET_IN_WORKER = "foo"', { eval: true, env: SHARE_ENV })
240272
});
241273
```
242274

275+
## `worker.setEnvironmentData(key[, value])`
276+
<!--YAML
277+
added: REPLACEME
278+
-->
279+
280+
> Stability: 1 - Experimental
281+
282+
* `key` {any} Any arbitrary, cloneable JavaScript value that can be used as a
283+
{Map} key.
284+
* `value` {any} Any arbitrary, cloneable JavaScript value that will be cloned
285+
and passed automatically to all new `Worker` instances. If `value` is passed
286+
as `undefined`, any previously set value for the `key` will be deleted.
287+
288+
The `worker.setEnvironmentData()` API sets the content of
289+
`worker.getEnvironmentData()` in the current thread and all new `Worker`
290+
instances spawned from the current context.
291+
243292
## `worker.threadId`
244293
<!-- YAML
245294
added: v10.5.0

‎lib/internal/main/worker_thread.js

+3
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ port.on('message', (message) => {
107107
filename,
108108
doEval,
109109
workerData,
110+
environmentData,
110111
publicPort,
111112
manifestSrc,
112113
manifestURL,
@@ -130,6 +131,8 @@ port.on('message', (message) => {
130131
publicWorker.parentPort = publicPort;
131132
publicWorker.workerData = workerData;
132133

134+
require('internal/worker').assignEnvironmentData(environmentData);
135+
133136
// The counter is only passed to the workers created by the main thread, not
134137
// to workers created by other workers.
135138
let cachedCwd = '';

‎lib/internal/worker.js

+25
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const {
1313
Promise,
1414
PromiseResolve,
1515
RegExpPrototypeTest,
16+
SafeMap,
1617
String,
1718
Symbol,
1819
SymbolFor,
@@ -85,6 +86,8 @@ let debug = require('internal/util/debuglog').debuglog('worker', (fn) => {
8586

8687
let cwdCounter;
8788

89+
const environmentData = new SafeMap();
90+
8891
if (isMainThread) {
8992
cwdCounter = new Uint32Array(new SharedArrayBuffer(4));
9093
const originalChdir = process.chdir;
@@ -94,6 +97,24 @@ if (isMainThread) {
9497
};
9598
}
9699

100+
function setEnvironmentData(key, value) {
101+
if (value === undefined)
102+
environmentData.delete(key);
103+
else
104+
environmentData.set(key, value);
105+
}
106+
107+
function getEnvironmentData(key) {
108+
return environmentData.get(key);
109+
}
110+
111+
function assignEnvironmentData(data) {
112+
if (data === undefined) return;
113+
data.forEach((value, key) => {
114+
environmentData.set(key, value);
115+
});
116+
}
117+
97118
class Worker extends EventEmitter {
98119
constructor(filename, options = {}) {
99120
super();
@@ -222,6 +243,7 @@ class Worker extends EventEmitter {
222243
doEval,
223244
cwdCounter: cwdCounter || workerIo.sharedCwdCounter,
224245
workerData: options.workerData,
246+
environmentData,
225247
publicPort: port2,
226248
manifestURL: getOptionValue('--experimental-policy') ?
227249
require('internal/process/policy').url :
@@ -482,6 +504,9 @@ module.exports = {
482504
SHARE_ENV,
483505
resourceLimits:
484506
!isMainThread ? makeResourceLimits(resourceLimitsRaw) : {},
507+
setEnvironmentData,
508+
getEnvironmentData,
509+
assignEnvironmentData,
485510
threadId,
486511
Worker,
487512
};

‎lib/worker_threads.js

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ const {
44
isMainThread,
55
SHARE_ENV,
66
resourceLimits,
7+
setEnvironmentData,
8+
getEnvironmentData,
79
threadId,
810
Worker
911
} = require('internal/worker');
@@ -32,4 +34,6 @@ module.exports = {
3234
Worker,
3335
parentPort: null,
3436
workerData: null,
37+
setEnvironmentData,
38+
getEnvironmentData,
3539
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
'use strict';
2+
3+
require('../common');
4+
const {
5+
Worker,
6+
getEnvironmentData,
7+
setEnvironmentData,
8+
threadId,
9+
} = require('worker_threads');
10+
11+
const {
12+
deepStrictEqual,
13+
strictEqual,
14+
} = require('assert');
15+
16+
if (!process.env.HAS_STARTED_WORKER) {
17+
process.env.HAS_STARTED_WORKER = 1;
18+
setEnvironmentData('foo', 'bar');
19+
setEnvironmentData('hello', { value: 'world' });
20+
setEnvironmentData(1, 2);
21+
strictEqual(getEnvironmentData(1), 2);
22+
setEnvironmentData(1); // Delete it, key won't show up in the worker.
23+
new Worker(__filename);
24+
setEnvironmentData('hello'); // Delete it. Has no impact on the worker.
25+
} else {
26+
strictEqual(getEnvironmentData('foo'), 'bar');
27+
deepStrictEqual(getEnvironmentData('hello'), { value: 'world' });
28+
strictEqual(getEnvironmentData(1), undefined);
29+
30+
// Recurse to make sure the environment data is inherited
31+
if (threadId <= 2)
32+
new Worker(__filename);
33+
}

0 commit comments

Comments
 (0)