ProvidedDependency.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Florent Cailhol @ooflorent
  4. */
  5. "use strict";
  6. const Dependency = require("../Dependency");
  7. const InitFragment = require("../InitFragment");
  8. const Template = require("../Template");
  9. const { InlinedUsedName } = require("../optimize/InlineExports");
  10. const makeSerializable = require("../util/makeSerializable");
  11. const { propertyAccess } = require("../util/property");
  12. const ModuleDependency = require("./ModuleDependency");
  13. /** @import { ReplaceSource } from "webpack-sources" */
  14. /**
  15. * @import {
  16. * ReferencedExports,
  17. * UpdateHashContext,
  18. * ExportInfoName
  19. * } from "../Dependency"
  20. */
  21. /** @import { DependencyTemplateContext } from "../DependencyTemplate" */
  22. /** @import ModuleGraph from "../ModuleGraph" */
  23. /** @import ModuleGraphConnection from "../ModuleGraphConnection" */
  24. /** @import { Range } from "../javascript/JavascriptParser" */
  25. /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext<[string, ExportInfoName[]]>} ObjectDeserializerContext */
  26. /** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext<[string, ExportInfoName[]]>} ObjectSerializerContext */
  27. /** @import Hash from "../util/Hash" */
  28. /** @import { RuntimeSpec } from "../util/runtime" */
  29. class ProvidedDependency extends ModuleDependency {
  30. /**
  31. * Creates an instance of ProvidedDependency.
  32. * @param {string} request request
  33. * @param {string} identifier identifier
  34. * @param {ExportInfoName[]} ids ids
  35. * @param {Range} range range
  36. */
  37. constructor(request, identifier, ids, range) {
  38. super(request);
  39. /** @type {string} */
  40. this.identifier = identifier;
  41. /** @type {string[]} */
  42. this.ids = ids;
  43. this.range = range;
  44. /** @type {undefined | string} */
  45. this._hashUpdate = undefined;
  46. }
  47. get type() {
  48. return "provided";
  49. }
  50. get category() {
  51. return "esm";
  52. }
  53. /**
  54. * Returns list of exports referenced by this dependency
  55. * @param {ModuleGraph} moduleGraph module graph
  56. * @param {RuntimeSpec} runtime the runtime for which the module is analysed
  57. * @returns {ReferencedExports} referenced exports
  58. */
  59. getReferencedExports(moduleGraph, runtime) {
  60. const ids = this.ids;
  61. if (ids.length === 0) return Dependency.EXPORTS_OBJECT_REFERENCED;
  62. return [ids];
  63. }
  64. /**
  65. * Updates the hash with the data contributed by this instance.
  66. * @param {Hash} hash hash to be updated
  67. * @param {UpdateHashContext} context context
  68. * @returns {void}
  69. */
  70. updateHash(hash, context) {
  71. if (this._hashUpdate === undefined) {
  72. this._hashUpdate = this.identifier + (this.ids ? this.ids.join(",") : "");
  73. }
  74. hash.update(this._hashUpdate);
  75. }
  76. /**
  77. * Serializes this instance into the provided serializer context.
  78. * @param {ObjectSerializerContext} context context
  79. */
  80. serialize(context) {
  81. context.write(this.identifier).write(this.ids);
  82. super.serialize(context);
  83. }
  84. /**
  85. * Restores this instance from the provided deserializer context.
  86. * @param {ObjectDeserializerContext} context context
  87. */
  88. deserialize(context) {
  89. this.identifier = context.read();
  90. const c1 = context.rest;
  91. this.ids = c1.read();
  92. super.deserialize(c1.rest);
  93. }
  94. }
  95. makeSerializable(
  96. ProvidedDependency,
  97. "webpack/lib/dependencies/ProvidedDependency"
  98. );
  99. class ProvidedDependencyTemplate extends ModuleDependency.Template {
  100. /**
  101. * Applies the plugin by registering its hooks on the compiler.
  102. * @param {Dependency} dependency the dependency for which the template should be applied
  103. * @param {ReplaceSource} source the current replace source which can be modified
  104. * @param {DependencyTemplateContext} templateContext the context object
  105. * @returns {void}
  106. */
  107. apply(
  108. dependency,
  109. source,
  110. {
  111. runtime,
  112. runtimeTemplate,
  113. moduleGraph,
  114. chunkGraph,
  115. initFragments,
  116. runtimeRequirements
  117. }
  118. ) {
  119. const dep = /** @type {ProvidedDependency} */ (dependency);
  120. const connection =
  121. /** @type {ModuleGraphConnection} */
  122. (moduleGraph.getConnection(dep));
  123. const exportsInfo = moduleGraph.getExportsInfo(connection.module);
  124. const usedName = exportsInfo.getUsedName(dep.ids, runtime);
  125. const moduleRaw = runtimeTemplate.moduleRaw({
  126. module: moduleGraph.getModule(dep),
  127. chunkGraph,
  128. request: dep.request,
  129. runtimeRequirements
  130. });
  131. const provided = !usedName
  132. ? moduleRaw
  133. : usedName instanceof InlinedUsedName
  134. ? `(${moduleRaw}, ${usedName.render(
  135. Template.toNormalComment(
  136. `inlined export ${propertyAccess(dep.ids)}`
  137. )
  138. )})`
  139. : `${moduleRaw}${propertyAccess(/** @type {string[]} */ (usedName), 0)}`;
  140. initFragments.push(
  141. new InitFragment(
  142. `/* provided dependency */ var ${dep.identifier} = ${provided};\n`,
  143. InitFragment.STAGE_PROVIDES,
  144. 1,
  145. `provided ${dep.identifier}`
  146. )
  147. );
  148. source.replace(dep.range[0], dep.range[1] - 1, dep.identifier);
  149. }
  150. }
  151. ProvidedDependency.Template = ProvidedDependencyTemplate;
  152. module.exports = ProvidedDependency;