embark/lib/core/modules/coderunner/codeRunner.js

107 lines
2.8 KiB
JavaScript
Raw Normal View History

2018-08-27 15:12:28 +00:00
const RunCode = require('./runCode.js');
2018-09-17 08:57:51 +00:00
const Utils = require('../../../utils/utils');
2018-08-28 10:47:40 +00:00
2018-05-21 21:22:19 +00:00
class CodeRunner {
constructor(options) {
2018-08-28 13:43:52 +00:00
this.config = options.config;
2018-05-21 21:22:19 +00:00
this.plugins = options.plugins;
this.logger = options.logger;
this.events = options.events;
2018-08-08 12:42:45 +00:00
this.ipc = options.ipc;
this.commands = [];
2018-09-10 08:26:37 +00:00
this.runCode = new RunCode({logger: this.logger});
2018-08-29 09:49:53 +00:00
this.registerIpcEvents();
this.IpcClientListen();
this.registerEvents();
this.registerCommands();
}
2018-05-23 15:16:56 +00:00
2018-08-29 09:49:53 +00:00
registerIpcEvents() {
if (!this.ipc.isServer()) {
return;
2018-08-08 12:42:45 +00:00
}
2018-08-29 09:49:53 +00:00
this.ipc.on('runcode:getCommands', (_err, callback) => {
let result = {web3Config: this.runCode.getWeb3Config(), commands: this.commands};
callback(null, result);
});
}
2018-08-28 11:16:36 +00:00
2018-08-29 09:49:53 +00:00
IpcClientListen() {
if (!this.ipc.isClient() || !this.ipc.connected) {
return;
2018-08-08 12:42:45 +00:00
}
2018-08-29 09:49:53 +00:00
this.ipc.listenTo('runcode:newCommand', (command) => {
if (command.varName) {
this.events.emit("runcode:register", command.varName, command.code);
} else {
this.events.request("runcode:eval", command.code);
2018-08-08 12:42:45 +00:00
}
2018-08-24 13:05:19 +00:00
});
2018-08-29 09:49:53 +00:00
}
registerEvents() {
this.events.on("runcode:register", this.registerVar.bind(this));
}
2018-08-24 13:05:19 +00:00
2018-08-29 09:49:53 +00:00
registerCommands() {
2018-08-24 13:05:19 +00:00
this.events.setCommandHandler('runcode:getContext', (cb) => {
2018-08-29 09:49:53 +00:00
cb(this.runCode.context);
2018-05-23 15:16:56 +00:00
});
2018-08-29 09:49:53 +00:00
this.events.setCommandHandler('runcode:eval', this.evalCode.bind(this));
}
2018-05-21 21:22:19 +00:00
2018-08-29 10:03:06 +00:00
registerVar(varName, code, toRecord = true) {
if (this.ipc.isServer() && toRecord) {
2018-08-29 09:49:53 +00:00
this.commands.push({varName, code});
this.ipc.broadcast("runcode:newCommand", {varName, code});
}
this.runCode.registerVar(varName, code);
}
2018-09-17 08:57:51 +00:00
async evalCode(code, cb, forConsoleOnly = false) {
2018-08-30 09:41:13 +00:00
cb = cb || function() {};
2018-08-29 09:49:53 +00:00
const awaitIdx = code.indexOf('await');
2018-09-17 08:57:51 +00:00
let awaiting = false;
2018-08-29 09:49:53 +00:00
if (awaitIdx > -1) {
2018-09-17 08:57:51 +00:00
awaiting = true;
const instructions = Utils.compact(code.split(';'));
const last = instructions.pop();
if (!last.trim().startsWith('return')) {
instructions.push(`return ${last}`);
2018-08-29 09:49:53 +00:00
} else {
2018-09-17 08:57:51 +00:00
instructions.push(last);
2018-08-22 15:32:15 +00:00
}
2018-09-17 08:57:51 +00:00
code = `(async function() {${instructions.join(';')}})();`;
2018-08-29 09:49:53 +00:00
}
let result = this.runCode.doEval(code);
2018-08-24 13:05:19 +00:00
2018-08-29 09:49:53 +00:00
if (forConsoleOnly && this.ipc.isServer()) {
this.commands.push({code});
this.ipc.broadcast("runcode:newCommand", {code});
}
2018-08-24 13:05:19 +00:00
2018-09-17 08:57:51 +00:00
if (!awaiting) {
return cb(null, result);
2018-08-29 09:49:53 +00:00
}
2018-08-24 13:05:19 +00:00
2018-09-17 08:57:51 +00:00
try {
const value = await result;
cb(null, value);
} catch (error) {
// Improve error message when there's no connection to node
if (error.message.indexOf('Invalid JSON RPC response') !== -1) {
error.message += '. Are you connected to an Ethereum node?';
}
2018-09-17 08:57:51 +00:00
cb(error);
}
2018-05-21 21:22:19 +00:00
}
}
module.exports = CodeRunner;