fields.js 29 KB

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