Skip to content

Commit

Permalink
nel: Server#transpile can return a Promise
Browse files Browse the repository at this point in the history
* To allow asynchronous transpilation, Server#transpile now accepts
  functions that return a Promise.

Closes #12
  • Loading branch information
n-riesco committed Nov 29, 2020
1 parent 1809539 commit c11c89e
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 13 deletions.
51 changes: 38 additions & 13 deletions lib/nel.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ var log = require("./log.js")("NEL:");
var server = require("./server/index.js"); // Server source code


function isPromise(x) {
if (!global.Promise || typeof global.Promise !== "function") {
return false;
}
return x instanceof global.Promise;
}


// File paths
var paths = {
node: process.argv[0],
Expand Down Expand Up @@ -81,7 +89,7 @@ var paths = {
*
* @type {function}
* @param {string} code Request code
* @returns {string} Transpiled code
* @returns {(string|Promise<string>)} Transpiled code
*
* @see {@link module:nel~Config}
*/
Expand Down Expand Up @@ -790,28 +798,45 @@ Session.prototype._runNow = function(task) {
task.beforeRun();
}

var sendTask = (function sendTask() {
this._server.send([task.action, task.code, id]);
}).bind(this);

var sendError = (function sendError(error) {
this._onMessage({
error: {
ename: (error && error.name) ?
error.name : typeof error,
evalue: (error && error.message) ?
error.message : util.inspect(error),
traceback: (error && error.stack) ?
error.stack.split("\n") : "",
},
});
}).bind(this);

if (this.transpile && task.action === "run") {
try {
// Adapted from https://github.com/n-riesco/nel/issues/1 by kebot
var transpiledCode = this.transpile(task.code);
log("SESSION: RUN: TRANSPILE:\n" + transpiledCode + "\n");
task.code = transpiledCode;
if (isPromise(transpiledCode)) {
transpiledCode.then(function(value) {
task.code = value;
sendTask();
}).catch(sendError);
return;
} else {
task.code = transpiledCode;
}
} catch (error) {
this._onMessage({
error: {
ename: (error && error.name) ?
error.name : typeof error,
evalue: (error && error.message) ?
error.message : util.inspect(error),
traceback: (error && error.stack) ?
error.stack.split("\n") : "",
},
});
sendError(error);
return;
}
}

this._server.send([task.action, task.code, id]);
sendTask();
return;
};

/**
Expand Down
100 changes: 100 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
*
*/

/* global Promise */

var fs = require("fs");
var nel = require("../index.js");
var path = require("path");
Expand Down Expand Up @@ -145,6 +147,104 @@ describe("NEL:", function() {
waitForSession(session, done);
});

it("Session#transpile can transpile execute requests", function(done) {
var originalTranspile = session.transpile;

var expected = inspect("the output of the transpiled code");
session.transpile = function() {
return expected;
};

session.execute("", {
onSuccess: function(result) {
expect(result.mime["text/plain"]).toDeepEqual(expected,
"Unexpected execution result");
session.transpile = originalTranspile;
done();
},
onError: done.fail,
});
});

it("Session#transpile thrown errors are handled", function(done) {
var originalTranspile = session.transpile;

var expectedError = new Error("expected error");
session.transpile = function() {
throw expectedError;
};

session.execute("", {
onSuccess: function(result) {
done.fail("transpile didn't throw an error");
},
onError: function(result) {
expect(result.error.ename).toEqual(expectedError.name,
"Unexpected error name");
expect(result.error.evalue).toEqual(expectedError.message,
"Unexpected error value");
done();
},
afterRun: function(error) {
session.transpile = originalTranspile;
},
});
});

global.Promise &&
it("Session#transpile can return a Promise", function(done) {
var originalTranspile = session.transpile;

var expected = inspect("the output of the transpiled code");
session.transpile = function() {
return new Promise(function(resolve) {
setImmediate(function() {
resolve(expected);
});
});
};

session.execute("", {
onSuccess: function(result) {
expect(result.mime["text/plain"]).toDeepEqual(expected,
"Unexpected execution result");
session.transpile = originalTranspile;
done();
},
onError: done.fail,
});
});

global.Promise &&
it("Session#transpile can handle a rejected Promise", function(done) {
var originalTranspile = session.transpile;

var expectedError = new Error("expected error");
session.transpile = function() {
return new Promise(function(resolve, reject) {
setImmediate(function() {
reject(expectedError);
});
});
};

session.execute("", {
onSuccess: function(result) {
done.fail("transpile didn't throw an error");
},
onError: function(result) {
expect(result.error.ename).toEqual(expectedError.name,
"Unexpected error name");
expect(result.error.evalue).toEqual(expectedError.message,
"Unexpected error value");
done();
},
afterRun: function(error) {
session.transpile = originalTranspile;
},
});
});

it("Session#restart can restart a session", function(done) {
var expectedSignal = (process.version.indexOf("v0.10.") === 0) ?
null : "SIGTERM";
Expand Down

0 comments on commit c11c89e

Please sign in to comment.