visit.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.getVisitor = void 0;
  6. var _assert = require("assert");
  7. var _hoist = require("./hoist.js");
  8. var _emit = require("./emit.js");
  9. var _replaceShorthandObjectMethod = require("./replaceShorthandObjectMethod.js");
  10. var util = require("./util.js");
  11. const getVisitor = t => ({
  12. Method(path, state) {
  13. const node = path.node;
  14. if (!shouldRegenerate(node, state)) return;
  15. const container = t.functionExpression(null, [], t.cloneNode(node.body, false), node.generator, node.async);
  16. path.get("body").set("body", [t.returnStatement(t.callExpression(container, []))]);
  17. node.async = false;
  18. node.generator = false;
  19. path.get("body.body.0.argument.callee").unwrapFunctionEnvironment();
  20. },
  21. Function: {
  22. exit: util.wrapWithTypes(t, function (path, state) {
  23. let node = path.node;
  24. if (!shouldRegenerate(node, state)) return;
  25. path = (0, _replaceShorthandObjectMethod.default)(path);
  26. node = path.node;
  27. const contextId = path.scope.generateUidIdentifier("context");
  28. const argsId = path.scope.generateUidIdentifier("args");
  29. path.ensureBlock();
  30. const bodyBlockPath = path.get("body");
  31. if (node.async) {
  32. bodyBlockPath.traverse(awaitVisitor, this);
  33. }
  34. bodyBlockPath.traverse(functionSentVisitor, {
  35. context: contextId,
  36. pluginPass: this
  37. });
  38. const outerBody = [];
  39. const innerBody = [];
  40. bodyBlockPath.get("body").forEach(function (childPath) {
  41. const node = childPath.node;
  42. if (t.isExpressionStatement(node) && t.isStringLiteral(node.expression)) {
  43. outerBody.push(node);
  44. } else if ((node == null ? void 0 : node._blockHoist) != null) {
  45. outerBody.push(node);
  46. } else {
  47. innerBody.push(node);
  48. }
  49. });
  50. if (outerBody.length > 0) {
  51. bodyBlockPath.node.body = innerBody;
  52. }
  53. const outerFnExpr = getOuterFnExpr(this, path);
  54. t.assertIdentifier(node.id);
  55. const vars = (0, _hoist.hoist)(path);
  56. const context = {
  57. usesThis: false,
  58. usesArguments: false,
  59. getArgsId: () => t.clone(argsId)
  60. };
  61. path.traverse(argumentsThisVisitor, context);
  62. if (context.usesArguments) {
  63. vars.push(t.variableDeclarator(t.clone(argsId), t.identifier("arguments")));
  64. }
  65. const emitter = new _emit.Emitter(contextId, path.scope, vars, this);
  66. emitter.explode(path.get("body"));
  67. if (vars.length > 0) {
  68. outerBody.push(t.variableDeclaration("var", vars));
  69. }
  70. const wrapArgs = [emitter.getContextFunction()];
  71. const tryLocsList = emitter.getTryLocsList();
  72. if (node.generator) {
  73. wrapArgs.push(outerFnExpr);
  74. } else if (context.usesThis || tryLocsList || node.async) {
  75. wrapArgs.push(t.nullLiteral());
  76. }
  77. if (context.usesThis) {
  78. wrapArgs.push(t.thisExpression());
  79. } else if (tryLocsList || node.async) {
  80. wrapArgs.push(t.nullLiteral());
  81. }
  82. if (tryLocsList) {
  83. wrapArgs.push(tryLocsList);
  84. } else if (node.async) {
  85. wrapArgs.push(t.nullLiteral());
  86. }
  87. if (node.async) {
  88. let currentScope = path.scope;
  89. do {
  90. if (currentScope.hasOwnBinding("Promise")) currentScope.rename("Promise");
  91. } while (currentScope = currentScope.parent);
  92. wrapArgs.push(t.identifier("Promise"));
  93. }
  94. const wrapCall = t.callExpression(util.newHelpersAvailable(this) ? !node.async ? t.memberExpression(t.callExpression(this.addHelper("regenerator"), []), t.identifier("w")) : node.generator ? this.addHelper("regeneratorAsyncGen") : this.addHelper("regeneratorAsync") : util.runtimeProperty(this, node.async ? "async" : "wrap"), wrapArgs);
  95. outerBody.push(t.returnStatement(wrapCall));
  96. node.body = t.blockStatement(outerBody);
  97. path.get("body.body").forEach(p => p.scope.registerDeclaration(p));
  98. const oldDirectives = bodyBlockPath.node.directives;
  99. if (oldDirectives) {
  100. node.body.directives = oldDirectives;
  101. }
  102. const wasGeneratorFunction = node.generator;
  103. if (wasGeneratorFunction) {
  104. node.generator = false;
  105. }
  106. if (node.async) {
  107. node.async = false;
  108. }
  109. if (wasGeneratorFunction && t.isExpression(node)) {
  110. util.replaceWithOrRemove(path, t.callExpression(util.newHelpersAvailable(this) ? t.memberExpression(t.callExpression(this.addHelper("regenerator"), []), t.identifier("m")) : util.runtimeProperty(this, "mark"), [node]));
  111. path.addComment("leading", "#__PURE__");
  112. }
  113. const insertedLocs = emitter.getInsertedLocs();
  114. path.traverse({
  115. NumericLiteral(path) {
  116. if (!insertedLocs.has(path.node)) {
  117. return;
  118. }
  119. path.replaceWith(t.numericLiteral(path.node.value));
  120. }
  121. });
  122. path.requeue();
  123. })
  124. }
  125. });
  126. exports.getVisitor = getVisitor;
  127. function shouldRegenerate(node, state) {
  128. if (node.generator) {
  129. if (node.async) {
  130. return state.opts.asyncGenerators !== false;
  131. } else {
  132. return state.opts.generators !== false;
  133. }
  134. } else if (node.async) {
  135. return state.opts.async !== false;
  136. } else {
  137. return false;
  138. }
  139. }
  140. function getOuterFnExpr(state, funPath) {
  141. const t = util.getTypes();
  142. const node = funPath.node;
  143. t.assertFunction(node);
  144. if (!node.id) {
  145. node.id = funPath.scope.parent.generateUidIdentifier("callee");
  146. }
  147. if (node.generator && t.isFunctionDeclaration(node)) {
  148. return getMarkedFunctionId(state, funPath);
  149. }
  150. return t.clone(node.id);
  151. }
  152. const markInfo = new WeakMap();
  153. function getMarkInfo(node) {
  154. if (!markInfo.has(node)) {
  155. markInfo.set(node, {});
  156. }
  157. return markInfo.get(node);
  158. }
  159. function getMarkedFunctionId(state, funPath) {
  160. const t = util.getTypes();
  161. const node = funPath.node;
  162. t.assertIdentifier(node.id);
  163. const blockPath = funPath.findParent(function (path) {
  164. return path.isProgram() || path.isBlockStatement();
  165. });
  166. if (!blockPath) {
  167. return node.id;
  168. }
  169. const block = blockPath.node;
  170. _assert.ok(Array.isArray(block.body));
  171. const info = getMarkInfo(block);
  172. if (!info.decl) {
  173. info.decl = t.variableDeclaration("var", []);
  174. blockPath.unshiftContainer("body", info.decl);
  175. info.declPath = blockPath.get("body.0");
  176. }
  177. _assert.strictEqual(info.declPath.node, info.decl);
  178. const markedId = blockPath.scope.generateUidIdentifier("marked");
  179. const markCallExp = t.callExpression(util.newHelpersAvailable(state) ? t.memberExpression(t.callExpression(state.addHelper("regenerator"), []), t.identifier("m")) : util.runtimeProperty(state, "mark"), [t.clone(node.id)]);
  180. const index = info.decl.declarations.push(t.variableDeclarator(markedId, markCallExp)) - 1;
  181. const markCallExpPath = info.declPath.get("declarations." + index + ".init");
  182. _assert.strictEqual(markCallExpPath.node, markCallExp);
  183. markCallExpPath.addComment("leading", "#__PURE__");
  184. return t.clone(markedId);
  185. }
  186. const argumentsThisVisitor = {
  187. "FunctionExpression|FunctionDeclaration|Method": function (path) {
  188. path.skip();
  189. },
  190. Identifier: function (path, state) {
  191. if (path.node.name === "arguments" && util.isReference(path)) {
  192. util.replaceWithOrRemove(path, state.getArgsId());
  193. state.usesArguments = true;
  194. }
  195. },
  196. ThisExpression: function (path, state) {
  197. state.usesThis = true;
  198. }
  199. };
  200. const functionSentVisitor = {
  201. MetaProperty(path, state) {
  202. const {
  203. node
  204. } = path;
  205. if (node.meta.name === "function" && node.property.name === "sent") {
  206. const t = util.getTypes();
  207. util.replaceWithOrRemove(path, t.memberExpression(t.clone(this.context), t.identifier(util.newHelpersAvailable(state.pluginPass) ? "v" : "_sent")));
  208. }
  209. }
  210. };
  211. const awaitVisitor = {
  212. Function: function (path) {
  213. path.skip();
  214. },
  215. AwaitExpression: function (path) {
  216. const t = util.getTypes();
  217. const argument = path.node.argument;
  218. const helper = util.newHelpersAvailable(this) ? this.addHelper("awaitAsyncGenerator") : util.runtimeProperty(this, "awrap");
  219. util.replaceWithOrRemove(path, t.yieldExpression(t.callExpression(helper, [argument]), false));
  220. }
  221. };
  222. //# sourceMappingURL=visit.js.map