@parcel/workers 2.0.0-nightly.144 → 2.0.0-nightly.1441

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 +95 -57
  4. package/lib/WorkerFarm.js +272 -192
  5. package/lib/backend.js +4 -6
  6. package/lib/bus.js +10 -11
  7. package/lib/child.js +140 -116
  8. package/lib/childState.js +1 -2
  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 +34 -30
  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 +92 -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/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: HandleFunction,
11
+ fn?: HandleFunction,
16
12
  childId?: ?number,
17
- workerApi: WorkerApi,
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: {|id: number, childId?: number|}) {
48
- return function(...args: Array<mixed>) {
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 {WorkerMessage, WorkerImpl, BackendType} from './types';
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
- patchConsole?: boolean,
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();
@@ -42,18 +48,46 @@ export default class Worker extends EventEmitter {
42
48
  }
43
49
 
44
50
  async fork(forkModule: FilePath) {
45
- let filteredArgs = process.execArgv.filter(
46
- v => !/^--(debug|inspect)/.test(v),
47
- );
48
-
49
- for (let i = 0; i < filteredArgs.length; i++) {
50
- let arg = filteredArgs[i];
51
- if (
52
- (arg === '-r' || arg === '--require') &&
53
- filteredArgs[i + 1] === '@parcel/register'
54
- ) {
55
- filteredArgs.splice(i, 2);
56
- i--;
51
+ let filteredArgs = [];
52
+ if (process.execArgv) {
53
+ filteredArgs = process.execArgv.filter(
54
+ v => !/^--(debug|inspect|no-opt|max-old-space-size=)/.test(v),
55
+ );
56
+
57
+ for (let i = 0; i < filteredArgs.length; i++) {
58
+ let arg = filteredArgs[i];
59
+ let isArgWithParam =
60
+ ((arg === '-r' || arg === '--require') &&
61
+ filteredArgs[i + 1] === '@parcel/register') ||
62
+ arg === '--title';
63
+ if (isArgWithParam) {
64
+ filteredArgs.splice(i, 2);
65
+ i--;
66
+ }
67
+ }
68
+ }
69
+
70
+ // Workaround for https://github.com/nodejs/node/issues/29117
71
+ if (process.env.NODE_OPTIONS) {
72
+ // arg parsing logic adapted from https://stackoverflow.com/a/46946420/2352201
73
+ let opts = [''];
74
+ let quote = false;
75
+ for (let c of nullthrows(process.env.NODE_OPTIONS.match(/.|^$/g))) {
76
+ if (c === '"') {
77
+ quote = !quote;
78
+ } else if (!quote && c === ' ') {
79
+ opts.push('');
80
+ } else {
81
+ opts[opts.length - 1] += c.replace(/\\(.)/, '$1');
82
+ }
83
+ }
84
+
85
+ for (let i = 0; i < opts.length; i++) {
86
+ let opt = opts[i];
87
+ if (opt === '-r' || opt === '--require') {
88
+ filteredArgs.push(opt, opts[i + 1]);
89
+ i++;
90
+ }
57
91
  }
58
92
  }
59
93
 
@@ -77,19 +111,49 @@ export default class Worker extends EventEmitter {
77
111
  args: [
78
112
  forkModule,
79
113
  {
80
- patchConsole: !!this.options.patchConsole,
114
+ shouldPatchConsole: !!this.options.shouldPatchConsole,
115
+ shouldTrace: !!this.options.shouldTrace,
81
116
  },
82
117
  ],
83
118
  retries: 0,
119
+ skipReadyCheck: true,
84
120
  resolve,
85
121
  reject,
86
122
  });
87
123
  });
88
124
 
125
+ let sharedRefs = this.options.sharedReferences;
126
+ let refsShared = new Set();
127
+ // in case more refs are created while initial refs are sending
128
+ while (refsShared.size < sharedRefs.size) {
129
+ await Promise.all(
130
+ [...sharedRefs]
131
+ .filter(([ref]) => !refsShared.has(ref))
132
+ .map(async ([ref, value]) => {
133
+ await this.sendSharedReference(ref, value);
134
+ refsShared.add(ref);
135
+ }),
136
+ );
137
+ }
138
+
89
139
  this.ready = true;
90
140
  this.emit('ready');
91
141
  }
92
142
 
143
+ sendSharedReference(ref: SharedReference, value: mixed): Promise<any> {
144
+ this.sentSharedReferences.add(ref);
145
+ return new Promise((resolve, reject) => {
146
+ this.call({
147
+ method: 'createSharedReference',
148
+ args: [ref, value],
149
+ resolve,
150
+ reject,
151
+ retries: 0,
152
+ skipReadyCheck: true,
153
+ });
154
+ });
155
+ }
156
+
93
157
  send(data: WorkerMessage): void {
94
158
  this.worker.send(data);
95
159
  }
@@ -102,14 +166,20 @@ export default class Worker extends EventEmitter {
102
166
  let idx = this.callId++;
103
167
  this.calls.set(idx, call);
104
168
 
105
- this.send({
169
+ let msg = {
106
170
  type: 'request',
107
171
  idx: idx,
108
172
  child: this.id,
109
173
  handle: call.handle,
110
174
  method: call.method,
111
175
  args: call.args,
112
- });
176
+ };
177
+
178
+ if (this.ready || call.skipReadyCheck === true) {
179
+ this.send(msg);
180
+ } else {
181
+ this.once('ready', () => this.send(msg));
182
+ }
113
183
  }
114
184
 
115
185
  receive(message: WorkerMessage): void {