index.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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, includeUpdateExpression = true) {
  19. path.traverse(simpleAssignmentVisitor, {
  20. scope: path.scope,
  21. bindingNames,
  22. seen: new WeakSet(),
  23. includeUpdateExpression
  24. });
  25. }
  26. const simpleAssignmentVisitor = {
  27. UpdateExpression: {
  28. exit(path) {
  29. const {
  30. scope,
  31. bindingNames,
  32. includeUpdateExpression
  33. } = this;
  34. if (!includeUpdateExpression) {
  35. return;
  36. }
  37. const arg = path.get("argument");
  38. if (!arg.isIdentifier()) return;
  39. const localName = arg.node.name;
  40. if (!bindingNames.has(localName)) return;
  41. if (scope.getBinding(localName) !== path.scope.getBinding(localName)) {
  42. return;
  43. }
  44. if (path.parentPath.isExpressionStatement() && !path.isCompletionRecord()) {
  45. const operator = path.node.operator == "++" ? "+=" : "-=";
  46. path.replaceWith(assignmentExpression(operator, arg.node, numericLiteral(1)));
  47. } else if (path.node.prefix) {
  48. path.replaceWith(assignmentExpression("=", identifier(localName), binaryExpression(path.node.operator[0], unaryExpression("+", arg.node), numericLiteral(1))));
  49. } else {
  50. const old = path.scope.generateUidIdentifierBasedOnNode(arg.node, "old");
  51. const varName = old.name;
  52. path.scope.push({
  53. id: old
  54. });
  55. const binary = binaryExpression(path.node.operator[0], identifier(varName), numericLiteral(1));
  56. path.replaceWith(sequenceExpression([assignmentExpression("=", identifier(varName), unaryExpression("+", arg.node)), assignmentExpression("=", cloneNode(arg.node), binary), identifier(varName)]));
  57. }
  58. }
  59. },
  60. AssignmentExpression: {
  61. exit(path) {
  62. const {
  63. scope,
  64. seen,
  65. bindingNames
  66. } = this;
  67. if (path.node.operator === "=") return;
  68. if (seen.has(path.node)) return;
  69. seen.add(path.node);
  70. const left = path.get("left");
  71. if (!left.isIdentifier()) return;
  72. const localName = left.node.name;
  73. if (!bindingNames.has(localName)) return;
  74. if (scope.getBinding(localName) !== path.scope.getBinding(localName)) {
  75. return;
  76. }
  77. const operator = path.node.operator.slice(0, -1);
  78. if (LOGICAL_OPERATORS.includes(operator)) {
  79. path.replaceWith(logicalExpression(operator, path.node.left, assignmentExpression("=", cloneNode(path.node.left), path.node.right)));
  80. } else {
  81. path.node.right = binaryExpression(operator, cloneNode(path.node.left), path.node.right);
  82. path.node.operator = "=";
  83. }
  84. }
  85. }
  86. };