Skip to content

Commit 5f0cfd0

Browse files
committed
fix(node): Correctly resolve module name
1 parent 679e149 commit 5f0cfd0

File tree

2 files changed

+59
-45
lines changed

2 files changed

+59
-45
lines changed

packages/node/src/module.ts

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { posix, sep } from 'path';
2-
3-
const isWindowsPlatform = sep === '\\';
2+
import { dirname } from '@sentry/utils';
43

54
/** normalizes Windows paths */
65
function normalizeWindowsPath(path: string): string {
@@ -9,52 +8,67 @@ function normalizeWindowsPath(path: string): string {
98
.replace(/\\/g, '/'); // replace all `\` instances with `/`
109
}
1110

11+
// We cache this so we don't have to recompute it
12+
let basePath: string | undefined;
13+
14+
function getBasePath(): string {
15+
if (!basePath) {
16+
const baseDir =
17+
require && require.main && require.main.filename ? dirname(require.main.filename) : global.process.cwd();
18+
basePath = `${baseDir}/`;
19+
}
20+
21+
return basePath;
22+
}
23+
1224
/** Gets the module from a filename */
1325
export function getModuleFromFilename(
1426
filename: string | undefined,
15-
normalizeWindowsPathSeparator: boolean = isWindowsPlatform,
27+
basePath: string = getBasePath(),
28+
isWindows: boolean = sep === '\\',
1629
): string | undefined {
1730
if (!filename) {
1831
return;
1932
}
2033

21-
const normalizedFilename = normalizeWindowsPathSeparator ? normalizeWindowsPath(filename) : filename;
22-
23-
// eslint-disable-next-line prefer-const
24-
let { root, dir, base: basename, ext } = posix.parse(normalizedFilename);
25-
26-
const base = (require && require.main && require.main.filename && dir) || global.process.cwd();
34+
// If it's a node internal module, we can just return it
35+
if (filename.startsWith('node:')) {
36+
return filename.replace(/\//g, '.');
37+
}
2738

28-
const normalizedBase = `${base}/`;
39+
const normalizedBase = isWindows ? normalizeWindowsPath(basePath) : basePath;
40+
const normalizedFilename = isWindows ? normalizeWindowsPath(filename) : filename;
2941

30-
// It's specifically a module
31-
let file = basename;
42+
// eslint-disable-next-line prefer-const
43+
let { dir, base: file, ext } = posix.parse(normalizedFilename);
3244

3345
if (ext === '.js' || ext === '.mjs' || ext === '.cjs') {
3446
file = file.slice(0, ext.length * -1);
3547
}
3648

37-
if (!root && !dir) {
49+
if (!dir) {
3850
// No dirname whatsoever
3951
dir = '.';
4052
}
4153

42-
let n = dir.lastIndexOf('/node_modules/');
54+
let n = dir.lastIndexOf('/node_modules');
4355
if (n > -1) {
44-
// /node_modules/ is 14 chars
4556
return `${dir.slice(n + 14).replace(/\//g, '.')}:${file}`;
4657
}
58+
4759
// Let's see if it's a part of the main module
4860
// To be a part of main module, it has to share the same base
4961
n = `${dir}/`.lastIndexOf(normalizedBase, 0);
50-
5162
if (n === 0) {
5263
let moduleName = dir.slice(normalizedBase.length).replace(/\//g, '.');
64+
5365
if (moduleName) {
5466
moduleName += ':';
5567
}
5668
moduleName += file;
69+
5770
return moduleName;
5871
}
72+
5973
return file;
6074
}

packages/node/test/module.test.ts

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,42 @@
11
import { getModuleFromFilename } from '../src/module';
22

3-
function withFilename(fn: () => void, filename: string) {
4-
const prevFilename = require.main?.filename;
5-
if (require.main?.filename) {
6-
require.main.filename = filename;
7-
}
8-
9-
try {
10-
fn();
11-
} finally {
12-
if (require.main && prevFilename) {
13-
require.main.filename = prevFilename;
14-
}
15-
}
16-
}
17-
183
describe('getModuleFromFilename', () => {
194
test('Windows', () => {
20-
withFilename(() => {
21-
expect(getModuleFromFilename('C:\\Users\\users\\Tim\\Desktop\\node_modules\\module.js', true)).toEqual('module');
22-
}, 'C:\\Users\\Tim\\app.js');
5+
expect(
6+
getModuleFromFilename('C:\\Users\\Tim\\node_modules\\some-dep\\module.js', 'C:\\Users\\Tim\\', true),
7+
).toEqual('some-dep:module');
8+
9+
expect(getModuleFromFilename('C:\\Users\\Tim\\some\\more\\feature.js', 'C:\\Users\\Tim\\', true)).toEqual(
10+
'some.more:feature',
11+
);
2312
});
2413

2514
test('POSIX', () => {
26-
withFilename(() => {
27-
expect(getModuleFromFilename('/Users/users/Tim/Desktop/node_modules/module.js')).toEqual('module');
28-
}, '/Users/Tim/app.js');
15+
expect(getModuleFromFilename('/Users/Tim/node_modules/some-dep/module.js', '/Users/Tim/')).toEqual(
16+
'some-dep:module',
17+
);
18+
19+
expect(getModuleFromFilename('/Users/Tim/some/more/feature.js', '/Users/Tim/')).toEqual('some.more:feature');
20+
expect(getModuleFromFilename('/Users/Tim/main.js', '/Users/Tim/')).toEqual('main');
21+
});
22+
23+
test('.mjs', () => {
24+
expect(getModuleFromFilename('/Users/Tim/node_modules/some-dep/module.mjs', '/Users/Tim/')).toEqual(
25+
'some-dep:module',
26+
);
2927
});
3028

31-
test('POSIX .mjs', () => {
32-
withFilename(() => {
33-
expect(getModuleFromFilename('/Users/users/Tim/Desktop/node_modules/module.mjs')).toEqual('module');
34-
}, '/Users/Tim/app.js');
29+
test('.cjs', () => {
30+
expect(getModuleFromFilename('/Users/Tim/node_modules/some-dep/module.cjs', '/Users/Tim/')).toEqual(
31+
'some-dep:module',
32+
);
3533
});
3634

37-
test('POSIX .cjs', () => {
38-
withFilename(() => {
39-
expect(getModuleFromFilename('/Users/users/Tim/Desktop/node_modules/module.cjs')).toEqual('module');
40-
}, '/Users/Tim/app.js');
35+
test('node internal', () => {
36+
expect(getModuleFromFilename('node.js', '/Users/Tim/')).toEqual('node');
37+
expect(getModuleFromFilename('node:internal/process/task_queues', '/Users/Tim/')).toEqual(
38+
'node:internal.process.task_queues',
39+
);
40+
expect(getModuleFromFilename('node:internal/timers', '/Users/Tim/')).toEqual('node:internal.timers');
4141
});
4242
});

0 commit comments

Comments
 (0)