index.js 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. var _renamer = require("./lib/renamer.js");
  7. var _index = require("../index.js");
  8. var _traverseForScope = require("./traverseForScope.js");
  9. var _binding = require("./binding.js");
  10. var _t = require("@babel/types");
  11. var t = _t;
  12. var _cache = require("../cache.js");
  13. const globalsBuiltinLower = require("@babel/helper-globals/data/builtin-lower.json"),
  14. globalsBuiltinUpper = require("@babel/helper-globals/data/builtin-upper.json");
  15. const {
  16. assignmentExpression,
  17. callExpression,
  18. cloneNode,
  19. getBindingIdentifiers,
  20. identifier,
  21. isArrayExpression,
  22. isBinary,
  23. isCallExpression,
  24. isClass,
  25. isClassBody,
  26. isClassDeclaration,
  27. isExportAllDeclaration,
  28. isExportDefaultDeclaration,
  29. isExportNamedDeclaration,
  30. isFunctionDeclaration,
  31. isIdentifier,
  32. isImportDeclaration,
  33. isLiteral,
  34. isMemberExpression,
  35. isMethod,
  36. isModuleSpecifier,
  37. isNullLiteral,
  38. isObjectExpression,
  39. isProperty,
  40. isPureish,
  41. isRegExpLiteral,
  42. isSuper,
  43. isTaggedTemplateExpression,
  44. isTemplateLiteral,
  45. isThisExpression,
  46. isUnaryExpression,
  47. isVariableDeclaration,
  48. expressionStatement,
  49. matchesPattern,
  50. memberExpression,
  51. numericLiteral,
  52. toIdentifier,
  53. variableDeclaration,
  54. variableDeclarator,
  55. isRecordExpression,
  56. isTupleExpression,
  57. isObjectProperty,
  58. isTopicReference,
  59. isMetaProperty,
  60. isPrivateName,
  61. isExportDeclaration,
  62. buildUndefinedNode,
  63. sequenceExpression
  64. } = _t;
  65. function gatherNodeParts(node, parts) {
  66. switch (node == null ? void 0 : node.type) {
  67. default:
  68. if (isImportDeclaration(node) || isExportDeclaration(node)) {
  69. var _node$specifiers;
  70. if ((isExportAllDeclaration(node) || isExportNamedDeclaration(node) || isImportDeclaration(node)) && node.source) {
  71. gatherNodeParts(node.source, parts);
  72. } else if ((isExportNamedDeclaration(node) || isImportDeclaration(node)) && (_node$specifiers = node.specifiers) != null && _node$specifiers.length) {
  73. for (const e of node.specifiers) gatherNodeParts(e, parts);
  74. } else if ((isExportDefaultDeclaration(node) || isExportNamedDeclaration(node)) && node.declaration) {
  75. gatherNodeParts(node.declaration, parts);
  76. }
  77. } else if (isModuleSpecifier(node)) {
  78. gatherNodeParts(node.local, parts);
  79. } else if (isLiteral(node) && !isNullLiteral(node) && !isRegExpLiteral(node) && !isTemplateLiteral(node)) {
  80. parts.push(node.value);
  81. }
  82. break;
  83. case "MemberExpression":
  84. case "OptionalMemberExpression":
  85. case "JSXMemberExpression":
  86. gatherNodeParts(node.object, parts);
  87. gatherNodeParts(node.property, parts);
  88. break;
  89. case "Identifier":
  90. case "JSXIdentifier":
  91. parts.push(node.name);
  92. break;
  93. case "CallExpression":
  94. case "OptionalCallExpression":
  95. case "NewExpression":
  96. gatherNodeParts(node.callee, parts);
  97. break;
  98. case "ObjectExpression":
  99. case "ObjectPattern":
  100. for (const e of node.properties) {
  101. gatherNodeParts(e, parts);
  102. }
  103. break;
  104. case "SpreadElement":
  105. case "RestElement":
  106. gatherNodeParts(node.argument, parts);
  107. break;
  108. case "ObjectProperty":
  109. case "ObjectMethod":
  110. case "ClassProperty":
  111. case "ClassMethod":
  112. case "ClassPrivateProperty":
  113. case "ClassPrivateMethod":
  114. gatherNodeParts(node.key, parts);
  115. break;
  116. case "ThisExpression":
  117. parts.push("this");
  118. break;
  119. case "Super":
  120. parts.push("super");
  121. break;
  122. case "Import":
  123. case "ImportExpression":
  124. parts.push("import");
  125. break;
  126. case "DoExpression":
  127. parts.push("do");
  128. break;
  129. case "YieldExpression":
  130. parts.push("yield");
  131. gatherNodeParts(node.argument, parts);
  132. break;
  133. case "AwaitExpression":
  134. parts.push("await");
  135. gatherNodeParts(node.argument, parts);
  136. break;
  137. case "AssignmentExpression":
  138. gatherNodeParts(node.left, parts);
  139. break;
  140. case "VariableDeclarator":
  141. gatherNodeParts(node.id, parts);
  142. break;
  143. case "FunctionExpression":
  144. case "FunctionDeclaration":
  145. case "ClassExpression":
  146. case "ClassDeclaration":
  147. gatherNodeParts(node.id, parts);
  148. break;
  149. case "PrivateName":
  150. gatherNodeParts(node.id, parts);
  151. break;
  152. case "ParenthesizedExpression":
  153. gatherNodeParts(node.expression, parts);
  154. break;
  155. case "UnaryExpression":
  156. case "UpdateExpression":
  157. gatherNodeParts(node.argument, parts);
  158. break;
  159. case "MetaProperty":
  160. gatherNodeParts(node.meta, parts);
  161. gatherNodeParts(node.property, parts);
  162. break;
  163. case "JSXElement":
  164. gatherNodeParts(node.openingElement, parts);
  165. break;
  166. case "JSXOpeningElement":
  167. gatherNodeParts(node.name, parts);
  168. break;
  169. case "JSXFragment":
  170. gatherNodeParts(node.openingFragment, parts);
  171. break;
  172. case "JSXOpeningFragment":
  173. parts.push("Fragment");
  174. break;
  175. case "JSXNamespacedName":
  176. gatherNodeParts(node.namespace, parts);
  177. gatherNodeParts(node.name, parts);
  178. break;
  179. }
  180. }
  181. function resetScope(scope) {
  182. {
  183. scope.references = Object.create(null);
  184. scope.uids = Object.create(null);
  185. }
  186. scope.bindings = Object.create(null);
  187. scope.globals = Object.create(null);
  188. }
  189. function isAnonymousFunctionExpression(path) {
  190. return path.isFunctionExpression() && !path.node.id || path.isArrowFunctionExpression();
  191. }
  192. {
  193. var NOT_LOCAL_BINDING = Symbol.for("should not be considered a local binding");
  194. }
  195. const collectorVisitor = {
  196. ForStatement(path) {
  197. const declar = path.get("init");
  198. if (declar.isVar()) {
  199. const {
  200. scope
  201. } = path;
  202. const parentScope = scope.getFunctionParent() || scope.getProgramParent();
  203. parentScope.registerBinding("var", declar);
  204. }
  205. },
  206. Declaration(path) {
  207. if (path.isBlockScoped()) return;
  208. if (path.isImportDeclaration()) return;
  209. if (path.isExportDeclaration()) return;
  210. const parent = path.scope.getFunctionParent() || path.scope.getProgramParent();
  211. parent.registerDeclaration(path);
  212. },
  213. ImportDeclaration(path) {
  214. const parent = path.scope.getBlockParent();
  215. parent.registerDeclaration(path);
  216. },
  217. TSImportEqualsDeclaration(path) {
  218. const parent = path.scope.getBlockParent();
  219. parent.registerDeclaration(path);
  220. },
  221. ReferencedIdentifier(path, state) {
  222. if (t.isTSQualifiedName(path.parent) && path.parent.right === path.node) {
  223. return;
  224. }
  225. if (path.parentPath.isTSImportEqualsDeclaration()) return;
  226. state.references.push(path);
  227. },
  228. ForXStatement(path, state) {
  229. const left = path.get("left");
  230. if (left.isPattern() || left.isIdentifier()) {
  231. state.constantViolations.push(path);
  232. } else if (left.isVar()) {
  233. const {
  234. scope
  235. } = path;
  236. const parentScope = scope.getFunctionParent() || scope.getProgramParent();
  237. parentScope.registerBinding("var", left);
  238. }
  239. },
  240. ExportDeclaration: {
  241. exit(path) {
  242. const {
  243. node,
  244. scope
  245. } = path;
  246. if (isExportAllDeclaration(node)) return;
  247. const declar = node.declaration;
  248. if (isClassDeclaration(declar) || isFunctionDeclaration(declar)) {
  249. const id = declar.id;
  250. if (!id) return;
  251. const binding = scope.getBinding(id.name);
  252. binding == null || binding.reference(path);
  253. } else if (isVariableDeclaration(declar)) {
  254. for (const decl of declar.declarations) {
  255. for (const name of Object.keys(getBindingIdentifiers(decl))) {
  256. const binding = scope.getBinding(name);
  257. binding == null || binding.reference(path);
  258. }
  259. }
  260. }
  261. }
  262. },
  263. LabeledStatement(path) {
  264. path.scope.getBlockParent().registerDeclaration(path);
  265. },
  266. AssignmentExpression(path, state) {
  267. state.assignments.push(path);
  268. },
  269. UpdateExpression(path, state) {
  270. state.constantViolations.push(path);
  271. },
  272. UnaryExpression(path, state) {
  273. if (path.node.operator === "delete") {
  274. state.constantViolations.push(path);
  275. }
  276. },
  277. BlockScoped(path) {
  278. let scope = path.scope;
  279. if (scope.path === path) scope = scope.parent;
  280. const parent = scope.getBlockParent();
  281. parent.registerDeclaration(path);
  282. if (path.isClassDeclaration() && path.node.id) {
  283. const id = path.node.id;
  284. const name = id.name;
  285. path.scope.bindings[name] = path.scope.parent.getBinding(name);
  286. }
  287. },
  288. CatchClause(path) {
  289. path.scope.registerBinding("let", path);
  290. },
  291. Function(path) {
  292. const params = path.get("params");
  293. for (const param of params) {
  294. path.scope.registerBinding("param", param);
  295. }
  296. if (path.isFunctionExpression() && path.node.id && !path.node.id[NOT_LOCAL_BINDING]) {
  297. path.scope.registerBinding("local", path.get("id"), path);
  298. }
  299. },
  300. ClassExpression(path) {
  301. if (path.node.id && !path.node.id[NOT_LOCAL_BINDING]) {
  302. path.scope.registerBinding("local", path.get("id"), path);
  303. }
  304. },
  305. TSTypeAnnotation(path) {
  306. path.skip();
  307. }
  308. };
  309. let scopeVisitor;
  310. let uid = 0;
  311. class Scope {
  312. constructor(path) {
  313. this.uid = void 0;
  314. this.path = void 0;
  315. this.block = void 0;
  316. this.inited = void 0;
  317. this.labels = void 0;
  318. this.bindings = void 0;
  319. this.referencesSet = void 0;
  320. this.globals = void 0;
  321. this.uidsSet = void 0;
  322. this.data = void 0;
  323. this.crawling = void 0;
  324. const {
  325. node
  326. } = path;
  327. const cached = _cache.scope.get(node);
  328. if ((cached == null ? void 0 : cached.path) === path) {
  329. return cached;
  330. }
  331. _cache.scope.set(node, this);
  332. this.uid = uid++;
  333. this.block = node;
  334. this.path = path;
  335. this.labels = new Map();
  336. this.inited = false;
  337. {
  338. Object.defineProperties(this, {
  339. references: {
  340. enumerable: true,
  341. configurable: true,
  342. writable: true,
  343. value: Object.create(null)
  344. },
  345. uids: {
  346. enumerable: true,
  347. configurable: true,
  348. writable: true,
  349. value: Object.create(null)
  350. }
  351. });
  352. }
  353. }
  354. get parent() {
  355. var _parent;
  356. let parent,
  357. path = this.path;
  358. do {
  359. var _path;
  360. const shouldSkip = path.key === "key" || path.listKey === "decorators";
  361. path = path.parentPath;
  362. if (shouldSkip && path.isMethod()) path = path.parentPath;
  363. if ((_path = path) != null && _path.isScope()) parent = path;
  364. } while (path && !parent);
  365. return (_parent = parent) == null ? void 0 : _parent.scope;
  366. }
  367. get references() {
  368. throw new Error("Scope#references is not available in Babel 8. Use Scope#referencesSet instead.");
  369. }
  370. get uids() {
  371. throw new Error("Scope#uids is not available in Babel 8. Use Scope#uidsSet instead.");
  372. }
  373. generateDeclaredUidIdentifier(name) {
  374. const id = this.generateUidIdentifier(name);
  375. this.push({
  376. id
  377. });
  378. return cloneNode(id);
  379. }
  380. generateUidIdentifier(name) {
  381. return identifier(this.generateUid(name));
  382. }
  383. generateUid(name = "temp") {
  384. name = toIdentifier(name).replace(/^_+/, "").replace(/\d+$/g, "");
  385. let uid;
  386. let i = 0;
  387. do {
  388. uid = `_${name}`;
  389. if (i >= 11) uid += i - 1;else if (i >= 9) uid += i - 9;else if (i >= 1) uid += i + 1;
  390. i++;
  391. } while (this.hasLabel(uid) || this.hasBinding(uid) || this.hasGlobal(uid) || this.hasReference(uid));
  392. const program = this.getProgramParent();
  393. {
  394. program.references[uid] = true;
  395. program.uids[uid] = true;
  396. }
  397. return uid;
  398. }
  399. generateUidBasedOnNode(node, defaultName) {
  400. const parts = [];
  401. gatherNodeParts(node, parts);
  402. let id = parts.join("$");
  403. id = id.replace(/^_/, "") || defaultName || "ref";
  404. return this.generateUid(id.slice(0, 20));
  405. }
  406. generateUidIdentifierBasedOnNode(node, defaultName) {
  407. return identifier(this.generateUidBasedOnNode(node, defaultName));
  408. }
  409. isStatic(node) {
  410. if (isThisExpression(node) || isSuper(node) || isTopicReference(node)) {
  411. return true;
  412. }
  413. if (isIdentifier(node)) {
  414. const binding = this.getBinding(node.name);
  415. if (binding) {
  416. return binding.constant;
  417. } else {
  418. return this.hasBinding(node.name);
  419. }
  420. }
  421. return false;
  422. }
  423. maybeGenerateMemoised(node, dontPush) {
  424. if (this.isStatic(node)) {
  425. return null;
  426. } else {
  427. const id = this.generateUidIdentifierBasedOnNode(node);
  428. if (!dontPush) {
  429. this.push({
  430. id
  431. });
  432. return cloneNode(id);
  433. }
  434. return id;
  435. }
  436. }
  437. checkBlockScopedCollisions(local, kind, name, id) {
  438. if (kind === "param") return;
  439. if (local.kind === "local") return;
  440. const duplicate = kind === "let" || local.kind === "let" || local.kind === "const" || local.kind === "module" || local.kind === "param" && kind === "const";
  441. if (duplicate) {
  442. throw this.path.hub.buildError(id, `Duplicate declaration "${name}"`, TypeError);
  443. }
  444. }
  445. rename(oldName, newName) {
  446. const binding = this.getBinding(oldName);
  447. if (binding) {
  448. newName || (newName = this.generateUidIdentifier(oldName).name);
  449. const renamer = new _renamer.default(binding, oldName, newName);
  450. {
  451. renamer.rename(arguments[2]);
  452. }
  453. }
  454. }
  455. dump() {
  456. const sep = "-".repeat(60);
  457. console.log(sep);
  458. let scope = this;
  459. do {
  460. console.log("#", scope.block.type);
  461. for (const name of Object.keys(scope.bindings)) {
  462. const binding = scope.bindings[name];
  463. console.log(" -", name, {
  464. constant: binding.constant,
  465. references: binding.references,
  466. violations: binding.constantViolations.length,
  467. kind: binding.kind
  468. });
  469. }
  470. } while (scope = scope.parent);
  471. console.log(sep);
  472. }
  473. hasLabel(name) {
  474. return !!this.getLabel(name);
  475. }
  476. getLabel(name) {
  477. return this.labels.get(name);
  478. }
  479. registerLabel(path) {
  480. this.labels.set(path.node.label.name, path);
  481. }
  482. registerDeclaration(path) {
  483. if (path.isLabeledStatement()) {
  484. this.registerLabel(path);
  485. } else if (path.isFunctionDeclaration()) {
  486. this.registerBinding("hoisted", path.get("id"), path);
  487. } else if (path.isVariableDeclaration()) {
  488. const declarations = path.get("declarations");
  489. const {
  490. kind
  491. } = path.node;
  492. for (const declar of declarations) {
  493. this.registerBinding(kind === "using" || kind === "await using" ? "const" : kind, declar);
  494. }
  495. } else if (path.isClassDeclaration()) {
  496. if (path.node.declare) return;
  497. this.registerBinding("let", path);
  498. } else if (path.isImportDeclaration()) {
  499. const isTypeDeclaration = path.node.importKind === "type" || path.node.importKind === "typeof";
  500. const specifiers = path.get("specifiers");
  501. for (const specifier of specifiers) {
  502. const isTypeSpecifier = isTypeDeclaration || specifier.isImportSpecifier() && (specifier.node.importKind === "type" || specifier.node.importKind === "typeof");
  503. this.registerBinding(isTypeSpecifier ? "unknown" : "module", specifier);
  504. }
  505. } else if (path.isExportDeclaration()) {
  506. const declar = path.get("declaration");
  507. if (declar.isClassDeclaration() || declar.isFunctionDeclaration() || declar.isVariableDeclaration()) {
  508. this.registerDeclaration(declar);
  509. }
  510. } else {
  511. this.registerBinding("unknown", path);
  512. }
  513. }
  514. buildUndefinedNode() {
  515. return buildUndefinedNode();
  516. }
  517. registerConstantViolation(path) {
  518. const ids = path.getAssignmentIdentifiers();
  519. for (const name of Object.keys(ids)) {
  520. var _this$getBinding;
  521. (_this$getBinding = this.getBinding(name)) == null || _this$getBinding.reassign(path);
  522. }
  523. }
  524. registerBinding(kind, path, bindingPath = path) {
  525. if (!kind) throw new ReferenceError("no `kind`");
  526. if (path.isVariableDeclaration()) {
  527. const declarators = path.get("declarations");
  528. for (const declar of declarators) {
  529. this.registerBinding(kind, declar);
  530. }
  531. return;
  532. }
  533. const parent = this.getProgramParent();
  534. const ids = path.getOuterBindingIdentifiers(true);
  535. for (const name of Object.keys(ids)) {
  536. {
  537. parent.references[name] = true;
  538. }
  539. for (const id of ids[name]) {
  540. const local = this.getOwnBinding(name);
  541. if (local) {
  542. if (local.identifier === id) continue;
  543. this.checkBlockScopedCollisions(local, kind, name, id);
  544. }
  545. if (local) {
  546. local.reassign(bindingPath);
  547. } else {
  548. this.bindings[name] = new _binding.default({
  549. identifier: id,
  550. scope: this,
  551. path: bindingPath,
  552. kind: kind
  553. });
  554. }
  555. }
  556. }
  557. }
  558. addGlobal(node) {
  559. this.globals[node.name] = node;
  560. }
  561. hasUid(name) {
  562. {
  563. let scope = this;
  564. do {
  565. if (scope.uids[name]) return true;
  566. } while (scope = scope.parent);
  567. return false;
  568. }
  569. }
  570. hasGlobal(name) {
  571. let scope = this;
  572. do {
  573. if (scope.globals[name]) return true;
  574. } while (scope = scope.parent);
  575. return false;
  576. }
  577. hasReference(name) {
  578. {
  579. return !!this.getProgramParent().references[name];
  580. }
  581. }
  582. isPure(node, constantsOnly) {
  583. if (isIdentifier(node)) {
  584. const binding = this.getBinding(node.name);
  585. if (!binding) return false;
  586. if (constantsOnly) return binding.constant;
  587. return true;
  588. } else if (isThisExpression(node) || isMetaProperty(node) || isTopicReference(node) || isPrivateName(node)) {
  589. return true;
  590. } else if (isClass(node)) {
  591. var _node$decorators;
  592. if (node.superClass && !this.isPure(node.superClass, constantsOnly)) {
  593. return false;
  594. }
  595. if (((_node$decorators = node.decorators) == null ? void 0 : _node$decorators.length) > 0) {
  596. return false;
  597. }
  598. return this.isPure(node.body, constantsOnly);
  599. } else if (isClassBody(node)) {
  600. for (const method of node.body) {
  601. if (!this.isPure(method, constantsOnly)) return false;
  602. }
  603. return true;
  604. } else if (isBinary(node)) {
  605. return this.isPure(node.left, constantsOnly) && this.isPure(node.right, constantsOnly);
  606. } else if (isArrayExpression(node) || isTupleExpression(node)) {
  607. for (const elem of node.elements) {
  608. if (elem !== null && !this.isPure(elem, constantsOnly)) return false;
  609. }
  610. return true;
  611. } else if (isObjectExpression(node) || isRecordExpression(node)) {
  612. for (const prop of node.properties) {
  613. if (!this.isPure(prop, constantsOnly)) return false;
  614. }
  615. return true;
  616. } else if (isMethod(node)) {
  617. var _node$decorators2;
  618. if (node.computed && !this.isPure(node.key, constantsOnly)) return false;
  619. if (((_node$decorators2 = node.decorators) == null ? void 0 : _node$decorators2.length) > 0) {
  620. return false;
  621. }
  622. return true;
  623. } else if (isProperty(node)) {
  624. var _node$decorators3;
  625. if (node.computed && !this.isPure(node.key, constantsOnly)) return false;
  626. if (((_node$decorators3 = node.decorators) == null ? void 0 : _node$decorators3.length) > 0) {
  627. return false;
  628. }
  629. if (isObjectProperty(node) || node.static) {
  630. if (node.value !== null && !this.isPure(node.value, constantsOnly)) {
  631. return false;
  632. }
  633. }
  634. return true;
  635. } else if (isUnaryExpression(node)) {
  636. return this.isPure(node.argument, constantsOnly);
  637. } else if (isTemplateLiteral(node)) {
  638. for (const expression of node.expressions) {
  639. if (!this.isPure(expression, constantsOnly)) return false;
  640. }
  641. return true;
  642. } else if (isTaggedTemplateExpression(node)) {
  643. return matchesPattern(node.tag, "String.raw") && !this.hasBinding("String", {
  644. noGlobals: true
  645. }) && this.isPure(node.quasi, constantsOnly);
  646. } else if (isMemberExpression(node)) {
  647. return !node.computed && isIdentifier(node.object) && node.object.name === "Symbol" && isIdentifier(node.property) && node.property.name !== "for" && !this.hasBinding("Symbol", {
  648. noGlobals: true
  649. });
  650. } else if (isCallExpression(node)) {
  651. return matchesPattern(node.callee, "Symbol.for") && !this.hasBinding("Symbol", {
  652. noGlobals: true
  653. }) && node.arguments.length === 1 && t.isStringLiteral(node.arguments[0]);
  654. } else {
  655. return isPureish(node);
  656. }
  657. }
  658. setData(key, val) {
  659. return this.data[key] = val;
  660. }
  661. getData(key) {
  662. let scope = this;
  663. do {
  664. const data = scope.data[key];
  665. if (data != null) return data;
  666. } while (scope = scope.parent);
  667. }
  668. removeData(key) {
  669. let scope = this;
  670. do {
  671. const data = scope.data[key];
  672. if (data != null) scope.data[key] = null;
  673. } while (scope = scope.parent);
  674. }
  675. init() {
  676. if (!this.inited) {
  677. this.inited = true;
  678. this.crawl();
  679. }
  680. }
  681. crawl() {
  682. const path = this.path;
  683. ;
  684. resetScope(this);
  685. this.data = Object.create(null);
  686. let scope = this;
  687. do {
  688. if (scope.crawling) return;
  689. if (scope.path.isProgram()) {
  690. break;
  691. }
  692. } while (scope = scope.parent);
  693. const programParent = scope;
  694. const state = {
  695. references: [],
  696. constantViolations: [],
  697. assignments: []
  698. };
  699. this.crawling = true;
  700. scopeVisitor || (scopeVisitor = _index.default.visitors.merge([{
  701. Scope(path) {
  702. resetScope(path.scope);
  703. }
  704. }, collectorVisitor]));
  705. if (path.type !== "Program") {
  706. const typeVisitors = scopeVisitor[path.type];
  707. if (typeVisitors) {
  708. for (const visit of typeVisitors.enter) {
  709. visit.call(state, path, state);
  710. }
  711. }
  712. }
  713. {
  714. path.traverse(scopeVisitor, state);
  715. }
  716. this.crawling = false;
  717. for (const path of state.assignments) {
  718. const ids = path.getAssignmentIdentifiers();
  719. for (const name of Object.keys(ids)) {
  720. if (path.scope.getBinding(name)) continue;
  721. programParent.addGlobal(ids[name]);
  722. }
  723. path.scope.registerConstantViolation(path);
  724. }
  725. for (const ref of state.references) {
  726. const binding = ref.scope.getBinding(ref.node.name);
  727. if (binding) {
  728. binding.reference(ref);
  729. } else {
  730. programParent.addGlobal(ref.node);
  731. }
  732. }
  733. for (const path of state.constantViolations) {
  734. path.scope.registerConstantViolation(path);
  735. }
  736. }
  737. push(opts) {
  738. let path = this.path;
  739. if (path.isPattern()) {
  740. path = this.getPatternParent().path;
  741. } else if (!path.isBlockStatement() && !path.isProgram()) {
  742. path = this.getBlockParent().path;
  743. }
  744. if (path.isSwitchStatement()) {
  745. path = (this.getFunctionParent() || this.getProgramParent()).path;
  746. }
  747. const {
  748. init,
  749. unique,
  750. kind = "var",
  751. id
  752. } = opts;
  753. if (!init && !unique && (kind === "var" || kind === "let") && isAnonymousFunctionExpression(path) && isCallExpression(path.parent, {
  754. callee: path.node
  755. }) && path.parent.arguments.length <= path.node.params.length && isIdentifier(id)) {
  756. path.pushContainer("params", id);
  757. path.scope.registerBinding("param", path.get("params")[path.node.params.length - 1]);
  758. return;
  759. }
  760. if (path.isLoop() || path.isCatchClause() || path.isFunction()) {
  761. path.ensureBlock();
  762. path = path.get("body");
  763. }
  764. const blockHoist = opts._blockHoist == null ? 2 : opts._blockHoist;
  765. const dataKey = `declaration:${kind}:${blockHoist}`;
  766. let declarPath = !unique && path.getData(dataKey);
  767. if (!declarPath) {
  768. const declar = variableDeclaration(kind, []);
  769. declar._blockHoist = blockHoist;
  770. [declarPath] = path.unshiftContainer("body", [declar]);
  771. if (!unique) path.setData(dataKey, declarPath);
  772. }
  773. const declarator = variableDeclarator(id, init);
  774. const len = declarPath.node.declarations.push(declarator);
  775. path.scope.registerBinding(kind, declarPath.get("declarations")[len - 1]);
  776. }
  777. getProgramParent() {
  778. let scope = this;
  779. do {
  780. if (scope.path.isProgram()) {
  781. return scope;
  782. }
  783. } while (scope = scope.parent);
  784. throw new Error("Couldn't find a Program");
  785. }
  786. getFunctionParent() {
  787. let scope = this;
  788. do {
  789. if (scope.path.isFunctionParent()) {
  790. return scope;
  791. }
  792. } while (scope = scope.parent);
  793. return null;
  794. }
  795. getBlockParent() {
  796. let scope = this;
  797. do {
  798. if (scope.path.isBlockParent()) {
  799. return scope;
  800. }
  801. } while (scope = scope.parent);
  802. throw new Error("We couldn't find a BlockStatement, For, Switch, Function, Loop or Program...");
  803. }
  804. getPatternParent() {
  805. let scope = this;
  806. do {
  807. if (!scope.path.isPattern()) {
  808. return scope.getBlockParent();
  809. }
  810. } while (scope = scope.parent.parent);
  811. throw new Error("We couldn't find a BlockStatement, For, Switch, Function, Loop or Program...");
  812. }
  813. getAllBindings() {
  814. const ids = Object.create(null);
  815. let scope = this;
  816. do {
  817. for (const key of Object.keys(scope.bindings)) {
  818. if (key in ids === false) {
  819. ids[key] = scope.bindings[key];
  820. }
  821. }
  822. scope = scope.parent;
  823. } while (scope);
  824. return ids;
  825. }
  826. bindingIdentifierEquals(name, node) {
  827. return this.getBindingIdentifier(name) === node;
  828. }
  829. getBinding(name) {
  830. let scope = this;
  831. let previousPath;
  832. do {
  833. const binding = scope.getOwnBinding(name);
  834. if (binding) {
  835. var _previousPath;
  836. if ((_previousPath = previousPath) != null && _previousPath.isPattern() && binding.kind !== "param" && binding.kind !== "local") {} else {
  837. return binding;
  838. }
  839. } else if (!binding && name === "arguments" && scope.path.isFunction() && !scope.path.isArrowFunctionExpression()) {
  840. break;
  841. }
  842. previousPath = scope.path;
  843. } while (scope = scope.parent);
  844. }
  845. getOwnBinding(name) {
  846. return this.bindings[name];
  847. }
  848. getBindingIdentifier(name) {
  849. var _this$getBinding2;
  850. return (_this$getBinding2 = this.getBinding(name)) == null ? void 0 : _this$getBinding2.identifier;
  851. }
  852. getOwnBindingIdentifier(name) {
  853. const binding = this.bindings[name];
  854. return binding == null ? void 0 : binding.identifier;
  855. }
  856. hasOwnBinding(name) {
  857. return !!this.getOwnBinding(name);
  858. }
  859. hasBinding(name, opts) {
  860. if (!name) return false;
  861. let noGlobals;
  862. let noUids;
  863. let upToScope;
  864. if (typeof opts === "object") {
  865. noGlobals = opts.noGlobals;
  866. noUids = opts.noUids;
  867. upToScope = opts.upToScope;
  868. } else if (typeof opts === "boolean") {
  869. noGlobals = opts;
  870. }
  871. let scope = this;
  872. do {
  873. if (upToScope === scope) {
  874. break;
  875. }
  876. if (scope.hasOwnBinding(name)) {
  877. return true;
  878. }
  879. } while (scope = scope.parent);
  880. if (!noUids && this.hasUid(name)) return true;
  881. if (!noGlobals && Scope.globals.includes(name)) return true;
  882. if (!noGlobals && Scope.contextVariables.includes(name)) return true;
  883. return false;
  884. }
  885. parentHasBinding(name, opts) {
  886. var _this$parent;
  887. return (_this$parent = this.parent) == null ? void 0 : _this$parent.hasBinding(name, opts);
  888. }
  889. moveBindingTo(name, scope) {
  890. const info = this.getBinding(name);
  891. if (info) {
  892. info.scope.removeOwnBinding(name);
  893. info.scope = scope;
  894. scope.bindings[name] = info;
  895. }
  896. }
  897. removeOwnBinding(name) {
  898. delete this.bindings[name];
  899. }
  900. removeBinding(name) {
  901. var _this$getBinding3;
  902. (_this$getBinding3 = this.getBinding(name)) == null || _this$getBinding3.scope.removeOwnBinding(name);
  903. {
  904. let scope = this;
  905. do {
  906. if (scope.uids[name]) {
  907. scope.uids[name] = false;
  908. }
  909. } while (scope = scope.parent);
  910. }
  911. }
  912. hoistVariables(emit = id => this.push({
  913. id
  914. })) {
  915. this.crawl();
  916. const seen = new Set();
  917. for (const name of Object.keys(this.bindings)) {
  918. const binding = this.bindings[name];
  919. if (!binding) continue;
  920. const {
  921. path
  922. } = binding;
  923. if (!path.isVariableDeclarator()) continue;
  924. const {
  925. parent,
  926. parentPath
  927. } = path;
  928. if (parent.kind !== "var" || seen.has(parent)) continue;
  929. seen.add(path.parent);
  930. let firstId;
  931. const init = [];
  932. for (const decl of parent.declarations) {
  933. firstId != null ? firstId : firstId = decl.id;
  934. if (decl.init) {
  935. init.push(assignmentExpression("=", decl.id, decl.init));
  936. }
  937. const ids = Object.keys(getBindingIdentifiers(decl, false, true, true));
  938. for (const name of ids) {
  939. emit(identifier(name), decl.init != null);
  940. }
  941. }
  942. if (parentPath.parentPath.isForXStatement({
  943. left: parent
  944. })) {
  945. parentPath.replaceWith(firstId);
  946. } else if (init.length === 0) {
  947. parentPath.remove();
  948. } else {
  949. const expr = init.length === 1 ? init[0] : sequenceExpression(init);
  950. if (parentPath.parentPath.isForStatement({
  951. init: parent
  952. })) {
  953. parentPath.replaceWith(expr);
  954. } else {
  955. parentPath.replaceWith(expressionStatement(expr));
  956. }
  957. }
  958. }
  959. }
  960. }
  961. exports.default = Scope;
  962. Scope.globals = [...globalsBuiltinLower, ...globalsBuiltinUpper];
  963. Scope.contextVariables = ["arguments", "undefined", "Infinity", "NaN"];
  964. {
  965. Scope.prototype._renameFromMap = function _renameFromMap(map, oldName, newName, value) {
  966. if (map[oldName]) {
  967. map[newName] = value;
  968. map[oldName] = null;
  969. }
  970. };
  971. Scope.prototype.traverse = function (node, opts, state) {
  972. (0, _index.default)(node, opts, this, state, this.path);
  973. };
  974. Scope.prototype._generateUid = function _generateUid(name, i) {
  975. let id = name;
  976. if (i > 1) id += i;
  977. return `_${id}`;
  978. };
  979. Scope.prototype.toArray = function toArray(node, i, arrayLikeIsIterable) {
  980. if (isIdentifier(node)) {
  981. const binding = this.getBinding(node.name);
  982. if (binding != null && binding.constant && binding.path.isGenericType("Array")) {
  983. return node;
  984. }
  985. }
  986. if (isArrayExpression(node)) {
  987. return node;
  988. }
  989. if (isIdentifier(node, {
  990. name: "arguments"
  991. })) {
  992. return callExpression(memberExpression(memberExpression(memberExpression(identifier("Array"), identifier("prototype")), identifier("slice")), identifier("call")), [node]);
  993. }
  994. let helperName;
  995. const args = [node];
  996. if (i === true) {
  997. helperName = "toConsumableArray";
  998. } else if (typeof i === "number") {
  999. args.push(numericLiteral(i));
  1000. helperName = "slicedToArray";
  1001. } else {
  1002. helperName = "toArray";
  1003. }
  1004. if (arrayLikeIsIterable) {
  1005. args.unshift(this.path.hub.addHelper(helperName));
  1006. helperName = "maybeArrayLike";
  1007. }
  1008. return callExpression(this.path.hub.addHelper(helperName), args);
  1009. };
  1010. Scope.prototype.getAllBindingsOfKind = function getAllBindingsOfKind(...kinds) {
  1011. const ids = Object.create(null);
  1012. for (const kind of kinds) {
  1013. let scope = this;
  1014. do {
  1015. for (const name of Object.keys(scope.bindings)) {
  1016. const binding = scope.bindings[name];
  1017. if (binding.kind === kind) ids[name] = binding;
  1018. }
  1019. scope = scope.parent;
  1020. } while (scope);
  1021. }
  1022. return ids;
  1023. };
  1024. Object.defineProperties(Scope.prototype, {
  1025. parentBlock: {
  1026. configurable: true,
  1027. enumerable: true,
  1028. get() {
  1029. return this.path.parent;
  1030. }
  1031. },
  1032. hub: {
  1033. configurable: true,
  1034. enumerable: true,
  1035. get() {
  1036. return this.path.hub;
  1037. }
  1038. }
  1039. });
  1040. }
  1041. //# sourceMappingURL=index.js.map