fields.js 28 KB

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