295 lines
9.2 KiB
JavaScript
295 lines
9.2 KiB
JavaScript
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.Child = void 0;
|
|
var coreWorker = _interopRequireWildcard(require("./core-worker"));
|
|
function _assert() {
|
|
const data = _interopRequireDefault(require("assert"));
|
|
_assert = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _nullthrows() {
|
|
const data = _interopRequireDefault(require("nullthrows"));
|
|
_nullthrows = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _logger() {
|
|
const data = _interopRequireWildcard(require("@parcel/logger"));
|
|
_logger = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _diagnostic() {
|
|
const data = _interopRequireWildcard(require("@parcel/diagnostic"));
|
|
_diagnostic = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _core() {
|
|
const data = require("@parcel/core");
|
|
_core = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
var _bus = _interopRequireDefault(require("./bus"));
|
|
function _profiler() {
|
|
const data = require("@parcel/profiler");
|
|
_profiler = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
var _Handle2 = _interopRequireDefault(require("./Handle"));
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
// The import of './Handle' should really be imported eagerly (with @babel/plugin-transform-modules-commonjs's lazy mode).
|
|
const Handle = _Handle2.default;
|
|
class Child {
|
|
callQueue = [];
|
|
maxConcurrentCalls = 10;
|
|
responseId = 0;
|
|
responseQueue = new Map();
|
|
handles = new Map();
|
|
sharedReferences = new Map();
|
|
sharedReferencesByValue = new Map();
|
|
constructor(ChildBackend) {
|
|
this.child = new ChildBackend(m => {
|
|
this.messageListener(m);
|
|
}, () => this.handleEnd());
|
|
|
|
// Monitior all logging events inside this child process and forward to
|
|
// the main process via the bus.
|
|
this.loggerDisposable = _logger().default.onLog(event => {
|
|
_bus.default.emit('logEvent', event);
|
|
});
|
|
// .. and do the same for trace events
|
|
this.tracerDisposable = _profiler().tracer.onTrace(event => {
|
|
_bus.default.emit('traceEvent', event);
|
|
});
|
|
}
|
|
workerApi = {
|
|
callMaster: (request, awaitResponse = true) => this.addCall(request, awaitResponse),
|
|
createReverseHandle: fn => this.createReverseHandle(fn),
|
|
runHandle: (handle, args) => this.workerApi.callMaster({
|
|
handle: handle.id,
|
|
args
|
|
}, true),
|
|
getSharedReference: ref => this.sharedReferences.get(ref),
|
|
resolveSharedReference: value => this.sharedReferencesByValue.get(value)
|
|
};
|
|
messageListener(message) {
|
|
if (message.type === 'response') {
|
|
return this.handleResponse(message);
|
|
} else if (message.type === 'request') {
|
|
return this.handleRequest(message);
|
|
}
|
|
}
|
|
send(data) {
|
|
this.child.send(data);
|
|
}
|
|
async childInit(module, childId) {
|
|
// $FlowFixMe
|
|
if (process.browser) {
|
|
if (module === '@parcel/core/src/worker.js') {
|
|
this.module = coreWorker;
|
|
} else {
|
|
throw new Error('No dynamic require possible: ' + module);
|
|
}
|
|
} else {
|
|
// $FlowFixMe this must be dynamic
|
|
this.module = require(module);
|
|
}
|
|
this.childId = childId;
|
|
if (this.module.childInit != null) {
|
|
await this.module.childInit();
|
|
}
|
|
}
|
|
async handleRequest(data) {
|
|
let {
|
|
idx,
|
|
method,
|
|
args,
|
|
handle: handleId
|
|
} = data;
|
|
let child = (0, _nullthrows().default)(data.child);
|
|
const responseFromContent = content => ({
|
|
idx,
|
|
child,
|
|
type: 'response',
|
|
contentType: 'data',
|
|
content
|
|
});
|
|
const errorResponseFromError = e => ({
|
|
idx,
|
|
child,
|
|
type: 'response',
|
|
contentType: 'error',
|
|
content: (0, _diagnostic().anyToDiagnostic)(e)
|
|
});
|
|
let result;
|
|
if (handleId != null) {
|
|
try {
|
|
var _this$handles$get;
|
|
let fn = (0, _nullthrows().default)((_this$handles$get = this.handles.get(handleId)) === null || _this$handles$get === void 0 ? void 0 : _this$handles$get.fn);
|
|
result = responseFromContent(fn(...args));
|
|
} catch (e) {
|
|
result = errorResponseFromError(e);
|
|
}
|
|
} else if (method === 'childInit') {
|
|
try {
|
|
let [moduleName, childOptions] = args;
|
|
if (childOptions.shouldPatchConsole) {
|
|
(0, _logger().patchConsole)();
|
|
} else {
|
|
(0, _logger().unpatchConsole)();
|
|
}
|
|
if (childOptions.shouldTrace) {
|
|
_profiler().tracer.enable();
|
|
}
|
|
result = responseFromContent(await this.childInit(moduleName, child));
|
|
} catch (e) {
|
|
result = errorResponseFromError(e);
|
|
}
|
|
} else if (method === 'startProfile') {
|
|
this.profiler = new (_profiler().SamplingProfiler)();
|
|
try {
|
|
result = responseFromContent(await this.profiler.startProfiling());
|
|
} catch (e) {
|
|
result = errorResponseFromError(e);
|
|
}
|
|
} else if (method === 'endProfile') {
|
|
try {
|
|
let res = this.profiler ? await this.profiler.stopProfiling() : null;
|
|
result = responseFromContent(res);
|
|
} catch (e) {
|
|
result = errorResponseFromError(e);
|
|
}
|
|
} else if (method === 'takeHeapSnapshot') {
|
|
try {
|
|
let v8 = require('v8');
|
|
result = responseFromContent(v8.writeHeapSnapshot('heap-' + args[0] + '-' + (this.childId ? 'worker' + this.childId : 'main') + '.heapsnapshot'));
|
|
} catch (e) {
|
|
result = errorResponseFromError(e);
|
|
}
|
|
} else if (method === 'createSharedReference') {
|
|
let [ref, _value] = args;
|
|
let value = _value instanceof ArrayBuffer ?
|
|
// In the case the value is pre-serialized as a buffer,
|
|
// deserialize it.
|
|
(0, _core().deserialize)(Buffer.from(_value)) : _value;
|
|
this.sharedReferences.set(ref, value);
|
|
this.sharedReferencesByValue.set(value, ref);
|
|
result = responseFromContent(null);
|
|
} else if (method === 'deleteSharedReference') {
|
|
let ref = args[0];
|
|
let value = this.sharedReferences.get(ref);
|
|
this.sharedReferencesByValue.delete(value);
|
|
this.sharedReferences.delete(ref);
|
|
result = responseFromContent(null);
|
|
} else {
|
|
try {
|
|
result = responseFromContent(
|
|
// $FlowFixMe
|
|
await this.module[method](this.workerApi, ...args));
|
|
} catch (e) {
|
|
result = errorResponseFromError(e);
|
|
}
|
|
}
|
|
try {
|
|
this.send(result);
|
|
} catch (e) {
|
|
result = this.send(errorResponseFromError(e));
|
|
}
|
|
}
|
|
handleResponse(data) {
|
|
let idx = (0, _nullthrows().default)(data.idx);
|
|
let contentType = data.contentType;
|
|
let content = data.content;
|
|
let call = (0, _nullthrows().default)(this.responseQueue.get(idx));
|
|
if (contentType === 'error') {
|
|
(0, _assert().default)(typeof content !== 'string');
|
|
call.reject(new (_diagnostic().default)({
|
|
diagnostic: content
|
|
}));
|
|
} else {
|
|
call.resolve(content);
|
|
}
|
|
this.responseQueue.delete(idx);
|
|
|
|
// Process the next call
|
|
this.processQueue();
|
|
}
|
|
|
|
// Keep in mind to make sure responses to these calls are JSON.Stringify safe
|
|
addCall(request, awaitResponse = true) {
|
|
var _promise;
|
|
// $FlowFixMe
|
|
let call = {
|
|
...request,
|
|
type: 'request',
|
|
child: this.childId,
|
|
// $FlowFixMe Added in Flow 0.121.0 upgrade in #4381
|
|
awaitResponse,
|
|
resolve: () => {},
|
|
reject: () => {}
|
|
};
|
|
let promise;
|
|
if (awaitResponse) {
|
|
promise = new Promise((resolve, reject) => {
|
|
call.resolve = resolve;
|
|
call.reject = reject;
|
|
});
|
|
}
|
|
this.callQueue.push(call);
|
|
this.processQueue();
|
|
return (_promise = promise) !== null && _promise !== void 0 ? _promise : Promise.resolve();
|
|
}
|
|
sendRequest(call) {
|
|
let idx;
|
|
if (call.awaitResponse) {
|
|
idx = this.responseId++;
|
|
this.responseQueue.set(idx, call);
|
|
}
|
|
this.send({
|
|
idx,
|
|
child: call.child,
|
|
type: call.type,
|
|
location: call.location,
|
|
handle: call.handle,
|
|
method: call.method,
|
|
args: call.args,
|
|
awaitResponse: call.awaitResponse
|
|
});
|
|
}
|
|
processQueue() {
|
|
if (!this.callQueue.length) {
|
|
return;
|
|
}
|
|
if (this.responseQueue.size < this.maxConcurrentCalls) {
|
|
this.sendRequest(this.callQueue.shift());
|
|
}
|
|
}
|
|
handleEnd() {
|
|
this.loggerDisposable.dispose();
|
|
this.tracerDisposable.dispose();
|
|
}
|
|
createReverseHandle(fn) {
|
|
let handle = new Handle({
|
|
fn,
|
|
childId: this.childId
|
|
});
|
|
this.handles.set(handle.id, handle);
|
|
return handle;
|
|
}
|
|
}
|
|
exports.Child = Child; |