You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

175 lines
5.0 KiB

4 years ago
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = _default;
  6. var _helperGetFunctionArity = _interopRequireDefault(require("@babel/helper-get-function-arity"));
  7. var _template = _interopRequireDefault(require("@babel/template"));
  8. var t = _interopRequireWildcard(require("@babel/types"));
  9. function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
  10. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
  11. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  12. const buildPropertyMethodAssignmentWrapper = (0, _template.default)(`
  13. (function (FUNCTION_KEY) {
  14. function FUNCTION_ID() {
  15. return FUNCTION_KEY.apply(this, arguments);
  16. }
  17. FUNCTION_ID.toString = function () {
  18. return FUNCTION_KEY.toString();
  19. }
  20. return FUNCTION_ID;
  21. })(FUNCTION)
  22. `);
  23. const buildGeneratorPropertyMethodAssignmentWrapper = (0, _template.default)(`
  24. (function (FUNCTION_KEY) {
  25. function* FUNCTION_ID() {
  26. return yield* FUNCTION_KEY.apply(this, arguments);
  27. }
  28. FUNCTION_ID.toString = function () {
  29. return FUNCTION_KEY.toString();
  30. };
  31. return FUNCTION_ID;
  32. })(FUNCTION)
  33. `);
  34. const visitor = {
  35. "ReferencedIdentifier|BindingIdentifier"(path, state) {
  36. if (path.node.name !== state.name) return;
  37. const localDeclar = path.scope.getBindingIdentifier(state.name);
  38. if (localDeclar !== state.outerDeclar) return;
  39. state.selfReference = true;
  40. path.stop();
  41. }
  42. };
  43. function getNameFromLiteralId(id) {
  44. if (t.isNullLiteral(id)) {
  45. return "null";
  46. }
  47. if (t.isRegExpLiteral(id)) {
  48. return `_${id.pattern}_${id.flags}`;
  49. }
  50. if (t.isTemplateLiteral(id)) {
  51. return id.quasis.map(quasi => quasi.value.raw).join("");
  52. }
  53. if (id.value !== undefined) {
  54. return id.value + "";
  55. }
  56. return "";
  57. }
  58. function wrap(state, method, id, scope) {
  59. if (state.selfReference) {
  60. if (scope.hasBinding(id.name) && !scope.hasGlobal(id.name)) {
  61. scope.rename(id.name);
  62. } else {
  63. if (!t.isFunction(method)) return;
  64. let build = buildPropertyMethodAssignmentWrapper;
  65. if (method.generator) {
  66. build = buildGeneratorPropertyMethodAssignmentWrapper;
  67. }
  68. const template = build({
  69. FUNCTION: method,
  70. FUNCTION_ID: id,
  71. FUNCTION_KEY: scope.generateUidIdentifier(id.name)
  72. }).expression;
  73. const params = template.callee.body.body[0].params;
  74. for (let i = 0, len = (0, _helperGetFunctionArity.default)(method); i < len; i++) {
  75. params.push(scope.generateUidIdentifier("x"));
  76. }
  77. return template;
  78. }
  79. }
  80. method.id = id;
  81. scope.getProgramParent().references[id.name] = true;
  82. }
  83. function visit(node, name, scope) {
  84. const state = {
  85. selfAssignment: false,
  86. selfReference: false,
  87. outerDeclar: scope.getBindingIdentifier(name),
  88. references: [],
  89. name: name
  90. };
  91. const binding = scope.getOwnBinding(name);
  92. if (binding) {
  93. if (binding.kind === "param") {
  94. state.selfReference = true;
  95. } else {}
  96. } else if (state.outerDeclar || scope.hasGlobal(name)) {
  97. scope.traverse(node, visitor, state);
  98. }
  99. return state;
  100. }
  101. function _default({
  102. node,
  103. parent,
  104. scope,
  105. id
  106. }, localBinding = false) {
  107. if (node.id) return;
  108. if ((t.isObjectProperty(parent) || t.isObjectMethod(parent, {
  109. kind: "method"
  110. })) && (!parent.computed || t.isLiteral(parent.key))) {
  111. id = parent.key;
  112. } else if (t.isVariableDeclarator(parent)) {
  113. id = parent.id;
  114. if (t.isIdentifier(id) && !localBinding) {
  115. const binding = scope.parent.getBinding(id.name);
  116. if (binding && binding.constant && scope.getBinding(id.name) === binding) {
  117. node.id = t.cloneNode(id);
  118. node.id[t.NOT_LOCAL_BINDING] = true;
  119. return;
  120. }
  121. }
  122. } else if (t.isAssignmentExpression(parent)) {
  123. id = parent.left;
  124. } else if (!id) {
  125. return;
  126. }
  127. let name;
  128. if (id && t.isLiteral(id)) {
  129. name = getNameFromLiteralId(id);
  130. } else if (id && t.isIdentifier(id)) {
  131. name = id.name;
  132. }
  133. if (name === undefined) {
  134. return;
  135. }
  136. name = t.toBindingIdentifierName(name);
  137. id = t.identifier(name);
  138. id[t.NOT_LOCAL_BINDING] = true;
  139. const state = visit(node, name, scope);
  140. return wrap(state, node, id, scope) || node;
  141. }