diff --git a/src/node.cc b/src/node.cc index 901cc7770b..7e0d19bcd5 100644 --- a/src/node.cc +++ b/src/node.cc @@ -111,6 +111,7 @@ static Persistent emit_symbol; static bool print_eval = false; +static bool force_repl = false; static char *eval_string = NULL; static int option_end_index = 0; static bool use_debug_agent = false; @@ -2155,6 +2156,10 @@ Handle SetupProcessObject(int argc, char *argv[]) { process->Set(String::NewSymbol("_print_eval"), Boolean::New(print_eval)); } + if (force_repl) { + process->Set(String::NewSymbol("_forceRepl"), True()); + } + size_t size = 2*PATH_MAX; char* execPath = new char[size]; if (uv_exepath(execPath, &size) != 0) { @@ -2299,6 +2304,8 @@ static void PrintHelp() { " -v, --version print node's version\n" " -e, --eval script evaluate script\n" " -p, --print print result of --eval\n" + " -i, --interactive always enter the REPL even if stdin\n" + " does not appear to be a terminal\n" " --v8-options print v8 command line options\n" " --vars print various compiled-in variables\n" " --max-stack-size=val set max v8 stack size (bytes)\n" @@ -2360,6 +2367,9 @@ static void ParseArgs(int argc, char **argv) { } else if (strcmp(arg, "--print") == 0 || strcmp(arg, "-p") == 0) { print_eval = true; argv[i] = const_cast(""); + } else if (strcmp(arg, "--interactive") == 0 || strcmp(arg, "-i") == 0) { + force_repl = true; + argv[i] = const_cast(""); } else if (strcmp(arg, "--v8-options") == 0) { argv[i] = const_cast("--help"); } else if (argv[i][0] != '-') { diff --git a/src/node.js b/src/node.js index d0cbc40422..e09465178a 100644 --- a/src/node.js +++ b/src/node.js @@ -118,8 +118,8 @@ } else { var Module = NativeModule.require('module'); - // If stdin is a TTY. - if (NativeModule.require('tty').isatty(0)) { + // If -i or --interactive were passed, or stdin is a TTY. + if (process._forceRepl || NativeModule.require('tty').isatty(0)) { // REPL var repl = Module.requireRepl().start('> ', null, null, true); repl.on('exit', function() { diff --git a/test/simple/test-force-repl.js b/test/simple/test-force-repl.js new file mode 100644 index 0000000000..60ba3485bb --- /dev/null +++ b/test/simple/test-force-repl.js @@ -0,0 +1,44 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var common = require('../common'); +var assert = require('assert'); +var spawn = require('child_process').spawn; + +// spawn a node child process in "interactive" mode (force the repl) +var cp = spawn(process.execPath, ['-i']); +var gotToEnd = false; +var timeoutId = setTimeout(function() { + throw new Error('timeout!'); +}, 1000); // give node + the repl 1 second to boot up + +cp.stdout.setEncoding('utf8'); + +cp.stdout.once('data', function(b) { + clearTimeout(timeoutId); + assert.equal(b, '> '); + gotToEnd = true; + cp.kill(); +}); + +process.on('exit', function() { + assert(gotToEnd); +});