ExternalModuleInitFragment.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Ivan Kopeykin @vankop
  4. */
  5. "use strict";
  6. const InitFragment = require("../InitFragment");
  7. const makeSerializable = require("../util/makeSerializable");
  8. /** @typedef {import("webpack-sources").Source} Source */
  9. /** @typedef {import("../Generator").GenerateContext} GenerateContext */
  10. /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
  11. /** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
  12. /** @typedef {Map<string, Set<string>>} ImportSpecifiers */
  13. /**
  14. * @extends {InitFragment<GenerateContext>}
  15. */
  16. class ExternalModuleInitFragment extends InitFragment {
  17. /**
  18. * @param {string} importedModule imported module
  19. * @param {Array<{ name: string, value?: string }> | ImportSpecifiers} specifiers import specifiers
  20. * @param {string=} defaultImport default import
  21. */
  22. constructor(importedModule, specifiers, defaultImport) {
  23. super(
  24. undefined,
  25. InitFragment.STAGE_CONSTANTS,
  26. 0,
  27. `external module imports|${importedModule}|${defaultImport || "null"}`
  28. );
  29. this.importedModule = importedModule;
  30. if (Array.isArray(specifiers)) {
  31. /** @type {ImportSpecifiers} */
  32. this.specifiers = new Map();
  33. for (const { name, value } of specifiers) {
  34. let specifiers = this.specifiers.get(name);
  35. if (!specifiers) {
  36. specifiers = new Set();
  37. this.specifiers.set(name, specifiers);
  38. }
  39. specifiers.add(value || name);
  40. }
  41. } else {
  42. this.specifiers = specifiers;
  43. }
  44. this.defaultImport = defaultImport;
  45. }
  46. /**
  47. * @param {ExternalModuleInitFragment} other other
  48. * @returns {ExternalModuleInitFragment} ExternalModuleInitFragment
  49. */
  50. merge(other) {
  51. const newSpecifiersMap = new Map(this.specifiers);
  52. for (const [name, specifiers] of other.specifiers) {
  53. if (newSpecifiersMap.has(name)) {
  54. const currentSpecifiers =
  55. /** @type {Set<string>} */
  56. (newSpecifiersMap.get(name));
  57. for (const spec of specifiers) currentSpecifiers.add(spec);
  58. } else {
  59. newSpecifiersMap.set(name, specifiers);
  60. }
  61. }
  62. return new ExternalModuleInitFragment(
  63. this.importedModule,
  64. newSpecifiersMap,
  65. this.defaultImport
  66. );
  67. }
  68. /**
  69. * @param {GenerateContext} context context
  70. * @returns {string | Source | undefined} the source code that will be included as initialization code
  71. */
  72. getContent({ runtimeRequirements }) {
  73. const namedImports = [];
  74. for (const [name, specifiers] of this.specifiers) {
  75. for (const spec of specifiers) {
  76. if (spec === name) {
  77. namedImports.push(name);
  78. } else {
  79. namedImports.push(`${name} as ${spec}`);
  80. }
  81. }
  82. }
  83. let importsString =
  84. namedImports.length > 0 ? `{${namedImports.join(",")}}` : "";
  85. if (this.defaultImport) {
  86. importsString = `${this.defaultImport}${
  87. importsString ? `, ${importsString}` : ""
  88. }`;
  89. }
  90. return `import ${importsString} from ${JSON.stringify(
  91. this.importedModule
  92. )};`;
  93. }
  94. /**
  95. * @param {ObjectSerializerContext} context context
  96. */
  97. serialize(context) {
  98. super.serialize(context);
  99. const { write } = context;
  100. write(this.importedModule);
  101. write(this.specifiers);
  102. write(this.defaultImport);
  103. }
  104. /**
  105. * @param {ObjectDeserializerContext} context context
  106. */
  107. deserialize(context) {
  108. super.deserialize(context);
  109. const { read } = context;
  110. this.importedModule = read();
  111. this.specifiers = read();
  112. this.defaultImport = read();
  113. }
  114. }
  115. makeSerializable(
  116. ExternalModuleInitFragment,
  117. "webpack/lib/dependencies/ExternalModuleInitFragment"
  118. );
  119. module.exports = ExternalModuleInitFragment;