index.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.createClassFeaturePlugin = createClassFeaturePlugin;
  6. Object.defineProperty(exports, "FEATURES", {
  7. enumerable: true,
  8. get: function () {
  9. return _features.FEATURES;
  10. }
  11. });
  12. function _helperFunctionName() {
  13. const data = _interopRequireDefault(require("@babel/helper-function-name"));
  14. _helperFunctionName = function () {
  15. return data;
  16. };
  17. return data;
  18. }
  19. function _helperSplitExportDeclaration() {
  20. const data = _interopRequireDefault(require("@babel/helper-split-export-declaration"));
  21. _helperSplitExportDeclaration = function () {
  22. return data;
  23. };
  24. return data;
  25. }
  26. var _fields = require("./fields");
  27. var _decorators = require("./decorators");
  28. var _misc = require("./misc");
  29. var _features = require("./features");
  30. var _package = _interopRequireDefault(require("../package.json"));
  31. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  32. const version = _package.default.version.split(".").reduce((v, x) => v * 1e5 + +x, 0);
  33. const versionKey = "@babel/plugin-class-features/version";
  34. function createClassFeaturePlugin({
  35. name,
  36. feature,
  37. loose,
  38. manipulateOptions
  39. }) {
  40. return {
  41. name,
  42. manipulateOptions,
  43. pre() {
  44. (0, _features.enableFeature)(this.file, feature, loose);
  45. if (!this.file.get(versionKey) || this.file.get(versionKey) < version) {
  46. this.file.set(versionKey, version);
  47. }
  48. },
  49. visitor: {
  50. Class(path, state) {
  51. if (this.file.get(versionKey) !== version) return;
  52. (0, _features.verifyUsedFeatures)(path, this.file);
  53. const loose = (0, _features.isLoose)(this.file, feature);
  54. let constructor;
  55. let isDecorated = (0, _decorators.hasOwnDecorators)(path.node);
  56. const props = [];
  57. const elements = [];
  58. const computedPaths = [];
  59. const privateNames = new Set();
  60. const body = path.get("body");
  61. for (const path of body.get("body")) {
  62. (0, _features.verifyUsedFeatures)(path, this.file);
  63. if (path.node.computed) {
  64. computedPaths.push(path);
  65. }
  66. if (path.isPrivate()) {
  67. const {
  68. name
  69. } = path.node.key.id;
  70. const getName = `get ${name}`;
  71. const setName = `set ${name}`;
  72. if (path.node.kind === "get") {
  73. if (privateNames.has(getName) || privateNames.has(name) && !privateNames.has(setName)) {
  74. throw path.buildCodeFrameError("Duplicate private field");
  75. }
  76. privateNames.add(getName).add(name);
  77. } else if (path.node.kind === "set") {
  78. if (privateNames.has(setName) || privateNames.has(name) && !privateNames.has(getName)) {
  79. throw path.buildCodeFrameError("Duplicate private field");
  80. }
  81. privateNames.add(setName).add(name);
  82. } else {
  83. if (privateNames.has(name) && !privateNames.has(getName) && !privateNames.has(setName) || privateNames.has(name) && (privateNames.has(getName) || privateNames.has(setName))) {
  84. throw path.buildCodeFrameError("Duplicate private field");
  85. }
  86. privateNames.add(name);
  87. }
  88. }
  89. if (path.isClassMethod({
  90. kind: "constructor"
  91. })) {
  92. constructor = path;
  93. } else {
  94. elements.push(path);
  95. if (path.isProperty() || path.isPrivate()) {
  96. props.push(path);
  97. }
  98. }
  99. if (!isDecorated) isDecorated = (0, _decorators.hasOwnDecorators)(path.node);
  100. }
  101. if (!props.length && !isDecorated) return;
  102. let ref;
  103. if (path.isClassExpression() || !path.node.id) {
  104. (0, _helperFunctionName().default)(path);
  105. ref = path.scope.generateUidIdentifier("class");
  106. } else {
  107. ref = path.node.id;
  108. }
  109. const privateNamesMap = (0, _fields.buildPrivateNamesMap)(props);
  110. const privateNamesNodes = (0, _fields.buildPrivateNamesNodes)(privateNamesMap, loose, state);
  111. (0, _fields.transformPrivateNamesUsage)(ref, path, privateNamesMap, loose, state);
  112. let keysNodes, staticNodes, instanceNodes, wrapClass;
  113. if (isDecorated) {
  114. staticNodes = keysNodes = [];
  115. ({
  116. instanceNodes,
  117. wrapClass
  118. } = (0, _decorators.buildDecoratedClass)(ref, path, elements, this.file));
  119. } else {
  120. keysNodes = (0, _misc.extractComputedKeys)(ref, path, computedPaths, this.file);
  121. ({
  122. staticNodes,
  123. instanceNodes,
  124. wrapClass
  125. } = (0, _fields.buildFieldsInitNodes)(ref, path.node.superClass, props, privateNamesMap, state, loose));
  126. }
  127. if (instanceNodes.length > 0) {
  128. (0, _misc.injectInitialization)(path, constructor, instanceNodes, (referenceVisitor, state) => {
  129. if (isDecorated) return;
  130. for (const prop of props) {
  131. if (prop.node.static) continue;
  132. prop.traverse(referenceVisitor, state);
  133. }
  134. });
  135. }
  136. path = wrapClass(path);
  137. path.insertBefore(keysNodes);
  138. path.insertAfter([...privateNamesNodes, ...staticNodes]);
  139. },
  140. PrivateName(path) {
  141. if (this.file.get(versionKey) !== version) return;
  142. throw path.buildCodeFrameError(`Unknown PrivateName "${path}"`);
  143. },
  144. ExportDefaultDeclaration(path) {
  145. if (this.file.get(versionKey) !== version) return;
  146. const decl = path.get("declaration");
  147. if (decl.isClassDeclaration() && (0, _decorators.hasDecorators)(decl.node)) {
  148. if (decl.node.id) {
  149. (0, _helperSplitExportDeclaration().default)(path);
  150. } else {
  151. decl.node.type = "ClassExpression";
  152. }
  153. }
  154. }
  155. }
  156. };
  157. }