@@ -32,6 +32,15 @@ import resolveAsset from './resolveAsset';
32
32
import isAssetFile from './utils/isAssetFile' ;
33
33
import path from 'path' ;
34
34
35
+ type ParsedBareSpecifier = $ReadOnly < {
36
+ isSinglePart : boolean ,
37
+ isValidPackageName : boolean ,
38
+ firstPart : string ,
39
+ normalizedSpecifier : string ,
40
+ packageName : string ,
41
+ posixSubpath : string ,
42
+ } > ;
43
+
35
44
function resolve (
36
45
context : ResolutionContext ,
37
46
moduleName : string ,
@@ -94,14 +103,24 @@ function resolve(
94
103
95
104
/**
96
105
* At this point, realModuleName is not a "direct" (absolute or relative)
97
- * import, so it's either Haste name or a package specifier.
106
+ * import, so it's a bare specifier - for our purposes either Haste name
107
+ * or a package specifier.
98
108
*/
99
109
110
+ const parsedSpecifier = parseBareSpecifier ( realModuleName ) ;
111
+
100
112
if ( context . allowHaste ) {
101
- const normalizedName = normalizePath ( realModuleName ) ;
102
- const result = resolveHasteName ( context , normalizedName , platform ) ;
103
- if ( result . type === 'resolved' ) {
104
- return result . resolution ;
113
+ if ( parsedSpecifier . isSinglePart ) {
114
+ const result = context . resolveHasteModule ( parsedSpecifier . firstPart ) ;
115
+ if ( result != null ) {
116
+ return { type : 'sourceFile' , filePath : result } ;
117
+ }
118
+ }
119
+ if ( parsedSpecifier . isValidPackageName ) {
120
+ const result = resolveHastePackage ( context , parsedSpecifier , platform ) ;
121
+ if ( result . type === 'resolved' ) {
122
+ return result . resolution ;
123
+ }
105
124
}
106
125
}
107
126
@@ -131,8 +150,6 @@ function resolve(
131
150
132
151
const extraPaths = [ ] ;
133
152
134
- const parsedSpecifier = parsePackageSpecifier ( realModuleName ) ;
135
-
136
153
const { extraNodeModules} = context ;
137
154
if ( extraNodeModules && extraNodeModules [ parsedSpecifier . packageName ] ) {
138
155
const newPackageName = extraNodeModules [ parsedSpecifier . packageName ] ;
@@ -179,35 +196,51 @@ function resolve(
179
196
throw new FailedToResolveNameError ( nodeModulesPaths , extraPaths ) ;
180
197
}
181
198
182
- function parsePackageSpecifier ( specifier : string ) {
199
+ function parseBareSpecifier ( specifier : string ) : ParsedBareSpecifier {
183
200
const normalized =
184
201
path . sep === '/' ? specifier : specifier . replaceAll ( '\\' , '/' ) ;
185
202
const firstSepIdx = normalized . indexOf ( '/' ) ;
186
203
if ( normalized . startsWith ( '@' ) && firstSepIdx !== - 1 ) {
187
204
const secondSepIdx = normalized . indexOf ( '/' , firstSepIdx + 1 ) ;
188
205
if ( secondSepIdx === - 1 ) {
206
+ // @foo /bar (valid scoped, no subpath)
189
207
return {
208
+ isSinglePart : false ,
209
+ isValidPackageName : true ,
190
210
firstPart : normalized . slice ( 0 , firstSepIdx ) ,
211
+ normalizedSpecifier : normalized ,
191
212
packageName : normalized ,
192
213
posixSubpath : '.' ,
193
214
} ;
194
215
}
216
+ // @foo /bar[/subpath] (valid scoped with subpath)
195
217
return {
218
+ isSinglePart : false ,
219
+ isValidPackageName : true ,
196
220
firstPart : normalized . slice ( 0 , firstSepIdx ) ,
221
+ normalizedSpecifier : normalized ,
197
222
packageName : normalized . slice ( 0 , secondSepIdx ) ,
198
223
posixSubpath : '.' + normalized . slice ( secondSepIdx ) ,
199
224
} ;
200
225
}
226
+ // foo or @foo , no subpath. Valid if doesn't start with '@'.
201
227
if ( firstSepIdx === - 1 ) {
202
228
return {
229
+ isSinglePart : true ,
230
+ isValidPackageName : ! normalized . startsWith ( '@' ) ,
203
231
firstPart : normalized ,
232
+ normalizedSpecifier : normalized ,
204
233
packageName : normalized ,
205
234
posixSubpath : '.' ,
206
235
} ;
207
236
}
208
237
const packageName = normalized . slice ( 0 , firstSepIdx ) ;
238
+ // foo/subpath, valid, not scoped, with subpath
209
239
return {
240
+ isSinglePart : false ,
241
+ isValidPackageName : true ,
210
242
firstPart : packageName ,
243
+ normalizedSpecifier : normalized ,
211
244
packageName,
212
245
posixSubpath : '.' + normalized . slice ( firstSepIdx ) ,
213
246
} ;
@@ -260,31 +293,22 @@ function resolveModulePath(
260
293
}
261
294
262
295
/**
263
- * Resolve a module as a Haste module or package. For example we might try to
264
- * resolve `Foo`, that is provided by file `/smth/Foo.js`. Or, in the case of
265
- * a Haste package, it could be `/smth/Foo/index.js`.
296
+ * Resolve a specifier as a Haste package.
266
297
*/
267
- function resolveHasteName (
298
+ function resolveHastePackage (
268
299
context : ResolutionContext ,
269
- moduleName : string ,
300
+ {
301
+ normalizedSpecifier : moduleName ,
302
+ packageName,
303
+ posixSubpath : pathInModule ,
304
+ } : ParsedBareSpecifier ,
270
305
platform : string | null ,
271
306
) : Result < Resolution , void > {
272
- const modulePath = context . resolveHasteModule ( moduleName ) ;
273
- if ( modulePath != null ) {
274
- return resolvedAs ( { type : 'sourceFile' , filePath : modulePath } ) ;
275
- }
276
- let packageName = moduleName ;
277
- let packageJsonPath = context . resolveHastePackage ( packageName ) ;
278
- while ( packageJsonPath == null && packageName && packageName !== '.' ) {
279
- packageName = path . dirname ( packageName ) ;
280
- packageJsonPath = context . resolveHastePackage ( packageName ) ;
281
- }
307
+ const packageJsonPath = context . resolveHastePackage ( packageName ) ;
282
308
if ( packageJsonPath == null ) {
283
309
return failedFor ( ) ;
284
310
}
285
- const packageDirPath = path . dirname ( packageJsonPath ) ;
286
- const pathInModule = moduleName . substring ( packageName . length + 1 ) ;
287
- const potentialModulePath = path . join ( packageDirPath , pathInModule ) ;
311
+ const potentialModulePath = path . join ( packageJsonPath , '..' , pathInModule ) ;
288
312
const result = resolvePackage ( context , potentialModulePath , platform ) ;
289
313
if ( result . type === 'resolved' ) {
290
314
return result ;
@@ -309,7 +333,7 @@ class MissingFileInHastePackageError extends Error {
309
333
super (
310
334
`While resolving module \`${ opts . moduleName } \`, ` +
311
335
`the Haste package \`${ opts . packageName } \` was found. However the ` +
312
- `module \`${ opts . pathInModule } \` could not be found within ` +
336
+ `subpath \`${ opts . pathInModule } \` could not be found within ` +
313
337
'the package. Indeed, none of these files exist:\n\n' +
314
338
[ opts . candidates . file , opts . candidates . dir ]
315
339
. filter ( Boolean )
@@ -588,16 +612,6 @@ function isRelativeImport(filePath: string) {
588
612
return / ^ [ . ] [ . ] ?( ?:[ / ] | $ ) / . test ( filePath ) ;
589
613
}
590
614
591
- function normalizePath(modulePath: any | string) {
592
- if ( path . sep === '/' ) {
593
- modulePath = path . normalize ( modulePath ) ;
594
- } else if (path.posix) {
595
- modulePath = path . posix . normalize ( modulePath ) ;
596
- }
597
-
598
- return modulePath.replace(/\/$/, '');
599
- }
600
-
601
615
function resolvedAs < TResolution , TCandidates > (
602
616
resolution : TResolution ,
603
617
) : Result < TResolution , TCandidates > {
0 commit comments