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