index.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = wrapFunction;
  6. var _helperFunctionName = require("@babel/helper-function-name");
  7. var _template = require("@babel/template");
  8. var t = require("@babel/types");
  9. const buildAnonymousExpressionWrapper = _template.default.expression(`
  10. (function () {
  11. var REF = FUNCTION;
  12. return function NAME(PARAMS) {
  13. return REF.apply(this, arguments);
  14. };
  15. })()
  16. `);
  17. const buildNamedExpressionWrapper = _template.default.expression(`
  18. (function () {
  19. var REF = FUNCTION;
  20. function NAME(PARAMS) {
  21. return REF.apply(this, arguments);
  22. }
  23. return NAME;
  24. })()
  25. `);
  26. const buildDeclarationWrapper = (0, _template.default)(`
  27. function NAME(PARAMS) { return REF.apply(this, arguments); }
  28. function REF() {
  29. REF = FUNCTION;
  30. return REF.apply(this, arguments);
  31. }
  32. `);
  33. function classOrObjectMethod(path, callId) {
  34. const node = path.node;
  35. const body = node.body;
  36. const container = t.functionExpression(null, [], t.blockStatement(body.body), true);
  37. body.body = [t.returnStatement(t.callExpression(t.callExpression(callId, [container]), []))];
  38. node.async = false;
  39. node.generator = false;
  40. path.get("body.body.0.argument.callee.arguments.0").unwrapFunctionEnvironment();
  41. }
  42. function plainFunction(path, callId, noNewArrows) {
  43. const node = path.node;
  44. const isDeclaration = path.isFunctionDeclaration();
  45. const functionId = node.id;
  46. const wrapper = isDeclaration ? buildDeclarationWrapper : functionId ? buildNamedExpressionWrapper : buildAnonymousExpressionWrapper;
  47. if (path.isArrowFunctionExpression()) {
  48. path.arrowFunctionToExpression({
  49. noNewArrows
  50. });
  51. }
  52. node.id = null;
  53. if (isDeclaration) {
  54. node.type = "FunctionExpression";
  55. }
  56. const built = t.callExpression(callId, [node]);
  57. const container = wrapper({
  58. NAME: functionId || null,
  59. REF: path.scope.generateUidIdentifier(functionId ? functionId.name : "ref"),
  60. FUNCTION: built,
  61. PARAMS: node.params.reduce((acc, param) => {
  62. acc.done = acc.done || t.isAssignmentPattern(param) || t.isRestElement(param);
  63. if (!acc.done) {
  64. acc.params.push(path.scope.generateUidIdentifier("x"));
  65. }
  66. return acc;
  67. }, {
  68. params: [],
  69. done: false
  70. }).params
  71. });
  72. if (isDeclaration) {
  73. path.replaceWith(container[0]);
  74. path.insertAfter(container[1]);
  75. } else {
  76. const retFunction = container.callee.body.body[1].argument;
  77. if (!functionId) {
  78. (0, _helperFunctionName.default)({
  79. node: retFunction,
  80. parent: path.parent,
  81. scope: path.scope
  82. });
  83. }
  84. if (!retFunction || retFunction.id || node.params.length) {
  85. path.replaceWith(container);
  86. } else {
  87. path.replaceWith(built);
  88. }
  89. }
  90. }
  91. function wrapFunction(path, callId, noNewArrows = true) {
  92. if (path.isMethod()) {
  93. classOrObjectMethod(path, callId);
  94. } else {
  95. plainFunction(path, callId, noNewArrows);
  96. }
  97. }