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.

210 lines
6.1 KiB

4 years ago
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = exports.environmentVisitor = void 0;
  6. var _traverse = _interopRequireDefault(require("@babel/traverse"));
  7. var _helperMemberExpressionToFunctions = _interopRequireDefault(require("@babel/helper-member-expression-to-functions"));
  8. var _helperOptimiseCallExpression = _interopRequireDefault(require("@babel/helper-optimise-call-expression"));
  9. var t = _interopRequireWildcard(require("@babel/types"));
  10. function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
  11. 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; }
  12. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  13. function getPrototypeOfExpression(objectRef, isStatic, file, isPrivateMethod) {
  14. objectRef = t.cloneNode(objectRef);
  15. const targetRef = isStatic || isPrivateMethod ? objectRef : t.memberExpression(objectRef, t.identifier("prototype"));
  16. return t.callExpression(file.addHelper("getPrototypeOf"), [targetRef]);
  17. }
  18. function skipAllButComputedKey(path) {
  19. if (!path.node.computed) {
  20. path.skip();
  21. return;
  22. }
  23. const keys = t.VISITOR_KEYS[path.type];
  24. for (const key of keys) {
  25. if (key !== "key") path.skipKey(key);
  26. }
  27. }
  28. const environmentVisitor = {
  29. TypeAnnotation(path) {
  30. path.skip();
  31. },
  32. Function(path) {
  33. if (path.isMethod()) return;
  34. if (path.isArrowFunctionExpression()) return;
  35. path.skip();
  36. },
  37. "Method|ClassProperty|ClassPrivateProperty"(path) {
  38. skipAllButComputedKey(path);
  39. }
  40. };
  41. exports.environmentVisitor = environmentVisitor;
  42. const visitor = _traverse.default.visitors.merge([environmentVisitor, {
  43. Super(path, state) {
  44. const {
  45. node,
  46. parentPath
  47. } = path;
  48. if (!parentPath.isMemberExpression({
  49. object: node
  50. })) return;
  51. state.handle(parentPath);
  52. }
  53. }]);
  54. const specHandlers = {
  55. memoise(superMember, count) {
  56. const {
  57. scope,
  58. node
  59. } = superMember;
  60. const {
  61. computed,
  62. property
  63. } = node;
  64. if (!computed) {
  65. return;
  66. }
  67. const memo = scope.maybeGenerateMemoised(property);
  68. if (!memo) {
  69. return;
  70. }
  71. this.memoiser.set(property, memo, count);
  72. },
  73. prop(superMember) {
  74. const {
  75. computed,
  76. property
  77. } = superMember.node;
  78. if (this.memoiser.has(property)) {
  79. return t.cloneNode(this.memoiser.get(property));
  80. }
  81. if (computed) {
  82. return t.cloneNode(property);
  83. }
  84. return t.stringLiteral(property.name);
  85. },
  86. get(superMember) {
  87. return t.callExpression(this.file.addHelper("get"), [getPrototypeOfExpression(this.getObjectRef(), this.isStatic, this.file, this.isPrivateMethod), this.prop(superMember), t.thisExpression()]);
  88. },
  89. set(superMember, value) {
  90. return t.callExpression(this.file.addHelper("set"), [getPrototypeOfExpression(this.getObjectRef(), this.isStatic, this.file, this.isPrivateMethod), this.prop(superMember), value, t.thisExpression(), t.booleanLiteral(superMember.isInStrictMode())]);
  91. },
  92. destructureSet(superMember) {
  93. throw superMember.buildCodeFrameError(`Destructuring to a super field is not supported yet.`);
  94. },
  95. call(superMember, args) {
  96. return (0, _helperOptimiseCallExpression.default)(this.get(superMember), t.thisExpression(), args);
  97. }
  98. };
  99. const looseHandlers = Object.assign({}, specHandlers, {
  100. prop(superMember) {
  101. const {
  102. property
  103. } = superMember.node;
  104. if (this.memoiser.has(property)) {
  105. return t.cloneNode(this.memoiser.get(property));
  106. }
  107. return t.cloneNode(property);
  108. },
  109. get(superMember) {
  110. const {
  111. isStatic,
  112. superRef
  113. } = this;
  114. const {
  115. computed
  116. } = superMember.node;
  117. const prop = this.prop(superMember);
  118. let object;
  119. if (isStatic) {
  120. object = superRef ? t.cloneNode(superRef) : t.memberExpression(t.identifier("Function"), t.identifier("prototype"));
  121. } else {
  122. object = superRef ? t.memberExpression(t.cloneNode(superRef), t.identifier("prototype")) : t.memberExpression(t.identifier("Object"), t.identifier("prototype"));
  123. }
  124. return t.memberExpression(object, prop, computed);
  125. },
  126. set(superMember, value) {
  127. const {
  128. computed
  129. } = superMember.node;
  130. const prop = this.prop(superMember);
  131. return t.assignmentExpression("=", t.memberExpression(t.thisExpression(), prop, computed), value);
  132. },
  133. destructureSet(superMember) {
  134. const {
  135. computed
  136. } = superMember.node;
  137. const prop = this.prop(superMember);
  138. return t.memberExpression(t.thisExpression(), prop, computed);
  139. }
  140. });
  141. class ReplaceSupers {
  142. constructor(opts) {
  143. const path = opts.methodPath;
  144. this.methodPath = path;
  145. this.isStatic = path.isObjectMethod() || path.node.static;
  146. this.isPrivateMethod = path.isPrivate() && path.isMethod();
  147. this.file = opts.file;
  148. this.superRef = opts.superRef;
  149. this.isLoose = opts.isLoose;
  150. this.opts = opts;
  151. }
  152. getObjectRef() {
  153. return t.cloneNode(this.opts.objectRef || this.opts.getObjectRef());
  154. }
  155. replace() {
  156. const handler = this.isLoose ? looseHandlers : specHandlers;
  157. (0, _helperMemberExpressionToFunctions.default)(this.methodPath, visitor, Object.assign({
  158. file: this.file,
  159. isStatic: this.isStatic,
  160. isPrivateMethod: this.isPrivateMethod,
  161. getObjectRef: this.getObjectRef.bind(this),
  162. superRef: this.superRef
  163. }, handler));
  164. }
  165. }
  166. exports.default = ReplaceSupers;