11// @flow
22import { flattenDeep , uniq , values } from 'lodash' ;
3+ import resolve from 'browser-resolve' ;
34
45import * as pathUtils from 'common/utils/path' ;
56
67import type { Module } from './entities/module' ;
78import TranspiledModule from './transpiled-module' ;
89import Preset from './presets' ;
9- import nodeResolvePath from './utils/node-resolve-path' ;
10- import fetchModule from './npm/fetch-npm-module' ;
10+ import fetchModule , { getCombinedMetas } from './npm/fetch-npm-module' ;
11+ import coreLibraries from './npm/get-core-libraries' ;
12+ import getDependencyName from './utils/get-dependency-name' ;
1113import DependencyNotFoundError from '../errors/dependency-not-found-error' ;
1214import ModuleNotFoundError from '../errors/module-not-found-error' ;
1315
@@ -20,15 +22,21 @@ type ModuleObject = {
2022} ;
2123
2224export type Manifest = {
23- aliases : {
24- [ path : string ] : string | false ,
25- } ,
2625 contents : {
2726 [ path : string ] : { content : string , requires : Array < string > } ,
2827 } ,
2928 dependencies : Array < { name : string , version : string } > ,
3029 dependencyDependencies : {
31- [ name : string ] : string ,
30+ [ name : string ] : {
31+ semver : string ,
32+ resolved : string ,
33+ parents : string [ ] ,
34+ } ,
35+ } ,
36+ dependencyAliases : {
37+ [ name : string ] : {
38+ [ depName : string ] : string ,
39+ } ,
3240 } ,
3341} ;
3442
@@ -73,8 +81,21 @@ export default class Manager {
7381 this . externals = externals ;
7482 }
7583
76- setManifest ( manifest : Manifest ) {
77- this . manifest = manifest ;
84+ setManifest ( manifest : ?Manifest ) {
85+ this . manifest = manifest || {
86+ contents : { } ,
87+ dependencies : [ ] ,
88+ dependencyDependencies : { } ,
89+ dependencyAliases : { } ,
90+ } ;
91+
92+ Object . keys ( this . manifest . contents ) . forEach ( path => {
93+ this . addModule ( {
94+ path,
95+ code : this . manifest . contents [ path ] . content ,
96+ requires : this . manifest . contents [ path ] . requires ,
97+ } ) ;
98+ } ) ;
7899 }
79100
80101 evaluateModule ( module : Module ) {
@@ -187,94 +208,102 @@ export default class Manager {
187208 return values ( this . transpiledModules ) . map ( t => t . module ) ;
188209 }
189210
190- resolveModule (
191- path : string ,
192- defaultExtensions : Array < string > = [ 'js' , 'jsx' , 'json' ]
193- ) : Module {
194- const moduleObject = this . transpiledModules ;
195- const foundPath = nodeResolvePath ( path , moduleObject , defaultExtensions ) ;
211+ getAliasedDependencyPath ( path : string , currentPath : string ) {
212+ const isDependency = / ^ ( \w | @ \w ) / . test ( path ) ;
213+
214+ if ( ! isDependency ) {
215+ return path ;
216+ }
196217
197- if ( foundPath && moduleObject [ foundPath ] ) {
198- return moduleObject [ foundPath ] . module ;
218+ const isCurrentPathDependency = currentPath . startsWith ( '/node_modules' ) ;
219+ if ( ! isCurrentPathDependency ) {
220+ return path ;
199221 }
200222
201- throw new ModuleNotFoundError ( path , false ) ;
223+ const dependencyName = getDependencyName ( path ) ;
224+ const previousDependencyName = getDependencyName ( currentPath ) ;
225+
226+ if (
227+ this . manifest . dependencyAliases [ previousDependencyName ] &&
228+ this . manifest . dependencyAliases [ previousDependencyName ] [ dependencyName ]
229+ ) {
230+ const aliasedDependencyName = this . manifest . dependencyAliases [
231+ previousDependencyName
232+ ] [ dependencyName ] ;
233+
234+ return path . replace ( dependencyName , aliasedDependencyName ) ;
235+ }
236+
237+ return path ;
202238 }
203239
204- resolveDependency (
240+ resolveModule (
205241 path : string ,
242+ currentPath : string ,
206243 defaultExtensions : Array < string > = [ 'js' , 'jsx' , 'json' ]
207244 ) : Module {
208- let depPath = path . replace ( '/node_modules/' , '' ) ;
245+ const aliasedPath = this . getAliasedDependencyPath ( path , currentPath ) ;
246+ const shimmedPath = coreLibraries [ aliasedPath ] || aliasedPath ;
247+ try {
248+ const resolvedPath = resolve . sync ( shimmedPath , {
249+ filename : currentPath ,
250+ extensions : defaultExtensions . map ( ext => '.' + ext ) ,
251+ isFile : p => ! ! this . transpiledModules [ p ] || ! ! getCombinedMetas ( ) [ p ] ,
252+ readFileSync : p => {
253+ if ( this . transpiledModules [ p ] ) {
254+ return this . transpiledModules [ p ] . module . code ;
255+ }
256+
257+ const err = new Error ( 'Could not find ' + p ) ;
258+ err . code = 'ENOENT' ;
259+
260+ throw err ;
261+ } ,
262+ } ) ;
263+
264+ if ( NODE_LIBS . includes ( resolvedPath ) ) {
265+ return {
266+ path : pathUtils . join ( '/node_modules' , resolvedPath ) ,
267+ code : `// empty` ,
268+ requires : [ ] ,
269+ } ;
270+ }
209271
210- const aliasedPath = nodeResolvePath (
211- depPath ,
212- this . manifest . aliases ,
213- defaultExtensions
214- ) ;
272+ return this . transpiledModules [ resolvedPath ] . module ;
273+ } catch ( e ) {
274+ let connectedPath = / ^ ( \w | @ \w ) / . test ( shimmedPath )
275+ ? pathUtils . join ( '/node_modules' , shimmedPath )
276+ : pathUtils . join ( pathUtils . dirname ( currentPath ) , shimmedPath ) ;
215277
216- depPath = aliasedPath == null ? depPath : aliasedPath ;
278+ const isDependency = connectedPath . includes ( '/node_modules/' ) ;
217279
218- const alias = this . manifest . aliases [ depPath ] ;
219- // So aliased to not be included in the bundle, decided by browser object on pkg
220- if ( alias === false ) {
221- return {
222- path : pathUtils . join ( '/node_modules' , depPath ) ,
223- code : 'module . exports = null ; ',
224- requires : [ ] ,
225- } ;
226- }
280+ connectedPath = connectedPath . replace ( '/node_modules/' , '' ) ;
227281
228- // Check if the module is already there
229- const foundPath = nodeResolvePath (
230- path ,
231- this . transpiledModules ,
232- defaultExtensions
233- ) ;
234- if ( foundPath && this . transpiledModules [ foundPath ] ) {
235- return this . transpiledModules [ foundPath ] . module;
236- }
282+ if ( ! isDependency ) {
283+ throw new ModuleNotFoundError ( shimmedPath , false ) ;
284+ }
237285
238- const resolvedPath = nodeResolvePath (
239- alias || depPath ,
240- this . manifest . contents ,
241- defaultExtensions
242- ) ;
243- if ( resolvedPath && this . manifest . contents [ resolvedPath ] ) {
244- return {
245- path : pathUtils . join ( '/node_modules' , resolvedPath ) ,
246- code : this . manifest . contents [ resolvedPath ] . content ,
247- requires : this . manifest . contents [ resolvedPath ] . requires ,
248- } ;
249- }
286+ const dependencyName = getDependencyName ( connectedPath ) ;
250287
251- const dependencyParts = depPath . split ( '/' ) ;
252- const dependencyName = depPath . startsWith ( '@' )
253- ? `${ dependencyParts [ 0 ] } /${ dependencyParts [ 1 ] } `
254- : dependencyParts [ 0 ] ;
255-
256- if ( NODE_LIBS . includes ( dependencyName ) ) {
257- return {
258- path : pathUtils . join ( '/node_modules' , depPath ) ,
259- code : `// empty` ,
260- requires : [ ] ,
261- } ;
262- }
263-
264- if (
265- this . manifest . dependencies . find ( d => d . name === dependencyName ) ||
266- this . manifest . dependencyDependencies [ dependencyName ]
267- ) {
268- throw new ModuleNotFoundError ( alias || depPath , true) ;
269- } else {
270- throw new DependencyNotFoundError ( alias || depPath ) ;
288+ if (
289+ this . manifest . dependencies . find ( d => d . name === dependencyName ) ||
290+ this . manifest . dependencyDependencies [ dependencyName ]
291+ ) {
292+ throw new ModuleNotFoundError ( connectedPath , true ) ;
293+ } else {
294+ throw new DependencyNotFoundError ( connectedPath ) ;
295+ }
271296 }
272297 }
273298
274- async downloadDependency ( path : string ) : Promise < TranspiledModule > {
299+ async downloadDependency (
300+ path : string ,
301+ currentPath : string
302+ ) : Promise < TranspiledModule > {
275303 return fetchModule (
276304 path ,
277- this . manifest ,
305+ currentPath ,
306+ this ,
278307 this . preset . ignoredExtensions
279308 ) . then ( module => this . getTranspiledModule ( module ) ) ;
280309 }
@@ -294,28 +323,15 @@ export default class Manager {
294323 // pop() mutates queryPath, queryPath is now just the loaders
295324 const modulePath = queryPath . pop ( ) ;
296325
297- let module ;
298-
299- let newPath = pathUtils
300- . join (
301- pathUtils . dirname ( currentPath ) ,
302- this . preset . getAliasedPath ( modulePath )
303- )
326+ const newPath = this . preset
327+ . getAliasedPath ( modulePath )
304328 . replace ( / .* \{ \{ s a n d b o x R o o t \} \} / , '' ) ;
305329
306- if ( / ^ ( \w | @ \w ) / . test ( modulePath ) && ! modulePath . includes ( '!' ) ) {
307- // Prepend node_modules and go to root if it is a dependency
308- newPath = pathUtils . join (
309- '/node_modules' ,
310- this . preset . getAliasedPath ( modulePath )
311- ) ;
312- }
313-
314- if ( newPath . startsWith ( '/node_modules' ) ) {
315- module = this . resolveDependency ( newPath , this . preset . ignoredExtensions ) ;
316- } else {
317- module = this . resolveModule ( newPath , this . preset . ignoredExtensions ) ;
318- }
330+ const module = this . resolveModule (
331+ newPath ,
332+ currentPath ,
333+ this . preset . ignoredExtensions
334+ ) ;
319335
320336 return this . getTranspiledModule ( module , queryPath . join ( '!' ) ) ;
321337 }
0 commit comments