web 3d图形渲染器
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

367 lines
11 KiB

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