fields.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.buildPrivateNamesMap = buildPrivateNamesMap;
  6. exports.buildPrivateNamesNodes = buildPrivateNamesNodes;
  7. exports.transformPrivateNamesUsage = transformPrivateNamesUsage;
  8. exports.buildFieldsInitNodes = buildFieldsInitNodes;
  9. var _core = require("@babel/core");
  10. var _helperReplaceSupers = require("@babel/helper-replace-supers");
  11. var _helperMemberExpressionToFunctions = require("@babel/helper-member-expression-to-functions");
  12. var _helperOptimiseCallExpression = require("@babel/helper-optimise-call-expression");
  13. var _helperAnnotateAsPure = require("@babel/helper-annotate-as-pure");
  14. var ts = require("./typescript");
  15. function buildPrivateNamesMap(props) {
  16. const privateNamesMap = new Map();
  17. for (const prop of props) {
  18. const isPrivate = prop.isPrivate();
  19. const isMethod = !prop.isProperty();
  20. const isInstance = !prop.node.static;
  21. if (isPrivate) {
  22. const {
  23. name
  24. } = prop.node.key.id;
  25. const update = privateNamesMap.has(name) ? privateNamesMap.get(name) : {
  26. id: prop.scope.generateUidIdentifier(name),
  27. static: !isInstance,
  28. method: isMethod
  29. };
  30. if (prop.node.kind === "get") {
  31. update.getId = prop.scope.generateUidIdentifier(`get_${name}`);
  32. } else if (prop.node.kind === "set") {
  33. update.setId = prop.scope.generateUidIdentifier(`set_${name}`);
  34. } else if (prop.node.kind === "method") {
  35. update.methodId = prop.scope.generateUidIdentifier(name);
  36. }
  37. privateNamesMap.set(name, update);
  38. }
  39. }
  40. return privateNamesMap;
  41. }
  42. function buildPrivateNamesNodes(privateNamesMap, privateFieldsAsProperties, state) {
  43. const initNodes = [];
  44. for (const [name, value] of privateNamesMap) {
  45. const {
  46. static: isStatic,
  47. method: isMethod,
  48. getId,
  49. setId
  50. } = value;
  51. const isAccessor = getId || setId;
  52. const id = _core.types.cloneNode(value.id);
  53. let init;
  54. if (privateFieldsAsProperties) {
  55. init = _core.types.callExpression(state.addHelper("classPrivateFieldLooseKey"), [_core.types.stringLiteral(name)]);
  56. } else if (!isStatic) {
  57. init = _core.types.newExpression(_core.types.identifier(!isMethod || isAccessor ? "WeakMap" : "WeakSet"), []);
  58. }
  59. if (init) {
  60. (0, _helperAnnotateAsPure.default)(init);
  61. initNodes.push(_core.template.statement.ast`var ${id} = ${init}`);
  62. }
  63. }
  64. return initNodes;
  65. }
  66. function privateNameVisitorFactory(visitor) {
  67. const privateNameVisitor = Object.assign({}, visitor, {
  68. Class(path) {
  69. const {
  70. privateNamesMap
  71. } = this;
  72. const body = path.get("body.body");
  73. const visiblePrivateNames = new Map(privateNamesMap);
  74. const redeclared = [];
  75. for (const prop of body) {
  76. if (!prop.isPrivate()) continue;
  77. const {
  78. name
  79. } = prop.node.key.id;
  80. visiblePrivateNames.delete(name);
  81. redeclared.push(name);
  82. }
  83. if (!redeclared.length) {
  84. return;
  85. }
  86. path.get("body").traverse(nestedVisitor, Object.assign({}, this, {
  87. redeclared
  88. }));
  89. path.traverse(privateNameVisitor, Object.assign({}, this, {
  90. privateNamesMap: visiblePrivateNames
  91. }));
  92. path.skipKey("body");
  93. }
  94. });
  95. const nestedVisitor = _core.traverse.visitors.merge([Object.assign({}, visitor), _helperReplaceSupers.environmentVisitor]);
  96. return privateNameVisitor;
  97. }
  98. const privateNameVisitor = privateNameVisitorFactory({
  99. PrivateName(path, {
  100. noDocumentAll
  101. }) {
  102. const {
  103. privateNamesMap,
  104. redeclared
  105. } = this;
  106. const {
  107. node,
  108. parentPath
  109. } = path;
  110. if (!parentPath.isMemberExpression({
  111. property: node
  112. }) && !parentPath.isOptionalMemberExpression({
  113. property: node
  114. })) {
  115. return;
  116. }
  117. const {
  118. name
  119. } = node.id;
  120. if (!privateNamesMap.has(name)) return;
  121. if (redeclared && redeclared.includes(name)) return;
  122. this.handle(parentPath, noDocumentAll);
  123. }
  124. });
  125. const privateInVisitor = privateNameVisitorFactory({
  126. BinaryExpression(path) {
  127. const {
  128. operator,
  129. left,
  130. right
  131. } = path.node;
  132. if (operator !== "in") return;
  133. if (!path.get("left").isPrivateName()) return;
  134. const {
  135. privateFieldsAsProperties,
  136. privateNamesMap,
  137. redeclared
  138. } = this;
  139. const {
  140. name
  141. } = left.id;
  142. if (!privateNamesMap.has(name)) return;
  143. if (redeclared && redeclared.includes(name)) return;
  144. if (privateFieldsAsProperties) {
  145. const {
  146. id
  147. } = privateNamesMap.get(name);
  148. path.replaceWith(_core.template.expression.ast`
  149. Object.prototype.hasOwnProperty.call(${right}, ${_core.types.cloneNode(id)})
  150. `);
  151. return;
  152. }
  153. const {
  154. id,
  155. static: isStatic
  156. } = privateNamesMap.get(name);
  157. if (isStatic) {
  158. path.replaceWith(_core.template.expression.ast`${right} === ${this.classRef}`);
  159. return;
  160. }
  161. path.replaceWith(_core.template.expression.ast`${_core.types.cloneNode(id)}.has(${right})`);
  162. }
  163. });
  164. const privateNameHandlerSpec = {
  165. memoise(member, count) {
  166. const {
  167. scope
  168. } = member;
  169. const {
  170. object
  171. } = member.node;
  172. const memo = scope.maybeGenerateMemoised(object);
  173. if (!memo) {
  174. return;
  175. }
  176. this.memoiser.set(object, memo, count);
  177. },
  178. receiver(member) {
  179. const {
  180. object
  181. } = member.node;
  182. if (this.memoiser.has(object)) {
  183. return _core.types.cloneNode(this.memoiser.get(object));
  184. }
  185. return _core.types.cloneNode(object);
  186. },
  187. get(member) {
  188. const {
  189. classRef,
  190. privateNamesMap,
  191. file
  192. } = this;
  193. const {
  194. name
  195. } = member.node.property.id;
  196. const {
  197. id,
  198. static: isStatic,
  199. method: isMethod,
  200. methodId,
  201. getId,
  202. setId
  203. } = privateNamesMap.get(name);
  204. const isAccessor = getId || setId;
  205. if (isStatic) {
  206. const helperName = isMethod && !isAccessor ? "classStaticPrivateMethodGet" : "classStaticPrivateFieldSpecGet";
  207. return _core.types.callExpression(file.addHelper(helperName), [this.receiver(member), _core.types.cloneNode(classRef), _core.types.cloneNode(id)]);
  208. }
  209. if (isMethod) {
  210. if (isAccessor) {
  211. if (!getId && setId) {
  212. if (file.availableHelper("writeOnlyError")) {
  213. return _core.types.sequenceExpression([this.receiver(member), _core.types.callExpression(file.addHelper("writeOnlyError"), [_core.types.stringLiteral(`#${name}`)])]);
  214. }
  215. console.warn(`@babel/helpers is outdated, update it to silence this warning.`);
  216. }
  217. return _core.types.callExpression(file.addHelper("classPrivateFieldGet"), [this.receiver(member), _core.types.cloneNode(id)]);
  218. }
  219. return _core.types.callExpression(file.addHelper("classPrivateMethodGet"), [this.receiver(member), _core.types.cloneNode(id), _core.types.cloneNode(methodId)]);
  220. }
  221. return _core.types.callExpression(file.addHelper("classPrivateFieldGet"), [this.receiver(member), _core.types.cloneNode(id)]);
  222. },
  223. boundGet(member) {
  224. this.memoise(member, 1);
  225. return _core.types.callExpression(_core.types.memberExpression(this.get(member), _core.types.identifier("bind")), [this.receiver(member)]);
  226. },
  227. set(member, value) {
  228. const {
  229. classRef,
  230. privateNamesMap,
  231. file
  232. } = this;
  233. const {
  234. name
  235. } = member.node.property.id;
  236. const {
  237. id,
  238. static: isStatic,
  239. method: isMethod,
  240. setId,
  241. getId
  242. } = privateNamesMap.get(name);
  243. const isAccessor = getId || setId;
  244. if (isStatic) {
  245. const helperName = isMethod && !isAccessor ? "classStaticPrivateMethodSet" : "classStaticPrivateFieldSpecSet";
  246. return _core.types.callExpression(file.addHelper(helperName), [this.receiver(member), _core.types.cloneNode(classRef), _core.types.cloneNode(id), value]);
  247. }
  248. if (isMethod) {
  249. if (setId) {
  250. return _core.types.callExpression(file.addHelper("classPrivateFieldSet"), [this.receiver(member), _core.types.cloneNode(id), value]);
  251. }
  252. return _core.types.sequenceExpression([this.receiver(member), value, _core.types.callExpression(file.addHelper("readOnlyError"), [_core.types.stringLiteral(`#${name}`)])]);
  253. }
  254. return _core.types.callExpression(file.addHelper("classPrivateFieldSet"), [this.receiver(member), _core.types.cloneNode(id), value]);
  255. },
  256. destructureSet(member) {
  257. const {
  258. classRef,
  259. privateNamesMap,
  260. file
  261. } = this;
  262. const {
  263. name
  264. } = member.node.property.id;
  265. const {
  266. id,
  267. static: isStatic
  268. } = privateNamesMap.get(name);
  269. if (isStatic) {
  270. try {
  271. var helper = file.addHelper("classStaticPrivateFieldDestructureSet");
  272. } catch (_unused) {
  273. throw new Error("Babel can not transpile `[C.#p] = [0]` with @babel/helpers < 7.13.10, \n" + "please update @babel/helpers to the latest version.");
  274. }
  275. return _core.types.memberExpression(_core.types.callExpression(helper, [this.receiver(member), _core.types.cloneNode(classRef), _core.types.cloneNode(id)]), _core.types.identifier("value"));
  276. }
  277. return _core.types.memberExpression(_core.types.callExpression(file.addHelper("classPrivateFieldDestructureSet"), [this.receiver(member), _core.types.cloneNode(id)]), _core.types.identifier("value"));
  278. },
  279. call(member, args) {
  280. this.memoise(member, 1);
  281. return (0, _helperOptimiseCallExpression.default)(this.get(member), this.receiver(member), args, false);
  282. },
  283. optionalCall(member, args) {
  284. this.memoise(member, 1);
  285. return (0, _helperOptimiseCallExpression.default)(this.get(member), this.receiver(member), args, true);
  286. }
  287. };
  288. const privateNameHandlerLoose = {
  289. get(member) {
  290. const {
  291. privateNamesMap,
  292. file
  293. } = this;
  294. const {
  295. object
  296. } = member.node;
  297. const {
  298. name
  299. } = member.node.property.id;
  300. return _core.template.expression`BASE(REF, PROP)[PROP]`({
  301. BASE: file.addHelper("classPrivateFieldLooseBase"),
  302. REF: _core.types.cloneNode(object),
  303. PROP: _core.types.cloneNode(privateNamesMap.get(name).id)
  304. });
  305. },
  306. boundGet(member) {
  307. return _core.types.callExpression(_core.types.memberExpression(this.get(member), _core.types.identifier("bind")), [_core.types.cloneNode(member.node.object)]);
  308. },
  309. simpleSet(member) {
  310. return this.get(member);
  311. },
  312. destructureSet(member) {
  313. return this.get(member);
  314. },
  315. call(member, args) {
  316. return _core.types.callExpression(this.get(member), args);
  317. },
  318. optionalCall(member, args) {
  319. return _core.types.optionalCallExpression(this.get(member), args, true);
  320. }
  321. };
  322. function transformPrivateNamesUsage(ref, path, privateNamesMap, {
  323. privateFieldsAsProperties,
  324. noDocumentAll
  325. }, state) {
  326. if (!privateNamesMap.size) return;
  327. const body = path.get("body");
  328. const handler = privateFieldsAsProperties ? privateNameHandlerLoose : privateNameHandlerSpec;
  329. (0, _helperMemberExpressionToFunctions.default)(body, privateNameVisitor, Object.assign({
  330. privateNamesMap,
  331. classRef: ref,
  332. file: state
  333. }, handler, {
  334. noDocumentAll
  335. }));
  336. body.traverse(privateInVisitor, {
  337. privateNamesMap,
  338. classRef: ref,
  339. file: state,
  340. privateFieldsAsProperties
  341. });
  342. }
  343. function buildPrivateFieldInitLoose(ref, prop, privateNamesMap) {
  344. const {
  345. id
  346. } = privateNamesMap.get(prop.node.key.id.name);
  347. const value = prop.node.value || prop.scope.buildUndefinedNode();
  348. return _core.template.statement.ast`
  349. Object.defineProperty(${ref}, ${_core.types.cloneNode(id)}, {
  350. // configurable is false by default
  351. // enumerable is false by default
  352. writable: true,
  353. value: ${value}
  354. });
  355. `;
  356. }
  357. function buildPrivateInstanceFieldInitSpec(ref, prop, privateNamesMap) {
  358. const {
  359. id
  360. } = privateNamesMap.get(prop.node.key.id.name);
  361. const value = prop.node.value || prop.scope.buildUndefinedNode();
  362. return _core.template.statement.ast`${_core.types.cloneNode(id)}.set(${ref}, {
  363. // configurable is always false for private elements
  364. // enumerable is always false for private elements
  365. writable: true,
  366. value: ${value},
  367. })`;
  368. }
  369. function buildPrivateStaticFieldInitSpec(prop, privateNamesMap) {
  370. const privateName = privateNamesMap.get(prop.node.key.id.name);
  371. const {
  372. id,
  373. getId,
  374. setId,
  375. initAdded
  376. } = privateName;
  377. const isAccessor = getId || setId;
  378. if (!prop.isProperty() && (initAdded || !isAccessor)) return;
  379. if (isAccessor) {
  380. privateNamesMap.set(prop.node.key.id.name, Object.assign({}, privateName, {
  381. initAdded: true
  382. }));
  383. return _core.template.statement.ast`
  384. var ${_core.types.cloneNode(id)} = {
  385. // configurable is false by default
  386. // enumerable is false by default
  387. // writable is false by default
  388. get: ${getId ? getId.name : prop.scope.buildUndefinedNode()},
  389. set: ${setId ? setId.name : prop.scope.buildUndefinedNode()}
  390. }
  391. `;
  392. }
  393. const value = prop.node.value || prop.scope.buildUndefinedNode();
  394. return _core.template.statement.ast`
  395. var ${_core.types.cloneNode(id)} = {
  396. // configurable is false by default
  397. // enumerable is false by default
  398. writable: true,
  399. value: ${value}
  400. };
  401. `;
  402. }
  403. function buildPrivateMethodInitLoose(ref, prop, privateNamesMap) {
  404. const privateName = privateNamesMap.get(prop.node.key.id.name);
  405. const {
  406. methodId,
  407. id,
  408. getId,
  409. setId,
  410. initAdded
  411. } = privateName;
  412. if (initAdded) return;
  413. if (methodId) {
  414. return _core.template.statement.ast`
  415. Object.defineProperty(${ref}, ${id}, {
  416. // configurable is false by default
  417. // enumerable is false by default
  418. // writable is false by default
  419. value: ${methodId.name}
  420. });
  421. `;
  422. }
  423. const isAccessor = getId || setId;
  424. if (isAccessor) {
  425. privateNamesMap.set(prop.node.key.id.name, Object.assign({}, privateName, {
  426. initAdded: true
  427. }));
  428. return _core.template.statement.ast`
  429. Object.defineProperty(${ref}, ${id}, {
  430. // configurable is false by default
  431. // enumerable is false by default
  432. // writable is false by default
  433. get: ${getId ? getId.name : prop.scope.buildUndefinedNode()},
  434. set: ${setId ? setId.name : prop.scope.buildUndefinedNode()}
  435. });
  436. `;
  437. }
  438. }
  439. function buildPrivateInstanceMethodInitSpec(ref, prop, privateNamesMap) {
  440. const privateName = privateNamesMap.get(prop.node.key.id.name);
  441. const {
  442. id,
  443. getId,
  444. setId,
  445. initAdded
  446. } = privateName;
  447. if (initAdded) return;
  448. const isAccessor = getId || setId;
  449. if (isAccessor) {
  450. privateNamesMap.set(prop.node.key.id.name, Object.assign({}, privateName, {
  451. initAdded: true
  452. }));
  453. return _core.template.statement.ast`
  454. ${id}.set(${ref}, {
  455. get: ${getId ? getId.name : prop.scope.buildUndefinedNode()},
  456. set: ${setId ? setId.name : prop.scope.buildUndefinedNode()}
  457. });
  458. `;
  459. }
  460. return _core.template.statement.ast`${id}.add(${ref})`;
  461. }
  462. function buildPublicFieldInitLoose(ref, prop) {
  463. const {
  464. key,
  465. computed
  466. } = prop.node;
  467. const value = prop.node.value || prop.scope.buildUndefinedNode();
  468. return _core.types.expressionStatement(_core.types.assignmentExpression("=", _core.types.memberExpression(ref, key, computed || _core.types.isLiteral(key)), value));
  469. }
  470. function buildPublicFieldInitSpec(ref, prop, state) {
  471. const {
  472. key,
  473. computed
  474. } = prop.node;
  475. const value = prop.node.value || prop.scope.buildUndefinedNode();
  476. return _core.types.expressionStatement(_core.types.callExpression(state.addHelper("defineProperty"), [ref, computed || _core.types.isLiteral(key) ? key : _core.types.stringLiteral(key.name), value]));
  477. }
  478. function buildPrivateStaticMethodInitLoose(ref, prop, state, privateNamesMap) {
  479. const privateName = privateNamesMap.get(prop.node.key.id.name);
  480. const {
  481. id,
  482. methodId,
  483. getId,
  484. setId,
  485. initAdded
  486. } = privateName;
  487. if (initAdded) return;
  488. const isAccessor = getId || setId;
  489. if (isAccessor) {
  490. privateNamesMap.set(prop.node.key.id.name, Object.assign({}, privateName, {
  491. initAdded: true
  492. }));
  493. return _core.template.statement.ast`
  494. Object.defineProperty(${ref}, ${id}, {
  495. // configurable is false by default
  496. // enumerable is false by default
  497. // writable is false by default
  498. get: ${getId ? getId.name : prop.scope.buildUndefinedNode()},
  499. set: ${setId ? setId.name : prop.scope.buildUndefinedNode()}
  500. })
  501. `;
  502. }
  503. return _core.template.statement.ast`
  504. Object.defineProperty(${ref}, ${id}, {
  505. // configurable is false by default
  506. // enumerable is false by default
  507. // writable is false by default
  508. value: ${methodId.name}
  509. });
  510. `;
  511. }
  512. function buildPrivateMethodDeclaration(prop, privateNamesMap, privateFieldsAsProperties = false) {
  513. const privateName = privateNamesMap.get(prop.node.key.id.name);
  514. const {
  515. id,
  516. methodId,
  517. getId,
  518. setId,
  519. getterDeclared,
  520. setterDeclared,
  521. static: isStatic
  522. } = privateName;
  523. const {
  524. params,
  525. body,
  526. generator,
  527. async
  528. } = prop.node;
  529. const isGetter = getId && !getterDeclared && params.length === 0;
  530. const isSetter = setId && !setterDeclared && params.length > 0;
  531. let declId = methodId;
  532. if (isGetter) {
  533. privateNamesMap.set(prop.node.key.id.name, Object.assign({}, privateName, {
  534. getterDeclared: true
  535. }));
  536. declId = getId;
  537. } else if (isSetter) {
  538. privateNamesMap.set(prop.node.key.id.name, Object.assign({}, privateName, {
  539. setterDeclared: true
  540. }));
  541. declId = setId;
  542. } else if (isStatic && !privateFieldsAsProperties) {
  543. declId = id;
  544. }
  545. return _core.types.functionDeclaration(_core.types.cloneNode(declId), params, body, generator, async);
  546. }
  547. const thisContextVisitor = _core.traverse.visitors.merge([{
  548. ThisExpression(path, state) {
  549. state.needsClassRef = true;
  550. path.replaceWith(_core.types.cloneNode(state.classRef));
  551. }
  552. }, _helperReplaceSupers.environmentVisitor]);
  553. function replaceThisContext(path, ref, getSuperRef, file, isStaticBlock, constantSuper) {
  554. const state = {
  555. classRef: ref,
  556. needsClassRef: false
  557. };
  558. const replacer = new _helperReplaceSupers.default({
  559. methodPath: path,
  560. constantSuper,
  561. file,
  562. refToPreserve: ref,
  563. getSuperRef,
  564. getObjectRef() {
  565. state.needsClassRef = true;
  566. return isStaticBlock || path.node.static ? ref : _core.types.memberExpression(ref, _core.types.identifier("prototype"));
  567. }
  568. });
  569. replacer.replace();
  570. if (isStaticBlock || path.isProperty()) {
  571. path.traverse(thisContextVisitor, state);
  572. }
  573. return state.needsClassRef;
  574. }
  575. function buildFieldsInitNodes(ref, superRef, props, privateNamesMap, state, setPublicClassFields, privateFieldsAsProperties, constantSuper) {
  576. let needsClassRef = false;
  577. let injectSuperRef;
  578. const staticNodes = [];
  579. const instanceNodes = [];
  580. const pureStaticNodes = [];
  581. const getSuperRef = _core.types.isIdentifier(superRef) ? () => superRef : () => {
  582. var _injectSuperRef;
  583. (_injectSuperRef = injectSuperRef) != null ? _injectSuperRef : injectSuperRef = props[0].scope.generateUidIdentifierBasedOnNode(superRef);
  584. return injectSuperRef;
  585. };
  586. for (const prop of props) {
  587. ts.assertFieldTransformed(prop);
  588. const isStatic = prop.node.static;
  589. const isInstance = !isStatic;
  590. const isPrivate = prop.isPrivate();
  591. const isPublic = !isPrivate;
  592. const isField = prop.isProperty();
  593. const isMethod = !isField;
  594. const isStaticBlock = prop.isStaticBlock == null ? void 0 : prop.isStaticBlock();
  595. if (isStatic || isMethod && isPrivate || isStaticBlock) {
  596. const replaced = replaceThisContext(prop, ref, getSuperRef, state, isStaticBlock, constantSuper);
  597. needsClassRef = needsClassRef || replaced;
  598. }
  599. switch (true) {
  600. case isStaticBlock:
  601. staticNodes.push(_core.template.statement.ast`(() => ${_core.types.blockStatement(prop.node.body)})()`);
  602. break;
  603. case isStatic && isPrivate && isField && privateFieldsAsProperties:
  604. needsClassRef = true;
  605. staticNodes.push(buildPrivateFieldInitLoose(_core.types.cloneNode(ref), prop, privateNamesMap));
  606. break;
  607. case isStatic && isPrivate && isField && !privateFieldsAsProperties:
  608. needsClassRef = true;
  609. staticNodes.push(buildPrivateStaticFieldInitSpec(prop, privateNamesMap));
  610. break;
  611. case isStatic && isPublic && isField && setPublicClassFields:
  612. needsClassRef = true;
  613. staticNodes.push(buildPublicFieldInitLoose(_core.types.cloneNode(ref), prop));
  614. break;
  615. case isStatic && isPublic && isField && !setPublicClassFields:
  616. needsClassRef = true;
  617. staticNodes.push(buildPublicFieldInitSpec(_core.types.cloneNode(ref), prop, state));
  618. break;
  619. case isInstance && isPrivate && isField && privateFieldsAsProperties:
  620. instanceNodes.push(buildPrivateFieldInitLoose(_core.types.thisExpression(), prop, privateNamesMap));
  621. break;
  622. case isInstance && isPrivate && isField && !privateFieldsAsProperties:
  623. instanceNodes.push(buildPrivateInstanceFieldInitSpec(_core.types.thisExpression(), prop, privateNamesMap));
  624. break;
  625. case isInstance && isPrivate && isMethod && privateFieldsAsProperties:
  626. instanceNodes.unshift(buildPrivateMethodInitLoose(_core.types.thisExpression(), prop, privateNamesMap));
  627. pureStaticNodes.push(buildPrivateMethodDeclaration(prop, privateNamesMap, privateFieldsAsProperties));
  628. break;
  629. case isInstance && isPrivate && isMethod && !privateFieldsAsProperties:
  630. instanceNodes.unshift(buildPrivateInstanceMethodInitSpec(_core.types.thisExpression(), prop, privateNamesMap));
  631. pureStaticNodes.push(buildPrivateMethodDeclaration(prop, privateNamesMap, privateFieldsAsProperties));
  632. break;
  633. case isStatic && isPrivate && isMethod && !privateFieldsAsProperties:
  634. needsClassRef = true;
  635. staticNodes.unshift(buildPrivateStaticFieldInitSpec(prop, privateNamesMap));
  636. pureStaticNodes.push(buildPrivateMethodDeclaration(prop, privateNamesMap, privateFieldsAsProperties));
  637. break;
  638. case isStatic && isPrivate && isMethod && privateFieldsAsProperties:
  639. needsClassRef = true;
  640. staticNodes.unshift(buildPrivateStaticMethodInitLoose(_core.types.cloneNode(ref), prop, state, privateNamesMap));
  641. pureStaticNodes.push(buildPrivateMethodDeclaration(prop, privateNamesMap, privateFieldsAsProperties));
  642. break;
  643. case isInstance && isPublic && isField && setPublicClassFields:
  644. instanceNodes.push(buildPublicFieldInitLoose(_core.types.thisExpression(), prop));
  645. break;
  646. case isInstance && isPublic && isField && !setPublicClassFields:
  647. instanceNodes.push(buildPublicFieldInitSpec(_core.types.thisExpression(), prop, state));
  648. break;
  649. default:
  650. throw new Error("Unreachable.");
  651. }
  652. }
  653. return {
  654. staticNodes: staticNodes.filter(Boolean),
  655. instanceNodes: instanceNodes.filter(Boolean),
  656. pureStaticNodes: pureStaticNodes.filter(Boolean),
  657. wrapClass(path) {
  658. for (const prop of props) {
  659. prop.remove();
  660. }
  661. if (injectSuperRef) {
  662. path.scope.push({
  663. id: _core.types.cloneNode(injectSuperRef)
  664. });
  665. path.set("superClass", _core.types.assignmentExpression("=", injectSuperRef, path.node.superClass));
  666. }
  667. if (!needsClassRef) return path;
  668. if (path.isClassExpression()) {
  669. path.scope.push({
  670. id: ref
  671. });
  672. path.replaceWith(_core.types.assignmentExpression("=", _core.types.cloneNode(ref), path.node));
  673. } else if (!path.node.id) {
  674. path.node.id = ref;
  675. }
  676. return path;
  677. }
  678. };
  679. }