From e7ec5a13ce42aeaf6dc3982e035ebf999752d469 Mon Sep 17 00:00:00 2001 From: Adam Powers Date: Sat, 5 Dec 2020 12:19:23 -0800 Subject: [PATCH 1/5] fix and enhance async transpiling --- lib/nel.js | 70 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 24 deletions(-) diff --git a/lib/nel.js b/lib/nel.js index 04ce867..b3c9f96 100755 --- a/lib/nel.js +++ b/lib/nel.js @@ -51,15 +51,41 @@ var doc = require("./mdn.js"); // Documentation for Javascript builtins var log = require("./log.js")("NEL:"); var server = require("./server/index.js"); // Server source code +// acts like 'new Promise(fn)', polyfilling if necessary +function newPromise(fn) { + if (global.Promise && typeof global.Promise === "function") { + // we have promises, use them + return new Promise(fn); + } else { + // create a dumb little synchronous thenable as a promise polyfill + // NOTE: this assumes that if you don't have built-in promises that your + // function isn't going to return a Promise or thenable + var fnRet, fnErr; + var chainable = { + then: function(thenFn) { + try { + fn(function resolve(v) { + fnRet = v; + }, function reject(e) { + fnErr = e; + }); + } catch (err) { + fnErr = err; + } + + if (!fnErr) thenFn(fnRet, fnErr); + + return chainable; + }, + catch: function(catchFn) { + if (fnErr) catchFn(fnErr); + } + }; -function isPromise(x) { - if (!global.Promise || typeof global.Promise !== "function") { - return false; + return chainable; } - return x instanceof global.Promise; } - // File paths var paths = { node: process.argv[0], @@ -816,27 +842,23 @@ Session.prototype._runNow = function(task) { }).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"); - if (isPromise(transpiledCode)) { - transpiledCode.then(function(value) { - task.code = value; - sendTask(); - }).catch(sendError); - return; - } else { + // run asynchronous transpiling using a polyfill if necessary + // for synchronous code this acts like Promise.resolve() + newPromise(function(resolve, reject) { + resolve(this.transpile(task.code)); + }) + .then(function(transpiledCode) { + log("SESSION: RUN: TRANSPILE:\n" + transpiledCode + "\n"); task.code = transpiledCode; - } - } catch (error) { - sendError(error); - return; - } + sendTask(); + }) + .catch(function(err) { + sendError(error); + }); + } else { + // no transpiling, just run task + sendTask(); } - - sendTask(); - return; }; /** From d275451fd95b7cd53854245e2e9f638cab8dc88a Mon Sep 17 00:00:00 2001 From: Adam Powers Date: Sat, 5 Dec 2020 12:40:00 -0800 Subject: [PATCH 2/5] fix promise polyfill bugs --- lib/nel.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/nel.js b/lib/nel.js index b3c9f96..b149f9c 100755 --- a/lib/nel.js +++ b/lib/nel.js @@ -51,12 +51,15 @@ var doc = require("./mdn.js"); // Documentation for Javascript builtins var log = require("./log.js")("NEL:"); var server = require("./server/index.js"); // Server source code +delete global.Promise; // acts like 'new Promise(fn)', polyfilling if necessary function newPromise(fn) { if (global.Promise && typeof global.Promise === "function") { + console.log("running with Promise"); // we have promises, use them - return new Promise(fn); + return new global.Promise(fn); } else { + console.log("running with polyfill"); // create a dumb little synchronous thenable as a promise polyfill // NOTE: this assumes that if you don't have built-in promises that your // function isn't going to return a Promise or thenable @@ -845,15 +848,17 @@ Session.prototype._runNow = function(task) { // run asynchronous transpiling using a polyfill if necessary // for synchronous code this acts like Promise.resolve() newPromise(function(resolve, reject) { + console.log("transpiling..."); resolve(this.transpile(task.code)); - }) + }.bind(this)) .then(function(transpiledCode) { + console.log("transpiled code", transpiledCode); log("SESSION: RUN: TRANSPILE:\n" + transpiledCode + "\n"); task.code = transpiledCode; sendTask(); }) .catch(function(err) { - sendError(error); + sendError(err); }); } else { // no transpiling, just run task From c205a6843b0f582bcf908403d897a24bfaf2a6bb Mon Sep 17 00:00:00 2001 From: Adam Powers Date: Sat, 5 Dec 2020 12:40:15 -0800 Subject: [PATCH 3/5] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 743aa4e..9545a33 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nel", - "version": "1.2.0", + "version": "1.2.1", "description": "Node.js Evaluation Loop (NEL): module to run a Node.js REPL session", "keywords": [ "javascript", From f2d11b877ac31074ddd14f925fcb254c2cd37c4e Mon Sep 17 00:00:00 2001 From: Adam Powers Date: Sat, 5 Dec 2020 12:45:52 -0800 Subject: [PATCH 4/5] don't delete global Promises --- lib/nel.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/nel.js b/lib/nel.js index b149f9c..ea3e8e9 100755 --- a/lib/nel.js +++ b/lib/nel.js @@ -51,7 +51,6 @@ var doc = require("./mdn.js"); // Documentation for Javascript builtins var log = require("./log.js")("NEL:"); var server = require("./server/index.js"); // Server source code -delete global.Promise; // acts like 'new Promise(fn)', polyfilling if necessary function newPromise(fn) { if (global.Promise && typeof global.Promise === "function") { From aa7c46ec339ac59662c9ec1bee34e20d4633d56d Mon Sep 17 00:00:00 2001 From: Adam Powers Date: Sat, 5 Dec 2020 12:47:23 -0800 Subject: [PATCH 5/5] remove stray debug messages --- lib/nel.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/nel.js b/lib/nel.js index ea3e8e9..2a7ab1e 100755 --- a/lib/nel.js +++ b/lib/nel.js @@ -54,11 +54,9 @@ var server = require("./server/index.js"); // Server source code // acts like 'new Promise(fn)', polyfilling if necessary function newPromise(fn) { if (global.Promise && typeof global.Promise === "function") { - console.log("running with Promise"); // we have promises, use them return new global.Promise(fn); } else { - console.log("running with polyfill"); // create a dumb little synchronous thenable as a promise polyfill // NOTE: this assumes that if you don't have built-in promises that your // function isn't going to return a Promise or thenable @@ -847,11 +845,9 @@ Session.prototype._runNow = function(task) { // run asynchronous transpiling using a polyfill if necessary // for synchronous code this acts like Promise.resolve() newPromise(function(resolve, reject) { - console.log("transpiling..."); resolve(this.transpile(task.code)); }.bind(this)) .then(function(transpiledCode) { - console.log("transpiled code", transpiledCode); log("SESSION: RUN: TRANSPILE:\n" + transpiledCode + "\n"); task.code = transpiledCode; sendTask();