Spaces:
Build error
Build error
| ; | |
| var _types = require('../types'); | |
| /** | |
| * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. | |
| * | |
| * This source code is licensed under the MIT license found in the | |
| * LICENSE file in the root directory of this source tree. | |
| */ | |
| let file = null; | |
| let setupArgs = []; | |
| let initialized = false; | |
| /** | |
| * This file is a small bootstrapper for workers. It sets up the communication | |
| * between the worker and the parent process, interpreting parent messages and | |
| * sending results back. | |
| * | |
| * The file loaded will be lazily initialized the first time any of the workers | |
| * is called. This is done for optimal performance: if the farm is initialized, | |
| * but no call is made to it, child Node processes will be consuming the least | |
| * possible amount of memory. | |
| * | |
| * If an invalid message is detected, the child will exit (by throwing) with a | |
| * non-zero exit code. | |
| */ | |
| const messageListener = request => { | |
| switch (request[0]) { | |
| case _types.CHILD_MESSAGE_INITIALIZE: | |
| const init = request; | |
| file = init[2]; | |
| setupArgs = request[3]; | |
| break; | |
| case _types.CHILD_MESSAGE_CALL: | |
| const call = request; | |
| execMethod(call[2], call[3]); | |
| break; | |
| case _types.CHILD_MESSAGE_END: | |
| end(); | |
| break; | |
| default: | |
| throw new TypeError( | |
| 'Unexpected request from parent process: ' + request[0] | |
| ); | |
| } | |
| }; | |
| process.on('message', messageListener); | |
| function reportSuccess(result) { | |
| if (!process || !process.send) { | |
| throw new Error('Child can only be used on a forked process'); | |
| } | |
| process.send([_types.PARENT_MESSAGE_OK, result]); | |
| } | |
| function reportClientError(error) { | |
| return reportError(error, _types.PARENT_MESSAGE_CLIENT_ERROR); | |
| } | |
| function reportInitializeError(error) { | |
| return reportError(error, _types.PARENT_MESSAGE_SETUP_ERROR); | |
| } | |
| function reportError(error, type) { | |
| if (!process || !process.send) { | |
| throw new Error('Child can only be used on a forked process'); | |
| } | |
| if (error == null) { | |
| error = new Error('"null" or "undefined" thrown'); | |
| } | |
| process.send([ | |
| type, | |
| error.constructor && error.constructor.name, | |
| error.message, | |
| error.stack, | |
| typeof error === 'object' ? {...error} : error | |
| ]); | |
| } | |
| function end() { | |
| const main = require(file); | |
| if (!main.teardown) { | |
| exitProcess(); | |
| return; | |
| } | |
| execFunction(main.teardown, main, [], exitProcess, exitProcess); | |
| } | |
| function exitProcess() { | |
| // Clean up open handles so the process ideally exits gracefully | |
| process.removeListener('message', messageListener); | |
| } | |
| function execMethod(method, args) { | |
| const main = require(file); | |
| let fn; | |
| if (method === 'default') { | |
| fn = main.__esModule ? main['default'] : main; | |
| } else { | |
| fn = main[method]; | |
| } | |
| function execHelper() { | |
| execFunction(fn, main, args, reportSuccess, reportClientError); | |
| } | |
| if (initialized || !main.setup) { | |
| execHelper(); | |
| return; | |
| } | |
| initialized = true; | |
| execFunction(main.setup, main, setupArgs, execHelper, reportInitializeError); | |
| } | |
| const isPromise = obj => | |
| !!obj && | |
| (typeof obj === 'object' || typeof obj === 'function') && | |
| typeof obj.then === 'function'; | |
| function execFunction(fn, ctx, args, onResult, onError) { | |
| let result; | |
| try { | |
| result = fn.apply(ctx, args); | |
| } catch (err) { | |
| onError(err); | |
| return; | |
| } | |
| if (isPromise(result)) { | |
| result.then(onResult, onError); | |
| } else { | |
| onResult(result); | |
| } | |
| } | |