normalize-and-load-metadata.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = normalizeModuleAndLoadMetadata;
  6. exports.hasExports = hasExports;
  7. exports.isSideEffectImport = isSideEffectImport;
  8. exports.validateImportInteropOption = validateImportInteropOption;
  9. var _path = require("path");
  10. var _helperValidatorIdentifier = require("@babel/helper-validator-identifier");
  11. function hasExports(metadata) {
  12. return metadata.hasExports;
  13. }
  14. function isSideEffectImport(source) {
  15. return source.imports.size === 0 && source.importsNamespace.size === 0 && source.reexports.size === 0 && source.reexportNamespace.size === 0 && !source.reexportAll;
  16. }
  17. function validateImportInteropOption(importInterop) {
  18. if (typeof importInterop !== "function" && importInterop !== "none" && importInterop !== "babel" && importInterop !== "node") {
  19. throw new Error(`.importInterop must be one of "none", "babel", "node", or a function returning one of those values (received ${importInterop}).`);
  20. }
  21. return importInterop;
  22. }
  23. function resolveImportInterop(importInterop, source, filename) {
  24. if (typeof importInterop === "function") {
  25. return validateImportInteropOption(importInterop(source, filename));
  26. }
  27. return importInterop;
  28. }
  29. function normalizeModuleAndLoadMetadata(programPath, exportName, {
  30. importInterop,
  31. initializeReexports = false,
  32. getWrapperPayload,
  33. esNamespaceOnly = false,
  34. filename
  35. }) {
  36. if (!exportName) {
  37. exportName = programPath.scope.generateUidIdentifier("exports").name;
  38. }
  39. const stringSpecifiers = new Set();
  40. nameAnonymousExports(programPath);
  41. const {
  42. local,
  43. sources,
  44. hasExports
  45. } = getModuleMetadata(programPath, {
  46. initializeReexports,
  47. getWrapperPayload
  48. }, stringSpecifiers);
  49. removeImportExportDeclarations(programPath);
  50. for (const [source, metadata] of sources) {
  51. const {
  52. importsNamespace,
  53. imports
  54. } = metadata;
  55. if (importsNamespace.size > 0 && imports.size === 0) {
  56. const [nameOfnamespace] = importsNamespace;
  57. metadata.name = nameOfnamespace;
  58. }
  59. const resolvedInterop = resolveImportInterop(importInterop, source, filename);
  60. if (resolvedInterop === "none") {
  61. metadata.interop = "none";
  62. } else if (resolvedInterop === "node" && metadata.interop === "namespace") {
  63. metadata.interop = "node-namespace";
  64. } else if (resolvedInterop === "node" && metadata.interop === "default") {
  65. metadata.interop = "node-default";
  66. } else if (esNamespaceOnly && metadata.interop === "namespace") {
  67. metadata.interop = "default";
  68. }
  69. }
  70. return {
  71. exportName,
  72. exportNameListName: null,
  73. hasExports,
  74. local,
  75. source: sources,
  76. stringSpecifiers
  77. };
  78. }
  79. function getExportSpecifierName(path, stringSpecifiers) {
  80. if (path.isIdentifier()) {
  81. return path.node.name;
  82. } else if (path.isStringLiteral()) {
  83. const stringValue = path.node.value;
  84. if (!(0, _helperValidatorIdentifier.isIdentifierName)(stringValue)) {
  85. stringSpecifiers.add(stringValue);
  86. }
  87. return stringValue;
  88. } else {
  89. throw new Error(`Expected export specifier to be either Identifier or StringLiteral, got ${path.node.type}`);
  90. }
  91. }
  92. function assertExportSpecifier(path) {
  93. if (path.isExportSpecifier()) {
  94. return;
  95. } else if (path.isExportNamespaceSpecifier()) {
  96. throw path.buildCodeFrameError("Export namespace should be first transformed by `@babel/plugin-transform-export-namespace-from`.");
  97. } else {
  98. throw path.buildCodeFrameError("Unexpected export specifier type");
  99. }
  100. }
  101. function getModuleMetadata(programPath, {
  102. getWrapperPayload,
  103. initializeReexports
  104. }, stringSpecifiers) {
  105. const localData = getLocalExportMetadata(programPath, initializeReexports, stringSpecifiers);
  106. const importNodes = new Map();
  107. const sourceData = new Map();
  108. const getData = (sourceNode, node) => {
  109. const source = sourceNode.value;
  110. let data = sourceData.get(source);
  111. if (!data) {
  112. data = {
  113. name: programPath.scope.generateUidIdentifier((0, _path.basename)(source, (0, _path.extname)(source))).name,
  114. interop: "none",
  115. loc: null,
  116. imports: new Map(),
  117. importsNamespace: new Set(),
  118. reexports: new Map(),
  119. reexportNamespace: new Set(),
  120. reexportAll: null,
  121. wrap: null,
  122. get lazy() {
  123. return this.wrap === "lazy";
  124. },
  125. referenced: false
  126. };
  127. sourceData.set(source, data);
  128. importNodes.set(source, [node]);
  129. } else {
  130. importNodes.get(source).push(node);
  131. }
  132. return data;
  133. };
  134. let hasExports = false;
  135. programPath.get("body").forEach(child => {
  136. if (child.isImportDeclaration()) {
  137. const data = getData(child.node.source, child.node);
  138. if (!data.loc) data.loc = child.node.loc;
  139. child.get("specifiers").forEach(spec => {
  140. if (spec.isImportDefaultSpecifier()) {
  141. const localName = spec.get("local").node.name;
  142. data.imports.set(localName, "default");
  143. const reexport = localData.get(localName);
  144. if (reexport) {
  145. localData.delete(localName);
  146. reexport.names.forEach(name => {
  147. data.reexports.set(name, "default");
  148. });
  149. data.referenced = true;
  150. }
  151. } else if (spec.isImportNamespaceSpecifier()) {
  152. const localName = spec.get("local").node.name;
  153. data.importsNamespace.add(localName);
  154. const reexport = localData.get(localName);
  155. if (reexport) {
  156. localData.delete(localName);
  157. reexport.names.forEach(name => {
  158. data.reexportNamespace.add(name);
  159. });
  160. data.referenced = true;
  161. }
  162. } else if (spec.isImportSpecifier()) {
  163. const importName = getExportSpecifierName(spec.get("imported"), stringSpecifiers);
  164. const localName = spec.get("local").node.name;
  165. data.imports.set(localName, importName);
  166. const reexport = localData.get(localName);
  167. if (reexport) {
  168. localData.delete(localName);
  169. reexport.names.forEach(name => {
  170. data.reexports.set(name, importName);
  171. });
  172. data.referenced = true;
  173. }
  174. }
  175. });
  176. } else if (child.isExportAllDeclaration()) {
  177. hasExports = true;
  178. const data = getData(child.node.source, child.node);
  179. if (!data.loc) data.loc = child.node.loc;
  180. data.reexportAll = {
  181. loc: child.node.loc
  182. };
  183. data.referenced = true;
  184. } else if (child.isExportNamedDeclaration() && child.node.source) {
  185. hasExports = true;
  186. const data = getData(child.node.source, child.node);
  187. if (!data.loc) data.loc = child.node.loc;
  188. child.get("specifiers").forEach(spec => {
  189. assertExportSpecifier(spec);
  190. const importName = getExportSpecifierName(spec.get("local"), stringSpecifiers);
  191. const exportName = getExportSpecifierName(spec.get("exported"), stringSpecifiers);
  192. data.reexports.set(exportName, importName);
  193. data.referenced = true;
  194. if (exportName === "__esModule") {
  195. throw spec.get("exported").buildCodeFrameError('Illegal export "__esModule".');
  196. }
  197. });
  198. } else if (child.isExportNamedDeclaration() || child.isExportDefaultDeclaration()) {
  199. hasExports = true;
  200. }
  201. });
  202. for (const metadata of sourceData.values()) {
  203. let needsDefault = false;
  204. let needsNamed = false;
  205. if (metadata.importsNamespace.size > 0) {
  206. needsDefault = true;
  207. needsNamed = true;
  208. }
  209. if (metadata.reexportAll) {
  210. needsNamed = true;
  211. }
  212. for (const importName of metadata.imports.values()) {
  213. if (importName === "default") needsDefault = true;else needsNamed = true;
  214. }
  215. for (const importName of metadata.reexports.values()) {
  216. if (importName === "default") needsDefault = true;else needsNamed = true;
  217. }
  218. if (needsDefault && needsNamed) {
  219. metadata.interop = "namespace";
  220. } else if (needsDefault) {
  221. metadata.interop = "default";
  222. }
  223. }
  224. if (getWrapperPayload) {
  225. for (const [source, metadata] of sourceData) {
  226. metadata.wrap = getWrapperPayload(source, metadata, importNodes.get(source));
  227. }
  228. }
  229. return {
  230. hasExports,
  231. local: localData,
  232. sources: sourceData
  233. };
  234. }
  235. function getLocalExportMetadata(programPath, initializeReexports, stringSpecifiers) {
  236. const bindingKindLookup = new Map();
  237. programPath.get("body").forEach(child => {
  238. let kind;
  239. if (child.isImportDeclaration()) {
  240. kind = "import";
  241. } else {
  242. if (child.isExportDefaultDeclaration()) {
  243. child = child.get("declaration");
  244. }
  245. if (child.isExportNamedDeclaration()) {
  246. if (child.node.declaration) {
  247. child = child.get("declaration");
  248. } else if (initializeReexports && child.node.source && child.get("source").isStringLiteral()) {
  249. child.get("specifiers").forEach(spec => {
  250. assertExportSpecifier(spec);
  251. bindingKindLookup.set(spec.get("local").node.name, "block");
  252. });
  253. return;
  254. }
  255. }
  256. if (child.isFunctionDeclaration()) {
  257. kind = "hoisted";
  258. } else if (child.isClassDeclaration()) {
  259. kind = "block";
  260. } else if (child.isVariableDeclaration({
  261. kind: "var"
  262. })) {
  263. kind = "var";
  264. } else if (child.isVariableDeclaration()) {
  265. kind = "block";
  266. } else {
  267. return;
  268. }
  269. }
  270. Object.keys(child.getOuterBindingIdentifiers()).forEach(name => {
  271. bindingKindLookup.set(name, kind);
  272. });
  273. });
  274. const localMetadata = new Map();
  275. const getLocalMetadata = idPath => {
  276. const localName = idPath.node.name;
  277. let metadata = localMetadata.get(localName);
  278. if (!metadata) {
  279. const kind = bindingKindLookup.get(localName);
  280. if (kind === undefined) {
  281. throw idPath.buildCodeFrameError(`Exporting local "${localName}", which is not declared.`);
  282. }
  283. metadata = {
  284. names: [],
  285. kind
  286. };
  287. localMetadata.set(localName, metadata);
  288. }
  289. return metadata;
  290. };
  291. programPath.get("body").forEach(child => {
  292. if (child.isExportNamedDeclaration() && (initializeReexports || !child.node.source)) {
  293. if (child.node.declaration) {
  294. const declaration = child.get("declaration");
  295. const ids = declaration.getOuterBindingIdentifierPaths();
  296. Object.keys(ids).forEach(name => {
  297. if (name === "__esModule") {
  298. throw declaration.buildCodeFrameError('Illegal export "__esModule".');
  299. }
  300. getLocalMetadata(ids[name]).names.push(name);
  301. });
  302. } else {
  303. child.get("specifiers").forEach(spec => {
  304. const local = spec.get("local");
  305. const exported = spec.get("exported");
  306. const localMetadata = getLocalMetadata(local);
  307. const exportName = getExportSpecifierName(exported, stringSpecifiers);
  308. if (exportName === "__esModule") {
  309. throw exported.buildCodeFrameError('Illegal export "__esModule".');
  310. }
  311. localMetadata.names.push(exportName);
  312. });
  313. }
  314. } else if (child.isExportDefaultDeclaration()) {
  315. const declaration = child.get("declaration");
  316. if (declaration.isFunctionDeclaration() || declaration.isClassDeclaration()) {
  317. getLocalMetadata(declaration.get("id")).names.push("default");
  318. } else {
  319. throw declaration.buildCodeFrameError("Unexpected default expression export.");
  320. }
  321. }
  322. });
  323. return localMetadata;
  324. }
  325. function nameAnonymousExports(programPath) {
  326. programPath.get("body").forEach(child => {
  327. if (!child.isExportDefaultDeclaration()) return;
  328. {
  329. var _child$splitExportDec;
  330. (_child$splitExportDec = child.splitExportDeclaration) != null ? _child$splitExportDec : child.splitExportDeclaration = require("@babel/traverse").NodePath.prototype.splitExportDeclaration;
  331. }
  332. child.splitExportDeclaration();
  333. });
  334. }
  335. function removeImportExportDeclarations(programPath) {
  336. programPath.get("body").forEach(child => {
  337. if (child.isImportDeclaration()) {
  338. child.remove();
  339. } else if (child.isExportNamedDeclaration()) {
  340. if (child.node.declaration) {
  341. child.node.declaration._blockHoist = child.node._blockHoist;
  342. child.replaceWith(child.node.declaration);
  343. } else {
  344. child.remove();
  345. }
  346. } else if (child.isExportDefaultDeclaration()) {
  347. const declaration = child.get("declaration");
  348. if (declaration.isFunctionDeclaration() || declaration.isClassDeclaration()) {
  349. declaration._blockHoist = child.node._blockHoist;
  350. child.replaceWith(declaration);
  351. } else {
  352. throw declaration.buildCodeFrameError("Unexpected default expression export.");
  353. }
  354. } else if (child.isExportAllDeclaration()) {
  355. child.remove();
  356. }
  357. });
  358. }
  359. //# sourceMappingURL=normalize-and-load-metadata.js.map