| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 | 
							- 'use strict';
 
- var _fs = require('fs');
 
- var _fs2 = _interopRequireDefault(_fs);
 
- var _module = require('module');
 
- var _module2 = _interopRequireDefault(_module);
 
- var _loaderRunner = require('loader-runner');
 
- var _loaderRunner2 = _interopRequireDefault(_loaderRunner);
 
- var _queue = require('neo-async/queue');
 
- var _queue2 = _interopRequireDefault(_queue);
 
- var _readBuffer = require('./readBuffer');
 
- var _readBuffer2 = _interopRequireDefault(_readBuffer);
 
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
- const writePipe = _fs2.default.createWriteStream(null, { fd: 3 }); /* global require */
 
- /* eslint-disable no-console */
 
- const readPipe = _fs2.default.createReadStream(null, { fd: 4 });
 
- writePipe.on('finish', onTerminateWrite);
 
- readPipe.on('end', onTerminateRead);
 
- writePipe.on('close', onTerminateWrite);
 
- readPipe.on('close', onTerminateRead);
 
- readPipe.on('error', onError);
 
- writePipe.on('error', onError);
 
- const PARALLEL_JOBS = +process.argv[2] || 20;
 
- let terminated = false;
 
- let nextQuestionId = 0;
 
- const callbackMap = Object.create(null);
 
- function onError(error) {
 
-   console.error(error);
 
- }
 
- function onTerminateRead() {
 
-   terminateRead();
 
- }
 
- function onTerminateWrite() {
 
-   terminateWrite();
 
- }
 
- function writePipeWrite(...args) {
 
-   if (!terminated) {
 
-     writePipe.write(...args);
 
-   }
 
- }
 
- function writePipeCork() {
 
-   if (!terminated) {
 
-     writePipe.cork();
 
-   }
 
- }
 
- function writePipeUncork() {
 
-   if (!terminated) {
 
-     writePipe.uncork();
 
-   }
 
- }
 
- function terminateRead() {
 
-   terminated = true;
 
-   readPipe.removeAllListeners();
 
- }
 
- function terminateWrite() {
 
-   terminated = true;
 
-   writePipe.removeAllListeners();
 
- }
 
- function terminate() {
 
-   terminateRead();
 
-   terminateWrite();
 
- }
 
- function toErrorObj(err) {
 
-   return {
 
-     message: err.message,
 
-     details: err.details,
 
-     stack: err.stack,
 
-     hideStack: err.hideStack
 
-   };
 
- }
 
- function toNativeError(obj) {
 
-   if (!obj) return null;
 
-   const err = new Error(obj.message);
 
-   err.details = obj.details;
 
-   err.missing = obj.missing;
 
-   return err;
 
- }
 
- function writeJson(data) {
 
-   writePipeCork();
 
-   process.nextTick(() => {
 
-     writePipeUncork();
 
-   });
 
-   const lengthBuffer = Buffer.alloc(4);
 
-   const messageBuffer = Buffer.from(JSON.stringify(data), 'utf-8');
 
-   lengthBuffer.writeInt32BE(messageBuffer.length, 0);
 
-   writePipeWrite(lengthBuffer);
 
-   writePipeWrite(messageBuffer);
 
- }
 
