visit.js 8.4 KB

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