diff --git a/lib/workers/child-browser.js b/lib/workers/child-browser.js index fe3e8e5e..aac029c1 100644 --- a/lib/workers/child-browser.js +++ b/lib/workers/child-browser.js @@ -16,16 +16,15 @@ const util = require('../utils/util'); * @constructor * @ignore * @param {String} file - * @param {Object} env */ -function Child(file, env) { +function Child(file) { if (!(this instanceof Child)) - return new Child(file, env); + return new Child(file); EventEmitter.call(this); - this.init(file, env); + this.init(file); } util.inherits(Child, EventEmitter); @@ -42,9 +41,10 @@ Child.hasSupport = function hasSupport() { /** * Initialize child process. Bind to events. * @private + * @param {String} file */ -Child.prototype.init = function init(file, env) { +Child.prototype.init = function init(file) { this.child = new global.Worker(file); this.child.onerror = (event) => { @@ -65,8 +65,6 @@ Child.prototype.init = function init(file, env) { } this.emit('data', data); }; - - this.child.postMessage(JSON.stringify(env)); }; /** diff --git a/lib/workers/child.js b/lib/workers/child.js index 55ca428e..67dcf9ba 100644 --- a/lib/workers/child.js +++ b/lib/workers/child.js @@ -19,19 +19,18 @@ let exitBound = false; * @alias module:workers.Child * @constructor * @param {String} file - * @param {Object} env */ -function Child(file, env) { +function Child(file) { if (!(this instanceof Child)) - return new Child(file, env); + return new Child(file); EventEmitter.call(this); bindExit(); children.add(this); - this.init(file, env); + this.init(file); } util.inherits(Child, EventEmitter); @@ -48,13 +47,13 @@ Child.hasSupport = function hasSupport() { /** * Initialize child process (node.js). * @private + * @param {String} file */ -Child.prototype.init = function init(file, env) { +Child.prototype.init = function init(file) { let bin = process.argv[0]; let filename = path.resolve(__dirname, file); - let environ = Object.assign({}, process.env, env); - let options = { stdio: 'pipe', env: environ }; + let options = { stdio: 'pipe', env: process.env }; this.child = cp.spawn(bin, [filename], options); diff --git a/lib/workers/master.js b/lib/workers/master.js index 1bc77155..a003f5f0 100644 --- a/lib/workers/master.js +++ b/lib/workers/master.js @@ -32,7 +32,6 @@ function Master() { this.parent = new Parent(); this.framer = new Framer(); this.parser = new Parser(); - this.env = {}; this.listening = false; this.color = false; @@ -69,6 +68,16 @@ Master.prototype.init = function init() { }); }; +/** + * Set environment. + * @param {Object} env + */ + +Master.prototype.setEnv = function setEnv(env) { + this.color = env.BCOIN_WORKER_ISTTY === '1'; + this.set(env.BCOIN_WORKER_NETWORK); +}; + /** * Set primary network. * @param {NetworkType|Network} network @@ -130,18 +139,12 @@ Master.prototype.log = function log(...items) { /** * Listen for messages from master process (only if worker). - * @param {Object} env - * @returns {Master} */ -Master.prototype.listen = function listen(env) { +Master.prototype.listen = function listen() { assert(!this.listening, 'Already listening.'); - this.env = env; this.listening = true; - this.color = +env.BCOIN_WORKER_ISTTY === 1; - - this.set(env.BCOIN_WORKER_NETWORK); util.log = this.log.bind(this); util.error = util.log; @@ -157,8 +160,6 @@ Master.prototype.listen = function listen(env) { this.emit('error', e); } }); - - return this; }; /** @@ -171,6 +172,9 @@ Master.prototype.handlePacket = function handlePacket(packet) { let result; switch (packet.cmd) { + case packets.types.ENV: + this.setEnv(packet.env); + break; case packets.types.EVENT: this.emit('event', packet.items); this.emit.apply(this, packet.items); diff --git a/lib/workers/packets.js b/lib/workers/packets.js index 1d801789..bbc65455 100644 --- a/lib/workers/packets.js +++ b/lib/workers/packets.js @@ -27,26 +27,27 @@ const CoinView = require('../coins/coinview'); */ const packetTypes = { - EVENT: 0, - LOG: 1, - ERROR: 2, - ERRORRESULT: 3, - VERIFY: 4, - VERIFYRESULT: 5, - SIGN: 6, - SIGNRESULT: 7, - VERIFYINPUT: 8, - VERIFYINPUTRESULT: 9, - SIGNINPUT: 10, - SIGNINPUTRESULT: 11, - ECVERIFY: 12, - ECVERIFYRESULT: 13, - ECSIGN: 14, - ECSIGNRESULT: 15, - MINE: 16, - MINERESULT: 17, - SCRYPT: 18, - SCRYPTRESULT: 19 + ENV: 0, + EVENT: 1, + LOG: 2, + ERROR: 3, + ERRORRESULT: 4, + VERIFY: 5, + VERIFYRESULT: 6, + SIGN: 7, + SIGNRESULT: 8, + VERIFYINPUT: 9, + VERIFYINPUTRESULT: 10, + SIGNINPUT: 11, + SIGNINPUTRESULT: 12, + ECVERIFY: 13, + ECVERIFYRESULT: 14, + ECSIGN: 15, + ECSIGNRESULT: 16, + MINE: 17, + MINERESULT: 18, + SCRYPT: 19, + SCRYPTRESULT: 20 }; /** @@ -66,6 +67,37 @@ Packet.prototype.toWriter = function toWriter() { throw new Error('Abstract method.'); }; +/** + * EnvPacket + * @constructor + */ + +function EnvPacket(env) { + Packet.call(this); + this.env = env || {}; + this.json = JSON.stringify(this.env); +} + +util.inherits(EnvPacket, Packet); + +EnvPacket.prototype.cmd = packetTypes.ENV; + +EnvPacket.prototype.getSize = function getSize() { + return encoding.sizeVarString(this.json, 'utf8'); +}; + +EnvPacket.prototype.toWriter = function toWriter(bw) { + bw.writeVarString(this.json, 'utf8'); +}; + +EnvPacket.fromRaw = function fromRaw(data) { + let br = new BufferReader(data, true); + let packet = new EnvPacket(); + packet.json = br.readVarString('utf8'); + packet.env = JSON.parse(packet.json); + return packet; +}; + /** * EventPacket * @constructor @@ -92,7 +124,8 @@ EventPacket.prototype.toWriter = function toWriter(bw) { EventPacket.fromRaw = function fromRaw(data) { let br = new BufferReader(data, true); let packet = new EventPacket(); - packet.items = JSON.parse(br.readVarString('utf8')); + packet.json = br.readVarString('utf8'); + packet.items = JSON.parse(packet.json); return packet; }; @@ -141,24 +174,68 @@ ErrorPacket.prototype.cmd = packetTypes.ERROR; ErrorPacket.prototype.getSize = function getSize() { let size = 0; + size += encoding.sizeVarString(this.error.message + '', 'utf8'); size += encoding.sizeVarString(this.error.stack + '', 'utf8'); - size += encoding.sizeVarString((this.error.type || ''), 'utf8'); + size += encoding.sizeVarString(this.error.type || '', 'utf8'); + + switch (typeof this.error.code) { + case 'number': + size += 1; + size += 4; + break; + case 'string': + size += 1; + size += encoding.sizeVarString(this.error.code, 'utf8'); + break; + default: + size += 1; + break; + } + return size; }; ErrorPacket.prototype.toWriter = function toWriter(bw) { bw.writeVarString(this.error.message + '', 'utf8'); bw.writeVarString(this.error.stack + '', 'utf8'); - bw.writeVarString((this.error.type || ''), 'utf8'); + bw.writeVarString(this.error.type || '', 'utf8'); + + switch (typeof this.error.code) { + case 'number': + bw.writeU8(2); + bw.write32(this.error.code); + break; + case 'string': + bw.writeU8(1); + bw.writeVarString(this.error.code, 'utf8'); + break; + default: + bw.writeU8(0); + break; + } }; ErrorPacket.fromRaw = function fromRaw(data) { let br = new BufferReader(data, true); let packet = new ErrorPacket(); + packet.error.message = br.readVarString('utf8'); packet.error.stack = br.readVarString('utf8'); packet.error.type = br.readVarString('utf8'); + + switch (br.readU8()) { + case 2: + packet.error.code = br.read32(); + break; + case 1: + packet.error.code = br.readVarString('utf8'); + break; + default: + packet.error.code = null; + break; + } + return packet; }; @@ -168,37 +245,13 @@ ErrorPacket.fromRaw = function fromRaw(data) { */ function ErrorResultPacket(error) { - Packet.call(this); - this.error = error || new Error(); + ErrorPacket.call(this, error); } -util.inherits(ErrorResultPacket, Packet); +util.inherits(ErrorResultPacket, ErrorPacket); ErrorResultPacket.prototype.cmd = packetTypes.ERRORRESULT; -ErrorResultPacket.prototype.getSize = function getSize() { - let size = 0; - size += encoding.sizeVarString(this.error.message + '', 'utf8'); - size += encoding.sizeVarString(this.error.stack + '', 'utf8'); - size += encoding.sizeVarString((this.error.type || ''), 'utf8'); - return size; -}; - -ErrorResultPacket.prototype.toWriter = function toWriter(bw) { - bw.writeVarString(this.error.message + '', 'utf8'); - bw.writeVarString(this.error.stack + '', 'utf8'); - bw.writeVarString((this.error.type || ''), 'utf8'); -}; - -ErrorResultPacket.fromRaw = function fromRaw(data) { - let br = new BufferReader(data, true); - let packet = new ErrorResultPacket(); - packet.error.message = br.readVarString('utf8'); - packet.error.stack = br.readVarString('utf8'); - packet.error.type = br.readVarString('utf8'); - return packet; -}; - /** * VerifyPacket * @constructor @@ -894,6 +947,7 @@ ScryptResultPacket.fromRaw = function fromRaw(data) { */ exports.types = packetTypes; +exports.EnvPacket = EnvPacket; exports.EventPacket = EventPacket; exports.LogPacket = LogPacket; exports.ErrorPacket = ErrorPacket; diff --git a/lib/workers/parser.js b/lib/workers/parser.js index fa844ae8..d3c74b09 100644 --- a/lib/workers/parser.js +++ b/lib/workers/parser.js @@ -133,6 +133,8 @@ Parser.prototype.parseHeader = function parseHeader(data) { Parser.prototype.parsePacket = function parsePacket(header, data) { switch (header.cmd) { + case packets.types.ENV: + return packets.EnvPacket.fromRaw(data); case packets.types.EVENT: return packets.EventPacket.fromRaw(data); case packets.types.LOG: diff --git a/lib/workers/worker-browser.js b/lib/workers/worker-browser.js deleted file mode 100644 index b53af601..00000000 --- a/lib/workers/worker-browser.js +++ /dev/null @@ -1,20 +0,0 @@ -/*! - * worker.js - worker thread/process for bcoin - * Copyright (c) 2014-2015, Fedor Indutny (MIT License) - * Copyright (c) 2014-2017, Christopher Jeffrey (MIT License). - * https://github.com/bcoin-org/bcoin - */ - -'use strict'; - -const Master = require('./master'); - -self.onmessage = function onmessage(event) { - let env, server; - - self.onmessage = function() {}; - - env = JSON.parse(event.data); - server = new Master(); - server.listen(env); -}; diff --git a/lib/workers/worker.js b/lib/workers/worker.js index bce8c991..92fdc33f 100644 --- a/lib/workers/worker.js +++ b/lib/workers/worker.js @@ -10,4 +10,4 @@ const Master = require('./master'); const server = new Master(); -server.listen(process.env); +server.listen(); diff --git a/lib/workers/workerpool.js b/lib/workers/workerpool.js index c702586d..942d67fc 100644 --- a/lib/workers/workerpool.js +++ b/lib/workers/workerpool.js @@ -364,12 +364,7 @@ function Worker(file) { this.parser = new Parser(); this.pending = new Map(); - this.child = new Child(file, { - BCOIN_WORKER_NETWORK: Network.type, - BCOIN_WORKER_ISTTY: process.stdout - ? (process.stdout.isTTY ? '1' : '0') - : '0' - }); + this.child = new Child(file); this.init(); } @@ -426,6 +421,13 @@ Worker.prototype.listen = function listen() { this.emit('error', e); } }); + + this.sendEnv({ + BCOIN_WORKER_NETWORK: Network.type, + BCOIN_WORKER_ISTTY: process.stdout + ? (process.stdout.isTTY ? '1' : '0') + : '0' + }); }; /** @@ -475,6 +477,16 @@ Worker.prototype.send = function send(packet) { return this.write(this.framer.packet(packet)); }; +/** + * Send environment. + * @param {Object} env + * @returns {Boolean} + */ + +Worker.prototype.sendEnv = function sendEnv(env) { + return this.send(new packets.EnvPacket(env)); +}; + /** * Emit an event on the worker side. * @param {String} event diff --git a/webpack.browser.js b/webpack.browser.js index 3229d794..d5bded28 100644 --- a/webpack.browser.js +++ b/webpack.browser.js @@ -10,7 +10,7 @@ module.exports = { target: 'web', entry: { 'bcoin': './lib/bcoin-browser', - 'bcoin-worker': './lib/workers/worker-browser' + 'bcoin-worker': './lib/workers/worker' }, output: { path: path.join(__dirname, 'browser'), diff --git a/webpack.compat.js b/webpack.compat.js index 424508c4..207aed8d 100644 --- a/webpack.compat.js +++ b/webpack.compat.js @@ -9,7 +9,7 @@ module.exports = { target: 'web', entry: { 'bcoin': './lib/bcoin-browser', - 'bcoin-worker': './lib/workers/worker-browser' + 'bcoin-worker': './lib/workers/worker' }, output: { path: path.join(__dirname, 'browser'),