@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.
- package/index.d.ts +23 -0
- package/lib/Handle.js +16 -58
- package/lib/Worker.js +103 -62
- package/lib/WorkerFarm.js +272 -192
- package/lib/backend.js +4 -6
- package/lib/bus.js +11 -13
- package/lib/child.js +140 -116
- package/lib/childState.js +2 -4
- package/lib/core-worker.browser.js +4 -0
- package/lib/core-worker.js +4 -0
- package/lib/cpuCount.js +36 -25
- package/lib/index.js +35 -32
- package/lib/process/ProcessChild.js +18 -24
- package/lib/process/ProcessWorker.js +27 -38
- package/lib/threads/ThreadsChild.js +26 -28
- package/lib/threads/ThreadsWorker.js +25 -31
- package/lib/web/WebChild.js +44 -0
- package/lib/web/WebWorker.js +85 -0
- package/package.json +19 -8
- package/src/Handle.js +10 -39
- package/src/Worker.js +95 -22
- package/src/WorkerFarm.js +267 -62
- package/src/backend.js +5 -0
- package/src/bus.js +3 -2
- package/src/child.js +95 -26
- package/src/core-worker.browser.js +3 -0
- package/src/core-worker.js +2 -0
- package/src/cpuCount.js +23 -10
- package/src/index.js +8 -2
- package/src/process/ProcessChild.js +2 -1
- package/src/process/ProcessWorker.js +1 -1
- package/src/threads/ThreadsWorker.js +2 -2
- package/src/types.js +1 -1
- package/src/web/WebChild.js +50 -0
- package/src/web/WebWorker.js +85 -0
- package/test/cpuCount.test.js +1 -1
- package/test/integration/workerfarm/console.js +1 -1
- package/test/integration/workerfarm/logging.js +1 -1
- package/test/integration/workerfarm/reverse-handle.js +2 -2
- package/test/workerfarm.js +5 -5
- package/lib/Profiler.js +0 -70
- package/lib/Trace.js +0 -126
- package/src/Profiler.js +0 -93
- 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
|
11
|
+
fn?: HandleFunction,
|
16
12
|
childId?: ?number,
|
17
|
-
|
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:
|
48
|
-
return
|
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 {
|
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
|
-
|
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 =
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
) {
|
55
|
-
filteredArgs
|
56
|
-
|
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
|
-
|
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
|
-
|
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 {
|