Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 5 additions & 10 deletions lib/internal/util/parse_args/parse_args.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

const {
ArrayPrototypeForEach,
ArrayPrototypeIncludes,
ArrayPrototypeMap,
ArrayPrototypePush,
ArrayPrototypePushApply,
Expand Down Expand Up @@ -54,20 +53,16 @@ const {
kEmptyObject,
} = require('internal/util');

const { getOptionValue } = require('internal/options');

function getMainArgs() {
// Work out where to slice process.argv for user supplied arguments.

// Check node options for scenarios where user CLI args follow executable.
const execArgv = process.execArgv;
if (ArrayPrototypeIncludes(execArgv, '-e') ||
ArrayPrototypeIncludes(execArgv, '--eval') ||
ArrayPrototypeIncludes(execArgv, '-p') ||
ArrayPrototypeIncludes(execArgv, '--print')) {
// -p / --print internally sets --eval, so this works for all cases
const evalValue = getOptionValue('--eval');

if (evalValue.length !== 0) {
return ArrayPrototypeSlice(process.argv, 1);
}

// Normally first two arguments are executable and script, then CLI arguments
return ArrayPrototypeSlice(process.argv, 2);
}

Expand Down
107 changes: 36 additions & 71 deletions test/parallel/test-parse-args.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import '../common/index.mjs';
import { spawnPromisified } from '../common/index.mjs';
import assert from 'node:assert';
import { test } from 'node:test';
import { suite, test } from 'node:test';
import { parseArgs } from 'node:util';

test('when short option used as flag then stored as flag', () => {
Expand Down Expand Up @@ -211,73 +211,41 @@ test('order of option and positional does not matter (per README)', () => {
);
});

test('correct default args when use node -p', () => {
const holdArgv = process.argv;
process.argv = [process.argv0, '--foo'];
const holdExecArgv = process.execArgv;
process.execArgv = ['-p', '0'];
const result = parseArgs({ strict: false });

const expected = { values: { __proto__: null, foo: true },
positionals: [] };
assert.deepStrictEqual(result, expected);
process.argv = holdArgv;
process.execArgv = holdExecArgv;
});

test('correct default args when use node --print', () => {
const holdArgv = process.argv;
process.argv = [process.argv0, '--foo'];
const holdExecArgv = process.execArgv;
process.execArgv = ['--print', '0'];
const result = parseArgs({ strict: false });

const expected = { values: { __proto__: null, foo: true },
positionals: [] };
assert.deepStrictEqual(result, expected);
process.argv = holdArgv;
process.execArgv = holdExecArgv;
});

test('correct default args when use node -e', () => {
const holdArgv = process.argv;
process.argv = [process.argv0, '--foo'];
const holdExecArgv = process.execArgv;
process.execArgv = ['-e', '0'];
const result = parseArgs({ strict: false });

const expected = { values: { __proto__: null, foo: true },
positionals: [] };
assert.deepStrictEqual(result, expected);
process.argv = holdArgv;
process.execArgv = holdExecArgv;
});

test('correct default args when use node --eval', () => {
const holdArgv = process.argv;
process.argv = [process.argv0, '--foo'];
const holdExecArgv = process.execArgv;
process.execArgv = ['--eval', '0'];
const result = parseArgs({ strict: false });
const expected = { values: { __proto__: null, foo: true },
positionals: [] };
assert.deepStrictEqual(result, expected);
process.argv = holdArgv;
process.execArgv = holdExecArgv;
});

test('correct default args when normal arguments', () => {
const holdArgv = process.argv;
process.argv = [process.argv0, 'script.js', '--foo'];
const holdExecArgv = process.execArgv;
process.execArgv = [];
const result = parseArgs({ strict: false });
suite('correct default args', () => {
suite('with CLI flags', () => {
const evalCode = "JSON.stringify(require('util').parseArgs({ strict: false }).values)";
const evalCodePrinted = `process.stdout.write(${evalCode})`;
const execArgsTests = {
'-e <script>': ['-e', evalCodePrinted],
'-p <script>': ['-p', evalCode],
'-pe <script>': ['-pe', evalCode],
'--eval <script>': ['--eval', evalCodePrinted],
'--eval=<script>': [`--eval=${evalCodePrinted}`],
'--print <script>': ['--print', evalCode],
'--print --eval <script>': ['--print', '--eval', evalCode],
'--print --eval=<script>': ['--print', `--eval=${evalCode}`],
};
for (const description in execArgsTests) {
const execArgs = execArgsTests[description];
test(description, async () => {
const { code, signal, stderr, stdout } = await spawnPromisified(
process.execPath,
[...execArgs, '--', '--foo', '--bar']);
assert.strictEqual(code, 0);
assert.strictEqual(signal, null);
assert.strictEqual(stderr, '');
assert.deepStrictEqual(JSON.parse(stdout), { foo: true, bar: true });
});
}
});

const expected = { values: { __proto__: null, foo: true },
positionals: [] };
assert.deepStrictEqual(result, expected);
process.argv = holdArgv;
process.execArgv = holdExecArgv;
test('without CLI flags', () => {
const holdArgv = process.argv;
process.argv = [process.argv0, 'script.js', '--foo', '--bar'];
const { values } = parseArgs({ strict: false });
assert.deepStrictEqual(values, { __proto__: null, foo: true, bar: true });
process.argv = holdArgv;
});
});

test('excess leading dashes on options are retained', () => {
Expand Down Expand Up @@ -1052,13 +1020,10 @@ test('allow negative options and passed multiple arguments', () => {
test('auto-detect --no-foo as negated when strict:false and allowNegative', () => {
const holdArgv = process.argv;
process.argv = [process.argv0, 'script.js', '--no-foo'];
const holdExecArgv = process.execArgv;
process.execArgv = [];
const result = parseArgs({ strict: false, allowNegative: true });

const expected = { values: { __proto__: null, foo: false },
positionals: [] };
assert.deepStrictEqual(result, expected);
process.argv = holdArgv;
process.execArgv = holdExecArgv;
});
Loading