@@ -8,16 +8,18 @@ const Module = require("./Module");
88const OriginalSource = require ( "webpack-sources" ) . OriginalSource ;
99const RawSource = require ( "webpack-sources" ) . RawSource ;
1010const AsyncDependenciesBlock = require ( "./AsyncDependenciesBlock" ) ;
11+ const DepBlockHelpers = require ( "./dependencies/DepBlockHelpers" ) ;
12+ const Template = require ( "./Template" ) ;
1113
1214class ContextModule extends Module {
13- constructor ( resolveDependencies , context , recursive , regExp , addon , isAsync , chunkName ) {
15+ constructor ( resolveDependencies , context , recursive , regExp , addon , asyncMode , chunkName ) {
1416 super ( ) ;
1517 this . resolveDependencies = resolveDependencies ;
1618 this . context = context ;
1719 this . recursive = recursive ;
1820 this . regExp = regExp ;
1921 this . addon = addon ;
20- this . async = ! ! isAsync ;
22+ this . async = asyncMode ;
2123 this . cacheable = true ;
2224 this . contextDependencies = [ context ] ;
2325 this . built = false ;
@@ -44,7 +46,7 @@ class ContextModule extends Module {
4446 identifier ( ) {
4547 let identifier = this . context ;
4648 if ( this . async )
47- identifier += " async" ;
49+ identifier += ` ${ this . async } ` ;
4850 if ( ! this . recursive )
4951 identifier += " nonrecursive" ;
5052 if ( this . addon )
@@ -58,7 +60,7 @@ class ContextModule extends Module {
5860 readableIdentifier ( requestShortener ) {
5961 let identifier = requestShortener . shorten ( this . context ) ;
6062 if ( this . async )
61- identifier += " async" ;
63+ identifier += ` ${ this . async } ` ;
6264 if ( ! this . recursive )
6365 identifier += " nonrecursive" ;
6466 if ( this . addon )
@@ -72,7 +74,7 @@ class ContextModule extends Module {
7274 libIdent ( options ) {
7375 let identifier = this . contextify ( options . context , this . context ) ;
7476 if ( this . async )
75- identifier += " async" ;
77+ identifier += ` ${ this . async } ` ;
7678 if ( this . recursive )
7779 identifier += " recursive" ;
7880 if ( this . addon )
@@ -103,42 +105,67 @@ class ContextModule extends Module {
103105 this . resolveDependencies ( fs , this . context , this . recursive , this . regExp , ( err , dependencies ) => {
104106 if ( err ) return callback ( err ) ;
105107
108+ // Reset children
109+ this . dependencies = [ ] ;
110+ this . blocks = [ ] ;
111+
112+ // abort if something failed
113+ // this will create an empty context
106114 if ( ! dependencies ) {
107- this . dependencies = [ ] ;
108115 callback ( ) ;
109116 return ;
110117 }
111118
112- // enhance dependencies
119+ // enhance dependencies with meta info
113120 dependencies . forEach ( dep => {
114121 dep . loc = dep . userRequest ;
115122 dep . request = this . addon + dep . request ;
116123 } ) ;
117124
118- // if these we are not a async context
119- // add dependencies and continue
120- if ( ! this . async ) {
125+ if ( ! this . async || this . async === "eager" ) {
126+
127+ // if we have an sync or eager context
128+ // just add all dependencies and continue
121129 this . dependencies = dependencies ;
122- callback ( ) ;
123- return ;
124- }
125130
126- // if we are async however create a new async dependency block
127- // and add that block to this context
128- dependencies . forEach ( dep => {
129- const block = new AsyncDependenciesBlock ( this . chunkName , dep . module , dep . loc ) ;
130- block . addDependency ( dep ) ;
131- this . addBlock ( block ) ;
132- } ) ;
131+ } else if ( this . async === "lazy-once" ) {
132+
133+ // for the lazy-once mode create a new async dependency block
134+ // and add that block to this context
135+ if ( dependencies . length > 0 ) {
136+ const block = new AsyncDependenciesBlock ( this . chunkName , this ) ;
137+ dependencies . forEach ( dep => {
138+ block . addDependency ( dep ) ;
139+ } ) ;
140+ this . addBlock ( block ) ;
141+ }
142+
143+ } else {
144+
145+ // if we are lazy create a new async dependency block per dependency
146+ // and add all blocks to this context
147+ dependencies . forEach ( ( dep , idx ) => {
148+ let chunkName = this . chunkName ;
149+ if ( chunkName ) {
150+ if ( ! / \[ ( i n d e x | r e q u e s t ) \] / . test ( chunkName ) )
151+ chunkName += "[index]" ;
152+ chunkName = chunkName . replace ( / \[ i n d e x \] / g, idx ) ;
153+ chunkName = chunkName . replace ( / \[ r e q u e s t \] / g, Template . toPath ( dep . userRequest ) ) ;
154+ }
155+ const block = new AsyncDependenciesBlock ( chunkName , dep . module , dep . loc ) ;
156+ block . addDependency ( dep ) ;
157+ this . addBlock ( block ) ;
158+ } ) ;
159+ }
133160 callback ( ) ;
134161 } ) ;
135162 }
136163
137- getSourceWithDependencies ( dependencies , id ) {
164+ getUserRequestMap ( dependencies ) {
138165 // if we filter first we get a new array
139166 // therefor we dont need to create a clone of dependencies explicitly
140167 // therefore the order of this is !important!
141- const map = dependencies
168+ return dependencies
142169 . filter ( dependency => dependency . module )
143170 . sort ( ( a , b ) => {
144171 if ( a . userRequest === b . userRequest ) {
@@ -149,6 +176,10 @@ class ContextModule extends Module {
149176 map [ dep . userRequest ] = dep . module . id ;
150177 return map ;
151178 } , Object . create ( null ) ) ;
179+ }
180+
181+ getSyncSource ( dependencies , id ) {
182+ const map = this . getUserRequestMap ( dependencies ) ;
152183 return `var map = ${ JSON . stringify ( map , null , "\t" ) } ;
153184function webpackContext(req) {
154185 return __webpack_require__(webpackContextResolve(req));
@@ -167,7 +198,53 @@ module.exports = webpackContext;
167198webpackContext.id = ${ JSON . stringify ( id ) } ;` ;
168199 }
169200
170- getSourceWithBlocks ( blocks , id ) {
201+ getEagerSource ( dependencies , id ) {
202+ const map = this . getUserRequestMap ( dependencies ) ;
203+ return `var map = ${ JSON . stringify ( map , null , "\t" ) } ;
204+ function webpackAsyncContext(req) {
205+ return webpackAsyncContextResolve(req).then(__webpack_require__);
206+ };
207+ function webpackAsyncContextResolve(req) {
208+ return new Promise(function(resolve, reject) {
209+ var id = map[req];
210+ if(!(id + 1)) // check for number or string
211+ reject(new Error("Cannot find module '" + req + "'."));
212+ else
213+ resolve(id);
214+ });
215+ };
216+ webpackAsyncContext.keys = function webpackAsyncContextKeys() {
217+ return Object.keys(map);
218+ };
219+ webpackAsyncContext.resolve = webpackAsyncContextResolve;
220+ module.exports = webpackAsyncContext;
221+ webpackAsyncContext.id = ${ JSON . stringify ( id ) } ;` ;
222+ }
223+
224+ getLazyOnceSource ( block , dependencies , id , outputOptions , requestShortener ) {
225+ const promise = DepBlockHelpers . getDepBlockPromise ( block , outputOptions , requestShortener , "lazy-once context" ) ;
226+ const map = this . getUserRequestMap ( dependencies ) ;
227+ return `var map = ${ JSON . stringify ( map , null , "\t" ) } ;
228+ function webpackAsyncContext(req) {
229+ return webpackAsyncContextResolve(req).then(__webpack_require__);
230+ };
231+ function webpackAsyncContextResolve(req) {
232+ return ${ promise } .then(function() {
233+ var id = map[req];
234+ if(!(id + 1)) // check for number or string
235+ throw new Error("Cannot find module '" + req + "'.");
236+ return id;
237+ });
238+ };
239+ webpackAsyncContext.keys = function webpackAsyncContextKeys() {
240+ return Object.keys(map);
241+ };
242+ webpackAsyncContext.resolve = webpackAsyncContextResolve;
243+ module.exports = webpackAsyncContext;
244+ webpackAsyncContext.id = ${ JSON . stringify ( id ) } ;` ;
245+ }
246+
247+ getLazySource ( blocks , id ) {
171248 let hasMultipleOrNoChunks = false ;
172249 const map = blocks
173250 . filter ( block => block . dependencies [ 0 ] . module )
@@ -219,15 +296,38 @@ module.exports = webpackEmptyContext;
219296webpackEmptyContext.id = ${ JSON . stringify ( id ) } ;` ;
220297 }
221298
222- getSourceString ( ) {
223- if ( this . dependencies && this . dependencies . length > 0 ) {
224- return this . getSourceWithDependencies ( this . dependencies , this . id ) ;
225- }
299+ getSourceForEmptyAsyncContext ( id ) {
300+ return `function webpackEmptyAsyncContext(req) {
301+ return new Promise(function(resolve, reject) { reject(new Error("Cannot find module '" + req + "'.")); });
302+ }
303+ webpackEmptyAsyncContext.keys = function() { return []; };
304+ webpackEmptyAsyncContext.resolve = webpackEmptyAsyncContext;
305+ module.exports = webpackEmptyAsyncContext;
306+ webpackEmptyAsyncContext.id = ${ JSON . stringify ( id ) } ;` ;
307+ }
226308
227- if ( this . blocks && this . blocks . length > 0 ) {
228- return this . getSourceWithBlocks ( this . blocks , this . id ) ;
309+ getSourceString ( asyncMode , outputOptions , requestShortener ) {
310+ if ( asyncMode === "lazy" ) {
311+ if ( this . blocks && this . blocks . length > 0 ) {
312+ return this . getLazySource ( this . blocks , this . id ) ;
313+ }
314+ return this . getSourceForEmptyAsyncContext ( this . id ) ;
315+ }
316+ if ( asyncMode === "eager" ) {
317+ if ( this . dependencies && this . dependencies . length > 0 ) {
318+ return this . getEagerSource ( this . dependencies , this . id ) ;
319+ }
320+ return this . getSourceForEmptyAsyncContext ( this . id ) ;
321+ } else if ( asyncMode === "lazy-once" ) {
322+ const block = this . blocks [ 0 ] ;
323+ if ( block ) {
324+ return this . getLazyOnceSource ( block , block . dependencies , this . id , outputOptions , requestShortener ) ;
325+ }
326+ return this . getSourceForEmptyAsyncContext ( this . id ) ;
327+ }
328+ if ( this . dependencies && this . dependencies . length > 0 ) {
329+ return this . getSyncSource ( this . dependencies , this . id ) ;
229330 }
230-
231331 return this . getSourceForEmptyContext ( this . id ) ;
232332 }
233333
@@ -238,9 +338,9 @@ webpackEmptyContext.id = ${JSON.stringify(id)};`;
238338 return new RawSource ( sourceString ) ;
239339 }
240340
241- source ( ) {
341+ source ( dependencyTemplates , outputOptions , requestShortener ) {
242342 return this . getSource (
243- this . getSourceString ( )
343+ this . getSourceString ( this . async , outputOptions , requestShortener )
244344 ) ;
245345 }
246346
0 commit comments