- const queue = (0, _queue2.default)(({ id, data }, taskCallback) => {
 
-   try {
 
-     _loaderRunner2.default.runLoaders({
 
-       loaders: data.loaders,
 
-       resource: data.resource,
 
-       readResource: _fs2.default.readFile.bind(_fs2.default),
 
-       context: {
 
-         version: 2,
 
-         resolve: (context, request, callback) => {
 
-           callbackMap[nextQuestionId] = callback;
 
-           writeJson({
 
-             type: 'resolve',
 
-             id,
 
-             questionId: nextQuestionId,
 
-             context,
 
-             request
 
-           });
 
-           nextQuestionId += 1;
 
-         },
 
-         emitWarning: warning => {
 
-           writeJson({
 
-             type: 'emitWarning',
 
-             id,
 
-             data: toErrorObj(warning)
 
-           });
 
-         },
 
-         emitError: error => {
 
-           writeJson({
 
-             type: 'emitError',
 
-             id,
 
-             data: toErrorObj(error)
 
-           });
 
-         },
 
-         exec: (code, filename) => {
 
-           const module = new _module2.default(filename, undefined);
 
-           module.paths = _module2.default._nodeModulePaths(undefined.context); // eslint-disable-line no-underscore-dangle
 
-           module.filename = filename;
 
-           module._compile(code, filename); // eslint-disable-line no-underscore-dangle
 
-           return module.exports;
 
-         },
 
-         options: {
 
-           context: data.optionsContext
 
-         },
 
-         webpack: true,
 
-         'thread-loader': true,
 
-         sourceMap: data.sourceMap,
 
-         target: data.target,
 
-         minimize: data.minimize,
 
-         resourceQuery: data.resourceQuery
 
-       }
 
-     }, (err, lrResult) => {
 
-       const {
 
-         result,
 
-         cacheable,
 
-         fileDependencies,
 
-         contextDependencies
 
-       } = lrResult;
 
-       const buffersToSend = [];
 
-       const convertedResult = Array.isArray(result) && result.map(item => {
 
-         const isBuffer = Buffer.isBuffer(item);
 
-         if (isBuffer) {
 
-           buffersToSend.push(item);
 
-           return {
 
-             buffer: true
 
-           };
 
-         }
 
-         if (typeof item === 'string') {
 
-           const stringBuffer = Buffer.from(item, 'utf-8');
 
-           buffersToSend.push(stringBuffer);
 
-           return {
 
-             buffer: true,
 
-             string: true
 
-           };
 
-         }
 
-         return {
 
-           data: item
 
-         };
 
-       });
 
-       writeJson({
 
-         type: 'job',
 
-         id,
 
-         error: err && toErrorObj(err),
 
-         result: {
 
-           result: convertedResult,
 
-           cacheable,
 
-           fileDependencies,
 
-           contextDependencies
 
-         },
 
-         data: buffersToSend.map(buffer => buffer.length)
 
-       });
 
-       buffersToSend.forEach(buffer => {
 
-         writePipeWrite(buffer);
 
-       });
 
-       setImmediate(taskCallback);
 
-     });
 
-   } catch (e) {
 
-     writeJson({
 
-       type: 'job',
 
-       id,
 
-       error: toErrorObj(e)
 
-     });
 
-     taskCallback();
 
-   }
 
- }, PARALLEL_JOBS);
 
- function dispose() {
 
-   terminate();
 
-   queue.kill();
 
-   process.exit(0);
 
- }
 
- function onMessage(message) {
 
-   try {
 
-     const { type, id } = message;
 
-     switch (type) {
 
-       case 'job':
 
-         {
 
-           queue.push(message);
 
-           break;
 
-         }
 
-       case 'result':
 
-         {
 
-           const { error, result } = message;
 
-           const callback = callbackMap[id];
 
-           if (callback) {
 
-             const nativeError = toNativeError(error);
 
-             callback(nativeError, result);
 
-           } else {
 
-             console.error(`Worker got unexpected result id ${id}`);
 
-           }
 
-           delete callbackMap[id];
 
-           break;
 
-         }
 
-       case 'warmup':
 
-         {
 
-           const { requires } = message;
 
-           // load modules into process
 
-           requires.forEach(r => require(r)); // eslint-disable-line import/no-dynamic-require, global-require
 
-           break;
 
-         }
 
-       default:
 
-         {
 
-           console.error(`Worker got unexpected job type ${type}`);
 
-           break;
 
-         }
 
-     }
 
-   } catch (e) {
 
-     console.error(`Error in worker ${e}`);
 
-   }
 
- }
 
- function readNextMessage() {
 
-   (0, _readBuffer2.default)(readPipe, 4, (lengthReadError, lengthBuffer) => {
 
-     if (lengthReadError) {
 
-       console.error(`Failed to communicate with main process (read length) ${lengthReadError}`);
 
-       return;
 
-     }
 
-     const length = lengthBuffer.length && lengthBuffer.readInt32BE(0);
 
-     if (length === 0) {
 
-       // worker should dispose and exit
 
-       dispose();
 
-       return;
 
-     }
 
-     (0, _readBuffer2.default)(readPipe, length, (messageError, messageBuffer) => {
 
-       if (terminated) {
 
-         return;
 
-       }
 
-       if (messageError) {
 
-         console.error(`Failed to communicate with main process (read message) ${messageError}`);
 
-         return;
 
-       }
 
-       const messageString = messageBuffer.toString('utf-8');
 
-       const message = JSON.parse(messageString);
 
-       onMessage(message);
 
-       setImmediate(() => readNextMessage());
 
-     });
 
-   });
 
- }
 
- // start reading messages from main process
 
- readNextMessage();
 
 
  |