diff --git a/doc/api/cli.md b/doc/api/cli.md index 34b2c7aff6adcc..e5ec77de04d9b0 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -10,7 +10,7 @@ To view this documentation as a manual page in your terminal, run `man node`. ## Synopsis -`node [options] [v8 options] [script.js | -e "script"] [arguments]` +`node [options] [v8 options] [script.js | -e "script"] [--] [arguments]` `node debug [script.js | -e "script" | :] …` @@ -251,6 +251,15 @@ added: v0.11.15 Specify ICU data load path. (overrides `NODE_ICU_DATA`) +### `--` + + +Indicate the end of node options. Pass the rest of the arguments to the script. +If no script filename or eval/print script is supplied prior to this, then +the next argument will be used as a script filename. + ## Environment Variables ### `NODE_DEBUG=module[,…]` diff --git a/doc/node.1 b/doc/node.1 index ec41a44c7598c3..7b39ef05ce9dc7 100644 --- a/doc/node.1 +++ b/doc/node.1 @@ -37,6 +37,7 @@ node \- Server-side JavaScript runtime .RI [ script.js \ | .B -e .RI \&" script \&"] +.B [--] .RI [ arguments ] .br .B node debug @@ -175,6 +176,13 @@ used to enable FIPS-compliant crypto if Node.js is built with .BR \-\-icu\-data\-dir =\fIfile\fR Specify ICU data load path. (overrides \fBNODE_ICU_DATA\fR) +.TP +.BR \-\-\fR +Indicate the end of node options. Pass the rest of the arguments to the script. + +If no script filename or eval/print script is supplied prior to this, then +the next argument will be used as a script filename. + .SH ENVIRONMENT VARIABLES .TP diff --git a/src/node.cc b/src/node.cc index 4ecfc0489c94ee..a8bf7bd2f5331c 100644 --- a/src/node.cc +++ b/src/node.cc @@ -3853,6 +3853,9 @@ static void ParseArgs(int* argc, } else if (strcmp(arg, "--expose-internals") == 0 || strcmp(arg, "--expose_internals") == 0) { // consumed in js + } else if (strcmp(arg, "--") == 0) { + index += 1; + break; } else { // V8 option. Pass through as-is. new_v8_argv[new_v8_argc] = arg; diff --git a/test/parallel/test-cli-eval.js b/test/parallel/test-cli-eval.js index 0198a0f1beda48..2dcb56ed4ae232 100644 --- a/test/parallel/test-cli-eval.js +++ b/test/parallel/test-cli-eval.js @@ -11,6 +11,10 @@ const child = require('child_process'); const path = require('path'); const nodejs = '"' + process.execPath + '"'; +if (process.argv.length > 2) { + console.log(process.argv.slice(2).join(' ')); + process.exit(0); +} // replace \ by / because windows uses backslashes in paths, but they're still // interpreted as the escape character when put between quotes. @@ -113,3 +117,38 @@ child.exec(nodejs + ` -e 'require("child_process").fork("${emptyFile}")'`, assert.strictEqual(proc.stderr, ''); assert.strictEqual(proc.stdout, 'start\nbeforeExit\nexit\n'); } + +[ '-arg1', + '-arg1 arg2 --arg3', + '--', + 'arg1 -- arg2', +].forEach(function(args) { + + // Ensure that arguments are successfully passed to eval. + const opt = ' --eval "console.log(process.argv.slice(1).join(\' \'))"'; + const cmd = `${nodejs}${opt} -- ${args}`; + child.exec(cmd, common.mustCall(function(err, stdout, stderr) { + assert.strictEqual(stdout, args + '\n'); + assert.strictEqual(stderr, ''); + assert.strictEqual(err, null); + })); + + // Ensure that arguments are successfully passed to print. + const popt = ' --print "process.argv.slice(1).join(\' \')"'; + const pcmd = `${nodejs}${popt} -- ${args}`; + child.exec(pcmd, common.mustCall(function(err, stdout, stderr) { + assert.strictEqual(stdout, args + '\n'); + assert.strictEqual(stderr, ''); + assert.strictEqual(err, null); + })); + + // Ensure that arguments are successfully passed to a script. + // The first argument after '--' should be interpreted as a script + // filename. + const filecmd = `${nodejs} -- ${__filename} ${args}`; + child.exec(filecmd, common.mustCall(function(err, stdout, stderr) { + assert.strictEqual(stdout, args + '\n'); + assert.strictEqual(stderr, ''); + assert.strictEqual(err, null); + })); +});