fields.js 40 KB

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