diff --git a/lib/assert.js b/lib/assert.js index b7d7a3da01d5209..6d9f5076a5720e9 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 { URL, 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 000000000000000..47a75ae14852de3 --- /dev/null +++ b/test/parallel/test-assert-esm-cjs-message-verify.js @@ -0,0 +1,55 @@ +'use strict'; + +require('../common'); +const tmpdir = require('../common/tmpdir'); +const assert = require('assert'); +const { writeFileSync, unlink } = require('fs'); +const { execSync } = require('child_process'); + +tmpdir.refresh(); + +// To ensure the assert ok throwing similar error messages for esm and cjs + +const nodejs = `${process.execPath}`; + +// Importing package for each extensions. +const fileImports = { + mjs: 'import assert from "assert";', + js: 'const assert = require("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);`); +} + +const errorsMessages = []; + +for (const fileName of fileNames) { + const command = `${nodejs} ${fileName}`; + assert.throws( + () => { + execSync(command, { stdio: 'pipe' }); + }, + (e) => { + // For each error message, filter the lines which will starts with AssertionError + errorsMessages.push( + e.message.split('\n').find((s) => s.startsWith('AssertionError')) + ); + return true; + } + ); +} + +assert.deepStrictEqual(errorsMessages[0], errorsMessages[1]); + +for (const fileName of fileNames) { + unlink(fileName, () => {}); +} + +tmpdir.refresh();