fields.js 40 KB

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