@parcel/workers 2.0.0-nightly.140 → 2.0.0-nightly.1400
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +23 -0
- package/lib/Handle.js +16 -58
- package/lib/Worker.js +88 -53
- package/lib/WorkerFarm.js +240 -188
- package/lib/backend.js +0 -6
- package/lib/bus.js +8 -10
- package/lib/child.js +128 -114
- package/lib/childState.js +1 -2
- package/lib/cpuCount.js +25 -22
- package/lib/index.js +34 -30
- package/lib/process/ProcessChild.js +18 -24
- package/lib/process/ProcessWorker.js +27 -38
- package/lib/threads/ThreadsChild.js +26 -28
- package/lib/threads/ThreadsWorker.js +25 -31
- package/package.json +19 -8
- package/src/Handle.js +10 -39
- package/src/Worker.js +82 -15
- package/src/WorkerFarm.js +228 -55
- package/src/bus.js +1 -1
- package/src/child.js +83 -24
- package/src/cpuCount.js +9 -4
- package/src/index.js +8 -2
- package/src/process/ProcessChild.js +2 -1
- package/src/process/ProcessWorker.js +1 -1
- package/src/threads/ThreadsWorker.js +2 -2
- package/test/cpuCount.test.js +1 -1
- package/test/integration/workerfarm/console.js +1 -1
- package/test/integration/workerfarm/logging.js +1 -1
- package/test/integration/workerfarm/reverse-handle.js +2 -2
- package/test/workerfarm.js +5 -5
- package/lib/Profiler.js +0 -70
- package/lib/Trace.js +0 -126
- package/src/Profiler.js +0 -93
- package/src/Trace.js +0 -121
@@ -4,46 +4,43 @@ Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
5
5
|
});
|
6
6
|
exports.default = void 0;
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
function _nullthrows() {
|
8
|
+
const data = _interopRequireDefault(require("nullthrows"));
|
9
|
+
_nullthrows = function () {
|
10
|
+
return data;
|
11
|
+
};
|
12
|
+
return data;
|
13
|
+
}
|
10
14
|
var _childState = require("../childState");
|
11
|
-
|
12
15
|
var _child = require("../child");
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
+
function _core() {
|
17
|
+
const data = require("@parcel/core");
|
18
|
+
_core = function () {
|
19
|
+
return data;
|
20
|
+
};
|
21
|
+
return data;
|
22
|
+
}
|
16
23
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
17
|
-
|
18
|
-
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
19
|
-
|
20
24
|
class ProcessChild {
|
21
25
|
constructor(onMessage, onExit) {
|
22
|
-
_defineProperty(this, "onMessage", void 0);
|
23
|
-
|
24
|
-
_defineProperty(this, "onExit", void 0);
|
25
|
-
|
26
26
|
if (!process.send) {
|
27
27
|
throw new Error('Only create ProcessChild instances in a worker!');
|
28
28
|
}
|
29
|
-
|
30
29
|
this.onMessage = onMessage;
|
31
30
|
this.onExit = onExit;
|
32
31
|
process.on('message', data => this.handleMessage(data));
|
33
32
|
}
|
34
|
-
|
35
33
|
handleMessage(data) {
|
36
34
|
if (data === 'die') {
|
37
35
|
return this.stop();
|
38
36
|
}
|
39
|
-
|
40
|
-
this.onMessage((0, _core.deserialize)(Buffer.from(data, 'base64')));
|
37
|
+
this.onMessage((0, _core().deserialize)(Buffer.from(data, 'base64')));
|
41
38
|
}
|
42
|
-
|
43
39
|
send(data) {
|
44
|
-
let processSend = (0, _nullthrows.default)(process.send).bind(process);
|
45
|
-
processSend((0, _core.serialize)(data).toString('base64'), err => {
|
40
|
+
let processSend = (0, _nullthrows().default)(process.send).bind(process);
|
41
|
+
processSend((0, _core().serialize)(data).toString('base64'), err => {
|
46
42
|
if (err && err instanceof Error) {
|
43
|
+
// $FlowFixMe[prop-missing]
|
47
44
|
if (err.code === 'ERR_IPC_CHANNEL_CLOSED') {
|
48
45
|
// IPC connection closed
|
49
46
|
// no need to keep the worker running if it can't send or receive data
|
@@ -52,13 +49,10 @@ class ProcessChild {
|
|
52
49
|
}
|
53
50
|
});
|
54
51
|
}
|
55
|
-
|
56
52
|
stop() {
|
57
53
|
this.onExit(0);
|
58
54
|
process.exit();
|
59
55
|
}
|
60
|
-
|
61
56
|
}
|
62
|
-
|
63
57
|
exports.default = ProcessChild;
|
64
58
|
(0, _childState.setChild)(new _child.Child(ProcessChild));
|
@@ -4,55 +4,51 @@ Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
5
5
|
});
|
6
6
|
exports.default = void 0;
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
7
|
+
function _child_process() {
|
8
|
+
const data = _interopRequireDefault(require("child_process"));
|
9
|
+
_child_process = function () {
|
10
|
+
return data;
|
11
|
+
};
|
12
|
+
return data;
|
13
|
+
}
|
14
|
+
function _path() {
|
15
|
+
const data = _interopRequireDefault(require("path"));
|
16
|
+
_path = function () {
|
17
|
+
return data;
|
18
|
+
};
|
19
|
+
return data;
|
20
|
+
}
|
21
|
+
function _core() {
|
22
|
+
const data = require("@parcel/core");
|
23
|
+
_core = function () {
|
24
|
+
return data;
|
25
|
+
};
|
26
|
+
return data;
|
27
|
+
}
|
14
28
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
15
|
-
|
16
|
-
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
17
|
-
|
18
|
-
const WORKER_PATH = _path.default.join(__dirname, 'ProcessChild.js');
|
19
|
-
|
29
|
+
const WORKER_PATH = _path().default.join(__dirname, 'ProcessChild.js');
|
20
30
|
class ProcessWorker {
|
31
|
+
processQueue = true;
|
32
|
+
sendQueue = [];
|
21
33
|
constructor(execArgv, onMessage, onError, onExit) {
|
22
|
-
_defineProperty(this, "execArgv", void 0);
|
23
|
-
|
24
|
-
_defineProperty(this, "onMessage", void 0);
|
25
|
-
|
26
|
-
_defineProperty(this, "onError", void 0);
|
27
|
-
|
28
|
-
_defineProperty(this, "onExit", void 0);
|
29
|
-
|
30
|
-
_defineProperty(this, "child", void 0);
|
31
|
-
|
32
|
-
_defineProperty(this, "processQueue", true);
|
33
|
-
|
34
|
-
_defineProperty(this, "sendQueue", []);
|
35
|
-
|
36
34
|
this.execArgv = execArgv;
|
37
35
|
this.onMessage = onMessage;
|
38
36
|
this.onError = onError;
|
39
37
|
this.onExit = onExit;
|
40
38
|
}
|
41
|
-
|
42
39
|
start() {
|
43
|
-
this.child = _child_process.default.fork(WORKER_PATH, process.argv, {
|
40
|
+
this.child = _child_process().default.fork(WORKER_PATH, process.argv, {
|
44
41
|
execArgv: this.execArgv,
|
45
42
|
env: process.env,
|
46
43
|
cwd: process.cwd()
|
47
44
|
});
|
48
45
|
this.child.on('message', data => {
|
49
|
-
this.onMessage((0, _core.deserialize)(Buffer.from(data, 'base64')));
|
46
|
+
this.onMessage((0, _core().deserialize)(Buffer.from(data, 'base64')));
|
50
47
|
});
|
51
48
|
this.child.once('exit', this.onExit);
|
52
49
|
this.child.on('error', this.onError);
|
53
50
|
return Promise.resolve();
|
54
51
|
}
|
55
|
-
|
56
52
|
async stop() {
|
57
53
|
this.child.send('die');
|
58
54
|
let forceKill = setTimeout(() => this.child.kill('SIGINT'), 500);
|
@@ -61,34 +57,27 @@ class ProcessWorker {
|
|
61
57
|
});
|
62
58
|
clearTimeout(forceKill);
|
63
59
|
}
|
64
|
-
|
65
60
|
send(data) {
|
66
61
|
if (!this.processQueue) {
|
67
62
|
this.sendQueue.push(data);
|
68
63
|
return;
|
69
64
|
}
|
70
|
-
|
71
|
-
let result = this.child.send((0, _core.serialize)(data).toString('base64'), error => {
|
65
|
+
let result = this.child.send((0, _core().serialize)(data).toString('base64'), error => {
|
72
66
|
if (error && error instanceof Error) {
|
73
67
|
// Ignore this, the workerfarm handles child errors
|
74
68
|
return;
|
75
69
|
}
|
76
|
-
|
77
70
|
this.processQueue = true;
|
78
|
-
|
79
71
|
if (this.sendQueue.length > 0) {
|
80
72
|
let queueCopy = this.sendQueue.slice(0);
|
81
73
|
this.sendQueue = [];
|
82
74
|
queueCopy.forEach(entry => this.send(entry));
|
83
75
|
}
|
84
76
|
});
|
85
|
-
|
86
77
|
if (!result || /^win/.test(process.platform)) {
|
87
78
|
// Queue is handling too much messages throttle it
|
88
79
|
this.processQueue = false;
|
89
80
|
}
|
90
81
|
}
|
91
|
-
|
92
82
|
}
|
93
|
-
|
94
83
|
exports.default = ProcessWorker;
|
@@ -4,48 +4,46 @@ Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
5
5
|
});
|
6
6
|
exports.default = void 0;
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
function _worker_threads() {
|
8
|
+
const data = require("worker_threads");
|
9
|
+
_worker_threads = function () {
|
10
|
+
return data;
|
11
|
+
};
|
12
|
+
return data;
|
13
|
+
}
|
14
|
+
function _nullthrows() {
|
15
|
+
const data = _interopRequireDefault(require("nullthrows"));
|
16
|
+
_nullthrows = function () {
|
17
|
+
return data;
|
18
|
+
};
|
19
|
+
return data;
|
20
|
+
}
|
12
21
|
var _childState = require("../childState");
|
13
|
-
|
14
22
|
var _child = require("../child");
|
15
|
-
|
16
|
-
|
17
|
-
|
23
|
+
function _core() {
|
24
|
+
const data = require("@parcel/core");
|
25
|
+
_core = function () {
|
26
|
+
return data;
|
27
|
+
};
|
28
|
+
return data;
|
29
|
+
}
|
18
30
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
19
|
-
|
20
|
-
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
21
|
-
|
22
31
|
class ThreadsChild {
|
23
32
|
constructor(onMessage, onExit) {
|
24
|
-
|
25
|
-
|
26
|
-
_defineProperty(this, "onExit", void 0);
|
27
|
-
|
28
|
-
if (_worker_threads.isMainThread || !_worker_threads.parentPort) {
|
33
|
+
if (_worker_threads().isMainThread || !_worker_threads().parentPort) {
|
29
34
|
throw new Error('Only create ThreadsChild instances in a worker!');
|
30
35
|
}
|
31
|
-
|
32
36
|
this.onMessage = onMessage;
|
33
37
|
this.onExit = onExit;
|
34
|
-
|
35
|
-
_worker_threads.parentPort.on('
|
36
|
-
|
37
|
-
_worker_threads.parentPort.on('close', this.onExit);
|
38
|
+
_worker_threads().parentPort.on('message', data => this.handleMessage(data));
|
39
|
+
_worker_threads().parentPort.on('close', this.onExit);
|
38
40
|
}
|
39
|
-
|
40
41
|
handleMessage(data) {
|
41
|
-
this.onMessage((0, _core.restoreDeserializedObject)(data));
|
42
|
+
this.onMessage((0, _core().restoreDeserializedObject)(data));
|
42
43
|
}
|
43
|
-
|
44
44
|
send(data) {
|
45
|
-
(0, _nullthrows.default)(_worker_threads.parentPort).postMessage((0, _core.prepareForSerialization)(data));
|
45
|
+
(0, _nullthrows().default)(_worker_threads().parentPort).postMessage((0, _core().prepareForSerialization)(data));
|
46
46
|
}
|
47
|
-
|
48
47
|
}
|
49
|
-
|
50
48
|
exports.default = ThreadsChild;
|
51
49
|
(0, _childState.setChild)(new _child.Child(ThreadsChild));
|
@@ -4,39 +4,38 @@ Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
5
5
|
});
|
6
6
|
exports.default = void 0;
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
7
|
+
function _worker_threads() {
|
8
|
+
const data = require("worker_threads");
|
9
|
+
_worker_threads = function () {
|
10
|
+
return data;
|
11
|
+
};
|
12
|
+
return data;
|
13
|
+
}
|
14
|
+
function _path() {
|
15
|
+
const data = _interopRequireDefault(require("path"));
|
16
|
+
_path = function () {
|
17
|
+
return data;
|
18
|
+
};
|
19
|
+
return data;
|
20
|
+
}
|
21
|
+
function _core() {
|
22
|
+
const data = require("@parcel/core");
|
23
|
+
_core = function () {
|
24
|
+
return data;
|
25
|
+
};
|
26
|
+
return data;
|
27
|
+
}
|
14
28
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
15
|
-
|
16
|
-
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
17
|
-
|
18
|
-
const WORKER_PATH = _path.default.join(__dirname, 'ThreadsChild.js');
|
19
|
-
|
29
|
+
const WORKER_PATH = _path().default.join(__dirname, 'ThreadsChild.js');
|
20
30
|
class ThreadsWorker {
|
21
31
|
constructor(execArgv, onMessage, onError, onExit) {
|
22
|
-
_defineProperty(this, "execArgv", void 0);
|
23
|
-
|
24
|
-
_defineProperty(this, "onMessage", void 0);
|
25
|
-
|
26
|
-
_defineProperty(this, "onError", void 0);
|
27
|
-
|
28
|
-
_defineProperty(this, "onExit", void 0);
|
29
|
-
|
30
|
-
_defineProperty(this, "worker", void 0);
|
31
|
-
|
32
32
|
this.execArgv = execArgv;
|
33
33
|
this.onMessage = onMessage;
|
34
34
|
this.onError = onError;
|
35
35
|
this.onExit = onExit;
|
36
36
|
}
|
37
|
-
|
38
37
|
start() {
|
39
|
-
this.worker = new _worker_threads.Worker(WORKER_PATH, {
|
38
|
+
this.worker = new (_worker_threads().Worker)(WORKER_PATH, {
|
40
39
|
execArgv: this.execArgv,
|
41
40
|
env: process.env
|
42
41
|
});
|
@@ -47,21 +46,16 @@ class ThreadsWorker {
|
|
47
46
|
this.worker.on('online', resolve);
|
48
47
|
});
|
49
48
|
}
|
50
|
-
|
51
49
|
stop() {
|
52
50
|
// In node 12, this returns a promise, but previously it accepted a callback
|
53
51
|
// TODO: Pass a callback in earlier versions of Node
|
54
52
|
return Promise.resolve(this.worker.terminate());
|
55
53
|
}
|
56
|
-
|
57
54
|
handleMessage(data) {
|
58
|
-
this.onMessage((0, _core.restoreDeserializedObject)(data));
|
55
|
+
this.onMessage((0, _core().restoreDeserializedObject)(data));
|
59
56
|
}
|
60
|
-
|
61
57
|
send(data) {
|
62
|
-
this.worker.postMessage((0, _core.prepareForSerialization)(data));
|
58
|
+
this.worker.postMessage((0, _core().prepareForSerialization)(data));
|
63
59
|
}
|
64
|
-
|
65
60
|
}
|
66
|
-
|
67
61
|
exports.default = ThreadsWorker;
|
package/package.json
CHANGED
@@ -1,29 +1,40 @@
|
|
1
1
|
{
|
2
2
|
"name": "@parcel/workers",
|
3
|
-
"version": "2.0.0-nightly.
|
3
|
+
"version": "2.0.0-nightly.1400+1a3a2544b",
|
4
4
|
"description": "Blazing fast, zero configuration web application bundler",
|
5
5
|
"license": "MIT",
|
6
6
|
"publishConfig": {
|
7
7
|
"access": "public"
|
8
8
|
},
|
9
|
+
"funding": {
|
10
|
+
"type": "opencollective",
|
11
|
+
"url": "https://opencollective.com/parcel"
|
12
|
+
},
|
9
13
|
"repository": {
|
10
14
|
"type": "git",
|
11
15
|
"url": "https://github.com/parcel-bundler/parcel.git"
|
12
16
|
},
|
13
17
|
"main": "lib/index.js",
|
14
18
|
"source": "src/index.js",
|
19
|
+
"types": "index.d.ts",
|
15
20
|
"engines": {
|
16
|
-
"node": ">=
|
21
|
+
"node": ">= 12.0.0"
|
17
22
|
},
|
18
23
|
"dependencies": {
|
19
|
-
"@parcel/diagnostic": "2.0.0-nightly.
|
20
|
-
"@parcel/logger": "2.0.0-nightly.
|
21
|
-
"@parcel/
|
22
|
-
"
|
24
|
+
"@parcel/diagnostic": "2.0.0-nightly.1400+1a3a2544b",
|
25
|
+
"@parcel/logger": "2.0.0-nightly.1400+1a3a2544b",
|
26
|
+
"@parcel/profiler": "2.9.4-nightly.3023+1a3a2544b",
|
27
|
+
"@parcel/types": "2.0.0-nightly.1400+1a3a2544b",
|
28
|
+
"@parcel/utils": "2.0.0-nightly.1400+1a3a2544b",
|
23
29
|
"nullthrows": "^1.1.1"
|
24
30
|
},
|
25
31
|
"peerDependencies": {
|
26
|
-
"@parcel/core": "
|
32
|
+
"@parcel/core": "2.0.0-nightly.1398+1a3a2544b"
|
33
|
+
},
|
34
|
+
"browser": {
|
35
|
+
"./src/cpuCount.js": false,
|
36
|
+
"./src/process/ProcessWorker.js": false,
|
37
|
+
"./src/threads/ThreadsWorker.js": false
|
27
38
|
},
|
28
|
-
"gitHead": "
|
39
|
+
"gitHead": "1a3a2544b568b1c2bb95eb17ce3b5d4514ab9f08"
|
29
40
|
}
|
package/src/Handle.js
CHANGED
@@ -1,20 +1,16 @@
|
|
1
|
-
// @flow
|
2
|
-
|
3
|
-
import type {WorkerApi} from './';
|
4
|
-
|
1
|
+
// @flow strict-local
|
5
2
|
import {registerSerializableClass} from '@parcel/core';
|
6
|
-
|
7
|
-
import {child} from './childState';
|
3
|
+
// $FlowFixMe
|
8
4
|
import packageJson from '../package.json';
|
9
5
|
|
10
6
|
let HANDLE_ID = 0;
|
11
|
-
|
7
|
+
// $FlowFixMe
|
12
8
|
export type HandleFunction = (...args: Array<any>) => any;
|
13
9
|
|
14
10
|
type HandleOpts = {|
|
15
|
-
fn
|
11
|
+
fn?: HandleFunction,
|
16
12
|
childId?: ?number,
|
17
|
-
|
13
|
+
id?: number,
|
18
14
|
|};
|
19
15
|
|
20
16
|
const handleById: Map<number, Handle> = new Map();
|
@@ -22,14 +18,12 @@ const handleById: Map<number, Handle> = new Map();
|
|
22
18
|
export default class Handle {
|
23
19
|
id: number;
|
24
20
|
childId: ?number;
|
25
|
-
fn: HandleFunction;
|
26
|
-
workerApi: WorkerApi;
|
21
|
+
fn: ?HandleFunction;
|
27
22
|
|
28
23
|
constructor(opts: HandleOpts) {
|
29
|
-
this.id = ++HANDLE_ID;
|
24
|
+
this.id = opts.id ?? ++HANDLE_ID;
|
30
25
|
this.fn = opts.fn;
|
31
26
|
this.childId = opts.childId;
|
32
|
-
this.workerApi = opts.workerApi;
|
33
27
|
handleById.set(this.id, this);
|
34
28
|
}
|
35
29
|
|
@@ -37,38 +31,15 @@ export default class Handle {
|
|
37
31
|
handleById.delete(this.id);
|
38
32
|
}
|
39
33
|
|
40
|
-
serialize() {
|
34
|
+
serialize(): {|childId: ?number, id: number|} {
|
41
35
|
return {
|
42
36
|
id: this.id,
|
43
37
|
childId: this.childId,
|
44
38
|
};
|
45
39
|
}
|
46
40
|
|
47
|
-
static deserialize(opts:
|
48
|
-
return
|
49
|
-
let workerApi;
|
50
|
-
if (child) {
|
51
|
-
workerApi = child.workerApi;
|
52
|
-
} else {
|
53
|
-
let handle = handleById.get(opts.id);
|
54
|
-
if (!handle) {
|
55
|
-
throw new Error(
|
56
|
-
'Corresponding Handle was not found. It may have been disposed.',
|
57
|
-
);
|
58
|
-
}
|
59
|
-
workerApi = handle.workerApi;
|
60
|
-
}
|
61
|
-
|
62
|
-
if (opts.childId != null && child) {
|
63
|
-
throw new Error('Cannot call another child from a child');
|
64
|
-
}
|
65
|
-
|
66
|
-
if (opts.childId != null && workerApi.callChild) {
|
67
|
-
return workerApi.callChild(opts.childId, {handle: opts.id, args});
|
68
|
-
}
|
69
|
-
|
70
|
-
return workerApi.callMaster({handle: opts.id, args}, true);
|
71
|
-
};
|
41
|
+
static deserialize(opts: HandleOpts): Handle {
|
42
|
+
return new Handle(opts);
|
72
43
|
}
|
73
44
|
}
|
74
45
|
|
package/src/Worker.js
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
// @flow
|
2
2
|
|
3
3
|
import type {FilePath} from '@parcel/types';
|
4
|
-
import type {
|
4
|
+
import type {BackendType, WorkerImpl, WorkerMessage} from './types';
|
5
|
+
import type {SharedReference} from './WorkerFarm';
|
5
6
|
|
7
|
+
import nullthrows from 'nullthrows';
|
6
8
|
import EventEmitter from 'events';
|
7
9
|
import ThrowableDiagnostic from '@parcel/diagnostic';
|
8
10
|
import {getWorkerBackend} from './backend';
|
@@ -12,6 +14,7 @@ export type WorkerCall = {|
|
|
12
14
|
handle?: number,
|
13
15
|
args: $ReadOnlyArray<any>,
|
14
16
|
retries: number,
|
17
|
+
skipReadyCheck?: boolean,
|
15
18
|
resolve: (result: Promise<any> | any) => void,
|
16
19
|
reject: (error: any) => void,
|
17
20
|
|};
|
@@ -19,7 +22,9 @@ export type WorkerCall = {|
|
|
19
22
|
type WorkerOpts = {|
|
20
23
|
forcedKillTime: number,
|
21
24
|
backend: BackendType,
|
22
|
-
|
25
|
+
shouldPatchConsole?: boolean,
|
26
|
+
shouldTrace?: boolean,
|
27
|
+
sharedReferences: $ReadOnlyMap<SharedReference, mixed>,
|
23
28
|
|};
|
24
29
|
|
25
30
|
let WORKER_ID = 0;
|
@@ -27,14 +32,15 @@ export default class Worker extends EventEmitter {
|
|
27
32
|
+options: WorkerOpts;
|
28
33
|
worker: WorkerImpl;
|
29
34
|
id: number = WORKER_ID++;
|
35
|
+
sentSharedReferences: Set<SharedReference> = new Set();
|
30
36
|
|
31
37
|
calls: Map<number, WorkerCall> = new Map();
|
32
|
-
exitCode = null;
|
33
|
-
callId = 0;
|
38
|
+
exitCode: ?number = null;
|
39
|
+
callId: number = 0;
|
34
40
|
|
35
|
-
ready = false;
|
36
|
-
stopped = false;
|
37
|
-
isStopping = false;
|
41
|
+
ready: boolean = false;
|
42
|
+
stopped: boolean = false;
|
43
|
+
isStopping: boolean = false;
|
38
44
|
|
39
45
|
constructor(options: WorkerOpts) {
|
40
46
|
super();
|
@@ -43,20 +49,45 @@ export default class Worker extends EventEmitter {
|
|
43
49
|
|
44
50
|
async fork(forkModule: FilePath) {
|
45
51
|
let filteredArgs = process.execArgv.filter(
|
46
|
-
v => !/^--(debug|inspect)/.test(v),
|
52
|
+
v => !/^--(debug|inspect|no-opt|max-old-space-size=)/.test(v),
|
47
53
|
);
|
48
54
|
|
49
55
|
for (let i = 0; i < filteredArgs.length; i++) {
|
50
56
|
let arg = filteredArgs[i];
|
51
|
-
|
52
|
-
(arg === '-r' || arg === '--require') &&
|
53
|
-
|
54
|
-
|
57
|
+
let isArgWithParam =
|
58
|
+
((arg === '-r' || arg === '--require') &&
|
59
|
+
filteredArgs[i + 1] === '@parcel/register') ||
|
60
|
+
arg === '--title';
|
61
|
+
if (isArgWithParam) {
|
55
62
|
filteredArgs.splice(i, 2);
|
56
63
|
i--;
|
57
64
|
}
|
58
65
|
}
|
59
66
|
|
67
|
+
// Workaround for https://github.com/nodejs/node/issues/29117
|
68
|
+
if (process.env.NODE_OPTIONS) {
|
69
|
+
// arg parsing logic adapted from https://stackoverflow.com/a/46946420/2352201
|
70
|
+
let opts = [''];
|
71
|
+
let quote = false;
|
72
|
+
for (let c of nullthrows(process.env.NODE_OPTIONS.match(/.|^$/g))) {
|
73
|
+
if (c === '"') {
|
74
|
+
quote = !quote;
|
75
|
+
} else if (!quote && c === ' ') {
|
76
|
+
opts.push('');
|
77
|
+
} else {
|
78
|
+
opts[opts.length - 1] += c.replace(/\\(.)/, '$1');
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
for (let i = 0; i < opts.length; i++) {
|
83
|
+
let opt = opts[i];
|
84
|
+
if (opt === '-r' || opt === '--require') {
|
85
|
+
filteredArgs.push(opt, opts[i + 1]);
|
86
|
+
i++;
|
87
|
+
}
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
60
91
|
let onMessage = data => this.receive(data);
|
61
92
|
let onExit = code => {
|
62
93
|
this.exitCode = code;
|
@@ -77,19 +108,49 @@ export default class Worker extends EventEmitter {
|
|
77
108
|
args: [
|
78
109
|
forkModule,
|
79
110
|
{
|
80
|
-
|
111
|
+
shouldPatchConsole: !!this.options.shouldPatchConsole,
|
112
|
+
shouldTrace: !!this.options.shouldTrace,
|
81
113
|
},
|
82
114
|
],
|
83
115
|
retries: 0,
|
116
|
+
skipReadyCheck: true,
|
84
117
|
resolve,
|
85
118
|
reject,
|
86
119
|
});
|
87
120
|
});
|
88
121
|
|
122
|
+
let sharedRefs = this.options.sharedReferences;
|
123
|
+
let refsShared = new Set();
|
124
|
+
// in case more refs are created while initial refs are sending
|
125
|
+
while (refsShared.size < sharedRefs.size) {
|
126
|
+
await Promise.all(
|
127
|
+
[...sharedRefs]
|
128
|
+
.filter(([ref]) => !refsShared.has(ref))
|
129
|
+
.map(async ([ref, value]) => {
|
130
|
+
await this.sendSharedReference(ref, value);
|
131
|
+
refsShared.add(ref);
|
132
|
+
}),
|
133
|
+
);
|
134
|
+
}
|
135
|
+
|
89
136
|
this.ready = true;
|
90
137
|
this.emit('ready');
|
91
138
|
}
|
92
139
|
|
140
|
+
sendSharedReference(ref: SharedReference, value: mixed): Promise<any> {
|
141
|
+
this.sentSharedReferences.add(ref);
|
142
|
+
return new Promise((resolve, reject) => {
|
143
|
+
this.call({
|
144
|
+
method: 'createSharedReference',
|
145
|
+
args: [ref, value],
|
146
|
+
resolve,
|
147
|
+
reject,
|
148
|
+
retries: 0,
|
149
|
+
skipReadyCheck: true,
|
150
|
+
});
|
151
|
+
});
|
152
|
+
}
|
153
|
+
|
93
154
|
send(data: WorkerMessage): void {
|
94
155
|
this.worker.send(data);
|
95
156
|
}
|
@@ -102,14 +163,20 @@ export default class Worker extends EventEmitter {
|
|
102
163
|
let idx = this.callId++;
|
103
164
|
this.calls.set(idx, call);
|
104
165
|
|
105
|
-
|
166
|
+
let msg = {
|
106
167
|
type: 'request',
|
107
168
|
idx: idx,
|
108
169
|
child: this.id,
|
109
170
|
handle: call.handle,
|
110
171
|
method: call.method,
|
111
172
|
args: call.args,
|
112
|
-
}
|
173
|
+
};
|
174
|
+
|
175
|
+
if (this.ready || call.skipReadyCheck === true) {
|
176
|
+
this.send(msg);
|
177
|
+
} else {
|
178
|
+
this.once('ready', () => this.send(msg));
|
179
|
+
}
|
113
180
|
}
|
114
181
|
|
115
182
|
receive(message: WorkerMessage): void {
|