ContextModule.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const util = require("util");
  7. const { OriginalSource, RawSource } = require("webpack-sources");
  8. const Module = require("./Module");
  9. const AsyncDependenciesBlock = require("./AsyncDependenciesBlock");
  10. const Template = require("./Template");
  11. const contextify = require("./util/identifier").contextify;
  12. /** @typedef {"sync" | "eager" | "weak" | "async-weak" | "lazy" | "lazy-once"} ContextMode Context mode */
  13. /** @typedef {import("./dependencies/ContextElementDependency")} ContextElementDependency */
  14. /**
  15. * @callback ResolveDependenciesCallback
  16. * @param {Error=} err
  17. * @param {ContextElementDependency[]} dependencies
  18. */
  19. /**
  20. * @callback ResolveDependencies
  21. * @param {TODO} fs
  22. * @param {TODO} options
  23. * @param {ResolveDependenciesCallback} callback
  24. */
  25. class ContextModule extends Module {
  26. // type ContextMode = "sync" | "eager" | "weak" | "async-weak" | "lazy" | "lazy-once"
  27. // type ContextOptions = { resource: string, recursive: boolean, regExp: RegExp, addon?: string, mode?: ContextMode, chunkName?: string, include?: RegExp, exclude?: RegExp, groupOptions?: Object }
  28. // resolveDependencies: (fs: FS, options: ContextOptions, (err: Error?, dependencies: Dependency[]) => void) => void
  29. // options: ContextOptions
  30. /**
  31. * @param {ResolveDependencies} resolveDependencies function to get dependencies in this context
  32. * @param {TODO} options options object
  33. */
  34. constructor(resolveDependencies, options) {
  35. let resource;
  36. let resourceQuery;
  37. const queryIdx = options.resource.indexOf("?");
  38. if (queryIdx >= 0) {
  39. resource = options.resource.substr(0, queryIdx);
  40. resourceQuery = options.resource.substr(queryIdx);
  41. } else {
  42. resource = options.resource;
  43. resourceQuery = "";
  44. }
  45. super("javascript/dynamic", resource);
  46. // Info from Factory
  47. this.resolveDependencies = resolveDependencies;
  48. this.options = Object.assign({}, options, {
  49. resource: resource,
  50. resourceQuery: resourceQuery
  51. });
  52. if (options.resolveOptions !== undefined) {
  53. this.resolveOptions = options.resolveOptions;
  54. }
  55. // Info from Build
  56. this._contextDependencies = new Set([this.context]);
  57. if (typeof options.mode !== "string") {
  58. throw new Error("options.mode is a required option");
  59. }
  60. this._identifier = this._createIdentifier();
  61. }
  62. updateCacheModule(module) {
  63. this.resolveDependencies = module.resolveDependencies;
  64. this.options = module.options;
  65. this.resolveOptions = module.resolveOptions;
  66. }
  67. prettyRegExp(regexString) {
  68. // remove the "/" at the front and the beginning
  69. // "/foo/" -> "foo"
  70. return regexString.substring(1, regexString.length - 1);
  71. }
  72. _createIdentifier() {
  73. let identifier = this.context;
  74. if (this.options.resourceQuery) {
  75. identifier += ` ${this.options.resourceQuery}`;
  76. }
  77. if (this.options.mode) {
  78. identifier += ` ${this.options.mode}`;
  79. }
  80. if (!this.options.recursive) {
  81. identifier += " nonrecursive";
  82. }
  83. if (this.options.addon) {
  84. identifier += ` ${this.options.addon}`;
  85. }
  86. if (this.options.regExp) {
  87. identifier += ` ${this.options.regExp}`;
  88. }
  89. if (this.options.include) {
  90. identifier += ` include: ${this.options.include}`;
  91. }
  92. if (this.options.exclude) {
  93. identifier += ` exclude: ${this.options.exclude}`;
  94. }
  95. if (this.options.groupOptions) {
  96. identifier += ` groupOptions: ${JSON.stringify(
  97. this.options.groupOptions
  98. )}`;
  99. }
  100. if (this.options.namespaceObject === "strict") {
  101. identifier += " strict namespace object";
  102. } else if (this.options.namespaceObject) {
  103. identifier += " namespace object";
  104. }
  105. return identifier;
  106. }
  107. identifier() {
  108. return this._identifier;
  109. }
  110. readableIdentifier(requestShortener) {
  111. let identifier = requestShortener.shorten(this.context);
  112. if (this.options.resourceQuery) {
  113. identifier += ` ${this.options.resourceQuery}`;
  114. }
  115. if (this.options.mode) {
  116. identifier += ` ${this.options.mode}`;
  117. }
  118. if (!this.options.recursive) {
  119. identifier += " nonrecursive";
  120. }
  121. if (this.options.addon) {
  122. identifier += ` ${requestShortener.shorten(this.options.addon)}`;
  123. }
  124. if (this.options.regExp) {
  125. identifier += ` ${this.prettyRegExp(this.options.regExp + "")}`;
  126. }
  127. if (this.options.include) {
  128. identifier += ` include: ${this.prettyRegExp(this.options.include + "")}`;
  129. }
  130. if (this.options.exclude) {
  131. identifier += ` exclude: ${this.prettyRegExp(this.options.exclude + "")}`;
  132. }
  133. if (this.options.groupOptions) {
  134. const groupOptions = this.options.groupOptions;
  135. for (const key of Object.keys(groupOptions)) {
  136. identifier += ` ${key}: ${groupOptions[key]}`;
  137. }
  138. }
  139. if (this.options.namespaceObject === "strict") {
  140. identifier += " strict namespace object";
  141. } else if (this.options.namespaceObject) {
  142. identifier += " namespace object";
  143. }
  144. return identifier;
  145. }
  146. libIdent(options) {
  147. let identifier = contextify(options.context, this.context);
  148. if (this.options.mode) {
  149. identifier += ` ${this.options.mode}`;
  150. }
  151. if (this.options.recursive) {
  152. identifier += " recursive";
  153. }
  154. if (this.options.addon) {
  155. identifier += ` ${contextify(options.context, this.options.addon)}`;
  156. }
  157. if (this.options.regExp) {
  158. identifier += ` ${this.prettyRegExp(this.options.regExp + "")}`;
  159. }
  160. if (this.options.include) {
  161. identifier += ` include: ${this.prettyRegExp(this.options.include + "")}`;
  162. }
  163. if (this.options.exclude) {
  164. identifier += ` exclude: ${this.prettyRegExp(this.options.exclude + "")}`;
  165. }
  166. return identifier;
  167. }
  168. needRebuild(fileTimestamps, contextTimestamps) {
  169. const ts = contextTimestamps.get(this.context);
  170. if (!ts) {
  171. return true;
  172. }
  173. return ts >= this.buildInfo.builtTime;
  174. }
  175. build(options, compilation, resolver, fs, callback) {
  176. this.built = true;
  177. this.buildMeta = {};
  178. this.buildInfo = {
  179. builtTime: Date.now(),
  180. contextDependencies: this._contextDependencies
  181. };
  182. this.resolveDependencies(fs, this.options, (err, dependencies) => {
  183. if (err) return callback(err);
  184. // abort if something failed
  185. // this will create an empty context
  186. if (!dependencies) {
  187. callback();
  188. return;
  189. }
  190. // enhance dependencies with meta info
  191. for (const dep of dependencies) {
  192. dep.loc = {
  193. name: dep.userRequest
  194. };
  195. dep.request = this.options.addon + dep.request;
  196. }
  197. if (this.options.mode === "sync" || this.options.mode === "eager") {
  198. // if we have an sync or eager context
  199. // just add all dependencies and continue
  200. this.dependencies = dependencies;
  201. } else if (this.options.mode === "lazy-once") {
  202. // for the lazy-once mode create a new async dependency block
  203. // and add that block to this context
  204. if (dependencies.length > 0) {
  205. const block = new AsyncDependenciesBlock(
  206. Object.assign({}, this.options.groupOptions, {
  207. name: this.options.chunkName
  208. }),
  209. this
  210. );
  211. for (const dep of dependencies) {
  212. block.addDependency(dep);
  213. }
  214. this.addBlock(block);
  215. }
  216. } else if (
  217. this.options.mode === "weak" ||
  218. this.options.mode === "async-weak"
  219. ) {
  220. // we mark all dependencies as weak
  221. for (const dep of dependencies) {
  222. dep.weak = true;
  223. }
  224. this.dependencies = dependencies;
  225. } else if (this.options.mode === "lazy") {
  226. // if we are lazy create a new async dependency block per dependency
  227. // and add all blocks to this context
  228. let index = 0;
  229. for (const dep of dependencies) {
  230. let chunkName = this.options.chunkName;
  231. if (chunkName) {
  232. if (!/\[(index|request)\]/.test(chunkName)) {
  233. chunkName += "[index]";
  234. }
  235. chunkName = chunkName.replace(/\[index\]/g, index++);
  236. chunkName = chunkName.replace(
  237. /\[request\]/g,
  238. Template.toPath(dep.userRequest)
  239. );
  240. }
  241. const block = new AsyncDependenciesBlock(
  242. Object.assign({}, this.options.groupOptions, {
  243. name: chunkName
  244. }),
  245. dep.module,
  246. dep.loc,
  247. dep.userRequest
  248. );
  249. block.addDependency(dep);
  250. this.addBlock(block);
  251. }
  252. } else {
  253. callback(
  254. new Error(`Unsupported mode "${this.options.mode}" in context`)
  255. );
  256. return;
  257. }
  258. callback();
  259. });
  260. }
  261. getUserRequestMap(dependencies) {
  262. // if we filter first we get a new array
  263. // therefor we dont need to create a clone of dependencies explicitly
  264. // therefore the order of this is !important!
  265. return dependencies
  266. .filter(dependency => dependency.module)
  267. .sort((a, b) => {
  268. if (a.userRequest === b.userRequest) {
  269. return 0;
  270. }
  271. return a.userRequest < b.userRequest ? -1 : 1;
  272. })
  273. .reduce((map, dep) => {
  274. map[dep.userRequest] = dep.module.id;
  275. return map;
  276. }, Object.create(null));
  277. }
  278. getFakeMap(dependencies) {
  279. if (!this.options.namespaceObject) {
  280. return 9;
  281. }
  282. // if we filter first we get a new array
  283. // therefor we dont need to create a clone of dependencies explicitly
  284. // therefore the order of this is !important!
  285. let hasNonHarmony = false;
  286. let hasNamespace = false;
  287. let hasNamed = false;
  288. const fakeMap = dependencies
  289. .filter(dependency => dependency.module)
  290. .sort((a, b) => {
  291. return b.module.id - a.module.id;
  292. })
  293. .reduce((map, dep) => {
  294. const exportsType =
  295. dep.module.buildMeta && dep.module.buildMeta.exportsType;
  296. const id = dep.module.id;
  297. if (!exportsType) {
  298. map[id] = this.options.namespaceObject === "strict" ? 1 : 7;
  299. hasNonHarmony = true;
  300. } else if (exportsType === "namespace") {
  301. map[id] = 9;
  302. hasNamespace = true;
  303. } else if (exportsType === "named") {
  304. map[id] = 3;
  305. hasNamed = true;
  306. }
  307. return map;
  308. }, Object.create(null));
  309. if (!hasNamespace && hasNonHarmony && !hasNamed) {
  310. return this.options.namespaceObject === "strict" ? 1 : 7;
  311. }
  312. if (hasNamespace && !hasNonHarmony && !hasNamed) {
  313. return 9;
  314. }
  315. if (!hasNamespace && !hasNonHarmony && hasNamed) {
  316. return 3;
  317. }
  318. if (!hasNamespace && !hasNonHarmony && !hasNamed) {
  319. return 9;
  320. }
  321. return fakeMap;
  322. }
  323. getFakeMapInitStatement(fakeMap) {
  324. return typeof fakeMap === "object"
  325. ? `var fakeMap = ${JSON.stringify(fakeMap, null, "\t")};`
  326. : "";
  327. }
  328. getReturn(type) {
  329. if (type === 9) {
  330. return "__webpack_require__(id)";
  331. }
  332. return `__webpack_require__.t(id, ${type})`;
  333. }
  334. getReturnModuleObjectSource(fakeMap, fakeMapDataExpression = "fakeMap[id]") {
  335. if (typeof fakeMap === "number") {
  336. return `return ${this.getReturn(fakeMap)};`;
  337. }
  338. return `return __webpack_require__.t(id, ${fakeMapDataExpression})`;
  339. }
  340. getSyncSource(dependencies, id) {
  341. const map = this.getUserRequestMap(dependencies);
  342. const fakeMap = this.getFakeMap(dependencies);
  343. const returnModuleObject = this.getReturnModuleObjectSource(fakeMap);
  344. return `var map = ${JSON.stringify(map, null, "\t")};
  345. ${this.getFakeMapInitStatement(fakeMap)}
  346. function webpackContext(req) {
  347. var id = webpackContextResolve(req);
  348. ${returnModuleObject}
  349. }
  350. function webpackContextResolve(req) {
  351. var id = map[req];
  352. if(!(id + 1)) { // check for number or string
  353. var e = new Error("Cannot find module '" + req + "'");
  354. e.code = 'MODULE_NOT_FOUND';
  355. throw e;
  356. }
  357. return id;
  358. }
  359. webpackContext.keys = function webpackContextKeys() {
  360. return Object.keys(map);
  361. };
  362. webpackContext.resolve = webpackContextResolve;
  363. module.exports = webpackContext;
  364. webpackContext.id = ${JSON.stringify(id)};`;
  365. }
  366. getWeakSyncSource(dependencies, id) {
  367. const map = this.getUserRequestMap(dependencies);
  368. const fakeMap = this.getFakeMap(dependencies);
  369. const returnModuleObject = this.getReturnModuleObjectSource(fakeMap);
  370. return `var map = ${JSON.stringify(map, null, "\t")};
  371. ${this.getFakeMapInitStatement(fakeMap)}
  372. function webpackContext(req) {
  373. var id = webpackContextResolve(req);
  374. if(!__webpack_require__.m[id]) {
  375. var e = new Error("Module '" + req + "' ('" + id + "') is not available (weak dependency)");
  376. e.code = 'MODULE_NOT_FOUND';
  377. throw e;
  378. }
  379. ${returnModuleObject}
  380. }
  381. function webpackContextResolve(req) {
  382. var id = map[req];
  383. if(!(id + 1)) { // check for number or string
  384. var e = new Error("Cannot find module '" + req + "'");
  385. e.code = 'MODULE_NOT_FOUND';
  386. throw e;
  387. }
  388. return id;
  389. }
  390. webpackContext.keys = function webpackContextKeys() {
  391. return Object.keys(map);
  392. };
  393. webpackContext.resolve = webpackContextResolve;
  394. webpackContext.id = ${JSON.stringify(id)};
  395. module.exports = webpackContext;`;
  396. }
  397. getAsyncWeakSource(dependencies, id) {
  398. const map = this.getUserRequestMap(dependencies);
  399. const fakeMap = this.getFakeMap(dependencies);
  400. const returnModuleObject = this.getReturnModuleObjectSource(fakeMap);
  401. return `var map = ${JSON.stringify(map, null, "\t")};
  402. ${this.getFakeMapInitStatement(fakeMap)}
  403. function webpackAsyncContext(req) {
  404. return webpackAsyncContextResolve(req).then(function(id) {
  405. if(!__webpack_require__.m[id]) {
  406. var e = new Error("Module '" + req + "' ('" + id + "') is not available (weak dependency)");
  407. e.code = 'MODULE_NOT_FOUND';
  408. throw e;
  409. }
  410. ${returnModuleObject}
  411. });
  412. }
  413. function webpackAsyncContextResolve(req) {
  414. // Here Promise.resolve().then() is used instead of new Promise() to prevent
  415. // uncaught exception popping up in devtools
  416. return Promise.resolve().then(function() {
  417. var id = map[req];
  418. if(!(id + 1)) { // check for number or string
  419. var e = new Error("Cannot find module '" + req + "'");
  420. e.code = 'MODULE_NOT_FOUND';
  421. throw e;
  422. }
  423. return id;
  424. });
  425. }
  426. webpackAsyncContext.keys = function webpackAsyncContextKeys() {
  427. return Object.keys(map);
  428. };
  429. webpackAsyncContext.resolve = webpackAsyncContextResolve;
  430. webpackAsyncContext.id = ${JSON.stringify(id)};
  431. module.exports = webpackAsyncContext;`;
  432. }
  433. getEagerSource(dependencies, id) {
  434. const map = this.getUserRequestMap(dependencies);
  435. const fakeMap = this.getFakeMap(dependencies);
  436. const thenFunction =
  437. fakeMap !== 9
  438. ? `function(id) {
  439. ${this.getReturnModuleObjectSource(fakeMap)}
  440. }`
  441. : "__webpack_require__";
  442. return `var map = ${JSON.stringify(map, null, "\t")};
  443. ${this.getFakeMapInitStatement(fakeMap)}
  444. function webpackAsyncContext(req) {
  445. return webpackAsyncContextResolve(req).then(${thenFunction});
  446. }
  447. function webpackAsyncContextResolve(req) {
  448. // Here Promise.resolve().then() is used instead of new Promise() to prevent
  449. // uncaught exception popping up in devtools
  450. return Promise.resolve().then(function() {
  451. var id = map[req];
  452. if(!(id + 1)) { // check for number or string
  453. var e = new Error("Cannot find module '" + req + "'");
  454. e.code = 'MODULE_NOT_FOUND';
  455. throw e;
  456. }
  457. return id;
  458. });
  459. }
  460. webpackAsyncContext.keys = function webpackAsyncContextKeys() {
  461. return Object.keys(map);
  462. };
  463. webpackAsyncContext.resolve = webpackAsyncContextResolve;
  464. webpackAsyncContext.id = ${JSON.stringify(id)};
  465. module.exports = webpackAsyncContext;`;
  466. }
  467. getLazyOnceSource(block, dependencies, id, runtimeTemplate) {
  468. const promise = runtimeTemplate.blockPromise({
  469. block,
  470. message: "lazy-once context"
  471. });
  472. const map = this.getUserRequestMap(dependencies);
  473. const fakeMap = this.getFakeMap(dependencies);
  474. const thenFunction =
  475. fakeMap !== 9
  476. ? `function(id) {
  477. ${this.getReturnModuleObjectSource(fakeMap)};
  478. }`
  479. : "__webpack_require__";
  480. return `var map = ${JSON.stringify(map, null, "\t")};
  481. ${this.getFakeMapInitStatement(fakeMap)}
  482. function webpackAsyncContext(req) {
  483. return webpackAsyncContextResolve(req).then(${thenFunction});
  484. }
  485. function webpackAsyncContextResolve(req) {
  486. return ${promise}.then(function() {
  487. var id = map[req];
  488. if(!(id + 1)) { // check for number or string
  489. var e = new Error("Cannot find module '" + req + "'");
  490. e.code = 'MODULE_NOT_FOUND';
  491. throw e;
  492. }
  493. return id;
  494. });
  495. }
  496. webpackAsyncContext.keys = function webpackAsyncContextKeys() {
  497. return Object.keys(map);
  498. };
  499. webpackAsyncContext.resolve = webpackAsyncContextResolve;
  500. webpackAsyncContext.id = ${JSON.stringify(id)};
  501. module.exports = webpackAsyncContext;`;
  502. }
  503. getLazySource(blocks, id) {
  504. let hasMultipleOrNoChunks = false;
  505. const fakeMap = this.getFakeMap(blocks.map(b => b.dependencies[0]));
  506. const map = blocks
  507. .filter(block => block.dependencies[0].module)
  508. .map(block => ({
  509. dependency: block.dependencies[0],
  510. block: block,
  511. userRequest: block.dependencies[0].userRequest
  512. }))
  513. .sort((a, b) => {
  514. if (a.userRequest === b.userRequest) return 0;
  515. return a.userRequest < b.userRequest ? -1 : 1;
  516. })
  517. .reduce((map, item) => {
  518. const chunks =
  519. (item.block.chunkGroup && item.block.chunkGroup.chunks) || [];
  520. if (chunks.length !== 1) {
  521. hasMultipleOrNoChunks = true;
  522. }
  523. const arrayStart = [item.dependency.module.id];
  524. if (typeof fakeMap === "object") {
  525. arrayStart.push(fakeMap[item.dependency.module.id]);
  526. }
  527. map[item.userRequest] = arrayStart.concat(
  528. chunks.map(chunk => chunk.id)
  529. );
  530. return map;
  531. }, Object.create(null));
  532. const chunksStartPosition = typeof fakeMap === "object" ? 2 : 1;
  533. const requestPrefix = hasMultipleOrNoChunks
  534. ? `Promise.all(ids.slice(${chunksStartPosition}).map(__webpack_require__.e))`
  535. : `__webpack_require__.e(ids[${chunksStartPosition}])`;
  536. const returnModuleObject = this.getReturnModuleObjectSource(
  537. fakeMap,
  538. "ids[1]"
  539. );
  540. return `var map = ${JSON.stringify(map, null, "\t")};
  541. function webpackAsyncContext(req) {
  542. var ids = map[req];
  543. if(!ids) {
  544. return Promise.resolve().then(function() {
  545. var e = new Error("Cannot find module '" + req + "'");
  546. e.code = 'MODULE_NOT_FOUND';
  547. throw e;
  548. });
  549. }
  550. return ${requestPrefix}.then(function() {
  551. var id = ids[0];
  552. ${returnModuleObject}
  553. });
  554. }
  555. webpackAsyncContext.keys = function webpackAsyncContextKeys() {
  556. return Object.keys(map);
  557. };
  558. webpackAsyncContext.id = ${JSON.stringify(id)};
  559. module.exports = webpackAsyncContext;`;
  560. }
  561. getSourceForEmptyContext(id) {
  562. return `function webpackEmptyContext(req) {
  563. var e = new Error("Cannot find module '" + req + "'");
  564. e.code = 'MODULE_NOT_FOUND';
  565. throw e;
  566. }
  567. webpackEmptyContext.keys = function() { return []; };
  568. webpackEmptyContext.resolve = webpackEmptyContext;
  569. module.exports = webpackEmptyContext;
  570. webpackEmptyContext.id = ${JSON.stringify(id)};`;
  571. }
  572. getSourceForEmptyAsyncContext(id) {
  573. return `function webpackEmptyAsyncContext(req) {
  574. // Here Promise.resolve().then() is used instead of new Promise() to prevent
  575. // uncaught exception popping up in devtools
  576. return Promise.resolve().then(function() {
  577. var e = new Error("Cannot find module '" + req + "'");
  578. e.code = 'MODULE_NOT_FOUND';
  579. throw e;
  580. });
  581. }
  582. webpackEmptyAsyncContext.keys = function() { return []; };
  583. webpackEmptyAsyncContext.resolve = webpackEmptyAsyncContext;
  584. module.exports = webpackEmptyAsyncContext;
  585. webpackEmptyAsyncContext.id = ${JSON.stringify(id)};`;
  586. }
  587. getSourceString(asyncMode, runtimeTemplate) {
  588. if (asyncMode === "lazy") {
  589. if (this.blocks && this.blocks.length > 0) {
  590. return this.getLazySource(this.blocks, this.id);
  591. }
  592. return this.getSourceForEmptyAsyncContext(this.id);
  593. }
  594. if (asyncMode === "eager") {
  595. if (this.dependencies && this.dependencies.length > 0) {
  596. return this.getEagerSource(this.dependencies, this.id);
  597. }
  598. return this.getSourceForEmptyAsyncContext(this.id);
  599. }
  600. if (asyncMode === "lazy-once") {
  601. const block = this.blocks[0];
  602. if (block) {
  603. return this.getLazyOnceSource(
  604. block,
  605. block.dependencies,
  606. this.id,
  607. runtimeTemplate
  608. );
  609. }
  610. return this.getSourceForEmptyAsyncContext(this.id);
  611. }
  612. if (asyncMode === "async-weak") {
  613. if (this.dependencies && this.dependencies.length > 0) {
  614. return this.getAsyncWeakSource(this.dependencies, this.id);
  615. }
  616. return this.getSourceForEmptyAsyncContext(this.id);
  617. }
  618. if (asyncMode === "weak") {
  619. if (this.dependencies && this.dependencies.length > 0) {
  620. return this.getWeakSyncSource(this.dependencies, this.id);
  621. }
  622. }
  623. if (this.dependencies && this.dependencies.length > 0) {
  624. return this.getSyncSource(this.dependencies, this.id);
  625. }
  626. return this.getSourceForEmptyContext(this.id);
  627. }
  628. getSource(sourceString) {
  629. if (this.useSourceMap) {
  630. return new OriginalSource(sourceString, this.identifier());
  631. }
  632. return new RawSource(sourceString);
  633. }
  634. source(dependencyTemplates, runtimeTemplate) {
  635. return this.getSource(
  636. this.getSourceString(this.options.mode, runtimeTemplate)
  637. );
  638. }
  639. size() {
  640. // base penalty
  641. const initialSize = 160;
  642. // if we dont have dependencies we stop here.
  643. return this.dependencies.reduce((size, dependency) => {
  644. const element = /** @type {ContextElementDependency} */ (dependency);
  645. return size + 5 + element.userRequest.length;
  646. }, initialSize);
  647. }
  648. }
  649. // TODO remove in webpack 5
  650. Object.defineProperty(ContextModule.prototype, "recursive", {
  651. configurable: false,
  652. get: util.deprecate(
  653. /**
  654. * @deprecated
  655. * @this {ContextModule}
  656. * @returns {boolean} is recursive
  657. */
  658. function() {
  659. return this.options.recursive;
  660. },
  661. "ContextModule.recursive has been moved to ContextModule.options.recursive"
  662. ),
  663. set: util.deprecate(
  664. /**
  665. * @deprecated
  666. * @this {ContextModule}
  667. * @param {boolean} value is recursive
  668. * @returns {void}
  669. */
  670. function(value) {
  671. this.options.recursive = value;
  672. },
  673. "ContextModule.recursive has been moved to ContextModule.options.recursive"
  674. )
  675. });
  676. // TODO remove in webpack 5
  677. Object.defineProperty(ContextModule.prototype, "regExp", {
  678. configurable: false,
  679. get: util.deprecate(
  680. /**
  681. * @deprecated
  682. * @this {ContextModule}
  683. * @returns {RegExp} regular expression
  684. */
  685. function() {
  686. return this.options.regExp;
  687. },
  688. "ContextModule.regExp has been moved to ContextModule.options.regExp"
  689. ),
  690. set: util.deprecate(
  691. /**
  692. * @deprecated
  693. * @this {ContextModule}
  694. * @param {RegExp} value Regular expression
  695. * @returns {void}
  696. */
  697. function(value) {
  698. this.options.regExp = value;
  699. },
  700. "ContextModule.regExp has been moved to ContextModule.options.regExp"
  701. )
  702. });
  703. // TODO remove in webpack 5
  704. Object.defineProperty(ContextModule.prototype, "addon", {
  705. configurable: false,
  706. get: util.deprecate(
  707. /**
  708. * @deprecated
  709. * @this {ContextModule}
  710. * @returns {string} addon
  711. */
  712. function() {
  713. return this.options.addon;
  714. },
  715. "ContextModule.addon has been moved to ContextModule.options.addon"
  716. ),
  717. set: util.deprecate(
  718. /**
  719. * @deprecated
  720. * @this {ContextModule}
  721. * @param {string} value addon
  722. * @returns {void}
  723. */
  724. function(value) {
  725. this.options.addon = value;
  726. },
  727. "ContextModule.addon has been moved to ContextModule.options.addon"
  728. )
  729. });
  730. // TODO remove in webpack 5
  731. Object.defineProperty(ContextModule.prototype, "async", {
  732. configurable: false,
  733. get: util.deprecate(
  734. /**
  735. * @deprecated
  736. * @this {ContextModule}
  737. * @returns {boolean} is async
  738. */
  739. function() {
  740. return this.options.mode;
  741. },
  742. "ContextModule.async has been moved to ContextModule.options.mode"
  743. ),
  744. set: util.deprecate(
  745. /**
  746. * @deprecated
  747. * @this {ContextModule}
  748. * @param {ContextMode} value Context mode
  749. * @returns {void}
  750. */
  751. function(value) {
  752. this.options.mode = value;
  753. },
  754. "ContextModule.async has been moved to ContextModule.options.mode"
  755. )
  756. });
  757. // TODO remove in webpack 5
  758. Object.defineProperty(ContextModule.prototype, "chunkName", {
  759. configurable: false,
  760. get: util.deprecate(
  761. /**
  762. * @deprecated
  763. * @this {ContextModule}
  764. * @returns {string} chunk name
  765. */
  766. function() {
  767. return this.options.chunkName;
  768. },
  769. "ContextModule.chunkName has been moved to ContextModule.options.chunkName"
  770. ),
  771. set: util.deprecate(
  772. /**
  773. * @deprecated
  774. * @this {ContextModule}
  775. * @param {string} value chunk name
  776. * @returns {void}
  777. */
  778. function(value) {
  779. this.options.chunkName = value;
  780. },
  781. "ContextModule.chunkName has been moved to ContextModule.options.chunkName"
  782. )
  783. });
  784. module.exports = ContextModule;