child.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /**
  2. * Copyright (c) 2017-present, Facebook, Inc. All rights reserved.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. *
  7. *
  8. */
  9. 'use strict';
  10. var _types;
  11. function _load_types() {
  12. return (_types = require('./types'));
  13. }
  14. let file = null;
  15. /**
  16. * This file is a small bootstrapper for workers. It sets up the communication
  17. * between the worker and the parent process, interpreting parent messages and
  18. * sending results back.
  19. *
  20. * The file loaded will be lazily initialized the first time any of the workers
  21. * is called. This is done for optimal performance: if the farm is initialized,
  22. * but no call is made to it, child Node processes will be consuming the least
  23. * possible amount of memory.
  24. *
  25. * If an invalid message is detected, the child will exit (by throwing) with a
  26. * non-zero exit code.
  27. */
  28. process.on('message', (request /* Should be ChildMessage */) => {
  29. switch (request[0]) {
  30. case (_types || _load_types()).CHILD_MESSAGE_INITIALIZE:
  31. file = request[2];
  32. break;
  33. case (_types || _load_types()).CHILD_MESSAGE_CALL:
  34. execMethod(request[2], request[3]);
  35. break;
  36. case (_types || _load_types()).CHILD_MESSAGE_END:
  37. process.exit(0);
  38. break;
  39. default:
  40. throw new TypeError(
  41. 'Unexpected request from parent process: ' + request[0]
  42. );
  43. }
  44. });
  45. function reportSuccess(result) {
  46. if (!process || !process.send) {
  47. throw new Error('Child can only be used on a forked process');
  48. }
  49. process.send([(_types || _load_types()).PARENT_MESSAGE_OK, result]);
  50. }
  51. function reportError(error) {
  52. if (!process || !process.send) {
  53. throw new Error('Child can only be used on a forked process');
  54. }
  55. if (error == null) {
  56. error = new Error('"null" or "undefined" thrown');
  57. }
  58. process.send([
  59. (_types || _load_types()).PARENT_MESSAGE_ERROR,
  60. error.constructor && error.constructor.name,
  61. error.message,
  62. error.stack,
  63. // $FlowFixMe: this is safe to just inherit from Object.
  64. typeof error === 'object' ? Object.assign({}, error) : error
  65. ]);
  66. }
  67. function execMethod(method, args) {
  68. // $FlowFixMe: This has to be a dynamic require.
  69. const main = require(file);
  70. let result;
  71. try {
  72. if (method === 'default') {
  73. result = (main.__esModule ? main['default'] : main).apply(global, args);
  74. } else {
  75. result = main[method].apply(main, args);
  76. }
  77. } catch (err) {
  78. reportError(err);
  79. return;
  80. }
  81. if (result && typeof result.then === 'function') {
  82. result.then(reportSuccess, reportError);
  83. } else {
  84. reportSuccess(result);
  85. }
  86. }