@parcel/workers 2.0.0-nightly.146 → 2.0.0-nightly.1470

Sign up to get free protection for your applications and to get access to all the features.
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;