11import trace from './trace' ;
2- import { cleanPath , parse , nodejsIds , mapId , resolveModuleId } from 'dumber-module-loader/dist/id-utils' ;
2+ import { cleanPath , parse , mapId } from 'dumber-module-loader/dist/id-utils' ;
33import alias from './transformers/alias' ;
44import defaultPackageFileReader from './package-file-reader/default' ;
55import PackageReader from './package-reader' ;
@@ -10,6 +10,8 @@ import {generateHash, stripJsExtension, resolvePackagePath, contentOrFile} from
1010import * as cache from './cache/default' ;
1111import path from 'path' ;
1212import mergeTransformed from './transformers/merge' ;
13+ import ModulesDone from './modules-done' ;
14+ import ModulesTodo from './modules-todo' ;
1315
1416// Bundler does
1517// 1. capture: capture units (unit is a file like object plus meta data)
@@ -57,8 +59,10 @@ export default class Bundler {
5759 this . _paths = _paths ;
5860
5961 this . _unitsMap = { } ;
60- this . _moduleId_done = new Set ( ) ;
61- this . _moduleIds_todo = new Set ( ) ;
62+
63+ this . _modules_done = new ModulesDone ( ) ;
64+ this . _modules_todo = new ModulesTodo ( this . _modules_done ) ;
65+
6266 this . _readersMap = { } ;
6367 this . _fileReader = opts . packageFileReader || defaultPackageFileReader ;
6468
@@ -86,6 +90,10 @@ export default class Bundler {
8690 // persist bundles in watch mode
8791 this . _bundles = { } ;
8892 this . _inWatchMode = false ;
93+
94+ this . _onAcquire = this . _onAcquire . bind ( this ) ;
95+ this . _supportInjectCssIfNeeded = this . _supportInjectCssIfNeeded . bind ( this ) ;
96+ this . _resolveExplicitDepsIfNeeded = this . _resolveExplicitDepsIfNeeded . bind ( this ) ;
8997 }
9098
9199 clearCache ( ) {
@@ -158,32 +166,13 @@ export default class Bundler {
158166 ) ;
159167 }
160168
161- _addToDone ( id ) {
162- if ( typeof id === 'string' ) {
163- this . _moduleId_done . add ( id ) ;
164- } else if ( Array . isArray ( id ) ) {
165- id . forEach ( d => this . _moduleId_done . add ( d ) ) ;
166- }
167- }
168-
169169 _capture ( tracedUnit ) {
170170 this . _unitsMap [ tracedUnit . path ] = tracedUnit ;
171171
172172 // mark as done.
173- this . _addToDone ( tracedUnit . moduleId ) ;
174- this . _addToDone ( tracedUnit . defined ) ;
175-
176- // mark todo. beware we didn't check whether the id is in _moduleId_done.
177- // they will be checked during resolve phase.
178- tracedUnit . deps . forEach ( d => {
179- const parsedId = parse ( resolveModuleId ( tracedUnit . moduleId , d ) ) ;
180- if ( ! parsedId . prefix && parsedId . ext === '.css' ) {
181- this . _needCssInjection = true ;
182- }
183- // ignore relative dep on local source
184- if ( ! tracedUnit . packageName && d . startsWith ( '.' ) ) return ;
185- this . _moduleIds_todo . add ( parsedId . cleanId ) ;
186- } ) ;
173+ this . _modules_done . addUnit ( tracedUnit ) ;
174+ // process deps.
175+ this . _modules_todo . process ( tracedUnit ) ;
187176
188177 const bundle = this . bundleOf ( tracedUnit ) ;
189178 // mark related bundle dirty
@@ -237,8 +226,6 @@ export default class Bundler {
237226 // to some browser replacement.
238227 // e.g. readable-stream/readable -> readable-stream/readable-browser
239228 _ensureNpmAlias ( tracedUnit , id ) {
240- if ( this . _moduleId_done . has ( id ) ) return ;
241-
242229 const defined = tracedUnit . defined ;
243230 let toId ;
244231 if ( Array . isArray ( defined ) ) {
@@ -256,12 +243,14 @@ export default class Bundler {
256243 if ( toId !== id && toId !== tracedUnit . packageName ) {
257244 const aliasResult = alias ( id , toId ) ;
258245 mergeTransformed ( tracedUnit , aliasResult ) ;
259- this . _addToDone ( aliasResult . defined ) ;
246+ this . _modules_done . addUnit ( tracedUnit ) ;
260247 }
261248 }
262249
263250 _supportInjectCssIfNeeded ( ) {
264- if ( ! this . _needCssInjection || ! this . _injectCss || this . _isInjectCssTurnedOn ) return Promise . resolve ( ) ;
251+ if ( ! this . _modules_todo . needCssInjection || ! this . _injectCss || this . _isInjectCssTurnedOn ) {
252+ return Promise . resolve ( ) ;
253+ }
265254 this . _isInjectCssTurnedOn = true ;
266255
267256 return this . capture ( {
@@ -272,107 +261,96 @@ export default class Bundler {
272261 }
273262
274263 resolve ( ) {
275- let todo = [ ] ;
276264 return this . _resolvePrependsAndAppends ( )
277- . then ( ( ) => this . _resolveExplicitDepsIfNeeded ( ) )
278- . then ( ( ) => this . _supportInjectCssIfNeeded ( ) )
279- . then ( ( ) => {
280- const consults = [ ] ;
281- const rawTodo = Array . from ( this . _moduleIds_todo ) ;
282- this . _moduleIds_todo . clear ( ) ;
283-
284- rawTodo . forEach ( id => {
285- const parsedId = parse ( mapId ( id , this . _paths ) ) ;
286-
287- if ( parsedId . prefix &&
288- parsedId . prefix !== 'text!' &&
289- parsedId . prefix !== 'json!' &&
290- parsedId . prefix !== 'raw!' ) {
291- // Trace any unknown plugin module.
292- // For simplicity, push it to next resolve cycle.
293- this . _moduleIds_todo . add ( parsedId . prefix . slice ( 0 , - 1 ) ) ;
265+ . then ( this . _resolveExplicitDepsIfNeeded )
266+ . then ( ( ) => this . _modules_todo . acquire ( this . _onAcquire ) )
267+ . then ( this . _supportInjectCssIfNeeded )
268+ . then ( ( ) => {
269+ // recursively resolve
270+ if ( this . _modules_todo . hasTodo ( ) ) {
271+ return this . resolve ( ) ;
294272 }
295-
296- const possibleIds = nodejsIds ( parsedId . bareId ) ;
297- if ( possibleIds . some ( id => this . _moduleId_done . has ( id ) ) ) return ;
298-
299- const j = new Promise ( resolve => {
300- resolve ( this . _onRequire && this . _onRequire ( parsedId . bareId , parsedId ) ) ;
301- } ) . then (
302- result => {
303- // ignore this module id
304- if ( result === false ) return ;
305-
306- // require other module ids instead
307- if ( Array . isArray ( result ) && result . length ) {
308- result . forEach ( d => todo . push ( parse ( d ) ) ) ;
309- return ;
310- }
311-
312- // got full content of this module
313- if ( typeof result === 'string' ) {
314- return this . capture ( {
315- path : '__on_require__/' + parsedId . bareId + ( parsedId . ext ? '' : '.js' ) ,
316- contents : result ,
317- moduleId : parsedId . bareId ,
318- packageName : parsedId . parts [ 0 ]
319- } ) ;
320- }
321-
322- // process normally if result is not recognizable
323- todo . push ( parsedId ) ;
324- } ,
325- // proceed normally after error
326- err => {
327- error ( 'onRequire call failed for ' + parsedId . bareId ) ;
328- error ( err ) ;
329- todo . push ( parsedId ) ;
330- }
331- ) ;
332- consults . push ( j ) ;
333273 } ) ;
274+ }
334275
335- if ( consults . length ) return Promise . all ( consults ) ;
336- } )
337- . then ( ( ) => {
338- let p = Promise . resolve ( ) ;
339-
340- todo . forEach ( td => {
341- const bareId = td . bareId ;
342- const packageName = td . parts [ 0 ] ;
343- const resource = bareId . slice ( packageName . length + 1 ) ;
344-
345- const stub = stubModule ( bareId ) ;
346- if ( stub ) info ( 'Stub module ' + bareId ) ;
347-
348- if ( typeof stub === 'string' ) {
349- p = p . then ( ( ) => this . capture ( {
350- // not a real file path
351- path :'__stub__/' + bareId + '.js' ,
352- contents : stub ,
353- moduleId : bareId ,
354- packageName
355- } ) ) ;
356- } else {
357- p = p . then ( ( ) => this . packageReaderFor ( stub || { name : packageName } ) )
358- . then ( reader => resource ? reader . readResource ( resource ) : reader . readMain ( ) )
359- . then ( unit => this . capture ( unit ) )
360- . then ( tracedUnit => {
361- this . _ensureNpmAlias ( tracedUnit , bareId ) ;
362- } )
363- . catch ( err => {
364- error ( 'Resolving failed for module ' + bareId ) ;
365- error ( err ) ;
276+ // trace missing dep
277+ _onAcquire ( id , opts ) {
278+ const checkUserSpace = opts . user ;
279+ const checkPackageSpace = opts . package ;
280+ const requiredBy = opts . requiredBy ;
281+ const parsedId = parse ( mapId ( id , this . _paths ) ) ;
282+
283+ // TODO add a callback point to fillup missing local dep.
284+ // This is needed by dumberify.
285+ if ( checkUserSpace && ! checkPackageSpace ) {
286+ // detected missing local dep
287+ warn ( `local dependency ${ parsedId . bareId } (requiredBy ${ requiredBy . join ( ', ' ) } ) is missing` ) ;
288+ }
289+
290+ return new Promise ( resolve => {
291+ resolve ( this . _onRequire && this . _onRequire ( parsedId . bareId , parsedId ) ) ;
292+ } ) . then (
293+ result => {
294+ // ignore this module id
295+ if ( result === false ) return true ;
296+
297+ // require other module ids instead
298+ if ( Array . isArray ( result ) && result . length ) {
299+ this . _modules_todo . process ( {
300+ moduleId : parsedId . bareId ,
301+ packageName : ( ! checkUserSpace && checkPackageSpace ) ? parsedId . parts [ 0 ] : undefined ,
302+ deps : result
366303 } ) ;
304+ return true ;
367305 }
368- } ) ;
369306
370- return p ;
371- } )
372- . then ( ( ) => {
373- if ( this . _moduleIds_todo . size ) {
374- return this . resolve ( ) ;
307+ // got full content of this module
308+ if ( typeof result === 'string' ) {
309+ return this . capture ( {
310+ path : '__on_require__/' + parsedId . bareId + ( parsedId . ext ? '' : '.js' ) ,
311+ contents : result ,
312+ moduleId : parsedId . bareId ,
313+ packageName : parsedId . parts [ 0 ]
314+ } ) . then ( ( ) => true ) ;
315+ }
316+
317+ // process normally if result is not recognizable
318+ } ,
319+ // proceed normally after error
320+ err => {
321+ error ( 'onRequire call failed for ' + parsedId . bareId ) ;
322+ error ( err ) ;
375323 }
324+ ) . then ( didRequire => {
325+ if ( didRequire === true ) return ;
326+
327+ const bareId = parsedId . bareId ;
328+ const packageName = parsedId . parts [ 0 ] ;
329+ const resource = bareId . slice ( packageName . length + 1 ) ;
330+
331+ const stub = stubModule ( bareId ) ;
332+ if ( stub ) info ( 'Stub module ' + bareId ) ;
333+
334+ if ( typeof stub === 'string' ) {
335+ return this . capture ( {
336+ // not a real file path
337+ path :'__stub__/' + bareId + '.js' ,
338+ contents : stub ,
339+ moduleId : bareId ,
340+ packageName
341+ } ) ;
342+ }
343+
344+ return this . packageReaderFor ( stub || { name : packageName } )
345+ . then ( reader => resource ? reader . readResource ( resource ) : reader . readMain ( ) )
346+ . then ( unit => this . capture ( unit ) )
347+ . then ( tracedUnit => {
348+ this . _ensureNpmAlias ( tracedUnit , bareId ) ;
349+ } )
350+ . catch ( err => {
351+ error ( 'Resolving failed for module ' + bareId ) ;
352+ error ( err ) ;
353+ } ) ;
376354 } ) ;
377355 }
378356
0 commit comments