From 8a6a568dbc5762043c80c2004bf5d9f74cea8545 Mon Sep 17 00:00:00 2001 From: Anton Gilgur Date: Sat, 15 Feb 2020 17:22:50 -0500 Subject: [PATCH 1/3] (fix): don't mutate process.argv with arr.splice - 1.7.1 introduced some arr.splice's into the code, which caused mutations in process.argv, affecting downstream code - set arr to a clone of process.argv instead so it can be freely mutated after - explicitly call the parameter processArgv so code is written more carefully when dealing with it - add a test to ensure process.argv is not mutated --- lib/index.js | 3 ++- test/index.js | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/index.js b/lib/index.js index 3779c22..f7690d1 100644 --- a/lib/index.js +++ b/lib/index.js @@ -105,7 +105,8 @@ class Sade { return this; } - parse(arr, opts={}) { + parse(processArgv, opts={}) { + let arr = processArgv.slice(); // DON'T mutate process.argv, clone first let offset=2, tmp, idx, isVoid, cmd; let alias = { h:'help', v:'version' }; let argv = mri(arr.slice(offset), { alias }); diff --git a/test/index.js b/test/index.js index 7f2eaf5..2863f82 100644 --- a/test/index.js +++ b/test/index.js @@ -212,6 +212,20 @@ test('prog.action (multi optional)', t => { (c=true) && run(); // +4 tests }); +test('prog.parse', t => { + t.plan(1); + + let ctx = sade('foo') + .command('build') + .action(() => {}); + + let args = ['', '', 'build']; + let argsCopy = args.slice(); + ctx.parse(argsCopy); + + t.deepEqual(argsCopy, args, '~> process.argv is not mutated'); +}); + test('prog.parse :: lazy', t => { t.plan(14); From c6a5ac21022caf7dcbaac6e5db9e008aa51d2552 Mon Sep 17 00:00:00 2001 From: Luke Edwards Date: Sat, 15 Feb 2020 23:52:52 -0800 Subject: [PATCH 2/3] chore: truncate --- lib/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/index.js b/lib/index.js index f7690d1..dac342b 100644 --- a/lib/index.js +++ b/lib/index.js @@ -105,8 +105,8 @@ class Sade { return this; } - parse(processArgv, opts={}) { - let arr = processArgv.slice(); // DON'T mutate process.argv, clone first + parse(arr, opts={}) { + arr = arr.slice(); // copy let offset=2, tmp, idx, isVoid, cmd; let alias = { h:'help', v:'version' }; let argv = mri(arr.slice(offset), { alias }); From c2318eea5bf86dd5dc445389e55bf7de6e5ac83a Mon Sep 17 00:00:00 2001 From: Luke Edwards Date: Sat, 15 Feb 2020 23:53:54 -0800 Subject: [PATCH 3/3] chore: add & improve tests --- test/index.js | 68 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 9 deletions(-) diff --git a/test/index.js b/test/index.js index 2863f82..240f780 100644 --- a/test/index.js +++ b/test/index.js @@ -212,18 +212,68 @@ test('prog.action (multi optional)', t => { (c=true) && run(); // +4 tests }); -test('prog.parse', t => { - t.plan(1); +test('prog.parse :: safe :: default', t => { + let ctx = sade('foo').command('build', '', { default: true }); - let ctx = sade('foo') - .command('build') - .action(() => {}); + let argv1 = ['', '', 'build']; + let foo = ctx.parse(argv1, { lazy: true }); + t.deepEqual(argv1, ['', '', 'build'], '~> argv unchanged'); + t.deepEqual(foo.args, [{ _: [] }], '~> args correct'); + + let argv2 = ['', '']; + let bar = ctx.parse(argv2, { lazy: true }); + t.deepEqual(argv2, ['', ''], '~> argv unchanged'); + t.deepEqual(bar.args, [{ _: [] }], '~> args correct'); + + t.end(); +}); + +test('prog.parse :: safe :: alias', t => { + let ctx = sade('foo').command('build').alias('b'); + + let argv1 = ['', '', 'build']; + let foo = ctx.parse(argv1, { lazy: true }); + t.deepEqual(argv1, ['', '', 'build'], '~> argv unchanged'); + t.deepEqual(foo.args, [{ _: [] }], '~> args correct'); + + let argv2 = ['', '', 'b']; + let bar = ctx.parse(argv2, { lazy: true }); + t.deepEqual(argv2, ['', '', 'b'], '~> argv unchanged'); + t.deepEqual(bar.args, [{ _: [] }], '~> args correct'); + + t.end(); +}); + +test('prog.parse :: safe :: default :: flags', t => { + let ctx = sade('foo').command('build ', '', { default: true }); + + let argv1 = ['', '', '-r', 'dotenv', 'build', 'public', '--fresh']; + let foo = ctx.parse(argv1, { lazy: true }); + t.deepEqual(argv1, ['', '', '-r', 'dotenv', 'build', 'public', '--fresh'], '~> argv unchanged'); + t.deepEqual(foo.args, ['public', { _: [], r: 'dotenv', fresh: true }], '~> args correct'); + + let argv2 = ['', '', '-r', 'dotenv', 'public', '--fresh']; + let bar = ctx.parse(argv2, { lazy: true }); + t.deepEqual(argv2, ['', '', '-r', 'dotenv', 'public', '--fresh'], '~> argv unchanged'); + t.deepEqual(bar.args, ['public', { _: [], r: 'dotenv', fresh: true }], '~> args correct'); + + t.end(); +}); + +test('prog.parse :: safe :: alias :: flags', t => { + let ctx = sade('foo').command('build ').alias('b'); - let args = ['', '', 'build']; - let argsCopy = args.slice(); - ctx.parse(argsCopy); + let argv1 = ['', '', '-r', 'dotenv', 'build', 'public', '--fresh']; + let foo = ctx.parse(argv1, { lazy: true }); + t.deepEqual(argv1, ['', '', '-r', 'dotenv', 'build', 'public', '--fresh'], '~> argv unchanged'); + t.deepEqual(foo.args, ['public', { _: [], r: 'dotenv', fresh: true }], '~> args correct'); - t.deepEqual(argsCopy, args, '~> process.argv is not mutated'); + let argv2 = ['', '', '-r', 'dotenv', 'b', 'public', '--fresh']; + let bar = ctx.parse(argv2, { lazy: true }); + t.deepEqual(argv2, ['', '', '-r', 'dotenv', 'b', 'public', '--fresh'], '~> argv unchanged'); + t.deepEqual(bar.args, ['public', { _: [], r: 'dotenv', fresh: true }], '~> args correct'); + + t.end(); }); test('prog.parse :: lazy', t => {