@parcel/workers 2.0.0-nightly.149 → 2.0.0-nightly.1491

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.
Files changed (44) hide show
  1. package/index.d.ts +23 -0
  2. package/lib/Handle.js +16 -58
  3. package/lib/Worker.js +103 -62
  4. package/lib/WorkerFarm.js +272 -192
  5. package/lib/backend.js +4 -6
  6. package/lib/bus.js +11 -13
  7. package/lib/child.js +140 -116
  8. package/lib/childState.js +2 -4
  9. package/lib/core-worker.browser.js +4 -0
  10. package/lib/core-worker.js +4 -0
  11. package/lib/cpuCount.js +36 -25
  12. package/lib/index.js +35 -32
  13. package/lib/process/ProcessChild.js +18 -24
  14. package/lib/process/ProcessWorker.js +27 -38
  15. package/lib/threads/ThreadsChild.js +26 -28
  16. package/lib/threads/ThreadsWorker.js +25 -31
  17. package/lib/web/WebChild.js +44 -0
  18. package/lib/web/WebWorker.js +85 -0
  19. package/package.json +19 -8
  20. package/src/Handle.js +10 -39
  21. package/src/Worker.js +95 -22
  22. package/src/WorkerFarm.js +267 -62
  23. package/src/backend.js +5 -0
  24. package/src/bus.js +3 -2
  25. package/src/child.js +95 -26
  26. package/src/core-worker.browser.js +3 -0
  27. package/src/core-worker.js +2 -0
  28. package/src/cpuCount.js +23 -10
  29. package/src/index.js +8 -2
  30. package/src/process/ProcessChild.js +2 -1
  31. package/src/process/ProcessWorker.js +1 -1
  32. package/src/threads/ThreadsWorker.js +2 -2
  33. package/src/types.js +1 -1
  34. package/src/web/WebChild.js +50 -0
  35. package/src/web/WebWorker.js +85 -0
  36. package/test/cpuCount.test.js +1 -1
  37. package/test/integration/workerfarm/console.js +1 -1
  38. package/test/integration/workerfarm/logging.js +1 -1
  39. package/test/integration/workerfarm/reverse-handle.js +2 -2
  40. package/test/workerfarm.js +5 -5
  41. package/lib/Profiler.js +0 -70
  42. package/lib/Trace.js +0 -126
  43. package/src/Profiler.js +0 -93
  44. package/src/Trace.js +0 -121
package/index.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ import {FilePath} from '@parcel/types';
2
+
3
+ type BackendType = 'process' | 'threads';
4
+
5
+ export type FarmOptions = {
6
+ maxConcurrentWorkers: number;
7
+ maxConcurrentCallsPerWorker: number;
8
+ forcedKillTime: number;
9
+ useLocalWorker: boolean;
10
+ warmWorkers: boolean;
11
+ workerPath?: FilePath;
12
+ backend: BackendType;
13
+ shouldPatchConsole?: boolean;
14
+ shouldTrace?: boolean;
15
+ };
16
+
17
+ declare class WorkerFarm {
18
+ constructor(options: FarmOptions);
19
+
20
+ end(): Promise<void>;
21
+ }
22
+
23
+ export default WorkerFarm;
package/lib/Handle.js CHANGED
@@ -4,85 +4,43 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
- var _core = require("@parcel/core");
9
-
10
- var _childState = require("./childState");
11
-
7
+ function _core() {
8
+ const data = require("@parcel/core");
9
+ _core = function () {
10
+ return data;
11
+ };
12
+ return data;
13
+ }
12
14
  var _package = _interopRequireDefault(require("../package.json"));
13
-
14
15
  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
-
16
+ // $FlowFixMe
18
17
  let HANDLE_ID = 0;
19
- const handleById = new Map();
18
+ // $FlowFixMe
20
19
 
20
+ const handleById = new Map();
21
21
  class Handle {
22
22
  constructor(opts) {
23
- _defineProperty(this, "id", void 0);
24
-
25
- _defineProperty(this, "childId", void 0);
26
-
27
- _defineProperty(this, "fn", void 0);
28
-
29
- _defineProperty(this, "workerApi", void 0);
30
-
31
- this.id = ++HANDLE_ID;
23
+ var _opts$id;
24
+ this.id = (_opts$id = opts.id) !== null && _opts$id !== void 0 ? _opts$id : ++HANDLE_ID;
32
25
  this.fn = opts.fn;
33
26
  this.childId = opts.childId;
34
- this.workerApi = opts.workerApi;
35
27
  handleById.set(this.id, this);
36
28
  }
37
-
38
29
  dispose() {
39
30
  handleById.delete(this.id);
40
31
  }
41
-
42
32
  serialize() {
43
33
  return {
44
34
  id: this.id,
45
35
  childId: this.childId
46
36
  };
47
37
  }
48
-
49
38
  static deserialize(opts) {
50
- return function (...args) {
51
- let workerApi;
52
-
53
- if (_childState.child) {
54
- workerApi = _childState.child.workerApi;
55
- } else {
56
- let handle = handleById.get(opts.id);
57
-
58
- if (!handle) {
59
- throw new Error('Corresponding Handle was not found. It may have been disposed.');
60
- }
61
-
62
- workerApi = handle.workerApi;
63
- }
64
-
65
- if (opts.childId != null && _childState.child) {
66
- throw new Error('Cannot call another child from a child');
67
- }
68
-
69
- if (opts.childId != null && workerApi.callChild) {
70
- return workerApi.callChild(opts.childId, {
71
- handle: opts.id,
72
- args
73
- });
74
- }
75
-
76
- return workerApi.callMaster({
77
- handle: opts.id,
78
- args
79
- }, true);
80
- };
39
+ return new Handle(opts);
81
40
  }
41
+ }
82
42
 
