fields.js 30 KB

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