110 lines
2.8 KiB
JavaScript
110 lines
2.8 KiB
JavaScript
const RunCode = require('./runCode.js');
|
|
const Utils = require('../../../utils/utils');
|
|
|
|
const WEB3_INVALID_RESPONSE_ERROR = 'Invalid JSON RPC response';
|
|
|
|
class CodeRunner {
|
|
constructor(options) {
|
|
this.config = options.config;
|
|
this.plugins = options.plugins;
|
|
this.logger = options.logger;
|
|
this.events = options.events;
|
|
this.ipc = options.ipc;
|
|
this.commands = [];
|
|
this.runCode = new RunCode({logger: this.logger});
|
|
this.registerIpcEvents();
|
|
this.IpcClientListen();
|
|
this.registerEvents();
|
|
this.registerCommands();
|
|
}
|
|
|
|
registerIpcEvents() {
|
|
if (!this.ipc.isServer()) {
|
|
return;
|
|
}
|
|
|
|
this.ipc.on('runcode:getCommands', (_err, callback) => {
|
|
let result = {web3Config: this.runCode.getWeb3Config(), commands: this.commands};
|
|
callback(null, result);
|
|
});
|
|
}
|
|
|
|
IpcClientListen() {
|
|
if (!this.ipc.isClient() || !this.ipc.connected) {
|
|
return;
|
|
}
|
|
|
|
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);
|
|
}
|
|
});
|
|
}
|
|
|
|
registerEvents() {
|
|
this.events.on("runcode:register", this.registerVar.bind(this));
|
|
}
|
|
|
|
registerCommands() {
|
|
this.events.setCommandHandler('runcode:getContext', (cb) => {
|
|
cb(this.runCode.context);
|
|
});
|
|
this.events.setCommandHandler('runcode:eval', this.evalCode.bind(this));
|
|
}
|
|
|
|
registerVar(varName, code, toRecord = true) {
|
|
if (this.ipc.isServer() && toRecord) {
|
|
this.commands.push({varName, code});
|
|
this.ipc.broadcast("runcode:newCommand", {varName, code});
|
|
}
|
|
this.runCode.registerVar(varName, code);
|
|
}
|
|
|
|
async evalCode(code, cb, forConsoleOnly = false) {
|
|
cb = cb || function() {};
|
|
const awaitIdx = code.indexOf('await');
|
|
let awaiting = false;
|
|
|
|
if (awaitIdx > -1) {
|
|
awaiting = true;
|
|
const instructions = Utils.compact(code.split(';'));
|
|
const last = instructions.pop();
|
|
|
|
if (!last.trim().startsWith('return')) {
|
|
instructions.push(`return ${last}`);
|
|
} else {
|
|
instructions.push(last);
|
|
}
|
|
|
|
code = `(async function() {${instructions.join(';')}})();`;
|
|
}
|
|
let result = this.runCode.doEval(code);
|
|
|
|
if (forConsoleOnly && this.ipc.isServer()) {
|
|
this.commands.push({code});
|
|
this.ipc.broadcast("runcode:newCommand", {code});
|
|
}
|
|
|
|
if (!awaiting) {
|
|
return cb(null, result);
|
|
}
|
|
|
|
try {
|
|
const value = await result;
|
|
cb(null, value);
|
|
} catch (error) {
|
|
// Improve error message when there's no connection to node
|
|
if (error.message.indexOf(WEB3_INVALID_RESPONSE_ERROR) !== -1) {
|
|
error.message += '. Are you connected to an Ethereum node?';
|
|
}
|
|
|
|
cb(error);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
module.exports = CodeRunner;
|