83
- } // Register the Handle as a serializable class so that it will properly be deserialized
43
+ // Register the Handle as a serializable class so that it will properly be deserialized
84
44
  // by anything that uses WorkerFarm.
85
-
86
-
87
45
  exports.default = Handle;
88
- (0, _core.registerSerializableClass)(`${_package.default.version}:Handle`, Handle);
46
+ (0, _core().registerSerializableClass)(`${_package.default.version}:Handle`, Handle);
package/lib/Worker.js CHANGED
@@ -4,144 +4,185 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
- var _events = _interopRequireDefault(require("events"));
9
-
10
- var _diagnostic = _interopRequireDefault(require("@parcel/diagnostic"));
11
-
7
+ function _nullthrows() {
8
+ const data = _interopRequireDefault(require("nullthrows"));
9
+ _nullthrows = function () {
10
+ return data;
11
+ };
12
+ return data;
13
+ }
14
+ function _events() {
15
+ const data = _interopRequireDefault(require("events"));
16
+ _events = function () {
17
+ return data;
18
+ };
19
+ return data;
20
+ }
21
+ function _diagnostic() {
22
+ const data = _interopRequireDefault(require("@parcel/diagnostic"));
23
+ _diagnostic = function () {
24
+ return data;
25
+ };
26
+ return data;
27
+ }
12
28
  var _backend = require("./backend");
13
-
14
29
  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
30
  let WORKER_ID = 0;
