@parcel/workers 2.0.0-nightly.120 → 2.0.0-nightly.1202

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/src/WorkerFarm.js CHANGED
@@ -20,7 +20,7 @@ import {
20
20
  restoreDeserializedObject,
21
21
  serialize,
22
22
  } from '@parcel/core';
23
- import ThrowableDiagnostic, {anyToDiagnostic} from '@parcel/diagnostic';
23
+ import ThrowableDiagnostic, {anyToDiagnostic, md} from '@parcel/diagnostic';
24
24
  import Worker, {type WorkerCall} from './Worker';
25
25
  import cpuCount from './cpuCount';
26
26
  import Handle from './Handle';
@@ -31,9 +31,10 @@ import Trace from './Trace';
31
31
  import fs from 'fs';
32
32
  import logger from '@parcel/logger';
33
33
 
34
- let profileId = 1;
35
34
  let referenceId = 1;
36
35
 
36
+ export opaque type SharedReference = number;
37
+
37
38
  export type FarmOptions = {|
38
39
  maxConcurrentWorkers: number,
39
40
  maxConcurrentCallsPerWorker: number,
@@ -42,7 +43,7 @@ export type FarmOptions = {|
42
43
  warmWorkers: boolean,
43
44
  workerPath?: FilePath,
44
45
  backend: BackendType,
45
- patchConsole?: boolean,
46
+ shouldPatchConsole?: boolean,
46
47
  |};
47
48
 
48
49
  type WorkerModule = {|
@@ -52,8 +53,8 @@ type WorkerModule = {|
52
53
  export type WorkerApi = {|
53
54
  callMaster(CallRequest, ?boolean): Promise<mixed>,
54
55
  createReverseHandle(fn: HandleFunction): Handle,
55
- getSharedReference(ref: number): mixed,
56
- resolveSharedReference(value: mixed): ?number,
56
+ getSharedReference(ref: SharedReference): mixed,
57
+ resolveSharedReference(value: mixed): ?SharedReference,
57
58
  callChild?: (childId: number, request: HandleCallRequest) => Promise<mixed>,
58
59
  |};
59
60
 
@@ -67,13 +68,15 @@ export default class WorkerFarm extends EventEmitter {
67
68
  callQueue: Array<WorkerCall> = [];
68
69
  ending: boolean = false;
69
70
  localWorker: WorkerModule;
71
+ localWorkerInit: ?Promise<void>;
70
72
  options: FarmOptions;
71
73
  run: HandleFunction;
72
74
  warmWorkers: number = 0;
73
75
  workers: Map<number, Worker> = new Map();
74
76
  handles: Map<number, Handle> = new Map();
75
- sharedReferences: Map<number, mixed> = new Map();
76
- sharedReferencesByValue: Map<mixed, number> = new Map();
77
+ sharedReferences: Map<SharedReference, mixed> = new Map();
78
+ sharedReferencesByValue: Map<mixed, SharedReference> = new Map();
79
+ serializedSharedReferences: Map<SharedReference, ?ArrayBuffer> = new Map();
77
80
  profiler: ?Profiler;
78
81
 
79
82
  constructor(farmOptions: $Shape<FarmOptions> = {}) {
@@ -94,12 +97,24 @@ export default class WorkerFarm extends EventEmitter {
94
97
 
95
98
  // $FlowFixMe this must be dynamic
96
99
  this.localWorker = require(this.options.workerPath);
100
+ this.localWorkerInit =
101
+ this.localWorker.childInit != null ? this.localWorker.childInit() : null;
97
102
  this.run = this.createHandle('run');
98
103
 
99
104
  this.startMaxWorkers();
100
105
  }
101
106
 
102
- workerApi = {
107
+ workerApi: {|
108
+ callChild: (childId: number, request: HandleCallRequest) => Promise<mixed>,
109
+ callMaster: (
110
+ request: CallRequest,
111
+ awaitResponse?: ?boolean,
112
+ ) => Promise<mixed>,
113
+ createReverseHandle: (fn: HandleFunction) => Handle,
114
+ getSharedReference: (ref: SharedReference) => mixed,
115
+ resolveSharedReference: (value: mixed) => void | SharedReference,
116
+ runHandle: (handle: Handle, args: Array<any>) => Promise<mixed>,
117
+ |} = {
103
118
  callMaster: async (
104
119
  request: CallRequest,
105
120
  awaitResponse: ?boolean = true,
@@ -122,7 +137,13 @@ export default class WorkerFarm extends EventEmitter {
122
137
  retries: 0,
123
138
  });
124
139
  }),
125
- getSharedReference: (ref: number) => this.sharedReferences.get(ref),
140
+ runHandle: (handle: Handle, args: Array<any>): Promise<mixed> =>
141
+ this.workerApi.callChild(nullthrows(handle.childId), {
142
+ handle: handle.id,
143
+ args,
144
+ }),
145
+ getSharedReference: (ref: SharedReference) =>
146
+ this.sharedReferences.get(ref),
126
147
  resolveSharedReference: (value: mixed) =>
127
148
  this.sharedReferencesByValue.get(value),
128
149
  };
@@ -155,30 +176,42 @@ export default class WorkerFarm extends EventEmitter {
155
176
  );
156
177
  }
157
178
 
158
- createHandle(method: string): HandleFunction {
159
- return (...args) => {
179
+ createHandle(method: string, useMainThread: boolean = false): HandleFunction {
180
+ return async (...args) => {
160
181
  // Child process workers are slow to start (~600ms).
161
182
  // While we're waiting, just run on the main thread.
162
183
  // This significantly speeds up startup time.
163
- if (this.shouldUseRemoteWorkers()) {
184
+ if (this.shouldUseRemoteWorkers() && !useMainThread) {
164
185
  return this.addCall(method, [...args, false]);
165
186
  } else {
166
187
  if (this.options.warmWorkers && this.shouldStartRemoteWorkers()) {
167
188
  this.warmupWorker(method, args);
168
189
  }
169
190
 
170
- let processedArgs = restoreDeserializedObject(
171
- prepareForSerialization([...args, false]),
172
- );
191
+ let processedArgs;
192
+ if (!useMainThread) {
193
+ processedArgs = restoreDeserializedObject(
194
+ prepareForSerialization([...args, false]),
195
+ );
196
+ } else {
197
+ processedArgs = args;
198
+ }
199
+
200
+ if (this.localWorkerInit != null) {
201
+ await this.localWorkerInit;
202
+ this.localWorkerInit = null;
203
+ }
173
204
  return this.localWorker[method](this.workerApi, ...processedArgs);
174
205
  }
175
206
  };
176
207
  }
177
208
 
178
- onError(error: ErrorWithCode, worker: Worker) {
209
+ onError(error: ErrorWithCode, worker: Worker): void | Promise<void> {
179
210
  // Handle ipc errors
180
211
  if (error.code === 'ERR_IPC_CHANNEL_CLOSED') {
181
212
  return this.stopWorker(worker);
213
+ } else {
214
+ logger.error(error, '@parcel/workers');
182
215
  }
183
216
  }
184
217
 
@@ -186,7 +219,8 @@ export default class WorkerFarm extends EventEmitter {
186
219
  let worker = new Worker({
187
220
  forcedKillTime: this.options.forcedKillTime,
188
221
  backend: this.options.backend,
189
- patchConsole: this.options.patchConsole,
222
+ shouldPatchConsole: this.options.shouldPatchConsole,
223
+ sharedReferences: this.sharedReferences,
190
224
  });
191
225
 
192
226
  worker.fork(nullthrows(this.options.workerPath));
@@ -231,7 +265,11 @@ export default class WorkerFarm extends EventEmitter {
231
265
  this.startChild();
232
266
  }
233
267
 
234
- for (let worker of this.workers.values()) {
268
+ let workers = [...this.workers.values()].sort(
269
+ (a, b) => a.calls.size - b.calls.size,
270
+ );
271
+
272
+ for (let worker of workers) {
235
273
  if (!this.callQueue.length) {
236
274
  break;
237
275
  }
@@ -241,9 +279,22 @@ export default class WorkerFarm extends EventEmitter {
241
279
  }
242
280
 
243
281
  if (worker.calls.size < this.options.maxConcurrentCallsPerWorker) {
244
- worker.call(this.callQueue.shift());
282
+ this.callWorker(worker, this.callQueue.shift());
283
+ }
284
+ }
285
+ }
286
+
287
+ async callWorker(worker: Worker, call: WorkerCall): Promise<void> {
288
+ for (let ref of this.sharedReferences.keys()) {
289
+ if (!worker.sentSharedReferences.has(ref)) {
290
+ await worker.sendSharedReference(
291
+ ref,
292
+ this.getSerializedSharedReference(ref),
293
+ );
245
294
  }
246
295
  }
296
+
297
+ worker.call(call);
247
298
  }
248
299
 
249
300
  async processRequest(
@@ -255,7 +306,7 @@ export default class WorkerFarm extends EventEmitter {
255
306
  let {method, args, location, awaitResponse, idx, handle: handleId} = data;
256
307
  let mod;
257
308
  if (handleId != null) {
258
- mod = nullthrows(this.handles.get(handleId)).fn;
309
+ mod = nullthrows(this.handles.get(handleId)?.fn);
259
310
  } else if (location) {
260
311
  // $FlowFixMe this must be dynamic
261
312
  mod = require(location);
@@ -286,7 +337,6 @@ export default class WorkerFarm extends EventEmitter {
286
337
  }
287
338
  } else {
288
339
  // ESModule default interop
289
- // $FlowFixMe
290
340
  if (mod.__esModule && !mod[method] && mod.default) {
291
341
  mod = mod.default;
292
342
  }
@@ -331,6 +381,10 @@ export default class WorkerFarm extends EventEmitter {
331
381
  async end(): Promise<void> {
332
382
  this.ending = true;
333
383
 
384
+ await Promise.all(
385
+ Array.from(this.workers.values()).map(worker => this.stopWorker(worker)),
386
+ );
387
+
334
388
  for (let handle of this.handles.values()) {
335
389
  handle.dispose();
336
390
  }
@@ -338,9 +392,6 @@ export default class WorkerFarm extends EventEmitter {
338
392
  this.sharedReferences = new Map();
339
393
  this.sharedReferencesByValue = new Map();
340
394
 
341
- await Promise.all(
342
- Array.from(this.workers.values()).map(worker => this.stopWorker(worker)),
343
- );
344
395
  this.ending = false;
345
396
  }
346
397
 
@@ -362,40 +413,37 @@ export default class WorkerFarm extends EventEmitter {
362
413
  );
363
414
  }
364
415
 
365
- createReverseHandle(fn: HandleFunction) {
366
- let handle = new Handle({fn, workerApi: this.workerApi});
416
+ createReverseHandle(fn: HandleFunction): Handle {
417
+ let handle = new Handle({fn});
367
418
  this.handles.set(handle.id, handle);
368
419
  return handle;
369
420
  }
370
421
 
371
- async createSharedReference(value: mixed) {
422
+ createSharedReference(
423
+ value: mixed,
424
+ isCacheable: boolean = true,
425
+ ): {|ref: SharedReference, dispose(): Promise<mixed>|} {
372
426
  let ref = referenceId++;
373
427
  this.sharedReferences.set(ref, value);
374
428
  this.sharedReferencesByValue.set(value, ref);
375
- let promises = [];
376
- for (let worker of this.workers.values()) {
377
- promises.push(
378
- new Promise((resolve, reject) => {
379
- worker.call({
380
- method: 'createSharedReference',
381
- args: [ref, value],
382
- resolve,
383
- reject,
384
- retries: 0,
385
- });
386
- }),
387
- );
429
+ if (!isCacheable) {
430
+ this.serializedSharedReferences.set(ref, null);
388
431
  }
389
432
 
390
- await Promise.all(promises);
391
-
392
433
  return {
393
434
  ref,
394
435
  dispose: () => {
395
436
  this.sharedReferences.delete(ref);
396
437
  this.sharedReferencesByValue.delete(value);
438
+ this.serializedSharedReferences.delete(ref);
439
+
397
440
  let promises = [];
398
441
  for (let worker of this.workers.values()) {
442
+ if (!worker.sentSharedReferences.has(ref)) {
443
+ continue;
444
+ }
445
+
446
+ worker.sentSharedReferences.delete(ref);
399
447
  promises.push(
400
448
  new Promise((resolve, reject) => {
401
449
  worker.call({
@@ -403,6 +451,7 @@ export default class WorkerFarm extends EventEmitter {
403
451
  args: [ref],
404
452
  resolve,
405
453
  reject,
454
+ skipReadyCheck: true,
406
455
  retries: 0,
407
456
  });
408
457
  }),
@@ -413,6 +462,24 @@ export default class WorkerFarm extends EventEmitter {
413
462
  };
414
463
  }
415
464
 
465
+ getSerializedSharedReference(ref: SharedReference): ArrayBuffer {
466
+ let cached = this.serializedSharedReferences.get(ref);
467
+ if (cached) {
468
+ return cached;
469
+ }
470
+
471
+ let value = this.sharedReferences.get(ref);
472
+ let buf = serialize(value).buffer;
473
+
474
+ // If the reference was created with the isCacheable option set to false,
475
+ // serializedSharedReferences will contain `null` as the value.
476
+ if (cached !== null) {
477
+ this.serializedSharedReferences.set(ref, buf);
478
+ }
479
+
480
+ return buf;
481
+ }
482
+
416
483
  async startProfile() {
417
484
  let promises = [];
418
485
  for (let worker of this.workers.values()) {
@@ -424,6 +491,7 @@ export default class WorkerFarm extends EventEmitter {
424
491
  resolve,
425
492
  reject,
426
493
  retries: 0,
494
+ skipReadyCheck: true,
427
495
  });
428
496
  }),
429
497
  );
@@ -453,6 +521,7 @@ export default class WorkerFarm extends EventEmitter {
453
521
  resolve,
454
522
  reject,
455
523
  retries: 0,
524
+ skipReadyCheck: true,
456
525
  });
457
526
  }),
458
527
  );
@@ -460,7 +529,7 @@ export default class WorkerFarm extends EventEmitter {
460
529
 
461
530
  var profiles = await Promise.all(promises);
462
531
  let trace = new Trace();
463
- let filename = `profile-${profileId++}.trace`;
532
+ let filename = `profile-${getTimeId()}.trace`;
464
533
  let stream = trace.pipe(fs.createWriteStream(filename));
465
534
 
466
535
  for (let profile of profiles) {
@@ -474,21 +543,84 @@ export default class WorkerFarm extends EventEmitter {
474
543
 
475
544
  logger.info({
476
545
  origin: '@parcel/workers',
477
- message: `Wrote profile to ${filename}`,
546
+ message: md`Wrote profile to ${filename}`,
478
547
  });
479
548
  }
480
549
 
481
- static getNumWorkers() {
550
+ async callAllWorkers(method: string, args: Array<any>) {
551
+ let promises = [];
552
+ for (let worker of this.workers.values()) {
553
+ promises.push(
554
+ new Promise((resolve, reject) => {
555
+ worker.call({
556
+ method,
557
+ args,
558
+ resolve,
559
+ reject,
560
+ retries: 0,
561
+ });
562
+ }),
563
+ );
564
+ }
565
+
566
+ promises.push(this.localWorker[method](this.workerApi, ...args));
567
+ await Promise.all(promises);
568
+ }
569
+
570
+ async takeHeapSnapshot() {
571
+ let snapshotId = getTimeId();
572
+
573
+ try {
574
+ let snapshotPaths = await Promise.all(
575
+ [...this.workers.values()].map(
576
+ worker =>
577
+ new Promise((resolve, reject) => {
578
+ worker.call({
579
+ method: 'takeHeapSnapshot',
580
+ args: [snapshotId],
581
+ resolve,
582
+ reject,
583
+ retries: 0,
584
+ skipReadyCheck: true,
585
+ });
586
+ }),
587
+ ),
588
+ );
589
+
590
+ logger.info({
591
+ origin: '@parcel/workers',
592
+ message: md`Wrote heap snapshots to the following paths:\n${snapshotPaths.join(
593
+ '\n',
594
+ )}`,
595
+ });
596
+ } catch {
597
+ logger.error({
598
+ origin: '@parcel/workers',
599
+ message: 'Unable to take heap snapshots. Note: requires Node 11.13.0+',
600
+ });
601
+ }
602
+ }
603
+
604
+ static getNumWorkers(): number {
482
605
  return process.env.PARCEL_WORKERS
483
606
  ? parseInt(process.env.PARCEL_WORKERS, 10)
484
- : cpuCount();
607
+ : Math.ceil(cpuCount() / 2);
485
608
  }
486
609
 
487
- static isWorker() {
610
+ static isWorker(): boolean {
488
611
  return !!child;
489
612
  }
490
613
 
491
- static getWorkerApi() {
614
+ static getWorkerApi(): {|
615
+ callMaster: (
616
+ request: CallRequest,
617
+ awaitResponse?: ?boolean,
618
+ ) => Promise<mixed>,
619
+ createReverseHandle: (fn: (...args: Array<any>) => mixed) => Handle,
620
+ getSharedReference: (ref: SharedReference) => mixed,
621
+ resolveSharedReference: (value: mixed) => void | SharedReference,
622
+ runHandle: (handle: Handle, args: Array<any>) => Promise<mixed>,
623
+ |} {
492
624
  invariant(
493
625
  child != null,
494
626
  'WorkerFarm.getWorkerApi can only be called within workers',
@@ -496,7 +628,20 @@ export default class WorkerFarm extends EventEmitter {
496
628
  return child.workerApi;
497
629
  }
498
630
 
499
- static getConcurrentCallsPerWorker() {
500
- return parseInt(process.env.PARCEL_MAX_CONCURRENT_CALLS, 10) || 5;
631
+ static getConcurrentCallsPerWorker(): number {
632
+ return parseInt(process.env.PARCEL_MAX_CONCURRENT_CALLS, 10) || 30;
501
633
  }
502
634
  }
635
+
636
+ function getTimeId() {
637
+ let now = new Date();
638
+ return (
639
+ String(now.getFullYear()) +
640
+ String(now.getMonth() + 1).padStart(2, '0') +
641
+ String(now.getDate()).padStart(2, '0') +
642
+ '-' +
643
+ String(now.getHours()).padStart(2, '0') +
644
+ String(now.getMinutes()).padStart(2, '0') +
645
+ String(now.getSeconds()).padStart(2, '0')
646
+ );
647
+ }
package/src/bus.js CHANGED
@@ -20,4 +20,4 @@ class Bus extends EventEmitter {
20
20
  }
21
21
  }
22
22
 
23
- export default new Bus();
23
+ export default (new Bus(): Bus);
package/src/child.js CHANGED
@@ -9,16 +9,20 @@ import type {
9
9
  WorkerResponse,
10
10
  ChildImpl,
11
11
  } from './types';
12
- import type {IDisposable} from '@parcel/types';
13
- import type {WorkerApi} from './WorkerFarm';
12
+ import type {Async, IDisposable} from '@parcel/types';
13
+ import type {SharedReference} from './WorkerFarm';
14
14
 
15
15
  import invariant from 'assert';
16
16
  import nullthrows from 'nullthrows';
17
17
  import Logger, {patchConsole, unpatchConsole} from '@parcel/logger';
18
18
  import ThrowableDiagnostic, {anyToDiagnostic} from '@parcel/diagnostic';
19
+ import {deserialize} from '@parcel/core';
19
20
  import bus from './bus';
20
21
  import Profiler from './Profiler';
21
- import Handle from './Handle';
22
+ import _Handle from './Handle';
23
+
24
+ // The import of './Handle' should really be imported eagerly (with @babel/plugin-transform-modules-commonjs's lazy mode).
25
+ const Handle = _Handle;
22
26
 
23
27
  type ChildCall = WorkerRequest & {|
24
28
  resolve: (result: Promise<any> | any) => void,
@@ -30,20 +34,21 @@ export class Child {
30
34
  childId: ?number;
31
35
  maxConcurrentCalls: number = 10;
32
36
  module: ?any;
33
- responseId = 0;
37
+ responseId: number = 0;
34
38
  responseQueue: Map<number, ChildCall> = new Map();
35
39
  loggerDisposable: IDisposable;
36
40
  child: ChildImpl;
37
41
  profiler: ?Profiler;
38
- workerApi: WorkerApi;
39
42
  handles: Map<number, Handle> = new Map();
40
- sharedReferences: Map<number, mixed> = new Map();
41
- sharedReferencesByValue: Map<mixed, number> = new Map();
43
+ sharedReferences: Map<SharedReference, mixed> = new Map();
44
+ sharedReferencesByValue: Map<mixed, SharedReference> = new Map();
42
45
 
43
46
  constructor(ChildBackend: Class<ChildImpl>) {
44
47
  this.child = new ChildBackend(
45
- this.messageListener.bind(this),
46
- this.handleEnd.bind(this),
48
+ m => {
49
+ this.messageListener(m);
50
+ },
51
+ () => this.handleEnd(),
47
52
  );
48
53
 
49
54
  // Monitior all logging events inside this child process and forward to
@@ -53,19 +58,31 @@ export class Child {
53
58
  });
54
59
  }
55
60
 
56
- workerApi = {
61
+ workerApi: {|
62
+ callMaster: (
63
+ request: CallRequest,
64
+ awaitResponse?: ?boolean,
65
+ ) => Promise<mixed>,
66
+ createReverseHandle: (fn: (...args: Array<any>) => mixed) => Handle,
67
+ getSharedReference: (ref: SharedReference) => mixed,
68
+ resolveSharedReference: (value: mixed) => void | SharedReference,
69
+ runHandle: (handle: Handle, args: Array<any>) => Promise<mixed>,
70
+ |} = {
57
71
  callMaster: (
58
72
  request: CallRequest,
59
73
  awaitResponse: ?boolean = true,
60
74
  ): Promise<mixed> => this.addCall(request, awaitResponse),
61
75
  createReverseHandle: (fn: (...args: Array<any>) => mixed): Handle =>
62
76
  this.createReverseHandle(fn),
63
- getSharedReference: (ref: number) => this.sharedReferences.get(ref),
77
+ runHandle: (handle: Handle, args: Array<any>): Promise<mixed> =>
78
+ this.workerApi.callMaster({handle: handle.id, args}, true),
79
+ getSharedReference: (ref: SharedReference) =>
80
+ this.sharedReferences.get(ref),
64
81
  resolveSharedReference: (value: mixed) =>
65
82
  this.sharedReferencesByValue.get(value),
66
83
  };
67
84
 
68
- messageListener(message: WorkerMessage): void | Promise<void> {
85
+ messageListener(message: WorkerMessage): Async<void> {
69
86
  if (message.type === 'response') {
70
87
  return this.handleResponse(message);
71
88
  } else if (message.type === 'request') {
@@ -77,10 +94,14 @@ export class Child {
77
94
  this.child.send(data);
78
95
  }
79
96
 
80
- childInit(module: string, childId: number): void {
97
+ async childInit(module: string, childId: number): Promise<void> {
81
98
  // $FlowFixMe this must be dynamic
82
99
  this.module = require(module);
83
100
  this.childId = childId;
101
+
102
+ if (this.module.childInit != null) {
103
+ await this.module.childInit();
104
+ }
84
105
  }
85
106
 
86
107
  async handleRequest(data: WorkerRequest): Promise<void> {
@@ -106,7 +127,7 @@ export class Child {
106
127
  let result;
107
128
  if (handleId != null) {
108
129
  try {
109
- let fn = nullthrows(this.handles.get(handleId)).fn;
130
+ let fn = nullthrows(this.handles.get(handleId)?.fn);
110
131
  result = responseFromContent(fn(...args));
111
132
  } catch (e) {
112
133
  result = errorResponseFromError(e);
@@ -114,13 +135,13 @@ export class Child {
114
135
  } else if (method === 'childInit') {
115
136
  try {
116
137
  let [moduleName, childOptions] = args;
117
- if (childOptions.patchConsole) {
138
+ if (childOptions.shouldPatchConsole) {
118
139
  patchConsole();
119
140
  } else {
120
141
  unpatchConsole();
121
142
  }
122
143
 
123
- result = responseFromContent(this.childInit(moduleName, child));
144
+ result = responseFromContent(await this.childInit(moduleName, child));
124
145
  } catch (e) {
125
146
  result = errorResponseFromError(e);
126
147
  }
@@ -138,13 +159,37 @@ export class Child {
138
159
  } catch (e) {
139
160
  result = errorResponseFromError(e);
140
161
  }
162
+ } else if (method === 'takeHeapSnapshot') {
163
+ try {
164
+ let v8 = require('v8');
165
+ result = responseFromContent(
166
+ v8.writeHeapSnapshot(
167
+ 'heap-' +
168
+ args[0] +
169
+ '-' +
170
+ (this.childId ? 'worker' + this.childId : 'main') +
171
+ '.heapsnapshot',
172
+ ),
173
+ );
174
+ } catch (e) {
175
+ result = errorResponseFromError(e);
176
+ }
141
177
  } else if (method === 'createSharedReference') {
142
- let [ref, value] = args;
178
+ let [ref, _value] = args;
179
+ let value =
180
+ _value instanceof ArrayBuffer
181
+ ? // In the case the value is pre-serialized as a buffer,
182
+ // deserialize it.
183
+ deserialize(Buffer.from(_value))
184
+ : _value;
143
185
  this.sharedReferences.set(ref, value);
144
186
  this.sharedReferencesByValue.set(value, ref);
145
187
  result = responseFromContent(null);
146
188
  } else if (method === 'deleteSharedReference') {
147
- this.sharedReferences.delete(args[0]);
189
+ let ref = args[0];
190
+ let value = this.sharedReferences.get(ref);
191
+ this.sharedReferencesByValue.delete(value);
192
+ this.sharedReferences.delete(ref);
148
193
  result = responseFromContent(null);
149
194
  } else {
150
195
  try {
@@ -157,7 +202,11 @@ export class Child {
157
202
  }
158
203
  }
159
204
 
160
- this.send(result);
205
+ try {
206
+ this.send(result);
207
+ } catch (e) {
208
+ result = this.send(errorResponseFromError(e));
209
+ }
161
210
  }
162
211
 
163
212
  handleResponse(data: WorkerResponse): void {
@@ -189,6 +238,7 @@ export class Child {
189
238
  ...request,
190
239
  type: 'request',
191
240
  child: this.childId,
241
+ // $FlowFixMe Added in Flow 0.121.0 upgrade in #4381
192
242
  awaitResponse,
193
243
  resolve: () => {},
194
244
  reject: () => {},
@@ -241,10 +291,9 @@ export class Child {
241
291
  this.loggerDisposable.dispose();
242
292
  }
243
293
 
244
- createReverseHandle(fn: (...args: Array<any>) => mixed) {
294
+ createReverseHandle(fn: (...args: Array<any>) => mixed): Handle {
245
295
  let handle = new Handle({
246
296
  fn,
247
- workerApi: this.workerApi,
248
297
  childId: this.childId,
249
298
  });
250
299
  this.handles.set(handle.id, handle);
package/src/cpuCount.js CHANGED
@@ -26,6 +26,11 @@ export function detectRealCores(): number {
26
26
  );
27
27
  } else if (platform === 'darwin') {
28
28
  amount = parseInt(exec('sysctl -n hw.physicalcpu_max'), 10);
29
+ } else if (platform === 'win32') {
30
+ const str = exec('wmic cpu get NumberOfCores').match(/\d+/g);
31
+ if (str !== null) {
32
+ amount = parseInt(str.filter(n => n !== '')[0], 10);
33
+ }
29
34
  }
30
35
 
31
36
  if (!amount || amount <= 0) {
@@ -36,9 +41,8 @@ export function detectRealCores(): number {
36
41
  }
37
42
 
38
43
  let cores;
39
- export default function getCores(bypassCache?: boolean = false) {
44
+ export default function getCores(bypassCache?: boolean = false): number {
40
45
  // Do not re-run commands if we already have the count...
41
- // $FlowFixMe
42
46
  if (cores && !bypassCache) {
43
47
  return cores;
44
48
  }
@@ -49,8 +53,9 @@ export default function getCores(bypassCache?: boolean = false) {
49
53
  // Guess the amount of real cores
50
54
  cores = os
51
55
  .cpus()
52
- .filter((cpu, index) => !cpu.model.includes('Intel') || index % 2 === 1)
53
- .length;
56
+ .filter(
57
+ (cpu, index) => !cpu.model.includes('Intel') || index % 2 === 1,
58
+ ).length;
54
59
  }
55
60
 
56
61
  // Another fallback
package/src/index.js CHANGED
@@ -34,4 +34,4 @@ if (!WorkerFarm.isWorker()) {
34
34
  export default WorkerFarm;
35
35
  export {bus};
36
36
  export {Handle} from './WorkerFarm';
37
- export type {WorkerApi, FarmOptions} from './WorkerFarm';
37
+ export type {WorkerApi, FarmOptions, SharedReference} from './WorkerFarm';