Skip to content

Instantly share code, notes, and snippets.

@mvertes
Created May 13, 2016 17:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mvertes/a1c01b2a6e2ce9b2d08db801bb587299 to your computer and use it in GitHub Desktop.
Save mvertes/a1c01b2a6e2ce9b2d08db801bb587299 to your computer and use it in GitHub Desktop.
co-process for ijavascript jupyter kernel
#!/usr/bin/env node
const vm = require('vm');
const done = function (result) {
process.send({mime: {"text/plain": "undefined"}});
}
// initialize VM context
vm.runInThisContext('(function (_require, _done) {require = _require; co = require("co"); $$done$$ = _done; })')(require, done);
// On parent socket, we receive code to execute, we send a result at completion
// Asynchronous callback must use the $$done$$ function, or yield/await can be used.
process.on('message', msg => {
var ret;
// If yield statement is found, encapsulate code in a co section.
// Variables initialized with a yield are forced global to be reused between cells.
// FIXME: other global vars in the original code should be also forced globals.
// They are not detected for now. Parsing code (see esprima) is required.
if (msg.code.match(/\W*yield\s+/)) {
msg.code = 'co(function *() {' +
msg.code.replace(/\s*var\s*(\w+)\s*=\s*yield\s/g, (match, p1) => ';' + p1 + '=yield ') +
';$$done$$();}).catch(err => null);';
}
if (msg.code) ret = vm.runInThisContext(msg.code);
if (!msg.code.match(/\$\$done\$\$/)) done();
});
var child_process = require('child_process');
var vm = require('vm');
function logToFile(value) {
require('fs').appendFileSync('/tmp/log', JSON.stringify(value, null, 4) + '\n\n')
}
function SkaleREPL() {
var queue = this.queue = [];
var self = this;
this.busy = false;
var child = this.child = child_process.spawn(process.argv[0], [__dirname + '/sandbox.js'], {
stdio: ['ignore', 'pipe', 'pipe', 'ipc' ]
});
child.stdout.setEncoding('utf8');
child.stdout.on('data', function (data) {
queue[0].jcbk.onStdout(data);
});
child.stderr.setEncoding('utf8');
child.stderr.on('data', function (data) {
queue[0].jcbk.onStderr(data);
});
child.on('message', function (result) {
var jcbk = queue[0].jcbk;
jcbk.onSuccess(result);
jcbk.afterRun();
queue.shift();
if (queue.length) {
queue[0].jcbk.beforeRun();
child.send({code: queue[0].code});
} else self.busy = false;
});
}
SkaleREPL.prototype.execute = function(code, jcbk) {
this.queue.push({code: code, jcbk: jcbk}); // Push new execution request inside queue
if (this.busy) return; // kernel currently running
this.busy = true;
jcbk.beforeRun();
this.child.send({code});
}
module.exports = {SkaleREPL: SkaleREPL};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment