Node.js comes up from time to time...and whether or not Rebol could run on something like a commodity Node.js server.
One of the selling points of Emscripten as a toolchain is that it can do the necessary things so WASM will run in Node. I hadn't tried it. But my impression was that if you had something working in the browser...it should be able to get working in Node also.
After Some Hours of Fiddling...
...I managed to get a test to work. I'm looking at the fundamental issues of what might be done to make it less ugly, but...here is Node calling into Rebol:
var express = require('express')
var app = express();
var reb = require('rebol')
reb.onRuntimeInitialized = function() {
reb.Startup()
app.get('/', function (req, res) {
let three = reb.Spell("to text! 1 + 2");
res.send('One plus Two is ' + three)
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
});
}
So it adds 1 and 2, turns the sum into a string, extracts that string as a JavaScript string, and serves you a page saying One plus Two is 3.
Okay that's something... BUT...
I think the more interesting story is Rebol-calling-JavaScript...as opposed to JavaScript-calling-Rebol. But Node kind of sits as the gatekeeper at a top level. I have a hard time seeing how to graft a Node program into an app.reb
that "occasionally asks Node to do things". But it seems a lot more clear with the browser.
There are some other points on why not to push on this too much right now:
-
Though Node.js has caught up with V8 features over time, Emscripten hasn't yet taken advantage of their workers or shared memory. That means that if you want rebPromise() and the other magic that makes libRebol cool, you'll have to use the emterpreter. The above program needs over 1.5mb of build products, well more than twice the size of a pure webassembly build...and as I've said, it's about 30x slower.
-
There's a way to package cross-platform native C code and build it as part of a node package--sidestepping webassembly and emscripten altogether. This would be the fastest option. It wouldn't be impossible to do, but it would be a lot of work on a new codebase that there aren't resources to allocate to. Waiting for emscripten to support WASM+pthreads on Node is probably a better bet, because it would mean being able to leverage common binding code with the browser--vs. a new project.
-
NPM modules deploy via GitHub. I don't see a turnkey way to get a static resource of a large webassembly file to go along with that installation, other than putting it in the GitHub repository itself. Strangely, if one ships native C code with a C++ binding to V8 (as described in the previous point), Node is set up to make that more turnkey. :-/
It is worth scoping out and understanding, though
It brings questions up, and they are good to think about:
-
Should we aim for modules and call like
reb.Spell()
instead ofrebSpell()
, even in the web version where we don't have to? (People talk about browsers getting a module model like Node's, so it would probably be forward-looking.) -
Should
var reb = require('rebol')
give you back an interpreter instance, or should that get an "engine", so you sayvar rebol = require('rebol')
,var reb = new rebol.Interpreter(...)
, and you could make several of these as independent? -
Should rebStartup() be a Promise, if we can't generically hide the WebAssembly load? Will users of libRebol be expected to put all of their code in a callback?
It's definitely forward-thinking to be working on answers to these questions. But I think we should be looking more to Rebol-based %httpd.reb and other things like that for the server side. Worth pointing out is that Node.js's creator has decided it's too flawed, and has gone off to promote another project...