Created
May 13, 2016 17:51
-
-
Save mvertes/a1c01b2a6e2ce9b2d08db801bb587299 to your computer and use it in GitHub Desktop.
co-process for ijavascript jupyter kernel
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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(); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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