index.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. var _helperPluginUtils = require("@babel/helper-plugin-utils");
  7. var _helperCreateClassFeaturesPlugin = require("@babel/helper-create-class-features-plugin");
  8. function generateUid(scope, denyList) {
  9. const name = "";
  10. let uid;
  11. let i = 1;
  12. do {
  13. uid = `_${name}`;
  14. if (i > 1) uid += i;
  15. i++;
  16. } while (denyList.has(uid));
  17. return uid;
  18. }
  19. function mapLast(arr, fn) {
  20. if (arr.length === 0) return arr;
  21. return [...arr.slice(0, -1), fn(arr[arr.length - 1])];
  22. }
  23. var _default = exports.default = (0, _helperPluginUtils.declare)(({
  24. types: t,
  25. template,
  26. traverse,
  27. assertVersion
  28. }) => {
  29. assertVersion("^7.12.0 || >8.0.0-alpha <8.0.0-beta");
  30. const rawNamedEvaluationVisitor = (0, _helperCreateClassFeaturesPlugin.buildNamedEvaluationVisitor)(path => {
  31. if (!path.isClassExpression()) return false;
  32. for (let i = path.node.body.body.length - 1; i >= 0; i--) {
  33. const el = path.node.body.body[i];
  34. if (t.isStaticBlock(el)) {
  35. return true;
  36. }
  37. if ((t.isClassProperty(el) || t.isClassPrivateProperty(el)) && el.static) {
  38. break;
  39. }
  40. }
  41. return false;
  42. }, (classPath, state, name) => {
  43. const nameNode = typeof name === "string" ? t.stringLiteral(name) : name;
  44. classPath.get("body").unshiftContainer("body", t.staticBlock([template.statement.ast`
  45. ${state.addHelper("setFunctionName")}(this, ${nameNode});
  46. `]));
  47. });
  48. if (!t.classAccessorProperty) {
  49. delete rawNamedEvaluationVisitor.ClassAccessorProperty;
  50. }
  51. const namedEvaluationVisitor = traverse.visitors.explode(rawNamedEvaluationVisitor);
  52. const maybeSequenceExpression = expressions => {
  53. if (expressions.length === 1) {
  54. return expressions[0];
  55. } else {
  56. return t.sequenceExpression(expressions);
  57. }
  58. };
  59. const blocksToExpressions = blocks => blocks.map(block => {
  60. const {
  61. body
  62. } = block;
  63. if (body.length === 1 && t.isExpressionStatement(body[0])) {
  64. return t.inheritsComments(t.inheritsComments(body[0].expression, body[0]), block);
  65. }
  66. return t.inheritsComments(template.expression.ast`(() => { ${body} })()`, block);
  67. });
  68. const prependToInitializer = (prop, expressions) => {
  69. prop.value = prop.value ? t.sequenceExpression([...expressions, prop.value]) : maybeSequenceExpression(mapLast(expressions, expr => t.unaryExpression("void", expr)));
  70. };
  71. return {
  72. name: "transform-class-static-block",
  73. manipulateOptions: (_, parser) => parser.plugins.push("classStaticBlock"),
  74. pre() {
  75. (0, _helperCreateClassFeaturesPlugin.enableFeature)(this.file, _helperCreateClassFeaturesPlugin.FEATURES.staticBlocks, false);
  76. },
  77. visitor: {
  78. ClassBody(classBody) {
  79. const {
  80. scope
  81. } = classBody;
  82. let parentPath = classBody.parentPath;
  83. if (parentPath.isClassExpression() && !parentPath.node.id) {
  84. do ({
  85. parentPath
  86. } = parentPath); while (parentPath && !namedEvaluationVisitor[parentPath.type] && !parentPath.isStatement());
  87. if (parentPath) {
  88. var _namedEvaluationVisit;
  89. (_namedEvaluationVisit = namedEvaluationVisitor[parentPath.type]) == null || _namedEvaluationVisit.enter.forEach(f => f.call(this, parentPath, this));
  90. }
  91. }
  92. const pendingStaticBlocks = [];
  93. let lastStaticProp = null;
  94. for (const path of classBody.get("body")) {
  95. if (path.isStaticBlock()) {
  96. pendingStaticBlocks.push(path.node);
  97. path.remove();
  98. } else if (path.isClassProperty({
  99. static: true
  100. }) || path.isClassPrivateProperty({
  101. static: true
  102. })) {
  103. lastStaticProp = path;
  104. if (pendingStaticBlocks.length > 0) {
  105. prependToInitializer(path.node, blocksToExpressions(pendingStaticBlocks));
  106. pendingStaticBlocks.length = 0;
  107. }
  108. }
  109. }
  110. if (pendingStaticBlocks.length > 0) {
  111. const tmp = scope.generateDeclaredUidIdentifier("staticBlock");
  112. let arrowBody;
  113. const needsCompletionValue = classBody.parentPath.isExpression();
  114. if (pendingStaticBlocks.length > 1 || pendingStaticBlocks[0].body.length === 1 && t.isExpressionStatement(pendingStaticBlocks[0].body[0])) {
  115. const expressions = blocksToExpressions(pendingStaticBlocks);
  116. if (needsCompletionValue) {
  117. expressions.push(t.thisExpression());
  118. }
  119. arrowBody = maybeSequenceExpression(expressions);
  120. } else {
  121. arrowBody = t.blockStatement(pendingStaticBlocks[0].body);
  122. if (needsCompletionValue) {
  123. arrowBody.body.push(t.returnStatement(t.thisExpression()));
  124. }
  125. }
  126. const init = template.expression.ast`${tmp} = () => ${arrowBody}`;
  127. if (lastStaticProp) {
  128. prependToInitializer(lastStaticProp.node, [init]);
  129. } else {
  130. const privateNames = new Set();
  131. for (const path of classBody.get("body")) {
  132. if (path.isPrivate()) {
  133. privateNames.add(path.get("key.id").node.name);
  134. }
  135. }
  136. const staticBlockPrivateId = generateUid(scope, privateNames);
  137. const staticBlockRef = t.privateName(t.identifier(staticBlockPrivateId));
  138. classBody.pushContainer("body", [t.classPrivateProperty(staticBlockRef, init, [], true)]);
  139. }
  140. const staticBlockClosureCall = t.callExpression(t.cloneNode(tmp), []);
  141. if (classBody.parentPath.isClassExpression()) {
  142. classBody.parentPath.replaceWith(t.sequenceExpression([classBody.parent, staticBlockClosureCall]));
  143. } else {
  144. classBody.parentPath.insertAfter(t.expressionStatement(staticBlockClosureCall));
  145. }
  146. }
  147. }
  148. }
  149. };
  150. });
  151. //# sourceMappingURL=index.js.map