@callstack/repack-dev-server 5.4.0-canary-20260913161840 → 5.4.0-canary-20260926141655

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import { URL } from 'node:url';
2
2
  import { codeFrameColumns } from '@babel/code-frame';
3
3
  import { SourceMapConsumer } from 'source-map';
4
- import { isGeneratedBundleFrame, isSymbolicatableFrame, normalizeInvalidWebpackSourceUrls, } from '../../utils/symbolication.js';
4
+ import { decodeSourceName, escapeSourceName, isGeneratedBundleFrame, isSymbolicatableFrame, prepareSourceMap, } from '../../utils/symbolication.js';
5
5
  /**
6
6
  * Class for transforming stack traces from React Native application with using Source Map.
7
7
  * Raw stack frames produced by React Native, points to some location from the bundle
@@ -77,7 +77,7 @@ export class Symbolicator {
77
77
  fileUrl: frame.file,
78
78
  sourceMapLength: rawSourceMap.length,
79
79
  });
80
- const sourceMapConsumer = await new SourceMapConsumer(normalizeInvalidWebpackSourceUrls(rawSourceMap));
80
+ const sourceMapConsumer = await new SourceMapConsumer(prepareSourceMap(rawSourceMap));
81
81
  logger.debug({
82
82
  msg: 'Saving source map instance into cache',
83
83
  fileUrl: frame.file,
@@ -157,7 +157,7 @@ export class Symbolicator {
157
157
  return {
158
158
  lineNumber: lookup.line ?? frame.lineNumber,
159
159
  column: lookup.column ?? frame.column,
160
- file: lookup.source,
160
+ file: decodeSourceName(lookup.source),
161
161
  methodName: lookup.name || frame.methodName,
162
162
  collapse: false,
163
163
  };
@@ -179,7 +179,7 @@ export class Symbolicator {
179
179
  });
180
180
  try {
181
181
  const consumer = sourceMapConsumers.get(inputFrames[index]?.file);
182
- const embeddedSource = consumer?.sourceContentFor(frame.file, true);
182
+ const embeddedSource = consumer?.sourceContentFor(escapeSourceName(frame.file), true);
183
183
  const source = embeddedSource ??
184
184
  (await this.delegate.getSource(frame.file)).toString();
185
185
  return {
@@ -2,7 +2,14 @@ import type { RawIndexMap, RawSourceMap } from 'source-map';
2
2
  interface StackFrameLike {
3
3
  file: string | null;
4
4
  }
5
- export declare function normalizeInvalidWebpackSourceUrls(rawSourceMap: string | Buffer): string | RawSourceMap | RawIndexMap;
5
+ export declare function escapeSourceName(source: string): string;
6
+ export declare function decodeSourceName(source: string): string;
7
+ /**
8
+ * Prepare a raw source map for `SourceMapConsumer`: replace webpack source
9
+ * URLs that would make it reject the map and escape every source name, so
10
+ * names returned by the consumer can be restored with `decodeSourceName`.
11
+ */
12
+ export declare function prepareSourceMap(rawSourceMap: string | Buffer): RawSourceMap | RawIndexMap;
6
13
  export declare function isGeneratedBundleFrame(frame: StackFrameLike): boolean;
7
14
  export declare function isSymbolicatableFrame<T extends StackFrameLike>(frame: T): frame is T & {
8
15
  file: string;
@@ -1,10 +1,22 @@
1
1
  import { URL } from 'node:url';
2
- export function normalizeInvalidWebpackSourceUrls(rawSourceMap) {
3
- const sourceMapText = rawSourceMap.toString();
4
- if (!sourceMapText.includes('webpack://')) {
5
- return sourceMapText;
6
- }
7
- const sourceMap = JSON.parse(sourceMapText);
2
+ // `source-map` normalises every source name through `new URL()`, which
3
+ // percent-encodes characters such as spaces, non-ASCII letters and the caret
4
+ // in `[projectRoot^N]`. Escaping `%` before the consumer reads the map makes
5
+ // `decodeSourceName` an exact inverse, so a file name that contains `%` keeps
6
+ // it instead of being decoded a second time.
7
+ export function escapeSourceName(source) {
8
+ return source.replaceAll('%', '%25');
9
+ }
10
+ export function decodeSourceName(source) {
11
+ return decodeURIComponent(source);
12
+ }
13
+ /**
14
+ * Prepare a raw source map for `SourceMapConsumer`: replace webpack source
15
+ * URLs that would make it reject the map and escape every source name, so
16
+ * names returned by the consumer can be restored with `decodeSourceName`.
17
+ */
18
+ export function prepareSourceMap(rawSourceMap) {
19
+ const sourceMap = JSON.parse(rawSourceMap.toString());
8
20
  let invalidSourceIndex = 0;
9
21
  const normalize = (map) => {
10
22
  if (!map || typeof map !== 'object') {
@@ -18,11 +30,11 @@ export function normalizeInvalidWebpackSourceUrls(rawSourceMap) {
18
30
  }
19
31
  const normalizedSource = source.replace(/^webpack:\/\/([^/|]+)\|\/?/, 'webpack://$1/');
20
32
  if (!normalizedSource.startsWith('webpack://')) {
21
- return normalizedSource;
33
+ return escapeSourceName(normalizedSource);
22
34
  }
23
35
  try {
24
36
  new URL(normalizedSource);
25
- return normalizedSource;
37
+ return escapeSourceName(normalizedSource);
26
38
  }
27
39
  catch {
28
40
  // Some generated Module Federation runtime modules use their source
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@callstack/repack-dev-server",
3
3
  "description": "A bundler-agnostic development server for React Native applications as part of @callstack/repack.",
4
4
  "license": "MIT",
5
- "version": "5.4.0-canary-20260913161840",
5
+ "version": "5.4.0-canary-20260926141655",
6
6
  "type": "module",
7
7
  "main": "./dist/index.js",
8
8
  "types": "./dist/index.d.ts",