index.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.rewriteModuleStatementsAndPrepareHeader = rewriteModuleStatementsAndPrepareHeader;
  6. exports.ensureStatementsHoisted = ensureStatementsHoisted;
  7. exports.wrapInterop = wrapInterop;
  8. exports.buildNamespaceInitStatements = buildNamespaceInitStatements;
  9. Object.defineProperty(exports, "isModule", {
  10. enumerable: true,
  11. get: function () {
  12. return _helperModuleImports.isModule;
  13. }
  14. });
  15. Object.defineProperty(exports, "rewriteThis", {
  16. enumerable: true,
  17. get: function () {
  18. return _rewriteThis.default;
  19. }
  20. });
  21. Object.defineProperty(exports, "hasExports", {
  22. enumerable: true,
  23. get: function () {
  24. return _normalizeAndLoadMetadata.hasExports;
  25. }
  26. });
  27. Object.defineProperty(exports, "isSideEffectImport", {
  28. enumerable: true,
  29. get: function () {
  30. return _normalizeAndLoadMetadata.isSideEffectImport;
  31. }
  32. });
  33. Object.defineProperty(exports, "getModuleName", {
  34. enumerable: true,
  35. get: function () {
  36. return _getModuleName.default;
  37. }
  38. });
  39. var _assert = require("assert");
  40. var t = require("@babel/types");
  41. var _template = require("@babel/template");
  42. var _helperModuleImports = require("@babel/helper-module-imports");
  43. var _rewriteThis = require("./rewrite-this");
  44. var _rewriteLiveReferences = require("./rewrite-live-references");
  45. var _normalizeAndLoadMetadata = require("./normalize-and-load-metadata");
  46. var _getModuleName = require("./get-module-name");
  47. function rewriteModuleStatementsAndPrepareHeader(path, {
  48. loose,
  49. exportName,
  50. strict,
  51. allowTopLevelThis,
  52. strictMode,
  53. noInterop,
  54. importInterop = noInterop ? "none" : "babel",
  55. lazy,
  56. esNamespaceOnly,
  57. constantReexports = loose,
  58. enumerableModuleMeta = loose
  59. }) {
  60. (0, _normalizeAndLoadMetadata.validateImportInteropOption)(importInterop);
  61. _assert((0, _helperModuleImports.isModule)(path), "Cannot process module statements in a script");
  62. path.node.sourceType = "script";
  63. const meta = (0, _normalizeAndLoadMetadata.default)(path, exportName, {
  64. importInterop,
  65. initializeReexports: constantReexports,
  66. lazy,
  67. esNamespaceOnly
  68. });
  69. if (!allowTopLevelThis) {
  70. (0, _rewriteThis.default)(path);
  71. }
  72. (0, _rewriteLiveReferences.default)(path, meta);
  73. if (strictMode !== false) {
  74. const hasStrict = path.node.directives.some(directive => {
  75. return directive.value.value === "use strict";
  76. });
  77. if (!hasStrict) {
  78. path.unshiftContainer("directives", t.directive(t.directiveLiteral("use strict")));
  79. }
  80. }
  81. const headers = [];
  82. if ((0, _normalizeAndLoadMetadata.hasExports)(meta) && !strict) {
  83. headers.push(buildESModuleHeader(meta, enumerableModuleMeta));
  84. }
  85. const nameList = buildExportNameListDeclaration(path, meta);
  86. if (nameList) {
  87. meta.exportNameListName = nameList.name;
  88. headers.push(nameList.statement);
  89. }
  90. headers.push(...buildExportInitializationStatements(path, meta, constantReexports));
  91. return {
  92. meta,
  93. headers
  94. };
  95. }
  96. function ensureStatementsHoisted(statements) {
  97. statements.forEach(header => {
  98. header._blockHoist = 3;
  99. });
  100. }
  101. function wrapInterop(programPath, expr, type) {
  102. if (type === "none") {
  103. return null;
  104. }
  105. if (type === "node-namespace") {
  106. return t.callExpression(programPath.hub.addHelper("interopRequireWildcard"), [expr, t.booleanLiteral(true)]);
  107. } else if (type === "node-default") {
  108. return null;
  109. }
  110. let helper;
  111. if (type === "default") {
  112. helper = "interopRequireDefault";
  113. } else if (type === "namespace") {
  114. helper = "interopRequireWildcard";
  115. } else {
  116. throw new Error(`Unknown interop: ${type}`);
  117. }
  118. return t.callExpression(programPath.hub.addHelper(helper), [expr]);
  119. }
  120. function buildNamespaceInitStatements(metadata, sourceMetadata, constantReexports = false) {
  121. const statements = [];
  122. let srcNamespace = t.identifier(sourceMetadata.name);
  123. if (sourceMetadata.lazy) srcNamespace = t.callExpression(srcNamespace, []);
  124. for (const localName of sourceMetadata.importsNamespace) {
  125. if (localName === sourceMetadata.name) continue;
  126. statements.push(_template.default.statement`var NAME = SOURCE;`({
  127. NAME: localName,
  128. SOURCE: t.cloneNode(srcNamespace)
  129. }));
  130. }
  131. if (constantReexports) {
  132. statements.push(...buildReexportsFromMeta(metadata, sourceMetadata, true));
  133. }
  134. for (const exportName of sourceMetadata.reexportNamespace) {
  135. statements.push((sourceMetadata.lazy ? _template.default.statement`
  136. Object.defineProperty(EXPORTS, "NAME", {
  137. enumerable: true,
  138. get: function() {
  139. return NAMESPACE;
  140. }
  141. });
  142. ` : _template.default.statement`EXPORTS.NAME = NAMESPACE;`)({
  143. EXPORTS: metadata.exportName,
  144. NAME: exportName,
  145. NAMESPACE: t.cloneNode(srcNamespace)
  146. }));
  147. }
  148. if (sourceMetadata.reexportAll) {
  149. const statement = buildNamespaceReexport(metadata, t.cloneNode(srcNamespace), constantReexports);
  150. statement.loc = sourceMetadata.reexportAll.loc;
  151. statements.push(statement);
  152. }
  153. return statements;
  154. }
  155. const ReexportTemplate = {
  156. constant: _template.default.statement`EXPORTS.EXPORT_NAME = NAMESPACE_IMPORT;`,
  157. constantComputed: _template.default.statement`EXPORTS["EXPORT_NAME"] = NAMESPACE_IMPORT;`,
  158. spec: (0, _template.default)`
  159. Object.defineProperty(EXPORTS, "EXPORT_NAME", {
  160. enumerable: true,
  161. get: function() {
  162. return NAMESPACE_IMPORT;
  163. },
  164. });
  165. `
  166. };
  167. const buildReexportsFromMeta = (meta, metadata, constantReexports) => {
  168. const namespace = metadata.lazy ? t.callExpression(t.identifier(metadata.name), []) : t.identifier(metadata.name);
  169. const {
  170. stringSpecifiers
  171. } = meta;
  172. return Array.from(metadata.reexports, ([exportName, importName]) => {
  173. let NAMESPACE_IMPORT = t.cloneNode(namespace);
  174. if (importName === "default" && metadata.interop === "node-default") {} else if (stringSpecifiers.has(importName)) {
  175. NAMESPACE_IMPORT = t.memberExpression(NAMESPACE_IMPORT, t.stringLiteral(importName), true);
  176. } else {
  177. NAMESPACE_IMPORT = t.memberExpression(NAMESPACE_IMPORT, t.identifier(importName));
  178. }
  179. const astNodes = {
  180. EXPORTS: meta.exportName,
  181. EXPORT_NAME: exportName,
  182. NAMESPACE_IMPORT
  183. };
  184. if (constantReexports || t.isIdentifier(NAMESPACE_IMPORT)) {
  185. if (stringSpecifiers.has(exportName)) {
  186. return ReexportTemplate.constantComputed(astNodes);
  187. } else {
  188. return ReexportTemplate.constant(astNodes);
  189. }
  190. } else {
  191. return ReexportTemplate.spec(astNodes);
  192. }
  193. });
  194. };
  195. function buildESModuleHeader(metadata, enumerableModuleMeta = false) {
  196. return (enumerableModuleMeta ? _template.default.statement`
  197. EXPORTS.__esModule = true;
  198. ` : _template.default.statement`
  199. Object.defineProperty(EXPORTS, "__esModule", {
  200. value: true,
  201. });
  202. `)({
  203. EXPORTS: metadata.exportName
  204. });
  205. }
  206. function buildNamespaceReexport(metadata, namespace, constantReexports) {
  207. return (constantReexports ? _template.default.statement`
  208. Object.keys(NAMESPACE).forEach(function(key) {
  209. if (key === "default" || key === "__esModule") return;
  210. VERIFY_NAME_LIST;
  211. if (key in EXPORTS && EXPORTS[key] === NAMESPACE[key]) return;
  212. EXPORTS[key] = NAMESPACE[key];
  213. });
  214. ` : _template.default.statement`
  215. Object.keys(NAMESPACE).forEach(function(key) {
  216. if (key === "default" || key === "__esModule") return;
  217. VERIFY_NAME_LIST;
  218. if (key in EXPORTS && EXPORTS[key] === NAMESPACE[key]) return;
  219. Object.defineProperty(EXPORTS, key, {
  220. enumerable: true,
  221. get: function() {
  222. return NAMESPACE[key];
  223. },
  224. });
  225. });
  226. `)({
  227. NAMESPACE: namespace,
  228. EXPORTS: metadata.exportName,
  229. VERIFY_NAME_LIST: metadata.exportNameListName ? (0, _template.default)`
  230. if (Object.prototype.hasOwnProperty.call(EXPORTS_LIST, key)) return;
  231. `({
  232. EXPORTS_LIST: metadata.exportNameListName
  233. }) : null
  234. });
  235. }
  236. function buildExportNameListDeclaration(programPath, metadata) {
  237. const exportedVars = Object.create(null);
  238. for (const data of metadata.local.values()) {
  239. for (const name of data.names) {
  240. exportedVars[name] = true;
  241. }
  242. }
  243. let hasReexport = false;
  244. for (const data of metadata.source.values()) {
  245. for (const exportName of data.reexports.keys()) {
  246. exportedVars[exportName] = true;
  247. }
  248. for (const exportName of data.reexportNamespace) {
  249. exportedVars[exportName] = true;
  250. }
  251. hasReexport = hasReexport || !!data.reexportAll;
  252. }
  253. if (!hasReexport || Object.keys(exportedVars).length === 0) return null;
  254. const name = programPath.scope.generateUidIdentifier("exportNames");
  255. delete exportedVars.default;
  256. return {
  257. name: name.name,
  258. statement: t.variableDeclaration("var", [t.variableDeclarator(name, t.valueToNode(exportedVars))])
  259. };
  260. }
  261. function buildExportInitializationStatements(programPath, metadata, constantReexports = false) {
  262. const initStatements = [];
  263. const exportNames = [];
  264. for (const [localName, data] of metadata.local) {
  265. if (data.kind === "import") {} else if (data.kind === "hoisted") {
  266. initStatements.push(buildInitStatement(metadata, data.names, t.identifier(localName)));
  267. } else {
  268. exportNames.push(...data.names);
  269. }
  270. }
  271. for (const data of metadata.source.values()) {
  272. if (!constantReexports) {
  273. initStatements.push(...buildReexportsFromMeta(metadata, data, false));
  274. }
  275. for (const exportName of data.reexportNamespace) {
  276. exportNames.push(exportName);
  277. }
  278. }
  279. initStatements.push(...chunk(exportNames, 100).map(members => {
  280. return buildInitStatement(metadata, members, programPath.scope.buildUndefinedNode());
  281. }));
  282. return initStatements;
  283. }
  284. const InitTemplate = {
  285. computed: _template.default.expression`EXPORTS["NAME"] = VALUE`,
  286. default: _template.default.expression`EXPORTS.NAME = VALUE`
  287. };
  288. function buildInitStatement(metadata, exportNames, initExpr) {
  289. const {
  290. stringSpecifiers,
  291. exportName: EXPORTS
  292. } = metadata;
  293. return t.expressionStatement(exportNames.reduce((acc, exportName) => {
  294. const params = {
  295. EXPORTS,
  296. NAME: exportName,
  297. VALUE: acc
  298. };
  299. if (stringSpecifiers.has(exportName)) {
  300. return InitTemplate.computed(params);
  301. } else {
  302. return InitTemplate.default(params);
  303. }
  304. }, initExpr));
  305. }
  306. function chunk(array, size) {
  307. const chunks = [];
  308. for (let i = 0; i < array.length; i += size) {
  309. chunks.push(array.slice(i, i + size));
  310. }
  311. return chunks;
  312. }