diff --git a/lib/assert.js b/lib/assert.js index f200507ad60537..a7d44b91e76e9e 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -78,6 +78,7 @@ let isDeepEqual; let isDeepStrictEqual; let parseExpressionAt; let findNodeAround; +let tokenizer; let decoder; function lazyLoadComparison() { @@ -247,34 +248,37 @@ function parseCode(code, offset) { ({ findNodeAround } = require('internal/deps/acorn/acorn-walk/dist/walk')); parseExpressionAt = FunctionPrototypeBind(Parser.parseExpressionAt, Parser); + tokenizer = FunctionPrototypeBind(Parser.tokenizer, Parser); } let node; - let start = 0; + let start; // Parse the read code until the correct expression is found. - do { + for (const token of tokenizer(code, { ecmaVersion: 'latest' })) { + start = token.start; + if (start > offset) { + // No matching expression found. This could happen if the assert + // expression is bigger than the provided buffer. + break; + } try { node = parseExpressionAt(code, start, { ecmaVersion: 'latest' }); - start = node.end + 1 || start; // Find the CallExpression in the tree. node = findNodeAround(node, offset, 'CallExpression'); - } catch (err) { - // Unexpected token error and the like. - start += err.raisedAt || 1; - if (start > offset) { - // No matching expression found. This could happen if the assert - // expression is bigger than the provided buffer. - // eslint-disable-next-line no-throw-literal - throw null; + if (node?.node.end >= offset) { + return [ + node.node.start, + StringPrototypeReplace(StringPrototypeSlice(code, + node.node.start, node.node.end), + escapeSequencesRegExp, escapeFn), + ]; } + // eslint-disable-next-line no-unused-vars + } catch (err) { + continue; } - } while (node === undefined || node.node.end < offset); - - return [ - node.node.start, - StringPrototypeReplace(StringPrototypeSlice(code, - node.node.start, node.node.end), - escapeSequencesRegExp, escapeFn), - ]; + } + // eslint-disable-next-line no-throw-literal + throw null; } function getErrMessage(message, fn) { diff --git a/test/parallel/test-assert.js b/test/parallel/test-assert.js index 0a270d030feea6..0343e8422885ad 100644 --- a/test/parallel/test-assert.js +++ b/test/parallel/test-assert.js @@ -726,6 +726,61 @@ assert.throws( 'assert.ok(null)\n' } ); +assert.throws( + () => { + // This test case checks if `try` left brace without a line break + // before the assertion causes any wrong assertion message. + // Therefore, don't reformat the following code. + // Refs: https://github.com/nodejs/node/issues/30872 + try { assert.ok(0); // eslint-disable-line no-useless-catch, brace-style + } catch (err) { + throw err; + } + }, + { + code: 'ERR_ASSERTION', + constructor: assert.AssertionError, + generatedMessage: true, + message: 'The expression evaluated to a falsy value:\n\n ' + + 'assert.ok(0)\n' + } +); +assert.throws( + () => { + try { + throw new Error(); + // This test case checks if `catch` left brace without a line break + // before the assertion causes any wrong assertion message. + // Therefore, don't reformat the following code. + // Refs: https://github.com/nodejs/node/issues/30872 + } catch (err) { assert.ok(0); } // eslint-disable-line no-unused-vars + }, + { + code: 'ERR_ASSERTION', + constructor: assert.AssertionError, + generatedMessage: true, + message: 'The expression evaluated to a falsy value:\n\n ' + + 'assert.ok(0)\n' + } +); +assert.throws( + () => { + // This test case checks if `function` left brace without a line break + // before the assertion causes any wrong assertion message. + // Therefore, don't reformat the following code. + // Refs: https://github.com/nodejs/node/issues/30872 + function test() { assert.ok(0); // eslint-disable-line brace-style + } + test(); + }, + { + code: 'ERR_ASSERTION', + constructor: assert.AssertionError, + generatedMessage: true, + message: 'The expression evaluated to a falsy value:\n\n ' + + 'assert.ok(0)\n' + } +); assert.throws( () => assert(typeof 123n === 'string'), {