123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. class FlagDependencyExportsPlugin {
  7. apply(compiler) {
  8. compiler.plugin("compilation", (compilation) => {
  9. compilation.plugin("finish-modules", (modules) => {
  10. const dependencies = Object.create(null);
  11. let module;
  12. let moduleWithExports;
  13. let moduleProvidedExports;
  14. const queue = modules.filter((m) => !m.providedExports);
  15. for(let i = 0; i < queue.length; i++) {
  16. module = queue[i];
  17. if(module.providedExports !== true) {
  18. moduleWithExports = module.meta && module.meta.harmonyModule;
  19. moduleProvidedExports = Array.isArray(module.providedExports) ? new Set(module.providedExports) : new Set();
  20. processDependenciesBlock(module);
  21. if(!moduleWithExports) {
  22. module.providedExports = true;
  23. notifyDependencies();
  24. } else if(module.providedExports !== true) {
  25. module.providedExports = Array.from(moduleProvidedExports);
  26. }
  27. }
  28. }
  29. function processDependenciesBlock(depBlock) {
  30. depBlock.dependencies.forEach((dep) => processDependency(dep));
  31. depBlock.variables.forEach((variable) => {
  32. variable.dependencies.forEach((dep) => processDependency(dep));
  33. });
  34. depBlock.blocks.forEach(processDependenciesBlock);
  35. }
  36. function processDependency(dep) {
  37. const exportDesc = dep.getExports && dep.getExports();
  38. if(!exportDesc) return;
  39. moduleWithExports = true;
  40. const exports = exportDesc.exports;
  41. const exportDeps = exportDesc.dependencies;
  42. if(exportDeps) {
  43. exportDeps.forEach((dep) => {
  44. const depIdent = dep.identifier();
  45. // if this was not yet initialized
  46. // initialize it as an array containing the module and stop
  47. const array = dependencies[depIdent];
  48. if(!array) {
  49. dependencies[depIdent] = [module];
  50. return;
  51. }
  52. // check if this module is known
  53. // if not, add it to the dependencies for this identifier
  54. if(array.indexOf(module) < 0)
  55. array.push(module);
  56. });
  57. }
  58. let changed = false;
  59. if(module.providedExports !== true) {
  60. if(exports === true) {
  61. module.providedExports = true;
  62. changed = true;
  63. } else if(Array.isArray(exports)) {
  64. changed = addToSet(moduleProvidedExports, exports);
  65. }
  66. }
  67. if(changed) {
  68. notifyDependencies();
  69. }
  70. }
  71. function notifyDependencies() {
  72. const deps = dependencies[module.identifier()];
  73. if(deps) {
  74. deps.forEach((dep) => queue.push(dep));
  75. }
  76. }
  77. });
  78. function addToSet(a, b) {
  79. let changed = false;
  80. b.forEach((item) => {
  81. if(!a.has(item)) {
  82. a.add(item);
  83. changed = true;
  84. }
  85. });
  86. return changed;
  87. }
  88. });
  89. }
  90. }
  91. module.exports = FlagDependencyExportsPlugin;