-
-
Notifications
You must be signed in to change notification settings - Fork 33.1k
Description
Version
v24.5.0
Platform
Linux dasprid-desktop 6.12.10-76061203-generic #202412060638~1753385872~22.04~dc2e00d SMP PREEMPT_DYNAMIC Thu J x86_64 x86_64 x86_64 GNU/Linux
Subsystem
internal/assert
What steps will reproduce the bug?
Create a test file in TypeScript with a test and an assertion in it:
import assert from "node:assert/strict";
import { it } from "node:test";
it("line issue", () => {
assert.ok(false);
});
Running it through node test
(through internal type stripping) will yield the correct result:
AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:
assert.ok(false)
Running it with a loader like tsx
will incorrectly identify the assertion source:
AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:
it("line issue", () => {
assert.ok(false);
})
How often does it reproduce? Is there a required condition?
Reproduces every time.
What is the expected behavior? Why is that the expected behavior?
Running through a TS loader should yield the same result as node with type stripping.
What do you see instead?
Assertion reports wrong source location.
Additional information
Previous finding can be found here: privatenumber/tsx#732
To summarize:
- To generate the assertion message, Node.js captures a stack trace in its interal getErrMessage(). That stack trace references the transpiled location though; in this case, line 0, column 74.
- It then loads the active file from disk (so test.ts). For line 0 it has a special handling in
getCode()
, where it will usefindColumn()
directly. Note that the column is the absolute column value, so a line break is simply considered a character in this case. - The parser then uses
acorn
internally to parse the TypeScript source. This search will most of the time yield partially or completely wrong results.
tsx
(through esbuild) does include a source map in the transpiled code. I'm not sure how Node.js could handle this best. Ideally it'd scan the transpiled code to find the assertion source and then reference the original file through the source map.
But looking at the current code which always loads the executed file from disk, I'm not sure if Node.js even has access to the executed code at runtime.