diff --git a/packages/metro/src/HmrServer.js b/packages/metro/src/HmrServer.js index 9396b632f6..c803f0a34c 100644 --- a/packages/metro/src/HmrServer.js +++ b/packages/metro/src/HmrServer.js @@ -28,6 +28,7 @@ import debounceAsyncQueue from './lib/debounceAsyncQueue'; import formatBundlingError from './lib/formatBundlingError'; import getGraphId from './lib/getGraphId'; import parseBundleOptionsFromBundleRequestUrl from './lib/parseBundleOptionsFromBundleRequestUrl'; +import RootUrlMap from './lib/RootUrlMap'; import splitBundleOptions from './lib/splitBundleOptions'; import * as transformHelpers from './lib/transformHelpers'; import debugModule from 'debug'; @@ -71,6 +72,7 @@ export default class HmrServer { _bundler: IncrementalBundler; _createModuleId: (path: string) => number; _clientGroups: Map; + _rootUrlMap: RootUrlMap; constructor( bundler: IncrementalBundler, @@ -81,6 +83,7 @@ export default class HmrServer { this._bundler = bundler; this._createModuleId = createModuleId; this._clientGroups = new Map(); + this._rootUrlMap = new RootUrlMap(config); } onClientConnect: ( @@ -121,19 +124,19 @@ export default class HmrServer { transformOptions.platform, resolverOptions, ); - const resolvedEntryFilePath = resolutionFn( - (this._config.server.unstable_serverRoot ?? this._config.projectRoot) + - '/.', - { - name: entryFile, - data: { - key: entryFile, - asyncType: null, - isESMImport: false, - locs: [], - }, + const absolutePath = + this._rootUrlMap.filePathOfUrlDecodedPathname(entryFile); + const rootDir = absolutePath != null ? '/' : this._rootUrlMap.serverRootDir; + const resolvedEntryFile = absolutePath ?? entryFile; + const resolvedEntryFilePath = resolutionFn(rootDir + '/.', { + name: resolvedEntryFile, + data: { + key: resolvedEntryFile, + asyncType: null, + isESMImport: false, + locs: [], }, - ).filePath; + }).filePath; const graphId = getGraphId(resolvedEntryFilePath, transformOptions, { resolverOptions, shallow: graphOptions.shallow, @@ -379,8 +382,7 @@ export default class HmrServer { createModuleId: this._createModuleId, includeAsyncPaths: group.graphOptions.lazy, projectRoot: this._config.projectRoot, - serverRoot: - this._config.server.unstable_serverRoot ?? this._config.projectRoot, + serverRoot: this._rootUrlMap.serverRootDir, }); logger?.point('serialize_end'); diff --git a/packages/metro/src/__tests__/HmrServer-test.js b/packages/metro/src/__tests__/HmrServer-test.js index 15a2e1d266..70d23172cb 100644 --- a/packages/metro/src/__tests__/HmrServer-test.js +++ b/packages/metro/src/__tests__/HmrServer-test.js @@ -131,6 +131,7 @@ describe('HmrServer', () => { unstable_allowRequireContext: false, }, resolver: {platforms: []}, + watchFolders: [p('/external/node_modules')], server: { rewriteRequestUrl(requrl) { const rewritten = requrl.replace( @@ -650,6 +651,60 @@ describe('HmrServer', () => { ]); }); + test('should resolve [metro-watchFolders] prefix in entry point', async () => { + await connect( + '/hot?bundleEntry=./[metro-watchFolders]/0/expo-router/entry.js&platform=ios', + ); + + expect(getRevisionByGraphIdMock).toBeCalledWith( + getGraphId( + p('/external/node_modules/expo-router/entry.js'), + { + customTransformOptions: {}, + dev: true, + minify: false, + platform: 'ios', + type: 'module', + unstable_transformProfile: 'default', + }, + { + shallow: false, + lazy: false, + unstable_allowRequireContext: false, + resolverOptions: { + dev: true, + }, + }, + ), + ); + }); + + test('should resolve [metro-project] prefix in entry point', async () => { + await connect('/hot?bundleEntry=./[metro-project]/src/App.js&platform=ios'); + + expect(getRevisionByGraphIdMock).toBeCalledWith( + getGraphId( + p('/root/src/App.js'), + { + customTransformOptions: {}, + dev: true, + minify: false, + platform: 'ios', + type: 'module', + unstable_transformProfile: 'default', + }, + { + shallow: false, + lazy: false, + unstable_allowRequireContext: false, + resolverOptions: { + dev: true, + }, + }, + ), + ); + }); + test('should return error messages when there is a transform error', async () => { jest.useRealTimers(); const sendMessage = jest.fn();