index.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = simplifyAccess;
  6. var _t = require("@babel/types");
  7. const {
  8. LOGICAL_OPERATORS,
  9. assignmentExpression,
  10. binaryExpression,
  11. cloneNode,
  12. identifier,
  13. logicalExpression,
  14. numericLiteral,
  15. sequenceExpression,
  16. unaryExpression
  17. } = _t;
  18. function simplifyAccess(path, bindingNames) {
  19. path.traverse(simpleAssignmentVisitor, {
  20. scope: path.scope,
  21. bindingNames,
  22. seen: new WeakSet()
  23. });
  24. }
  25. const simpleAssignmentVisitor = {
  26. UpdateExpression: {
  27. exit(path) {
  28. const {
  29. scope,
  30. bindingNames
  31. } = this;
  32. const arg = path.get("argument");
  33. if (!arg.isIdentifier()) return;
  34. const localName = arg.node.name;
  35. if (!bindingNames.has(localName)) return;
  36. if (scope.getBinding(localName) !== path.scope.getBinding(localName)) {
  37. return;
  38. }
  39. if (path.parentPath.isExpressionStatement() && !path.isCompletionRecord()) {
  40. const operator = path.node.operator == "++" ? "+=" : "-=";
  41. path.replaceWith(assignmentExpression(operator, arg.node, numericLiteral(1)));
  42. } else if (path.node.prefix) {
  43. path.replaceWith(assignmentExpression("=", identifier(localName), binaryExpression(path.node.operator[0], unaryExpression("+", arg.node), numericLiteral(1))));
  44. } else {
  45. const old = path.scope.generateUidIdentifierBasedOnNode(arg.node, "old");
  46. const varName = old.name;
  47. path.scope.push({
  48. id: old
  49. });
  50. const binary = binaryExpression(path.node.operator[0], identifier(varName), numericLiteral(1));
  51. path.replaceWith(sequenceExpression([assignmentExpression("=", identifier(varName), unaryExpression("+", arg.node)), assignmentExpression("=", cloneNode(arg.node), binary), identifier(varName)]));
  52. }
  53. }
  54. },
  55. AssignmentExpression: {
  56. exit(path) {
  57. const {
  58. scope,
  59. seen,
  60. bindingNames
  61. } = this;
  62. if (path.node.operator === "=") return;
  63. if (seen.has(path.node)) return;
  64. seen.add(path.node);
  65. const left = path.get("left");
  66. if (!left.isIdentifier()) return;
  67. const localName = left.node.name;
  68. if (!bindingNames.has(localName)) return;
  69. if (scope.getBinding(localName) !== path.scope.getBinding(localName)) {
  70. return;
  71. }
  72. const operator = path.node.operator.slice(0, -1);
  73. if (LOGICAL_OPERATORS.includes(operator)) {
  74. path.replaceWith(logicalExpression(operator, path.node.left, assignmentExpression("=", cloneNode(path.node.left), path.node.right)));
  75. } else {
  76. path.node.right = binaryExpression(operator, cloneNode(path.node.left), path.node.right);
  77. path.node.operator = "=";
  78. }
  79. }
  80. }
  81. };