Skip to content

Commit

Permalink
Optionally emit URL paths in source maps
Browse files Browse the repository at this point in the history
Summary:
Changelog:
* **[Feature]:** Emit URL paths in source maps if passed the `sourcePaths=url-server` bundle parameter.

The URL paths are the ones that Metro gained the ability to serve in D56952064.

Reviewed By: GijsWeterings

Differential Revision: D56952063

fbshipit-source-id: ac6d2fd6e0ff1ebcd5ea368afa452589b96c3132
  • Loading branch information
motiz88 authored and facebook-github-bot committed May 8, 2024
1 parent 40ce24f commit 788ff0d
Show file tree
Hide file tree
Showing 14 changed files with 105 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ it('should generate a very simple bundle', () => {
shouldAddToIgnoreList: () => false,
sourceMapUrl: 'http://localhost/bundle.map',
sourceUrl: null,
getSourceUrl: null,
},
),
).toMatchInlineSnapshot(`
Expand Down Expand Up @@ -170,6 +171,7 @@ it('should add runBeforeMainModule statements if found in the graph', () => {
shouldAddToIgnoreList: () => false,
sourceMapUrl: 'http://localhost/bundle.map',
sourceUrl: null,
getSourceUrl: null,
},
).post,
).toMatchInlineSnapshot(`
Expand Down Expand Up @@ -208,6 +210,7 @@ it('should handle numeric module ids', () => {
shouldAddToIgnoreList: () => false,
sourceMapUrl: 'http://localhost/bundle.map',
sourceUrl: null,
getSourceUrl: null,
},
).modules,
).toMatchInlineSnapshot(`
Expand Down Expand Up @@ -255,6 +258,7 @@ it('outputs custom runModule statements', () => {
shouldAddToIgnoreList: () => false,
sourceMapUrl: null,
sourceUrl: null,
getSourceUrl: null,
},
).post,
).toMatchInlineSnapshot(`
Expand Down Expand Up @@ -292,6 +296,7 @@ it('should add an inline source map to a very simple bundle', () => {
shouldAddToIgnoreList: () => false,
sourceMapUrl: null,
sourceUrl: null,
getSourceUrl: null,
},
);
expect(bundle.post.slice(0, bundle.post.lastIndexOf('base64'))).toEqual(
Expand Down Expand Up @@ -342,6 +347,7 @@ it('emits x_google_ignoreList based on shouldAddToIgnoreList', () => {
shouldAddToIgnoreList: () => true,
sourceMapUrl: null,
sourceUrl: null,
getSourceUrl: null,
},
);
expect(bundle.post.slice(0, bundle.post.lastIndexOf('base64'))).toEqual(
Expand Down Expand Up @@ -392,6 +398,7 @@ it('does not add polyfills when `modulesOnly` is used', () => {
shouldAddToIgnoreList: () => false,
sourceMapUrl: 'http://localhost/bundle.map',
sourceUrl: null,
getSourceUrl: null,
},
),
).toMatchInlineSnapshot(`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ it('should return the RAM bundle info', async () => {
shouldAddToIgnoreList: () => false,
sourceMapUrl: 'http://localhost/bundle.map',
sourceUrl: null,
getSourceUrl: null,
},
),
).toMatchSnapshot();
Expand Down Expand Up @@ -140,6 +141,7 @@ it('emits x_google_ignoreList based on shouldAddToIgnoreList', async () => {
shouldAddToIgnoreList: () => true,
sourceMapUrl: 'http://localhost/bundle.map',
sourceUrl: null,
getSourceUrl: null,
},
),
).toMatchSnapshot();
Expand Down Expand Up @@ -175,6 +177,7 @@ it('should use the preloadedModules and ramGroup configs to build a RAM bundle',
shouldAddToIgnoreList: () => false,
sourceMapUrl: 'http://localhost/bundle.map',
sourceUrl: null,
getSourceUrl: null,
},
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ it('should serialize a very simple bundle', () => {
excludeSource: false,
processModuleFilter: module => true,
shouldAddToIgnoreList: module => false,
getSourceUrl: null,
}),
),
).toEqual({
Expand All @@ -103,6 +104,7 @@ it('modules should appear in their original order', () => {
excludeSource: false,
processModuleFilter: module => true,
shouldAddToIgnoreList: module => false,
getSourceUrl: null,
}),
),
).toEqual({
Expand Down Expand Up @@ -141,6 +143,7 @@ it('should not include the source of an asset', () => {
excludeSource: false,
processModuleFilter: module => true,
shouldAddToIgnoreList: module => false,
getSourceUrl: null,
}),
),
).toEqual({
Expand All @@ -160,6 +163,7 @@ it('should emit x_google_ignoreList based on shouldAddToIgnoreList', () => {
excludeSource: false,
processModuleFilter: module => true,
shouldAddToIgnoreList: module => true,
getSourceUrl: null,
}),
),
).toEqual({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ function baseJSBundle(
shouldAddToIgnoreList: options.shouldAddToIgnoreList,
sourceMapUrl: options.sourceMapUrl,
sourceUrl: options.sourceUrl,
getSourceUrl: options.getSourceUrl,
}),
processModulesOptions,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ async function getRamBundleInfo(
excludeSource: options.excludeSource,
processModuleFilter: options.processModuleFilter,
shouldAddToIgnoreList: options.shouldAddToIgnoreList,
getSourceUrl: options.getSourceUrl,
}),
name: path.basename(module.path),
sourcePath: module.path,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ function getSourceMapInfo(
options: {
+excludeSource: boolean,
+shouldAddToIgnoreList: (Module<>) => boolean,
getSourceUrl: ?(module: Module<>) => string,
},
): {
+map: Array<MetroSourceMapSegmentTuple>,
Expand All @@ -37,7 +38,7 @@ function getSourceMapInfo(
return {
...getJsOutput(module).data,
isIgnored: options.shouldAddToIgnoreList(module),
path: module.path,
path: options?.getSourceUrl?.(module) ?? module.path,
source: options.excludeSource ? '' : getModuleSource(module),
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export type SourceMapGeneratorOptions = $ReadOnly<{
excludeSource: boolean,
processModuleFilter: (module: Module<>) => boolean,
shouldAddToIgnoreList: (module: Module<>) => boolean,
getSourceUrl: ?(module: Module<>) => string,
}>;

function getSourceMapInfosImpl(
Expand All @@ -46,6 +47,7 @@ function getSourceMapInfosImpl(
const info = getSourceMapInfo(mod, {
excludeSource: options.excludeSource,
shouldAddToIgnoreList: options.shouldAddToIgnoreList,
getSourceUrl: options.getSourceUrl,
});
sourceMapInfos.push(info);
return false;
Expand Down
1 change: 1 addition & 0 deletions packages/metro/src/DeltaBundler/types.flow.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,5 @@ export type SerializerOptions = $ReadOnly<{
shouldAddToIgnoreList: (Module<>) => boolean,
sourceMapUrl: ?string,
sourceUrl: ?string,
getSourceUrl: ?(Module<>) => string,
}>;
41 changes: 41 additions & 0 deletions packages/metro/src/Server.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ import type {
import type {CustomResolverOptions} from 'metro-resolver/src/types';
import type {CustomTransformOptions} from 'metro-transform-worker';

import {SourcePathsMode} from './shared/types.flow';

const {getAsset} = require('./Assets');
const baseJSBundle = require('./DeltaBundler/Serializers/baseJSBundle');
const getAllFiles = require('./DeltaBundler/Serializers/getAllFiles');
Expand Down Expand Up @@ -262,6 +264,8 @@ class Server {
this._config.server.unstable_serverRoot ?? this._config.projectRoot,
shouldAddToIgnoreList: (module: Module<>) =>
this._shouldAddModuleToIgnoreList(module),
getSourceUrl: (module: Module<>) =>
this._getModuleSourceUrl(module, serializerOptions.sourcePaths),
};
let bundleCode = null;
let bundleMap = null;
Expand Down Expand Up @@ -290,6 +294,8 @@ class Server {
excludeSource: serializerOptions.excludeSource,
processModuleFilter: this._config.serializer.processModuleFilter,
shouldAddToIgnoreList: bundleOptions.shouldAddToIgnoreList,
getSourceUrl: (module: Module<>) =>
this._getModuleSourceUrl(module, serializerOptions.sourcePaths),
},
);
}
Expand Down Expand Up @@ -353,6 +359,8 @@ class Server {
this._config.server.unstable_serverRoot ?? this._config.projectRoot,
shouldAddToIgnoreList: (module: Module<>) =>
this._shouldAddModuleToIgnoreList(module),
getSourceUrl: (module: Module<>) =>
this._getModuleSourceUrl(module, serializerOptions.sourcePaths),
});
}

Expand Down Expand Up @@ -1000,6 +1008,8 @@ class Server {
this._config.server.unstable_serverRoot ?? this._config.projectRoot,
shouldAddToIgnoreList: (module: Module<>) =>
this._shouldAddModuleToIgnoreList(module),
getSourceUrl: (module: Module<>) =>
this._getModuleSourceUrl(module, serializerOptions.sourcePaths),
},
);
bundlePerfLogger.point('serializingBundle_end');
Expand Down Expand Up @@ -1146,6 +1156,8 @@ class Server {
processModuleFilter: this._config.serializer.processModuleFilter,
shouldAddToIgnoreList: (module: Module<>) =>
this._shouldAddModuleToIgnoreList(module),
getSourceUrl: (module: Module<>) =>
this._getModuleSourceUrl(module, serializerOptions.sourcePaths),
});
},
finish({mres, result}) {
Expand Down Expand Up @@ -1451,6 +1463,7 @@ class Server {
shallow: false,
sourceMapUrl: null,
sourceUrl: null,
sourcePaths: SourcePathsMode,
} = {
...Server.DEFAULT_GRAPH_OPTIONS,
excludeSource: false,
Expand All @@ -1462,6 +1475,7 @@ class Server {
shallow: false,
sourceMapUrl: null,
sourceUrl: null,
sourcePaths: SourcePathsMode.Absolute,
};

_getServerRootDir(): string {
Expand All @@ -1488,6 +1502,33 @@ class Server {
this._config.serializer.isThirdPartyModule(module)
);
}

// Flow checking is enough to ensure that a value is returned in all cases.
// eslint-disable-next-line consistent-return
_getModuleSourceUrl(module: Module<>, mode: SourcePathsMode): string {
switch (mode) {
case SourcePathsMode.ServerUrl:
for (const [pathnamePrefix, normalizedRootDir] of this
._sourceRequestRoutingMap) {
if (module.path.startsWith(normalizedRootDir + path.sep)) {
const relativePath = module.path.slice(
normalizedRootDir.length + 1,
);
const relativePathPosix = relativePath.split(path.sep).join('/');
return pathnamePrefix + encodeURI(relativePathPosix);
}
}
// Ordinarily all files should match one of the roots above. If they
// don't, try to preserve useful information, even if fetching the path
// from Metro might fail.
const modulePathPosix = module.path.split(path.sep).join('/');
return modulePathPosix.startsWith('/')
? encodeURI(modulePathPosix)
: '/' + encodeURI(modulePathPosix);
case SourcePathsMode.Absolute:
return module.path;
}
}
}

function* zip<X, Y>(xs: Iterable<X>, ys: Iterable<Y>): Iterable<[X, Y]> {
Expand Down
27 changes: 27 additions & 0 deletions packages/metro/src/Server/__tests__/Server-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,33 @@ describe('processRequest', () => {
});
});

test('sourcePaths=url-server mode', async () => {
const response = await makeRequest('mybundle.map?sourcePaths=url-server');

expect(response._getJSON()).toEqual({
version: 3,
sources: [
'/require-js',
'/[metro-project]/mybundle.js',
'/[metro-project]/foo.js',
],
sourcesContent: ['code-require', 'code-mybundle', 'code-foo'],
names: [],
mappings: ';gBCAA;gBCAA',
x_facebook_sources: [
null,
null,
[
{
mappings: 'AAA',
names: ['<global>'],
},
],
],
x_google_ignoreList: [2],
});
});

it('passes in the unstable_transformProfile param', async () => {
await makeRequest('index.bundle?unstable_transformProfile=hermes-stable');

Expand Down
2 changes: 2 additions & 0 deletions packages/metro/src/lib/getAppendScripts.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type Options<T: number | string> = $ReadOnly<{
shouldAddToIgnoreList: (Module<>) => boolean,
sourceMapUrl: ?string,
sourceUrl: ?string,
getSourceUrl: ?(Module<>) => string,
...
}>;

Expand Down Expand Up @@ -75,6 +76,7 @@ function getAppendScripts<T: number | string>(
processModuleFilter: (): boolean => true,
excludeSource: false,
shouldAddToIgnoreList: options.shouldAddToIgnoreList,
getSourceUrl: options.getSourceUrl,
}),
)
: nullthrows(options.sourceMapUrl);
Expand Down
4 changes: 4 additions & 0 deletions packages/metro/src/lib/parseOptionsFromUrl.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import type {BundleOptions} from '../shared/types.flow';
import type {TransformProfile} from 'metro-babel-transformer';

import {SourcePathsMode} from '../shared/types.flow';

const parsePlatformFilePath = require('../node-haste/lib/parsePlatformFilePath');
const parseCustomResolverOptions = require('./parseCustomResolverOptions');
const parseCustomTransformOptions = require('./parseCustomTransformOptions');
Expand Down Expand Up @@ -81,6 +83,8 @@ module.exports = function parseOptionsFromUrl(
: '',
pathname: pathname.replace(/\.(bundle|delta)$/, '.map'),
}),
sourcePaths:
SourcePathsMode.cast(query.sourcePaths) ?? SourcePathsMode.Absolute,
sourceUrl: jscSafeUrl.toJscSafeUrl(normalizedRequestUrl),
unstable_transformProfile: getTransformProfile(
query.unstable_transformProfile,
Expand Down
1 change: 1 addition & 0 deletions packages/metro/src/lib/splitBundleOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ function splitBundleOptions(options: BundleOptions): SplitBundleOptions {
runModule: options.runModule,
sourceMapUrl: options.sourceMapUrl,
sourceUrl: options.sourceUrl,
sourcePaths: options.sourcePaths,
},
graphOptions: {
shallow: options.shallow,
Expand Down
9 changes: 9 additions & 0 deletions packages/metro/src/shared/types.flow.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ type MetroSourceMapOrMappings =
| MixedSourceMap
| Array<MetroSourceMapSegmentTuple>;

export enum SourcePathsMode {
/* Use absolute paths for source files in source maps (default). */
Absolute = 'absolute',
/* Use server-relative URL paths for source files in source maps. */
ServerUrl = 'url-server',
}

export type BundleOptions = {
bundleType: BundleType,
+customResolverOptions: CustomResolverOptions,
Expand All @@ -61,6 +68,7 @@ export type BundleOptions = {
sourceUrl: ?string,
createModuleIdFactory?: () => (path: string) => number,
+unstable_transformProfile: TransformProfile,
+sourcePaths: SourcePathsMode,
};

export type ResolverInputOptions = $ReadOnly<{
Expand All @@ -75,6 +83,7 @@ export type SerializerOptions = {
+excludeSource: boolean,
+inlineSourceMap: boolean,
+modulesOnly: boolean,
+sourcePaths: SourcePathsMode,
};

export type GraphOptions = {
Expand Down

0 comments on commit 788ff0d

Please sign in to comment.