From f6074d165005810ca1337090f05caaba9a04f82d Mon Sep 17 00:00:00 2001 From: bcoe Date: Sun, 20 Jun 2021 09:53:53 -0700 Subject: [PATCH 1/3] fix(perf): address slow perf when using unknown-options-as-args --- lib/yargs-parser.ts | 4 +++- test/yargs-parser.cjs | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/lib/yargs-parser.ts b/lib/yargs-parser.ts index a2a97f42..80cc3cbf 100644 --- a/lib/yargs-parser.ts +++ b/lib/yargs-parser.ts @@ -210,6 +210,7 @@ export class YargsParser { for (let i = 0; i < args.length; i++) { const arg = args[i] + const truncatedArg = arg.replace(/^-{3,}/, '---'); let broken: boolean let key: string | undefined let letters: string[] @@ -221,7 +222,7 @@ export class YargsParser { if (arg !== '--' && isUnknownOptionAsArg(arg)) { pushPositional(arg) // ---, ---=, ----, etc, - } else if (arg.match(/---+(=|$)/)) { + } else if (truncatedArg.match(/---+(=|$)/)) { // options without key name are invalid. pushPositional(arg) continue @@ -969,6 +970,7 @@ export class YargsParser { } function isUnknownOption (arg: string): boolean { + arg = arg.replace(/^-{2,}/, '--') // ignore negative numbers if (arg.match(negative)) { return false } // if this is a short option group and all of them are configured, it isn't unknown diff --git a/test/yargs-parser.cjs b/test/yargs-parser.cjs index f45256ed..95bee24a 100644 --- a/test/yargs-parser.cjs +++ b/test/yargs-parser.cjs @@ -3963,4 +3963,37 @@ describe('yargs-parser', function () { }).to.throw(/yargs parser supports a minimum Node.js version of 55/) delete process.env.YARGS_MIN_NODE_VERSION }) + + // Refs: https://github.com/yargs/yargs-parser/issues/386 + describe('perf', () => { + const i = 100000 + describe('unknown-options-as-args', () => { + it('parses long chain of "-" with reasonable performance', function () { + this.timeout(500) + const s = (new Array(i).fill('-').join('')) + 'a' + const parsed = parser([s], { configuration: { 'unknown-options-as-args': true } }) + parsed._[0].should.equal(s) + }) + it('parses long chain of "-a-a" with reasonable performance', function () { + this.timeout(500) + const s = '-' + (new Array(i).fill('-a').join('')) + '=35' + const parsed = parser([s], { configuration: { 'unknown-options-as-args': true } }) + parsed._[0].should.equal(s) + }) + }) + it('parses long chain of "-" with reasonable performance', function () { + this.timeout(500) + const s = (new Array(i).fill('-').join('')) + 'a' + const arg = (new Array(i - 2).fill('-').join('')) + 'a' + const parsed = parser([s]) + parsed[arg].should.equal(true) + }) + it('parses long chain of "-a-a" with reasonable performance', function () { + this.timeout(500) + const s = '-' + (new Array(i).fill('-a').join('')) + '=35' + const arg = 'a' + (new Array(i - 1).fill('A').join('')) + const parsed = parser([s]) + parsed[arg].should.equal(35) + }) + }) }) From bc4818de00a886be0e52f2086e9eaeeb2aa66c91 Mon Sep 17 00:00:00 2001 From: bcoe Date: Sun, 20 Jun 2021 09:59:53 -0700 Subject: [PATCH 2/3] chore: truncate at 3 --- lib/yargs-parser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/yargs-parser.ts b/lib/yargs-parser.ts index 80cc3cbf..84ab046e 100644 --- a/lib/yargs-parser.ts +++ b/lib/yargs-parser.ts @@ -970,7 +970,7 @@ export class YargsParser { } function isUnknownOption (arg: string): boolean { - arg = arg.replace(/^-{2,}/, '--') + arg = arg.replace(/^-{3,}/, '--') // ignore negative numbers if (arg.match(negative)) { return false } // if this is a short option group and all of them are configured, it isn't unknown From 50f8ef503790ce2a3c0a91ff548053a3d3d9c123 Mon Sep 17 00:00:00 2001 From: bcoe Date: Sun, 20 Jun 2021 10:07:08 -0700 Subject: [PATCH 3/3] ran linter --- lib/yargs-parser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/yargs-parser.ts b/lib/yargs-parser.ts index 84ab046e..141bea23 100644 --- a/lib/yargs-parser.ts +++ b/lib/yargs-parser.ts @@ -210,7 +210,7 @@ export class YargsParser { for (let i = 0; i < args.length; i++) { const arg = args[i] - const truncatedArg = arg.replace(/^-{3,}/, '---'); + const truncatedArg = arg.replace(/^-{3,}/, '---') let broken: boolean let key: string | undefined let letters: string[]