index.js 30 KB

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