AssetBytesGenerator.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Alexander Akait @alexander-akait
  4. */
  5. "use strict";
  6. const { RawSource } = require("webpack-sources");
  7. const ConcatenationScope = require("../ConcatenationScope");
  8. const Generator = require("../Generator");
  9. const {
  10. ASSET_URL_TYPE,
  11. ASSET_URL_TYPES,
  12. CSS_TYPE,
  13. HTML_TYPE,
  14. JAVASCRIPT_AND_ASSET_URL_TYPES,
  15. JAVASCRIPT_TYPE,
  16. JAVASCRIPT_TYPES,
  17. NO_TYPES
  18. } = require("../ModuleSourceTypeConstants");
  19. const RuntimeGlobals = require("../RuntimeGlobals");
  20. /** @import { Source } from "webpack-sources" */
  21. /** @import { GenerateContext } from "../Generator" */
  22. /**
  23. * @import {
  24. * ConcatenationBailoutReasonContext,
  25. * SourceType,
  26. * SourceTypes
  27. * } from "../Module"
  28. */
  29. /** @import ModuleGraph from "../ModuleGraph" */
  30. /** @import NormalModule from "../NormalModule" */
  31. class AssetBytesGenerator extends Generator {
  32. /**
  33. * Creates an instance of AssetBytesGenerator.
  34. * @param {ModuleGraph} moduleGraph the module graph
  35. */
  36. constructor(moduleGraph) {
  37. super();
  38. /** @type {ModuleGraph} */
  39. this._moduleGraph = moduleGraph;
  40. }
  41. /**
  42. * Generates generated code for this runtime module.
  43. * @param {NormalModule} module module for which the code should be generated
  44. * @param {GenerateContext} generateContext context for generate
  45. * @returns {Source | null} generated code
  46. */
  47. generate(
  48. module,
  49. { type, concatenationScope, getData, runtimeTemplate, runtimeRequirements }
  50. ) {
  51. const originalSource = module.originalSource();
  52. const data = getData ? getData() : undefined;
  53. switch (type) {
  54. case JAVASCRIPT_TYPE: {
  55. if (!originalSource) {
  56. return new RawSource("");
  57. }
  58. const encodedSource = originalSource.buffer().toString("base64");
  59. runtimeRequirements.add(RuntimeGlobals.requireScope);
  60. runtimeRequirements.add(RuntimeGlobals.toBinary);
  61. /** @type {string} */
  62. let sourceContent;
  63. if (concatenationScope) {
  64. concatenationScope.registerNamespaceExport(
  65. ConcatenationScope.NAMESPACE_OBJECT_EXPORT
  66. );
  67. sourceContent = `${runtimeTemplate.renderConst()} ${
  68. ConcatenationScope.NAMESPACE_OBJECT_EXPORT
  69. } = ${RuntimeGlobals.toBinary}(${JSON.stringify(encodedSource)});`;
  70. } else {
  71. runtimeRequirements.add(RuntimeGlobals.module);
  72. sourceContent = `${module.moduleArgument}.exports = ${RuntimeGlobals.toBinary}(${JSON.stringify(
  73. encodedSource
  74. )});`;
  75. }
  76. return new RawSource(sourceContent);
  77. }
  78. case ASSET_URL_TYPE: {
  79. if (!originalSource) {
  80. return null;
  81. }
  82. const encodedSource = originalSource.buffer().toString("base64");
  83. if (data) {
  84. data.set("url", {
  85. [type]: `data:application/octet-stream;base64,${encodedSource}`
  86. });
  87. }
  88. return null;
  89. }
  90. default:
  91. return null;
  92. }
  93. }
  94. /**
  95. * Generates fallback output for the provided error condition.
  96. * @param {Error} error the error
  97. * @param {NormalModule} module module for which the code should be generated
  98. * @param {GenerateContext} generateContext context for generate
  99. * @returns {Source | null} generated code
  100. */
  101. generateError(error, module, generateContext) {
  102. switch (generateContext.type) {
  103. case JAVASCRIPT_TYPE: {
  104. return new RawSource(Generator.throwBuildErrorCode(error));
  105. }
  106. default:
  107. return null;
  108. }
  109. }
  110. /**
  111. * Returns the reason this module cannot be concatenated, when one exists.
  112. * @param {NormalModule} module module for which the bailout reason should be determined
  113. * @param {ConcatenationBailoutReasonContext} context context
  114. * @returns {string | undefined} reason why this module can't be concatenated, undefined when it can be concatenated
  115. */
  116. getConcatenationBailoutReason(module, context) {
  117. return undefined;
  118. }
  119. /**
  120. * Returns the source types available for this module.
  121. * @param {NormalModule} module fresh module
  122. * @returns {SourceTypes} available types (do not mutate)
  123. */
  124. getTypes(module) {
  125. /** @type {Set<string>} */
  126. const sourceTypes = new Set();
  127. const connections = this._moduleGraph.getIncomingConnections(module);
  128. for (const connection of connections) {
  129. if (!connection.originModule) {
  130. continue;
  131. }
  132. sourceTypes.add(connection.originModule.type.split("/")[0]);
  133. }
  134. if (sourceTypes.size > 0) {
  135. if (
  136. sourceTypes.has(JAVASCRIPT_TYPE) &&
  137. (sourceTypes.has(CSS_TYPE) || sourceTypes.has(HTML_TYPE))
  138. ) {
  139. return JAVASCRIPT_AND_ASSET_URL_TYPES;
  140. } else if (sourceTypes.has(CSS_TYPE) || sourceTypes.has(HTML_TYPE)) {
  141. return ASSET_URL_TYPES;
  142. }
  143. return JAVASCRIPT_TYPES;
  144. }
  145. return NO_TYPES;
  146. }
  147. /**
  148. * @returns {boolean} whether getTypes() depends on the module's incoming connections
  149. */
  150. getTypesDependOnIncomingConnections() {
  151. return true;
  152. }
  153. /**
  154. * Returns the estimated size for the requested source type.
  155. * @param {NormalModule} module the module
  156. * @param {SourceType=} type source type
  157. * @returns {number} estimate size of the module
  158. */
  159. getSize(module, type) {
  160. const originalSource = module.originalSource();
  161. if (!originalSource) {
  162. return 0;
  163. }
  164. // Example: m.exports="abcd"
  165. return originalSource.size() + 12;
  166. }
  167. }
  168. module.exports = AssetBytesGenerator;