From 6a0b05f4286a2b639901d5edbcaf7ceb0e7a1141 Mon Sep 17 00:00:00 2001 From: June Kim Date: Tue, 26 May 2026 16:45:59 -0700 Subject: [PATCH 1/3] lib: fix ERR_INVALID_ARG_TYPE with --enable-source-maps Signed-off-by: June Kim --- lib/internal/errors/error_source.js | 11 +++++- .../source-map/assert-no-source-map.cjs | 15 ++++++++ .../source-map/assert-no-source-map.mjs | 16 ++++++++ test/parallel/test-assert-ok-source-maps.js | 38 +++++++++++++++++++ 4 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 test/fixtures/source-map/assert-no-source-map.cjs create mode 100644 test/fixtures/source-map/assert-no-source-map.mjs create mode 100644 test/parallel/test-assert-ok-source-maps.js diff --git a/lib/internal/errors/error_source.js b/lib/internal/errors/error_source.js index eddd6af230801b..c17f5a151c7014 100644 --- a/lib/internal/errors/error_source.js +++ b/lib/internal/errors/error_source.js @@ -32,6 +32,10 @@ function getErrorSourceLocation(error) { startColumn, } = pos; + if (!sourceLine) { + return; + } + // Source map is not enabled. Return the source line directly. if (!getSourceMapsSupport().enabled) { return { sourceLine, startColumn }; @@ -39,7 +43,8 @@ function getErrorSourceLocation(error) { const sm = findSourceMap(scriptResourceName); if (sm === undefined) { - return; + // No source map for this file; use the generated source line. + return { sourceLine, startColumn }; } const { originalLine, @@ -49,7 +54,9 @@ function getErrorSourceLocation(error) { const originalSourceLine = getSourceLine(sm, originalSource, originalLine, originalColumn); if (!originalSourceLine) { - return; + // Source map exists but original source is unavailable; use the + // generated source line rather than returning undefined. + return { sourceLine, startColumn }; } return { diff --git a/test/fixtures/source-map/assert-no-source-map.cjs b/test/fixtures/source-map/assert-no-source-map.cjs new file mode 100644 index 00000000000000..09629af3056441 --- /dev/null +++ b/test/fixtures/source-map/assert-no-source-map.cjs @@ -0,0 +1,15 @@ +'use strict'; + +// Fixture for test/parallel/test-assert-ok-source-maps.js (CommonJS variant). +// See assert-no-source-map.mjs for the rationale (issue #63169). +const assert = require('node:assert'); + +try { + assert.ok(false); +} catch (e) { + process.stdout.write(e.constructor.name + '\n'); + process.stdout.write(e.code + '\n'); + process.stdout.write(e.message + '\n'); + process.exit(0); +} +process.exit(1); diff --git a/test/fixtures/source-map/assert-no-source-map.mjs b/test/fixtures/source-map/assert-no-source-map.mjs new file mode 100644 index 00000000000000..faeb6031a5ba13 --- /dev/null +++ b/test/fixtures/source-map/assert-no-source-map.mjs @@ -0,0 +1,16 @@ +// Fixture for test/parallel/test-assert-ok-source-maps.js. +// Run with --enable-source-maps; the file has no source map, so the error's +// source line resolution must fall back to the generated line instead of +// throwing ERR_INVALID_ARG_TYPE (regression test for +// https://github.com/nodejs/node/issues/63169). +import { strict as assert } from 'node:assert'; + +try { + assert(false); +} catch (e) { + process.stdout.write(e.constructor.name + '\n'); + process.stdout.write(e.code + '\n'); + process.stdout.write(e.message + '\n'); + process.exit(0); +} +process.exit(1); diff --git a/test/parallel/test-assert-ok-source-maps.js b/test/parallel/test-assert-ok-source-maps.js new file mode 100644 index 00000000000000..71e6860664fda6 --- /dev/null +++ b/test/parallel/test-assert-ok-source-maps.js @@ -0,0 +1,38 @@ +'use strict'; + +// Regression test for https://github.com/nodejs/node/issues/63169 +// When --enable-source-maps is enabled but the script has no source map, +// assert(false) should throw AssertionError, not TypeError ERR_INVALID_ARG_TYPE. + +require('../common'); +const assert = require('node:assert'); +const { spawnSync } = require('node:child_process'); +const { test } = require('node:test'); +const fixtures = require('../common/fixtures'); + +function runWithSourceMaps(fixture) { + return spawnSync(process.execPath, [ + '--enable-source-maps', + fixtures.path('source-map', fixture), + ]); +} + +test('assert(false) in .mjs with --enable-source-maps throws AssertionError', () => { + const result = runWithSourceMaps('assert-no-source-map.mjs'); + + assert.strictEqual(result.status, 0, `process exited with ${result.status}: ${result.stderr}`); + const lines = result.stdout.toString().trim().split('\n'); + assert.strictEqual(lines[0], 'AssertionError'); + assert.strictEqual(lines[1], 'ERR_ASSERTION'); + assert.match(lines[2], /assert\(false\)/); +}); + +test('assert.ok(false) in .cjs with --enable-source-maps throws AssertionError', () => { + const result = runWithSourceMaps('assert-no-source-map.cjs'); + + assert.strictEqual(result.status, 0, `process exited with ${result.status}: ${result.stderr}`); + const lines = result.stdout.toString().trim().split('\n'); + assert.strictEqual(lines[0], 'AssertionError'); + assert.strictEqual(lines[1], 'ERR_ASSERTION'); + assert.match(lines[2], /assert\.ok\(false\)/); +}); From 9a7f346fcd7142a7c97f3634db45c59b9d2d6df2 Mon Sep 17 00:00:00 2001 From: June Kim Date: Fri, 26 Jun 2026 20:26:42 -0400 Subject: [PATCH 2/3] test: move source-map assert regression into output snapshots Fold the .mjs and .cjs --enable-source-maps cases from the standalone test-assert-ok-source-maps.js into the existing snapshot output test, following the setup in test-node-output-sourcemaps.mjs as requested in review. The fixtures live under test/fixtures/source-map/output/ with a `// Flags: --enable-source-maps` directive and assert AssertionError output via snapshots instead of bespoke spawnSync assertions. Refs: https://github.com/nodejs/node/issues/63169 Signed-off-by: June Kim --- .../source-map/assert-no-source-map.cjs | 15 -------- .../source-map/assert-no-source-map.mjs | 16 -------- .../source_map_assert_no_source_map.mjs | 9 +++++ .../source_map_assert_no_source_map.snapshot | 20 ++++++++++ .../source_map_assert_ok_no_source_map.cjs | 10 +++++ ...ource_map_assert_ok_no_source_map.snapshot | 20 ++++++++++ test/parallel/test-assert-ok-source-maps.js | 38 ------------------- test/parallel/test-node-output-sourcemaps.mjs | 2 + 8 files changed, 61 insertions(+), 69 deletions(-) delete mode 100644 test/fixtures/source-map/assert-no-source-map.cjs delete mode 100644 test/fixtures/source-map/assert-no-source-map.mjs create mode 100644 test/fixtures/source-map/output/source_map_assert_no_source_map.mjs create mode 100644 test/fixtures/source-map/output/source_map_assert_no_source_map.snapshot create mode 100644 test/fixtures/source-map/output/source_map_assert_ok_no_source_map.cjs create mode 100644 test/fixtures/source-map/output/source_map_assert_ok_no_source_map.snapshot delete mode 100644 test/parallel/test-assert-ok-source-maps.js diff --git a/test/fixtures/source-map/assert-no-source-map.cjs b/test/fixtures/source-map/assert-no-source-map.cjs deleted file mode 100644 index 09629af3056441..00000000000000 --- a/test/fixtures/source-map/assert-no-source-map.cjs +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; - -// Fixture for test/parallel/test-assert-ok-source-maps.js (CommonJS variant). -// See assert-no-source-map.mjs for the rationale (issue #63169). -const assert = require('node:assert'); - -try { - assert.ok(false); -} catch (e) { - process.stdout.write(e.constructor.name + '\n'); - process.stdout.write(e.code + '\n'); - process.stdout.write(e.message + '\n'); - process.exit(0); -} -process.exit(1); diff --git a/test/fixtures/source-map/assert-no-source-map.mjs b/test/fixtures/source-map/assert-no-source-map.mjs deleted file mode 100644 index faeb6031a5ba13..00000000000000 --- a/test/fixtures/source-map/assert-no-source-map.mjs +++ /dev/null @@ -1,16 +0,0 @@ -// Fixture for test/parallel/test-assert-ok-source-maps.js. -// Run with --enable-source-maps; the file has no source map, so the error's -// source line resolution must fall back to the generated line instead of -// throwing ERR_INVALID_ARG_TYPE (regression test for -// https://github.com/nodejs/node/issues/63169). -import { strict as assert } from 'node:assert'; - -try { - assert(false); -} catch (e) { - process.stdout.write(e.constructor.name + '\n'); - process.stdout.write(e.code + '\n'); - process.stdout.write(e.message + '\n'); - process.exit(0); -} -process.exit(1); diff --git a/test/fixtures/source-map/output/source_map_assert_no_source_map.mjs b/test/fixtures/source-map/output/source_map_assert_no_source_map.mjs new file mode 100644 index 00000000000000..d6035109d56db8 --- /dev/null +++ b/test/fixtures/source-map/output/source_map_assert_no_source_map.mjs @@ -0,0 +1,9 @@ +// Flags: --enable-source-maps + +import '../../../common/index.mjs'; +import { strict as assert } from 'node:assert'; + +// Regression test for https://github.com/nodejs/node/issues/63169 +// Under --enable-source-maps with no source map for this file, a failing +// assert(value) must throw AssertionError, not TypeError ERR_INVALID_ARG_TYPE. +assert(false); diff --git a/test/fixtures/source-map/output/source_map_assert_no_source_map.snapshot b/test/fixtures/source-map/output/source_map_assert_no_source_map.snapshot new file mode 100644 index 00000000000000..0a2ea1a45fe6f3 --- /dev/null +++ b/test/fixtures/source-map/output/source_map_assert_no_source_map.snapshot @@ -0,0 +1,20 @@ +node:internal/modules/run_main: + triggerUncaughtException( + ^ + +AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value: + + assert(false) + + at file:///test/fixtures/source-map/output/source_map_assert_no_source_map.mjs:9:1 + at + at { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: false, + expected: true, + operator: '==', + diff: 'simple' +} + +Node.js diff --git a/test/fixtures/source-map/output/source_map_assert_ok_no_source_map.cjs b/test/fixtures/source-map/output/source_map_assert_ok_no_source_map.cjs new file mode 100644 index 00000000000000..21f2ec8965fb05 --- /dev/null +++ b/test/fixtures/source-map/output/source_map_assert_ok_no_source_map.cjs @@ -0,0 +1,10 @@ +// Flags: --enable-source-maps + +'use strict'; +require('../../../common'); +const assert = require('node:assert'); + +// Regression test for https://github.com/nodejs/node/issues/63169 +// Under --enable-source-maps with no source map for this file, a failing +// assert.ok(value) must throw AssertionError, not TypeError ERR_INVALID_ARG_TYPE. +assert.ok(false); diff --git a/test/fixtures/source-map/output/source_map_assert_ok_no_source_map.snapshot b/test/fixtures/source-map/output/source_map_assert_ok_no_source_map.snapshot new file mode 100644 index 00000000000000..8ee5ff2ee29498 --- /dev/null +++ b/test/fixtures/source-map/output/source_map_assert_ok_no_source_map.snapshot @@ -0,0 +1,20 @@ +node:internal/assert/utils: + throw error; + ^ + +AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value: + + assert.ok(false) + + at Object. (/test/fixtures/source-map/output/source_map_assert_ok_no_source_map.cjs:10:8) + at + at { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: false, + expected: true, + operator: '==', + diff: 'simple' +} + +Node.js diff --git a/test/parallel/test-assert-ok-source-maps.js b/test/parallel/test-assert-ok-source-maps.js deleted file mode 100644 index 71e6860664fda6..00000000000000 --- a/test/parallel/test-assert-ok-source-maps.js +++ /dev/null @@ -1,38 +0,0 @@ -'use strict'; - -// Regression test for https://github.com/nodejs/node/issues/63169 -// When --enable-source-maps is enabled but the script has no source map, -// assert(false) should throw AssertionError, not TypeError ERR_INVALID_ARG_TYPE. - -require('../common'); -const assert = require('node:assert'); -const { spawnSync } = require('node:child_process'); -const { test } = require('node:test'); -const fixtures = require('../common/fixtures'); - -function runWithSourceMaps(fixture) { - return spawnSync(process.execPath, [ - '--enable-source-maps', - fixtures.path('source-map', fixture), - ]); -} - -test('assert(false) in .mjs with --enable-source-maps throws AssertionError', () => { - const result = runWithSourceMaps('assert-no-source-map.mjs'); - - assert.strictEqual(result.status, 0, `process exited with ${result.status}: ${result.stderr}`); - const lines = result.stdout.toString().trim().split('\n'); - assert.strictEqual(lines[0], 'AssertionError'); - assert.strictEqual(lines[1], 'ERR_ASSERTION'); - assert.match(lines[2], /assert\(false\)/); -}); - -test('assert.ok(false) in .cjs with --enable-source-maps throws AssertionError', () => { - const result = runWithSourceMaps('assert-no-source-map.cjs'); - - assert.strictEqual(result.status, 0, `process exited with ${result.status}: ${result.stderr}`); - const lines = result.stdout.toString().trim().split('\n'); - assert.strictEqual(lines[0], 'AssertionError'); - assert.strictEqual(lines[1], 'ERR_ASSERTION'); - assert.match(lines[2], /assert\.ok\(false\)/); -}); diff --git a/test/parallel/test-node-output-sourcemaps.mjs b/test/parallel/test-node-output-sourcemaps.mjs index 26baa0cd53afed..c96eac2bd0310c 100644 --- a/test/parallel/test-node-output-sourcemaps.mjs +++ b/test/parallel/test-node-output-sourcemaps.mjs @@ -5,6 +5,8 @@ import { describe, it } from 'node:test'; describe('sourcemaps output', { concurrency: !process.env.TEST_PARALLEL }, () => { const tests = [ + { name: 'source-map/output/source_map_assert_no_source_map.mjs' }, + { name: 'source-map/output/source_map_assert_ok_no_source_map.cjs' }, { name: 'source-map/output/source_map_disabled_by_api.js' }, { name: 'source-map/output/source_map_disabled_by_process_api.js' }, { name: 'source-map/output/source_map_enabled_by_api.js' }, From b15e1c6b9bb7eb85d39e9167e458cf577ad612bc Mon Sep 17 00:00:00 2001 From: June Date: Mon, 29 Jun 2026 13:23:16 -0700 Subject: [PATCH 3/3] test: silence no-restricted-syntax in source-map assert fixtures The literal first argument to assert() is intentional in these regression fixtures (the .snapshot files pin the exact source line and column), so disable the rule inline rather than rewriting the call. --- .../source-map/output/source_map_assert_no_source_map.mjs | 2 +- .../source-map/output/source_map_assert_ok_no_source_map.cjs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/fixtures/source-map/output/source_map_assert_no_source_map.mjs b/test/fixtures/source-map/output/source_map_assert_no_source_map.mjs index d6035109d56db8..34d81d0f249adf 100644 --- a/test/fixtures/source-map/output/source_map_assert_no_source_map.mjs +++ b/test/fixtures/source-map/output/source_map_assert_no_source_map.mjs @@ -6,4 +6,4 @@ import { strict as assert } from 'node:assert'; // Regression test for https://github.com/nodejs/node/issues/63169 // Under --enable-source-maps with no source map for this file, a failing // assert(value) must throw AssertionError, not TypeError ERR_INVALID_ARG_TYPE. -assert(false); +assert(false); // eslint-disable-line no-restricted-syntax diff --git a/test/fixtures/source-map/output/source_map_assert_ok_no_source_map.cjs b/test/fixtures/source-map/output/source_map_assert_ok_no_source_map.cjs index 21f2ec8965fb05..2dd8cbd07b1f59 100644 --- a/test/fixtures/source-map/output/source_map_assert_ok_no_source_map.cjs +++ b/test/fixtures/source-map/output/source_map_assert_ok_no_source_map.cjs @@ -7,4 +7,4 @@ const assert = require('node:assert'); // Regression test for https://github.com/nodejs/node/issues/63169 // Under --enable-source-maps with no source map for this file, a failing // assert.ok(value) must throw AssertionError, not TypeError ERR_INVALID_ARG_TYPE. -assert.ok(false); +assert.ok(false); // eslint-disable-line no-restricted-syntax