Skip to content

Commit 87c6d94

Browse files
authored
fix: resolve absolute stack frame paths in the webpack compiler (#1446)
1 parent 9f3278c commit 87c6d94

3 files changed

Lines changed: 50 additions & 1 deletion

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@callstack/repack": patch
3+
---
4+
5+
Fix the webpack compiler double-joining absolute paths in `getSource`. The dev server resolves symbolicated stack frames to absolute paths before asking the compiler for their source, but the webpack compiler joined them onto the project root a second time, so the lookup failed. This only affected the fallback used when a frame's source is not embedded in the source map, for example with `nosources-*` devtools, and now matches the Rspack compiler.

packages/repack/src/commands/webpack/Compiler.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,9 @@ export class Compiler implements CompilerInterface {
276276
}
277277

278278
try {
279-
const filePath = path.join(this.rootDir, filename);
279+
const filePath = path.isAbsolute(filename)
280+
? filename
281+
: path.join(this.rootDir, filename);
280282
const source = await fs.promises.readFile(filePath, 'utf8');
281283
return source;
282284
} catch {

packages/repack/src/commands/webpack/__tests__/Compiler.test.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import type { EventEmitter } from 'node:events';
22
import { Worker } from 'node:worker_threads';
3+
import { fs, vol } from 'memfs';
34
import type { Reporter } from '../../../logging/types.js';
45
import { Compiler } from '../Compiler.js';
56

7+
jest.mock('node:fs', () => jest.requireActual('memfs').fs);
8+
69
jest.mock('node:worker_threads', () => {
710
const { EventEmitter } =
811
jest.requireActual<typeof import('node:events')>('node:events');
@@ -70,3 +73,42 @@ test('terminates active workers when closed', async () => {
7073

7174
expect(worker.terminate).toHaveBeenCalledTimes(1);
7275
});
76+
77+
describe('getSource', () => {
78+
const reporter: Reporter = {
79+
process: jest.fn(),
80+
flush: jest.fn(),
81+
stop: jest.fn(),
82+
};
83+
84+
const createCompiler = () =>
85+
new Compiler(['ios'], { host: '' }, reporter, '/project', '/react-native');
86+
87+
beforeEach(() => {
88+
vol.reset();
89+
});
90+
91+
afterEach(() => {
92+
jest.restoreAllMocks();
93+
});
94+
95+
test('reads an absolute filename as-is', async () => {
96+
vol.fromJSON({ '/outside/project/file.js': 'absolute source' });
97+
const readFile = jest.spyOn(fs.promises, 'readFile');
98+
99+
await expect(
100+
createCompiler().getSource('/outside/project/file.js', 'ios')
101+
).resolves.toBe('absolute source');
102+
expect(readFile).toHaveBeenCalledWith('/outside/project/file.js', 'utf8');
103+
});
104+
105+
test('resolves a relative filename against the project root', async () => {
106+
vol.fromJSON({ '/project/src/index.js': 'source under the project root' });
107+
const readFile = jest.spyOn(fs.promises, 'readFile');
108+
109+
await expect(
110+
createCompiler().getSource('src/index.js', 'ios')
111+
).resolves.toBe('source under the project root');
112+
expect(readFile).toHaveBeenCalledWith('/project/src/index.js', 'utf8');
113+
});
114+
});

0 commit comments

Comments
 (0)