DelegatedModuleFactoryPlugin.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const DelegatedModule = require("./DelegatedModule");
  7. /**
  8. * @import {
  9. * DllReferencePluginOptions,
  10. * DllReferencePluginOptionsContent
  11. * } from "../../declarations/plugins/dll/DllReferencePlugin"
  12. */
  13. /**
  14. * @import {
  15. * DelegatedModuleData,
  16. * DelegatedModuleSourceRequest,
  17. * DelegatedModuleType
  18. * } from "./DelegatedModule"
  19. */
  20. /** @import NormalModuleFactory from "../NormalModuleFactory" */
  21. /** @import { AssociatedObjectForCache } from "../util/identifier" */
  22. /**
  23. * Defines the options type used by this module.
  24. * @typedef {object} Options
  25. * @property {DelegatedModuleSourceRequest} source source
  26. * @property {NonNullable<DllReferencePluginOptions["context"]>} context absolute context path to which lib ident is relative to
  27. * @property {DllReferencePluginOptionsContent} content content
  28. * @property {DllReferencePluginOptions["type"]} type type
  29. * @property {DllReferencePluginOptions["extensions"]} extensions extensions
  30. * @property {DllReferencePluginOptions["scope"]} scope scope
  31. * @property {AssociatedObjectForCache=} associatedObjectForCache object for caching
  32. */
  33. const PLUGIN_NAME = "DelegatedModuleFactoryPlugin";
  34. class DelegatedModuleFactoryPlugin {
  35. /**
  36. * Creates an instance of DelegatedModuleFactoryPlugin.
  37. * @param {Options} options options
  38. */
  39. constructor(options) {
  40. /** @type {Options} */
  41. this.options = options;
  42. options.type = options.type || "require";
  43. options.extensions = options.extensions || ["", ".js", ".json", ".wasm"];
  44. }
  45. /**
  46. * Applies the plugin by registering its hooks on the compiler.
  47. * @param {NormalModuleFactory} normalModuleFactory the normal module factory
  48. * @returns {void}
  49. */
  50. apply(normalModuleFactory) {
  51. const scope = this.options.scope;
  52. if (scope) {
  53. normalModuleFactory.hooks.factorize.tapAsync(
  54. PLUGIN_NAME,
  55. (data, callback) => {
  56. const [dependency] = data.dependencies;
  57. const { request } = dependency;
  58. if (request && request.startsWith(`${scope}/`)) {
  59. const innerRequest = `.${request.slice(scope.length)}`;
  60. /** @type {undefined | DelegatedModuleData} */
  61. let resolved;
  62. if (innerRequest in this.options.content) {
  63. resolved = this.options.content[innerRequest];
  64. return callback(
  65. null,
  66. new DelegatedModule(
  67. this.options.source,
  68. resolved,
  69. /** @type {DelegatedModuleType} */
  70. (this.options.type),
  71. innerRequest,
  72. request
  73. )
  74. );
  75. }
  76. const extensions =
  77. /** @type {string[]} */
  78. (this.options.extensions);
  79. for (let i = 0; i < extensions.length; i++) {
  80. const extension = extensions[i];
  81. const requestPlusExt = innerRequest + extension;
  82. if (requestPlusExt in this.options.content) {
  83. resolved = this.options.content[requestPlusExt];
  84. return callback(
  85. null,
  86. new DelegatedModule(
  87. this.options.source,
  88. resolved,
  89. /** @type {DelegatedModuleType} */
  90. (this.options.type),
  91. requestPlusExt,
  92. request + extension
  93. )
  94. );
  95. }
  96. }
  97. // Directory request: resolve to its index file, like the default resolver.
  98. for (let i = 0; i < extensions.length; i++) {
  99. const extension = extensions[i];
  100. const requestPlusExt = `${innerRequest}/index${extension}`;
  101. if (requestPlusExt in this.options.content) {
  102. resolved = this.options.content[requestPlusExt];
  103. return callback(
  104. null,
  105. new DelegatedModule(
  106. this.options.source,
  107. resolved,
  108. /** @type {DelegatedModuleType} */
  109. (this.options.type),
  110. requestPlusExt,
  111. `${request}/index${extension}`
  112. )
  113. );
  114. }
  115. }
  116. }
  117. return callback();
  118. }
  119. );
  120. } else {
  121. normalModuleFactory.hooks.module.tap(PLUGIN_NAME, (module) => {
  122. const request = module.libIdent(this.options);
  123. if (request && request in this.options.content) {
  124. const resolved = this.options.content[request];
  125. return new DelegatedModule(
  126. this.options.source,
  127. resolved,
  128. /** @type {DelegatedModuleType} */
  129. (this.options.type),
  130. request,
  131. module
  132. );
  133. }
  134. return module;
  135. });
  136. }
  137. }
  138. }
  139. module.exports = DelegatedModuleFactoryPlugin;