From 3787b9fc16bc3332b37880597339e5a9386cdeb4 Mon Sep 17 00:00:00 2001 From: Jos de Jong Date: Wed, 23 Apr 2025 11:21:33 +0200 Subject: [PATCH 1/2] fix: #3421 require a space or delimiter after hex, bin, and oct values --- src/expression/parse.js | 21 ++++++++------------- test/unit-tests/expression/parse.test.js | 17 ++++++++++++++++- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/expression/parse.js b/src/expression/parse.js index 8eab0230db..4bb9de056b 100644 --- a/src/expression/parse.js +++ b/src/expression/parse.js @@ -346,7 +346,10 @@ export const createParse = /* #__PURE__ */ factory(name, dependencies, ({ next(state) state.token += currentCharacter(state) next(state) - while (parse.isHexDigit(currentCharacter(state))) { + while ( + parse.isAlpha(currentCharacter(state), prevCharacter(state), nextCharacter(state)) || + parse.isDigit(currentCharacter(state)) + ) { state.token += currentCharacter(state) next(state) } @@ -355,7 +358,10 @@ export const createParse = /* #__PURE__ */ factory(name, dependencies, ({ state.token += '.' next(state) // get the digits after the radix - while (parse.isHexDigit(currentCharacter(state))) { + while ( + parse.isAlpha(currentCharacter(state), prevCharacter(state), nextCharacter(state)) || + parse.isDigit(currentCharacter(state)) + ) { state.token += currentCharacter(state) next(state) } @@ -574,17 +580,6 @@ export const createParse = /* #__PURE__ */ factory(name, dependencies, ({ return (c >= '0' && c <= '9') } - /** - * checks if the given char c is a hex digit - * @param {string} c a string with one character - * @return {boolean} - */ - parse.isHexDigit = function isHexDigit (c) { - return ((c >= '0' && c <= '9') || - (c >= 'a' && c <= 'f') || - (c >= 'A' && c <= 'F')) - } - /** * Start of the parse levels below, in order of precedence * @return {Node} node diff --git a/test/unit-tests/expression/parse.test.js b/test/unit-tests/expression/parse.test.js index d0eec260a9..6d5b00c38c 100644 --- a/test/unit-tests/expression/parse.test.js +++ b/test/unit-tests/expression/parse.test.js @@ -286,6 +286,21 @@ describe('parse', function () { assert.strictEqual(parseAndEval('0x1.'), 1) }) + it('should require hex, bin, oct values to be followed by whitespace or a delimiter', function () { + assert.throws(() => parseAndEval('0b0a'), /SyntaxError: String "0b0a" is not a valid number/ ) + assert.throws(() => parseAndEval('0x1k'), /SyntaxError: String "0x1k" is not a valid number/ ) + assert.throws(() => parseAndEval('0o1k'), /SyntaxError: String "0o1k" is not a valid number/ ) + assert.throws(() => parseAndEval('0b1k'), /SyntaxError: String "0b1k" is not a valid number/ ) + + assert.strictEqual(parseAndEval('0x1 k', { k: 2}), 2 ) + assert.strictEqual(parseAndEval('0o1 k', { k: 2}), 2 ) + assert.strictEqual(parseAndEval('0b1 k', { k: 2}), 2 ) + + assert.strictEqual(parseAndEval('0x1 * k', { k: 2}), 2 ) + assert.strictEqual(parseAndEval('0o1 * k', { k: 2}), 2 ) + assert.strictEqual(parseAndEval('0b1 * k', { k: 2}), 2 ) + }) + it('should parse a number followed by e', function () { approxEqual(parseAndEval('2e'), 2 * Math.E) }) @@ -334,7 +349,7 @@ describe('parse', function () { assert.throws(function () { parseAndEval('0b123.45') }, /SyntaxError: String "0b123\.45" is not a valid number/) assert.throws(function () { parseAndEval('0o89.89') }, /SyntaxError: String "0o89\.89" is not a valid number/) - assert.throws(function () { parseAndEval('0xghji.xyz') }, /SyntaxError: String "0x" is not a valid number/) + assert.throws(function () { parseAndEval('0xghji.xyz') }, /SyntaxError: String "0xghji.xyz" is not a valid number/) }) }) From b148d8bee30d0aba61370704f5dd82aa548fb8a9 Mon Sep 17 00:00:00 2001 From: Jos de Jong Date: Wed, 23 Apr 2025 11:32:02 +0200 Subject: [PATCH 2/2] chore: remove spaces in some of the unit tests, fix linting issues --- test/unit-tests/expression/parse.test.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/unit-tests/expression/parse.test.js b/test/unit-tests/expression/parse.test.js index 6d5b00c38c..27f3e2a1f6 100644 --- a/test/unit-tests/expression/parse.test.js +++ b/test/unit-tests/expression/parse.test.js @@ -287,18 +287,18 @@ describe('parse', function () { }) it('should require hex, bin, oct values to be followed by whitespace or a delimiter', function () { - assert.throws(() => parseAndEval('0b0a'), /SyntaxError: String "0b0a" is not a valid number/ ) - assert.throws(() => parseAndEval('0x1k'), /SyntaxError: String "0x1k" is not a valid number/ ) - assert.throws(() => parseAndEval('0o1k'), /SyntaxError: String "0o1k" is not a valid number/ ) - assert.throws(() => parseAndEval('0b1k'), /SyntaxError: String "0b1k" is not a valid number/ ) - - assert.strictEqual(parseAndEval('0x1 k', { k: 2}), 2 ) - assert.strictEqual(parseAndEval('0o1 k', { k: 2}), 2 ) - assert.strictEqual(parseAndEval('0b1 k', { k: 2}), 2 ) - - assert.strictEqual(parseAndEval('0x1 * k', { k: 2}), 2 ) - assert.strictEqual(parseAndEval('0o1 * k', { k: 2}), 2 ) - assert.strictEqual(parseAndEval('0b1 * k', { k: 2}), 2 ) + assert.throws(() => parseAndEval('0b0a'), /SyntaxError: String "0b0a" is not a valid number/) + assert.throws(() => parseAndEval('0x1k'), /SyntaxError: String "0x1k" is not a valid number/) + assert.throws(() => parseAndEval('0o1k'), /SyntaxError: String "0o1k" is not a valid number/) + assert.throws(() => parseAndEval('0b1k'), /SyntaxError: String "0b1k" is not a valid number/) + + assert.strictEqual(parseAndEval('0x1 k', { k: 2 }), 2) + assert.strictEqual(parseAndEval('0o1 k', { k: 2 }), 2) + assert.strictEqual(parseAndEval('0b1 k', { k: 2 }), 2) + + assert.strictEqual(parseAndEval('0x1*k', { k: 2 }), 2) + assert.strictEqual(parseAndEval('0o1*k', { k: 2 }), 2) + assert.strictEqual(parseAndEval('0b1*k', { k: 2 }), 2) }) it('should parse a number followed by e', function () {