ExternalModuleInitFragment.js 3.7 KB

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