Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

repl-promise

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

repl-promise - npm Package Compare versions

Comparing version 0.0.4 to 0.0.5

lib/LineReader.js

421

lib/index.js

@@ -5,9 +5,12 @@ // repl-promise/lib/index.js

var _ = require('lodash');
var chalk = require('chalk');
var Q = require('q');
var chalk = require('chalk');
var util = require('util');
var vm = require('vm');
var _ = require('lodash');
var dlog = require('debug')('repl-promise');
var LineReader = require('./LineReader.js');
var plog = require('debug')('repl-promise');
// If the error is that we've unexpectedly ended the input,

@@ -17,4 +20,4 @@ // then let the user try to recover by adding more input.

return e &&
e.name === 'SyntaxError' &&
/^(Unexpected end of input|Unexpected token :)/.test(e.message);
e.name === 'SyntaxError' &&
/^(Unexpected end of input|Unexpected token :)/.test(e.message);
}

@@ -27,75 +30,10 @@

function LineReader(inputStream, endOfInput) {
if (!(this instanceof LineReader)) {
return new LineReader(inputStream);
}
function ReplServer() {
if (!(this instanceof ReplServer)) {
return new ReplServer();
}
var self = this;
var self = this;
self.inputStream = inputStream;
self.remaining = '';
self.lines = [];
self.pendingDeferred = null;
self.done = false;
self.isDone = function() {
return self.done && self.lines.length===0;
};
self.fullfill = function() {
var line = self.lines.shift();
if (line)
line = line + '\n';
self.pendingDeferred.resolve(line);
var result = self.pendingDeferred.promise;
self.pendingDeferred = null;
return result;
};
self.readLine = function() {
if (self.pendingDeferred !== null) {
throw new Error('LineReader.readLine called before pendingDeferred fulfilled');
}
self.pendingDeferred = Q.defer();
if (self.isDone()) {
endOfInput.resolve(null);
return self.fullfill();
}
if (self.lines.length > 0) {
return self.fullfill();
}
return self.pendingDeferred.promise;
};
process.on('SIGINT', function() {
self.remaining = '';
self.lines = [''];
if (self.pendingDeferred !== null) {
self.fullfill();
}
});
inputStream.on('data', function(chunk) {
self.remaining = self.remaining + chunk.toString();
var newLines = self.remaining.split('\n');
self.lines = self.lines.concat(_.initial(newLines));
self.remaining = _.last(newLines);
if (self.pendingDeferred!==null && self.lines.length>0) {
self.fullfill();
}
});
inputStream.on('end', function() {
self.done = true;
});
}
function identityTransformResult(result) {
return new Q(result);
}
function start(options, _initialContext) {
self.init = function(options, _initialContext) {
options = options || {};

@@ -105,11 +43,17 @@ options.input = options.input || process.stdin;

options.prompt = options.prompt || '> ';
options.transformResult = options.transformResult || identityTransformResult;
options.writer = options.writer || _writer;
var echoInputToOutput = !options.output.isTTY || !options.input.isTTY;
function _writer(obj) {
return util.inspect(obj, {depth: null, colors: options.output.isTTY });
}
self.echoInputToOutput = !options.output.isTTY || !options.input.isTTY;
self.options = options;
var initialContext = {
require: require,
console: console,
process: process,
Q: Q,
require: require,
console: console,
process: process,
Q: Q,
};

@@ -121,190 +65,187 @@

var sandbox = vm.createContext(initialContext);
var bufferedInput = '';
var nullScript = vm.createScript('null;', {filename: 'null.vm', displayErrors: false});
self.bufferedInput = '';
self.context = vm.createContext(initialContext);
self.endOfSessionPromise = self.newSession();
function promiseOutput(line) {
if (line === '')
dlog('promiseOutput: Empty line');
return self;
};
var deferred = Q.defer();
self.promiseOutput = function(line) {
if (line === '')
plog('promiseOutput: Empty line');
// This may seem like a case where we could use Q.nbind or deferred.makeNodeResolver(),
// but output.write uses a callback that only takes an err argument, and we need
// to call deferred.resolve(line), i.e. with line as an argument.
options.output.write(line, "utf8", function(err) {
if (err) {
deferred.reject(err);
}
else {
deferred.resolve(line);
}
});
var deferred = Q.defer();
return deferred.promise;
}
// This may seem like a case where we could use Q.nbind or deferred.makeNodeResolver(),
// but output.write uses a callback that only takes an err argument, and we need
// to call deferred.resolve(line), i.e. with line as an argument.
self.options.output.write(line, "utf8", function(err) {
if (err) {
deferred.reject(err);
}
else {
deferred.resolve(line);
}
});
function promptForInput() {
var prompt = options.prompt;
if (bufferedInput !== '')
prompt = '... ';
if (options.output.isTTY)
prompt = chalk.bold.blue(prompt);
return promiseOutput(prompt);
}
return deferred.promise;
};
function compileAndExecuteScript(text) {
var executeScriptDeferred = Q.defer();
self.promptForInput = function() {
var prompt = self.options.prompt;
if (self.bufferedInput !== '')
prompt = '... ';
if (self.options.output.isTTY)
prompt = chalk.bold.blue(prompt);
return self.promiseOutput(prompt);
};
var isBufferingInput = bufferedInput !== '';
if (bufferedInput !== '') {
text = bufferedInput + text;
bufferedInput = '';
dlog('buffered input:', bufferedInput.length);
}
self.compileAndExecuteScript = function(text) {
if (text===null && self.lineReader.isDone())
return new Q(null);
// var (symbol) = (expression)
var scopeVar = /^\s*var\s*([_\w\$]+)\s*=\s*(.*)$/m;
var matches = scopeVar.exec(text);
var isScopedVar = !isBufferingInput && matches!==null && matches.length===3;
dlog('Is scoped var:', isScopedVar);
var executeScriptDeferred = Q.defer();
var symbol;
if (isScopedVar) {
symbol = matches[1];
text = matches[2]; // change text that will be compiled & executed!
dlog('var assignment', symbol, text);
}
var isBufferingInput = self.bufferedInput !== '';
if (self.bufferedInput !== '') {
text = self.bufferedInput + text;
self.bufferedInput = '';
plog('buffered input:', self.bufferedInput.length);
}
var script;
try {
script = vm.createScript(text, {filename: 'repl.vm', displayErrors: false});
dlog('text successfully compiled');
// (var) (symbol) = (expression)
var assignmentExpr = /^(\s*|var\s+)([_\w\$]+)\s*=\s*(.*)$/m;
var matches = assignmentExpr.exec(text);
var isScopedVar = matches!==null;
// var isScopedVar = !isBufferingInput && matches!==null && matches.length===3;
plog('Is scoped var:', isScopedVar);
var result;
try {
result = script.runInNewContext(sandbox);
dlog('text successfully executed');
if (!isScopedVar) {
dlog('simple expression result resolved');
executeScriptDeferred.resolve(result);
}
else {
if (!Q.isPromise(result)) {
dlog('simple expression assignment resolved');
sandbox[symbol] = result;
executeScriptDeferred.resolve(undefined);
}
else {
dlog('promise expression assignment deferred');
result.then(function (resolvedResult) {
dlog('promise expression assignment resolved');
sandbox[symbol] = resolvedResult;
executeScriptDeferred.resolve(undefined);
});
}
}
}
catch (err) {
dlog('script execution failed');
console.error(chalk.bold.red(err));
executeScriptDeferred.resolve(null);
return executeScriptDeferred.promise;
}
}
catch (e) {
var err;
if (isRecoverableError(e)) {
dlog('recoverable error in compilation');
if (isScopedVar) {
text = util.format('var %s = %s', symbol, text);
}
bufferedInput = text;
executeScriptDeferred.resolve(undefined);
}
else {
dlog('nonrecoverable error in compilation');
err = e;
executeScriptDeferred.reject(err);
}
}
return executeScriptDeferred.promise;
var symbol;
if (isScopedVar) {
symbol = matches[2];
text = matches[3]; // change text that will be compiled & executed!
plog('var assignment', symbol, text);
}
function printResult(result) {
if (result === null || result === undefined) {
return new Q(result);
var script;
try {
script = vm.createScript(text, {filename: 'repl.vm', displayErrors: false});
plog('text successfully compiled');
var result;
try {
result = script.runInNewContext(self.context);
plog('text successfully executed');
if (!isScopedVar) {
plog('simple expression result resolved');
executeScriptDeferred.resolve(result);
}
else {
var resultAsString = util.inspect(result, {depth: null, colors: options.output.isTTY });
return promiseOutput(resultAsString + '\n');
if (!Q.isPromise(result)) {
plog('simple expression assignment resolved');
self.context[symbol] = result;
if (matches[1].trim() === 'var')
result = undefined;
executeScriptDeferred.resolve(result);
}
else {
plog('promise expression assignment deferred');
result.then(function (resolvedResult) {
plog('promise expression assignment resolved');
self.context[symbol] = resolvedResult;
if (matches[1].trim() === 'var')
resolvedResult = undefined;
executeScriptDeferred.resolve(resolvedResult);
});
}
}
}
catch (err) {
plog('script execution failed');
console.error(chalk.bold.red(err));
executeScriptDeferred.resolve(null);
return executeScriptDeferred.promise;
}
}
function onEchoInput(line) {
if (line === '')
line = '\n';
if (!echoInputToOutput)
return new Q(line);
return promiseOutput(line);
catch (e) {
var err;
if (isRecoverableError(e)) {
plog('recoverable error in compilation');
if (isScopedVar) {
text = util.format('var %s = %s', symbol, text);
}
self.bufferedInput = text;
executeScriptDeferred.resolve(undefined);
}
else {
plog('nonrecoverable error in compilation');
err = e;
executeScriptDeferred.reject(err);
}
}
function newSession() {
var replSessionDeferred = Q.defer();
return executeScriptDeferred.promise;
};
var lineReader = new LineReader(options.input, replSessionDeferred);
self.printResult = function(result) {
if (result===null && self.lineReader.isDone())
return new Q(null);
function onScriptInput() {
if (lineReader.isDone()) {
if (options.output != process.stdout) {
options.output.end();
}
return;
}
if (result === null || result === undefined) {
return new Q(result);
}
else {
var resultAsString = self.options.writer(result);
return self.promiseOutput(resultAsString + '\n');
}
};
promptForInput()
.then(lineReader.readLine)
.then(onEchoInput)
.then(compileAndExecuteScript)
.then(options.transformResult)
.then(printResult)
.catch(function(err) { console.error(chalk.bold.red(err)); })
.done(onScriptInput);
}
self.onEchoInput = function(line) {
if (line===null && self.lineReader.isDone())
return new Q(null);
if (!_.isString(line))
throw new Error('LineReader.readLine return null!');
if (line === '')
line = '\n';
if (!self.echoInputToOutput)
return new Q(line);
return self.promiseOutput(line);
};
function sigintHandler() {
options.output.write('\n');
if (bufferedInput === '') {
process.exit();
}
else {
bufferedInput = '';
}
}
self.newSession = function() {
var replSessionDeferred = Q.defer();
process.on('SIGINT', sigintHandler);
var lineReader = self.lineReader = new LineReader(self.options.input);
options.input.on('end', function() {
process.removeListener('SIGINT', sigintHandler);
replSessionDeferred.resolve("end-of-input");
});
options.input.on('error', function(err) {
process.removeListener('SIGINT', sigintHandler);
replSessionDeferred.reject(err);
});
function onScriptInput() {
if (lineReader.isDone()) {
if (self.options.output != process.stdout) {
plog('lineReader is done, closing output');
self.options.output.end();
}
replSessionDeferred.resolve(null);
return;
}
onScriptInput();
return replSessionDeferred.promise;
self.promptForInput()
.then(lineReader.readLine)
.then(self.onEchoInput)
.then(self.compileAndExecuteScript)
.then(self.printResult)
.catch(function(err) { console.error(chalk.bold.red(err)); })
.delay(1)
.done(onScriptInput);
}
var replServer = {
context: sandbox,
endOfSessionPromise: newSession()
};
onScriptInput();
return replServer;
return replSessionDeferred.promise;
};
}
module.exports = { start: start };
module.exports = {
start: function(options, _initialContext) {
var replServer = new ReplServer();
return replServer.init(options, _initialContext);
}
};
{
"name": "repl-promise",
"version": "0.0.4",
"version": "0.0.5",
"description": "An alternative REPL implementation using Promises.",

@@ -5,0 +5,0 @@ "bin": {

@@ -23,7 +23,6 @@ // # Transcript-test.js

prompt: 'node > ',
input: fs.createReadStream('test/data/'+name+'.txt'),
input: 'test/data/'+name+'.txt',
output: output,
};
var initialContext = { timers: require('timers') };

@@ -30,0 +29,0 @@ var replServer = repl.start(options, initialContext);

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc