From 441f059d585d446551068ad213db79ac91daf83a Mon Sep 17 00:00:00 2001 From: "Benjamin E. Coe" Date: Sun, 20 Jun 2021 18:06:57 -0400 Subject: [PATCH] fix(perf): address slow parse when using unknown-options-as-args (#394) --- 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 77b47ce7..1499fc60 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(/^-{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 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) + }) + }) })