normalize-and-load-metadata.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  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. const programScope = programPath.scope;
  238. const programChildren = programPath.get("body");
  239. programChildren.forEach(child => {
  240. let kind;
  241. if (child.isImportDeclaration()) {
  242. kind = "import";
  243. } else {
  244. if (child.isExportDefaultDeclaration()) {
  245. child = child.get("declaration");
  246. }
  247. if (child.isExportNamedDeclaration()) {
  248. if (child.node.declaration) {
  249. child = child.get("declaration");
  250. } else if (initializeReexports && child.node.source && child.get("source").isStringLiteral()) {
  251. child.get("specifiers").forEach(spec => {
  252. assertExportSpecifier(spec);
  253. bindingKindLookup.set(spec.get("local").node.name, "block");
  254. });
  255. return;
  256. }
  257. }
  258. if (child.isFunctionDeclaration()) {
  259. kind = "hoisted";
  260. } else if (child.isClassDeclaration()) {
  261. kind = "block";
  262. } else if (child.isVariableDeclaration({
  263. kind: "var"
  264. })) {
  265. kind = "var";
  266. } else if (child.isVariableDeclaration()) {
  267. kind = "block";
  268. } else {
  269. return;
  270. }
  271. }
  272. Object.keys(child.getOuterBindingIdentifiers()).forEach(name => {
  273. bindingKindLookup.set(name, kind);
  274. });
  275. });
  276. const localMetadata = new Map();
  277. const getLocalMetadata = idPath => {
  278. const localName = idPath.node.name;
  279. let metadata = localMetadata.get(localName);
  280. if (!metadata) {
  281. var _bindingKindLookup$ge, _programScope$getBind;
  282. const kind = (_bindingKindLookup$ge = bindingKindLookup.get(localName)) != null ? _bindingKindLookup$ge : (_programScope$getBind = programScope.getBinding(localName)) == null ? void 0 : _programScope$getBind.kind;
  283. if (kind === undefined) {
  284. throw idPath.buildCodeFrameError(`Exporting local "${localName}", which is not declared.`);
  285. }
  286. metadata = {
  287. names: [],
  288. kind
  289. };
  290. localMetadata.set(localName, metadata);
  291. }
  292. return metadata;
  293. };
  294. programChildren.forEach(child => {
  295. if (child.isExportNamedDeclaration() && (initializeReexports || !child.node.source)) {
  296. if (child.node.declaration) {
  297. const declaration = child.get("declaration");
  298. const ids = declaration.getOuterBindingIdentifierPaths();
  299. Object.keys(ids).forEach(name => {
  300. if (name === "__esModule") {
  301. throw declaration.buildCodeFrameError('Illegal export "__esModule".');
  302. }
  303. getLocalMetadata(ids[name]).names.push(name);
  304. });
  305. } else {
  306. child.get("specifiers").forEach(spec => {
  307. const local = spec.get("local");
  308. const exported = spec.get("exported");
  309. const localMetadata = getLocalMetadata(local);
  310. const exportName = getExportSpecifierName(exported, stringSpecifiers);
  311. if (exportName === "__esModule") {
  312. throw exported.buildCodeFrameError('Illegal export "__esModule".');
  313. }
  314. localMetadata.names.push(exportName);
  315. });
  316. }
  317. } else if (child.isExportDefaultDeclaration()) {
  318. const declaration = child.get("declaration");
  319. if (declaration.isFunctionDeclaration() || declaration.isClassDeclaration()) {
  320. getLocalMetadata(declaration.get("id")).names.push("default");
  321. } else {
  322. throw declaration.buildCodeFrameError("Unexpected default expression export.");
  323. }
  324. }
  325. });
  326. return localMetadata;
  327. }
  328. function nameAnonymousExports(programPath) {
  329. programPath.get("body").forEach(child => {
  330. if (!child.isExportDefaultDeclaration()) return;
  331. {
  332. var _child$splitExportDec;
  333. (_child$splitExportDec = child.splitExportDeclaration) != null ? _child$splitExportDec : child.splitExportDeclaration = require("@babel/traverse").NodePath.prototype.splitExportDeclaration;
  334. }
  335. child.splitExportDeclaration();
  336. });
  337. }
  338. function removeImportExportDeclarations(programPath) {
  339. programPath.get("body").forEach(child => {
  340. if (child.isImportDeclaration()) {
  341. child.remove();
  342. } else if (child.isExportNamedDeclaration()) {
  343. if (child.node.declaration) {
  344. child.node.declaration._blockHoist = child.node._blockHoist;
  345. child.replaceWith(child.node.declaration);
  346. } else {
  347. child.remove();
  348. }
  349. } else if (child.isExportDefaultDeclaration()) {
  350. const declaration = child.get("declaration");
  351. if (declaration.isFunctionDeclaration() || declaration.isClassDeclaration()) {
  352. declaration._blockHoist = child.node._blockHoist;
  353. child.replaceWith(declaration);
  354. } else {
  355. throw declaration.buildCodeFrameError("Unexpected default expression export.");
  356. }
  357. } else if (child.isExportAllDeclaration()) {
  358. child.remove();
  359. }
  360. });
  361. }
  362. //# sourceMappingURL=normalize-and-load-metadata.js.map