You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

110 lines
2.9 KiB

4 years ago
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const ExternalModule = require("./ExternalModule");
  7. class ExternalModuleFactoryPlugin {
  8. constructor(type, externals) {
  9. this.type = type;
  10. this.externals = externals;
  11. }
  12. apply(normalModuleFactory) {
  13. const globalType = this.type;
  14. normalModuleFactory.hooks.factory.tap(
  15. "ExternalModuleFactoryPlugin",
  16. factory => (data, callback) => {
  17. const context = data.context;
  18. const dependency = data.dependencies[0];
  19. const handleExternal = (value, type, callback) => {
  20. if (typeof type === "function") {
  21. callback = type;
  22. type = undefined;
  23. }
  24. if (value === false) return factory(data, callback);
  25. if (value === true) value = dependency.request;
  26. if (type === undefined && /^[a-z0-9]+ /.test(value)) {
  27. const idx = value.indexOf(" ");
  28. type = value.substr(0, idx);
  29. value = value.substr(idx + 1);
  30. }
  31. callback(
  32. null,
  33. new ExternalModule(value, type || globalType, dependency.request)
  34. );
  35. return true;
  36. };
  37. const handleExternals = (externals, callback) => {
  38. if (typeof externals === "string") {
  39. if (externals === dependency.request) {
  40. return handleExternal(dependency.request, callback);
  41. }
  42. } else if (Array.isArray(externals)) {
  43. let i = 0;
  44. const next = () => {
  45. let asyncFlag;
  46. const handleExternalsAndCallback = (err, module) => {
  47. if (err) return callback(err);
  48. if (!module) {
  49. if (asyncFlag) {
  50. asyncFlag = false;
  51. return;
  52. }
  53. return next();
  54. }
  55. callback(null, module);
  56. };
  57. do {
  58. asyncFlag = true;
  59. if (i >= externals.length) return callback();
  60. handleExternals(externals[i++], handleExternalsAndCallback);
  61. } while (!asyncFlag);
  62. asyncFlag = false;
  63. };
  64. next();
  65. return;
  66. } else if (externals instanceof RegExp) {
  67. if (externals.test(dependency.request)) {
  68. return handleExternal(dependency.request, callback);
  69. }
  70. } else if (typeof externals === "function") {
  71. externals.call(
  72. null,
  73. context,
  74. dependency.request,
  75. (err, value, type) => {
  76. if (err) return callback(err);
  77. if (value !== undefined) {
  78. handleExternal(value, type, callback);
  79. } else {
  80. callback();
  81. }
  82. }
  83. );
  84. return;
  85. } else if (
  86. typeof externals === "object" &&
  87. Object.prototype.hasOwnProperty.call(externals, dependency.request)
  88. ) {
  89. return handleExternal(externals[dependency.request], callback);
  90. }
  91. callback();
  92. };
  93. handleExternals(this.externals, (err, module) => {
  94. if (err) return callback(err);
  95. if (!module) return handleExternal(false, callback);
  96. return callback(null, module);
  97. });
  98. }
  99. );
  100. }
  101. }
  102. module.exports = ExternalModuleFactoryPlugin;