diff --git a/lib/assert.js b/lib/assert.js index b7d7a3da01d520..9dfcf80a913942 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -73,6 +73,7 @@ const CallTracker = require('internal/assert/calltracker'); const { validateFunction, } = require('internal/validators'); +const { fileURLToPath } = require('internal/url'); let isDeepEqual; let isDeepStrictEqual; @@ -296,7 +297,7 @@ function getErrMessage(message, fn) { overrideStackTrace.set(err, (_, stack) => stack); const call = err.stack[0]; - const filename = call.getFileName(); + let filename = call.getFileName(); const line = call.getLineNumber() - 1; let column = call.getColumnNumber() - 1; let identifier; @@ -330,6 +331,14 @@ function getErrMessage(message, fn) { const { StringDecoder } = require('string_decoder'); decoder = new StringDecoder('utf8'); } + + // ESM file prop is a file proto. Convert that to path. + // This ensure opensync will not throw ENOENT for ESM files. + const fileProtoPrefix = 'file://'; + if (StringPrototypeStartsWith(filename, fileProtoPrefix)) { + filename = fileURLToPath(filename); + } + fd = openSync(filename, 'r', 0o666); // Reset column and message. ({ 0: column, 1: message } = getCode(fd, line, column)); diff --git a/test/parallel/test-assert-esm-cjs-message-verify.js b/test/parallel/test-assert-esm-cjs-message-verify.js new file mode 100644 index 00000000000000..9a66d83abd9c4b --- /dev/null +++ b/test/parallel/test-assert-esm-cjs-message-verify.js @@ -0,0 +1,51 @@ +'use strict'; + +const { spawnPromisified } = require('../common'); +const tmpdir = require('../common/tmpdir'); +const assert = require('assert'); +const { writeFileSync, unlink } = require('fs'); +const { describe, after, it } = require('node:test'); + +tmpdir.refresh(); + +const fileImports = { + cjs: 'const assert = require("assert");', + mjs: 'import assert from "assert";', +}; + +const fileNames = []; + +for (const [ext, header] of Object.entries(fileImports)) { + const fileName = `test-file.${ext}`; + // Store the generated filesnames in an array + fileNames.push(`${tmpdir.path}/${fileName}`); + + writeFileSync(tmpdir.resolve(fileName), `${header}\nassert.ok(0 === 2);`); +} + +describe('ensure the assert.ok throwing similar error messages for esm and cjs files', () => { + const nodejsPath = `${process.execPath}`; + const errorsMessages = []; + + it('should return code 1 for each command', async () => { + for (const fileName of fileNames) { + const { stderr, code } = await spawnPromisified(nodejsPath, [fileName]); + assert.strictEqual(code, 1); + // For each error message, filter the lines which will starts with AssertionError + errorsMessages.push( + stderr.split('\n').find((s) => s.startsWith('AssertionError')) + ); + } + }); + + after(() => { + assert.strictEqual(errorsMessages.length, 2); + assert.deepStrictEqual(errorsMessages[0], errorsMessages[1]); + + for (const fileName of fileNames) { + unlink(fileName, () => {}); + } + + tmpdir.refresh(); + }); +});