19
-
20
- class Worker extends _events.default {
31
+ class Worker extends _events().default {
32
+ id = WORKER_ID++;
33
+ sentSharedReferences = new Set();
34
+ calls = new Map();
35
+ exitCode = null;
36
+ callId = 0;
37
+ ready = false;
38
+ stopped = false;
39
+ isStopping = false;
21
40
  constructor(options) {
22
41
  super();
23
-
24
- _defineProperty(this, "options", void 0);
25
-
26
- _defineProperty(this, "worker", void 0);
27
-
28
- _defineProperty(this, "id", WORKER_ID++);
29
-
30
- _defineProperty(this, "calls", new Map());
31
-
32
- _defineProperty(this, "exitCode", null);
33
-
34
- _defineProperty(this, "callId", 0);
35
-
36
- _defineProperty(this, "ready", false);
37
-
38
- _defineProperty(this, "stopped", false);
39
-
40
- _defineProperty(this, "isStopping", false);
41
-
42
42
  this.options = options;
43
43
  }
44
-
45
44
  async fork(forkModule) {
46
- let filteredArgs = process.execArgv.filter(v => !/^--(debug|inspect)/.test(v));
47
-
48
- for (let i = 0; i < filteredArgs.length; i++) {
49
- let arg = filteredArgs[i];
50
-
51
- if ((arg === '-r' || arg === '--require') && filteredArgs[i + 1] === '@parcel/register') {
52
- filteredArgs.splice(i, 2);
53
- i--;
45
+ let filteredArgs = [];
46
+ if (process.execArgv) {
47
+ filteredArgs = process.execArgv.filter(v => !/^--(debug|inspect|no-opt|max-old-space-size=|max-semi-space-size=|expose-gc)/.test(v));
48
+ for (let i = 0; i < filteredArgs.length; i++) {
49
+ let arg = filteredArgs[i];
50
+ let isArgWithParam = (arg === '-r' || arg === '--require') && filteredArgs[i + 1] === '@parcel/register' || arg === '--title';
51
+ if (isArgWithParam) {
52
+ filteredArgs.splice(i, 2);
53
+ i--;
54
+ }
54
55
  }
55
56
  }
56
57
 
57
- let WorkerBackend = (0, _backend.getWorkerBackend)(this.options.backend);
58
- this.worker = new WorkerBackend(filteredArgs, data => this.receive(data), err => {
59
- this.emit('error', err);
60
- }, code => {
58
+ // Workaround for https://github.com/nodejs/node/issues/29117
59
+ if (process.env.NODE_OPTIONS) {
60
+ // arg parsing logic adapted from https://stackoverflow.com/a/46946420/2352201
61
+ let opts = [''];
62
+ let quote = false;
63
+ for (let c of (0, _nullthrows().default)(process.env.NODE_OPTIONS.match(/.|^$/g))) {
64
+ if (c === '"') {
65
+ quote = !quote;
66
+ } else if (!quote && c === ' ') {
67
+ opts.push('');
68
+ } else {
69
+ opts[opts.length - 1] += c.replace(/\\(.)/, '$1');
70
+ }
71
+ }
72
+ for (let i = 0; i < opts.length; i++) {
73
+ let opt = opts[i];
74
+ if (opt === '-r' || opt === '--require') {
75
+ filteredArgs.push(opt, opts[i + 1]);
76
+ i++;
77
+ }
78
+ }
79
+ }
80
+ let onMessage = data => this.receive(data);
81
+ let onExit = code => {
61
82
  this.exitCode = code;
62
83
  this.emit('exit', code);
63
- });
84
+ };
85
+ let onError = err => {
86
+ this.emit('error', err);
87
+ };
88
+ let WorkerBackend = (0, _backend.getWorkerBackend)(this.options.backend);
89
+ this.worker = new WorkerBackend(filteredArgs, onMessage, onError, onExit);
64
90
  await this.worker.start();
65
91
  await new Promise((resolve, reject) => {
66
92
  this.call({
67
93
  method: 'childInit',
68
94
  args: [forkModule, {
69
- patchConsole: !!this.options.patchConsole
95
+ shouldPatchConsole: !!this.options.shouldPatchConsole,
96
+ shouldTrace: !!this.options.shouldTrace
70
97
  }],
71
98
  retries: 0,
99
+ skipReadyCheck: true,
72
100
  resolve,
73
101
  reject
74
102
  });
75
103
  });
104
+ let sharedRefs = this.options.sharedReferences;
105
+ let refsShared = new Set();
106
+ // in case more refs are created while initial refs are sending
107
+ while (refsShared.size < sharedRefs.size) {
108
+ await Promise.all([...sharedRefs].filter(([ref]) => !refsShared.has(ref)).map(async ([ref, value]) => {
109
+ await this.sendSharedReference(ref, value);
110
+ refsShared.add(ref);
111
+ }));
112
+ }
76
113
  this.ready = true;
77
114
  this.emit('ready');
78
115
  }
79
-
116
+ sendSharedReference(ref, value) {
117
+ this.sentSharedReferences.add(ref);
118
+ return new Promise((resolve, reject) => {
119
+ this.call({
120
+ method: 'createSharedReference',
121
+ args: [ref, value],
122
+ resolve,
123
+ reject,
124
+ retries: 0,
125
+ skipReadyCheck: true
126
+ });
127
+ });
128
+ }
80
129
  send(data) {
81
130
  this.worker.send(data);
82
131
  }
83
-
84
132
  call(call) {
85
133
  if (this.stopped || this.isStopping) {
86
134
  return;
87
135
  }
88
-
89
136
  let idx = this.callId++;
90
137
  this.calls.set(idx, call);
91
- this.send({
138
+ let msg = {
92
139
  type: 'request',
93
140
  idx: idx,
94
141
  child: this.id,
95
142
  handle: call.handle,
96
143
  method: call.method,
97
144
  args: call.args
98
- });
145
+ };
146
+ if (this.ready || call.skipReadyCheck === true) {
147
+ this.send(msg);
148
+ } else {
149
+ this.once('ready', () => this.send(msg));
150
+ }
99
151
  }
100
-
101
152
  receive(message) {
102
153
  if (this.stopped || this.isStopping) {
103
154
  return;
104
155
  }
105
-
106
156
  if (message.type === 'request') {
107
157
  this.emit('request', message);
108
158
  } else if (message.type === 'response') {
109
159
  let idx = message.idx;
110
-
111
160
  if (idx == null) {
112
161
  return;
113
162
  }
114
-
115
163
  let call = this.calls.get(idx);
116
-
117
164
  if (!call) {
118
165
  // Return for unknown calls, these might accur if a third party process uses workers
119
166
  return;
120
167
  }
121
-
122
168
  if (message.contentType === 'error') {
123
- call.reject(new _diagnostic.default({
169
+ call.reject(new (_diagnostic().default)({
124
170
  diagnostic: message.content
125
171
  }));
126
172
  } else {
127
173
  call.resolve(message.content);
128
174
  }
129
-
130
175
  this.calls.delete(idx);
131
176
  this.emit('response', message);
132
177
  }
133
178
  }
134
-
135
179
  async stop() {
136
180
  if (!this.stopped) {
137
181
  this.stopped = true;
138
-
139
182
  if (this.worker) {
140
183
  await this.worker.stop();
141
184
  }
142
185
  }
143
186
  }
144
-
145
187
  }
146
-
147
188
  exports.default = Worker;