ExternalModuleInitFragment.js 3.6 KB

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