From 2dd9bfec5249f9adbd14557e4e5526ade944be98 Mon Sep 17 00:00:00 2001 From: scripthunter7 <57285466+scripthunter7@users.noreply.github.com> Date: Wed, 22 Feb 2023 20:03:59 +0100 Subject: [PATCH] Fix false positive parsing error (#8) --- src/syntax/index.js | 26 +++++++++++++++----------- test/syntax/upward.test.js | 20 ++++++++++++++++++++ 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/syntax/index.js b/src/syntax/index.js index 401a662..668db24 100644 --- a/src/syntax/index.js +++ b/src/syntax/index.js @@ -90,17 +90,21 @@ const numberOrSelector = { * @see {@link https://github.com/csstree/csstree/blob/master/lib/syntax/pseudo/index.js} */ parse() { - return this.createSingleNodeList( - // If the next token is a number, parse it as a number, - // otherwise parse it as a selector as fallback - // * PLEASE NOTE: If the number parsing is failed, CSSTree - // * will throw an "internal error" via "onParsingError" - // * callback. - // * See: https://github.com/csstree/csstree/blob/master/docs/parsing.md#onparseerror - // * This not a breaking issue, because the parsing will - // * continue its work. - this.parseWithFallback(this.Number, this.Selector), - ); + // Save the current token index + const startToken = this.tokenIndex; + + // Don't use "parseWithFallback" here, because we don't want to + // throw parsing error, if just the number parsing fails. + try { + // Try to parse :upward()'s argument as a number, but if it fails, + // that's not a problem, because we can try to parse it as a selector. + return this.createSingleNodeList(this.Number.call(this)); + } catch (error) { + // If the number parsing fails, then we try to parse a selector. + // If the selector parsing fails, then an error will be thrown, + // because the argument is invalid. + return this.createSingleNodeList(this.Selector.call(this, startToken)); + } }, }; diff --git a/test/syntax/upward.test.js b/test/syntax/upward.test.js index a13610d..969085d 100644 --- a/test/syntax/upward.test.js +++ b/test/syntax/upward.test.js @@ -220,4 +220,24 @@ describe(':upward()', () => { 'div:upward(.something+#another)', ); }); + + test('no false positive parsing errors', () => { + // "Local" parser config for this test + const localParserConfig = { + ...parserConfig, + onParseError: (error) => { + throw error; + }, + }; + + expect(() => parse('div:upward(0)', localParserConfig)).not.toThrow(); + expect(() => parse('div:upward(42)', localParserConfig)).not.toThrow(); + expect(() => parse('div:upward(.something + #another)', localParserConfig)).not.toThrow(); + expect( + () => parse( + 'div:upward(div + :-abp-has(> a[href^="https://example.com/"]) + div)', + localParserConfig, + ), + ).not.toThrow(); + }); });