123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  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 DependenciesBlock = require("./DependenciesBlock");
  8. const ModuleReason = require("./ModuleReason");
  9. const SortableSet = require("./util/SortableSet");
  10. const Template = require("./Template");
  11. let debugId = 1000;
  12. const sortById = (a, b) => {
  13. return a.id - b.id;
  14. };
  15. const sortByDebugId = (a, b) => {
  16. return a.debugId - b.debugId;
  17. };
  18. class Module extends DependenciesBlock {
  19. constructor() {
  20. super();
  21. this.context = null;
  22. this.reasons = [];
  23. this.debugId = debugId++;
  24. this.id = null;
  25. this.portableId = null;
  26. this.index = null;
  27. this.index2 = null;
  28. this.depth = null;
  29. this.used = null;
  30. this.usedExports = null;
  31. this.providedExports = null;
  32. this._chunks = new SortableSet(undefined, sortById);
  33. this._chunksDebugIdent = undefined;
  34. this.warnings = [];
  35. this.dependenciesWarnings = [];
  36. this.errors = [];
  37. this.dependenciesErrors = [];
  38. this.strict = false;
  39. this.meta = {};
  40. this.optimizationBailout = [];
  41. }
  42. disconnect() {
  43. this.reasons.length = 0;
  44. this.id = null;
  45. this.index = null;
  46. this.index2 = null;
  47. this.depth = null;
  48. this.used = null;
  49. this.usedExports = null;
  50. this.providedExports = null;
  51. this._chunks.clear();
  52. this._chunksDebugIdent = undefined;
  53. this.optimizationBailout.length = 0;
  54. super.disconnect();
  55. }
  56. unseal() {
  57. this.id = null;
  58. this.index = null;
  59. this.index2 = null;
  60. this.depth = null;
  61. this._chunks.clear();
  62. this._chunksDebugIdent = undefined;
  63. super.unseal();
  64. }
  65. setChunks(chunks) {
  66. this._chunks = new SortableSet(chunks, sortById);
  67. this._chunksDebugIdent = undefined;
  68. }
  69. addChunk(chunk) {
  70. this._chunks.add(chunk);
  71. this._chunksDebugIdent = undefined;
  72. }
  73. removeChunk(chunk) {
  74. if(this._chunks.delete(chunk)) {
  75. this._chunksDebugIdent = undefined;
  76. chunk.removeModule(this);
  77. return true;
  78. }
  79. return false;
  80. }
  81. isInChunk(chunk) {
  82. return this._chunks.has(chunk);
  83. }
  84. getChunkIdsIdent() {
  85. if(this._chunksDebugIdent !== undefined) return this._chunksDebugIdent;
  86. this._chunks.sortWith(sortByDebugId);
  87. const chunks = this._chunks;
  88. const list = [];
  89. for(const chunk of chunks) {
  90. const debugId = chunk.debugId;
  91. if(typeof debugId !== "number") {
  92. return this._chunksDebugIdent = null;
  93. }
  94. list.push(debugId);
  95. }
  96. return this._chunksDebugIdent = list.join(",");
  97. }
  98. forEachChunk(fn) {
  99. this._chunks.forEach(fn);
  100. }
  101. mapChunks(fn) {
  102. return Array.from(this._chunks, fn);
  103. }
  104. getChunks() {
  105. return Array.from(this._chunks);
  106. }
  107. getNumberOfChunks() {
  108. return this._chunks.size;
  109. }
  110. hasEqualsChunks(otherModule) {
  111. if(this._chunks.size !== otherModule._chunks.size) return false;
  112. this._chunks.sortWith(sortByDebugId);
  113. otherModule._chunks.sortWith(sortByDebugId);
  114. const a = this._chunks[Symbol.iterator]();
  115. const b = otherModule._chunks[Symbol.iterator]();
  116. while(true) { // eslint-disable-line
  117. const aItem = a.next();
  118. const bItem = b.next();
  119. if(aItem.done) return true;
  120. if(aItem.value !== bItem.value) return false;
  121. }
  122. }
  123. addReason(module, dependency) {
  124. this.reasons.push(new ModuleReason(module, dependency));
  125. }
  126. removeReason(module, dependency) {
  127. for(let i = 0; i < this.reasons.length; i++) {
  128. let r = this.reasons[i];
  129. if(r.module === module && r.dependency === dependency) {
  130. this.reasons.splice(i, 1);
  131. return true;
  132. }
  133. }
  134. return false;
  135. }
  136. hasReasonForChunk(chunk) {
  137. for(let i = 0; i < this.reasons.length; i++) {
  138. if(this.reasons[i].hasChunk(chunk))
  139. return true;
  140. }
  141. return false;
  142. }
  143. rewriteChunkInReasons(oldChunk, newChunks) {
  144. for(let i = 0; i < this.reasons.length; i++) {
  145. this.reasons[i].rewriteChunks(oldChunk, newChunks);
  146. }
  147. }
  148. isUsed(exportName) {
  149. if(this.used === null) return exportName;
  150. if(!exportName) return !!this.used;
  151. if(!this.used) return false;
  152. if(!this.usedExports) return false;
  153. if(this.usedExports === true) return exportName;
  154. let idx = this.usedExports.indexOf(exportName);
  155. if(idx < 0) return false;
  156. if(this.isProvided(exportName))
  157. return Template.numberToIdentifer(idx);
  158. return exportName;
  159. }
  160. isProvided(exportName) {
  161. if(!Array.isArray(this.providedExports))
  162. return null;
  163. return this.providedExports.indexOf(exportName) >= 0;
  164. }
  165. toString() {
  166. return `Module[${this.id || this.debugId}]`;
  167. }
  168. needRebuild(fileTimestamps, contextTimestamps) {
  169. return true;
  170. }
  171. updateHash(hash) {
  172. hash.update(this.id + "" + this.used);
  173. hash.update(JSON.stringify(this.usedExports));
  174. super.updateHash(hash);
  175. }
  176. sortItems(sortChunks) {
  177. super.sortItems();
  178. if(sortChunks)
  179. this._chunks.sort();
  180. this.reasons.sort((a, b) => sortById(a.module, b.module));
  181. if(Array.isArray(this.usedExports)) {
  182. this.usedExports.sort();
  183. }
  184. }
  185. unbuild() {
  186. this.disconnect();
  187. }
  188. }
  189. Object.defineProperty(Module.prototype, "entry", {
  190. configurable: false,
  191. get() {
  192. throw new Error("Module.entry was removed. Use Chunk.entryModule");
  193. },
  194. set() {
  195. throw new Error("Module.entry was removed. Use Chunk.entryModule");
  196. }
  197. });
  198. Object.defineProperty(Module.prototype, "chunks", {
  199. configurable: false,
  200. get: util.deprecate(function() {
  201. return Array.from(this._chunks);
  202. }, "Module.chunks: Use Module.forEachChunk/mapChunks/getNumberOfChunks/isInChunk/addChunk/removeChunk instead"),
  203. set() {
  204. throw new Error("Readonly. Use Module.addChunk/removeChunk to modify chunks.");
  205. }
  206. });
  207. Module.prototype.identifier = null;
  208. Module.prototype.readableIdentifier = null;
  209. Module.prototype.build = null;
  210. Module.prototype.source = null;
  211. Module.prototype.size = null;
  212. Module.prototype.nameForCondition = null;
  213. module.exports = Module;