index.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. var _includes = _interopRequireDefault(require("lodash/includes"));
  7. var _repeat = _interopRequireDefault(require("lodash/repeat"));
  8. var _renamer = _interopRequireDefault(require("./lib/renamer"));
  9. var _index = _interopRequireDefault(require("../index"));
  10. var _defaults = _interopRequireDefault(require("lodash/defaults"));
  11. var _binding = _interopRequireDefault(require("./binding"));
  12. var _globals = _interopRequireDefault(require("globals"));
  13. var t = _interopRequireWildcard(require("@babel/types"));
  14. var _cache = require("../cache");
  15. function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
  16. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
  17. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  18. function gatherNodeParts(node, parts) {
  19. switch (node == null ? void 0 : node.type) {
  20. default:
  21. if (t.isModuleDeclaration(node)) {
  22. if (node.source) {
  23. gatherNodeParts(node.source, parts);
  24. } else if (node.specifiers && node.specifiers.length) {
  25. for (const e of node.specifiers) gatherNodeParts(e, parts);
  26. } else if (node.declaration) {
  27. gatherNodeParts(node.declaration, parts);
  28. }
  29. } else if (t.isModuleSpecifier(node)) {
  30. gatherNodeParts(node.local, parts);
  31. } else if (t.isLiteral(node)) {
  32. parts.push(node.value);
  33. }
  34. break;
  35. case "MemberExpression":
  36. case "OptionalMemberExpression":
  37. case "JSXMemberExpression":
  38. gatherNodeParts(node.object, parts);
  39. gatherNodeParts(node.property, parts);
  40. break;
  41. case "Identifier":
  42. case "JSXIdentifier":
  43. parts.push(node.name);
  44. break;
  45. case "CallExpression":
  46. case "OptionalCallExpression":
  47. case "NewExpression":
  48. gatherNodeParts(node.callee, parts);
  49. break;
  50. case "ObjectExpression":
  51. case "ObjectPattern":
  52. for (const e of node.properties) {
  53. gatherNodeParts(e, parts);
  54. }
  55. break;
  56. case "SpreadElement":
  57. case "RestElement":
  58. gatherNodeParts(node.argument, parts);
  59. break;
  60. case "ObjectProperty":
  61. case "ObjectMethod":
  62. case "ClassProperty":
  63. case "ClassMethod":
  64. case "ClassPrivateProperty":
  65. case "ClassPrivateMethod":
  66. gatherNodeParts(node.key, parts);
  67. break;
  68. case "ThisExpression":
  69. parts.push("this");
  70. break;
  71. case "Super":
  72. parts.push("super");
  73. break;
  74. case "Import":
  75. parts.push("import");
  76. break;
  77. case "DoExpression":
  78. parts.push("do");
  79. break;
  80. case "YieldExpression":
  81. parts.push("yield");
  82. gatherNodeParts(node.argument, parts);
  83. break;
  84. case "AwaitExpression":
  85. parts.push("await");
  86. gatherNodeParts(node.argument, parts);
  87. break;
  88. case "AssignmentExpression":
  89. gatherNodeParts(node.left, parts);
  90. break;
  91. case "VariableDeclarator":
  92. gatherNodeParts(node.id, parts);
  93. break;
  94. case "FunctionExpression":
  95. case "FunctionDeclaration":
  96. case "ClassExpression":
  97. case "ClassDeclaration":
  98. gatherNodeParts(node.id, parts);
  99. break;
  100. case "PrivateName":
  101. gatherNodeParts(node.id, parts);
  102. break;
  103. case "ParenthesizedExpression":
  104. gatherNodeParts(node.expression, parts);
  105. break;
  106. case "UnaryExpression":
  107. case "UpdateExpression":
  108. gatherNodeParts(node.argument, parts);
  109. break;
  110. case "MetaProperty":
  111. gatherNodeParts(node.meta, parts);
  112. gatherNodeParts(node.property, parts);
  113. break;
  114. case "JSXElement":
  115. gatherNodeParts(node.openingElement, parts);
  116. break;
  117. case "JSXOpeningElement":
  118. parts.push(node.name);
  119. break;
  120. case "JSXFragment":
  121. gatherNodeParts(node.openingFragment, parts);
  122. break;
  123. case "JSXOpeningFragment":
  124. parts.push("Fragment");
  125. break;
  126. case "JSXNamespacedName":
  127. gatherNodeParts(node.namespace, parts);
  128. gatherNodeParts(node.name, parts);
  129. break;
  130. }
  131. }
  132. const collectorVisitor = {
  133. For(path) {
  134. for (const key of t.FOR_INIT_KEYS) {
  135. const declar = path.get(key);
  136. if (declar.isVar()) {
  137. const parentScope = path.scope.getFunctionParent() || path.scope.getProgramParent();
  138. parentScope.registerBinding("var", declar);
  139. }
  140. }
  141. },
  142. Declaration(path) {
  143. if (path.isBlockScoped()) return;
  144. if (path.isExportDeclaration() && path.get("declaration").isDeclaration()) {
  145. return;
  146. }
  147. const parent = path.scope.getFunctionParent() || path.scope.getProgramParent();
  148. parent.registerDeclaration(path);
  149. },
  150. ReferencedIdentifier(path, state) {
  151. state.references.push(path);
  152. },
  153. ForXStatement(path, state) {
  154. const left = path.get("left");
  155. if (left.isPattern() || left.isIdentifier()) {
  156. state.constantViolations.push(path);
  157. }
  158. },
  159. ExportDeclaration: {
  160. exit(path) {
  161. const {
  162. node,
  163. scope
  164. } = path;
  165. const declar = node.declaration;
  166. if (t.isClassDeclaration(declar) || t.isFunctionDeclaration(declar)) {
  167. const id = declar.id;
  168. if (!id) return;
  169. const binding = scope.getBinding(id.name);
  170. if (binding) binding.reference(path);
  171. } else if (t.isVariableDeclaration(declar)) {
  172. for (const decl of declar.declarations) {
  173. for (const name of Object.keys(t.getBindingIdentifiers(decl))) {
  174. const binding = scope.getBinding(name);
  175. if (binding) binding.reference(path);
  176. }
  177. }
  178. }
  179. }
  180. },
  181. LabeledStatement(path) {
  182. path.scope.getProgramParent().addGlobal(path.node);
  183. path.scope.getBlockParent().registerDeclaration(path);
  184. },
  185. AssignmentExpression(path, state) {
  186. state.assignments.push(path);
  187. },
  188. UpdateExpression(path, state) {
  189. state.constantViolations.push(path);
  190. },
  191. UnaryExpression(path, state) {
  192. if (path.node.operator === "delete") {
  193. state.constantViolations.push(path);
  194. }
  195. },
  196. BlockScoped(path) {
  197. let scope = path.scope;
  198. if (scope.path === path) scope = scope.parent;
  199. const parent = scope.getBlockParent();
  200. parent.registerDeclaration(path);
  201. if (path.isClassDeclaration() && path.node.id) {
  202. const id = path.node.id;
  203. const name = id.name;
  204. path.scope.bindings[name] = path.scope.parent.getBinding(name);
  205. }
  206. },
  207. Block(path) {
  208. const paths = path.get("body");
  209. for (const bodyPath of paths) {
  210. if (bodyPath.isFunctionDeclaration()) {
  211. path.scope.getBlockParent().registerDeclaration(bodyPath);
  212. }
  213. }
  214. },
  215. CatchClause(path) {
  216. path.scope.registerBinding("let", path);
  217. },
  218. Function(path) {
  219. if (path.isFunctionExpression() && path.has("id") && !path.get("id").node[t.NOT_LOCAL_BINDING]) {
  220. path.scope.registerBinding("local", path.get("id"), path);
  221. }
  222. const params = path.get("params");
  223. for (const param of params) {
  224. path.scope.registerBinding("param", param);
  225. }
  226. },
  227. ClassExpression(path) {
  228. if (path.has("id") && !path.get("id").node[t.NOT_LOCAL_BINDING]) {
  229. path.scope.registerBinding("local", path);
  230. }
  231. }
  232. };
  233. let uid = 0;
  234. class Scope {
  235. constructor(path) {
  236. const {
  237. node
  238. } = path;
  239. const cached = _cache.scope.get(node);
  240. if (cached && cached.path === path) {
  241. return cached;
  242. }
  243. _cache.scope.set(node, this);
  244. this.uid = uid++;
  245. this.block = node;
  246. this.path = path;
  247. this.labels = new Map();
  248. this.inited = false;
  249. }
  250. get parent() {
  251. const parent = this.path.findParent(p => p.isScope());
  252. return parent && parent.scope;
  253. }
  254. get parentBlock() {
  255. return this.path.parent;
  256. }
  257. get hub() {
  258. return this.path.hub;
  259. }
  260. traverse(node, opts, state) {
  261. (0, _index.default)(node, opts, this, state, this.path);
  262. }
  263. generateDeclaredUidIdentifier(name) {
  264. const id = this.generateUidIdentifier(name);
  265. this.push({
  266. id
  267. });
  268. return t.cloneNode(id);
  269. }
  270. generateUidIdentifier(name) {
  271. return t.identifier(this.generateUid(name));
  272. }
  273. generateUid(name = "temp") {
  274. name = t.toIdentifier(name).replace(/^_+/, "").replace(/[0-9]+$/g, "");
  275. let uid;
  276. let i = 0;
  277. do {
  278. uid = this._generateUid(name, i);
  279. i++;
  280. } while (this.hasLabel(uid) || this.hasBinding(uid) || this.hasGlobal(uid) || this.hasReference(uid));
  281. const program = this.getProgramParent();
  282. program.references[uid] = true;
  283. program.uids[uid] = true;
  284. return uid;
  285. }
  286. _generateUid(name, i) {
  287. let id = name;
  288. if (i > 1) id += i;
  289. return `_${id}`;
  290. }
  291. generateUidBasedOnNode(node, defaultName) {
  292. const parts = [];
  293. gatherNodeParts(node, parts);
  294. let id = parts.join("$");
  295. id = id.replace(/^_/, "") || defaultName || "ref";
  296. return this.generateUid(id.slice(0, 20));
  297. }
  298. generateUidIdentifierBasedOnNode(node, defaultName) {
  299. return t.identifier(this.generateUidBasedOnNode(node, defaultName));
  300. }
  301. isStatic(node) {
  302. if (t.isThisExpression(node) || t.isSuper(node)) {
  303. return true;
  304. }
  305. if (t.isIdentifier(node)) {
  306. const binding = this.getBinding(node.name);
  307. if (binding) {
  308. return binding.constant;
  309. } else {
  310. return this.hasBinding(node.name);
  311. }
  312. }
  313. return false;
  314. }
  315. maybeGenerateMemoised(node, dontPush) {
  316. if (this.isStatic(node)) {
  317. return null;
  318. } else {
  319. const id = this.generateUidIdentifierBasedOnNode(node);
  320. if (!dontPush) {
  321. this.push({
  322. id
  323. });
  324. return t.cloneNode(id);
  325. }
  326. return id;
  327. }
  328. }
  329. checkBlockScopedCollisions(local, kind, name, id) {
  330. if (kind === "param") return;
  331. if (local.kind === "local") return;
  332. const duplicate = kind === "let" || local.kind === "let" || local.kind === "const" || local.kind === "module" || local.kind === "param" && (kind === "let" || kind === "const");
  333. if (duplicate) {
  334. throw this.hub.buildError(id, `Duplicate declaration "${name}"`, TypeError);
  335. }
  336. }
  337. rename(oldName, newName, block) {
  338. const binding = this.getBinding(oldName);
  339. if (binding) {
  340. newName = newName || this.generateUidIdentifier(oldName).name;
  341. return new _renamer.default(binding, oldName, newName).rename(block);
  342. }
  343. }
  344. _renameFromMap(map, oldName, newName, value) {
  345. if (map[oldName]) {
  346. map[newName] = value;
  347. map[oldName] = null;
  348. }
  349. }
  350. dump() {
  351. const sep = (0, _repeat.default)("-", 60);
  352. console.log(sep);
  353. let scope = this;
  354. do {
  355. console.log("#", scope.block.type);
  356. for (const name of Object.keys(scope.bindings)) {
  357. const binding = scope.bindings[name];
  358. console.log(" -", name, {
  359. constant: binding.constant,
  360. references: binding.references,
  361. violations: binding.constantViolations.length,
  362. kind: binding.kind
  363. });
  364. }
  365. } while (scope = scope.parent);
  366. console.log(sep);
  367. }
  368. toArray(node, i) {
  369. if (t.isIdentifier(node)) {
  370. const binding = this.getBinding(node.name);
  371. if (binding && binding.constant && binding.path.isGenericType("Array")) {
  372. return node;
  373. }
  374. }
  375. if (t.isArrayExpression(node)) {
  376. return node;
  377. }
  378. if (t.isIdentifier(node, {
  379. name: "arguments"
  380. })) {
  381. return t.callExpression(t.memberExpression(t.memberExpression(t.memberExpression(t.identifier("Array"), t.identifier("prototype")), t.identifier("slice")), t.identifier("call")), [node]);
  382. }
  383. let helperName;
  384. const args = [node];
  385. if (i === true) {
  386. helperName = "toConsumableArray";
  387. } else if (i) {
  388. args.push(t.numericLiteral(i));
  389. helperName = "slicedToArray";
  390. } else {
  391. helperName = "toArray";
  392. }
  393. return t.callExpression(this.hub.addHelper(helperName), args);
  394. }
  395. hasLabel(name) {
  396. return !!this.getLabel(name);
  397. }
  398. getLabel(name) {
  399. return this.labels.get(name);
  400. }
  401. registerLabel(path) {
  402. this.labels.set(path.node.label.name, path);
  403. }
  404. registerDeclaration(path) {
  405. if (path.isLabeledStatement()) {
  406. this.registerLabel(path);
  407. } else if (path.isFunctionDeclaration()) {
  408. this.registerBinding("hoisted", path.get("id"), path);
  409. } else if (path.isVariableDeclaration()) {
  410. const declarations = path.get("declarations");
  411. for (const declar of declarations) {
  412. this.registerBinding(path.node.kind, declar);
  413. }
  414. } else if (path.isClassDeclaration()) {
  415. this.registerBinding("let", path);
  416. } else if (path.isImportDeclaration()) {
  417. const specifiers = path.get("specifiers");
  418. for (const specifier of specifiers) {
  419. this.registerBinding("module", specifier);
  420. }
  421. } else if (path.isExportDeclaration()) {
  422. const declar = path.get("declaration");
  423. if (declar.isClassDeclaration() || declar.isFunctionDeclaration() || declar.isVariableDeclaration()) {
  424. this.registerDeclaration(declar);
  425. }
  426. } else {
  427. this.registerBinding("unknown", path);
  428. }
  429. }
  430. buildUndefinedNode() {
  431. return t.unaryExpression("void", t.numericLiteral(0), true);
  432. }
  433. registerConstantViolation(path) {
  434. const ids = path.getBindingIdentifiers();
  435. for (const name of Object.keys(ids)) {
  436. const binding = this.getBinding(name);
  437. if (binding) binding.reassign(path);
  438. }
  439. }
  440. registerBinding(kind, path, bindingPath = path) {
  441. if (!kind) throw new ReferenceError("no `kind`");
  442. if (path.isVariableDeclaration()) {
  443. const declarators = path.get("declarations");
  444. for (const declar of declarators) {
  445. this.registerBinding(kind, declar);
  446. }
  447. return;
  448. }
  449. const parent = this.getProgramParent();
  450. const ids = path.getOuterBindingIdentifiers(true);
  451. for (const name of Object.keys(ids)) {
  452. parent.references[name] = true;
  453. for (const id of ids[name]) {
  454. const local = this.getOwnBinding(name);
  455. if (local) {
  456. if (local.identifier === id) continue;
  457. this.checkBlockScopedCollisions(local, kind, name, id);
  458. }
  459. if (local) {
  460. this.registerConstantViolation(bindingPath);
  461. } else {
  462. this.bindings[name] = new _binding.default({
  463. identifier: id,
  464. scope: this,
  465. path: bindingPath,
  466. kind: kind
  467. });
  468. }
  469. }
  470. }
  471. }
  472. addGlobal(node) {
  473. this.globals[node.name] = node;
  474. }
  475. hasUid(name) {
  476. let scope = this;
  477. do {
  478. if (scope.uids[name]) return true;
  479. } while (scope = scope.parent);
  480. return false;
  481. }
  482. hasGlobal(name) {
  483. let scope = this;
  484. do {
  485. if (scope.globals[name]) return true;
  486. } while (scope = scope.parent);
  487. return false;
  488. }
  489. hasReference(name) {
  490. return !!this.getProgramParent().references[name];
  491. }
  492. isPure(node, constantsOnly) {
  493. if (t.isIdentifier(node)) {
  494. const binding = this.getBinding(node.name);
  495. if (!binding) return false;
  496. if (constantsOnly) return binding.constant;
  497. return true;
  498. } else if (t.isClass(node)) {
  499. if (node.superClass && !this.isPure(node.superClass, constantsOnly)) {
  500. return false;
  501. }
  502. return this.isPure(node.body, constantsOnly);
  503. } else if (t.isClassBody(node)) {
  504. for (const method of node.body) {
  505. if (!this.isPure(method, constantsOnly)) return false;
  506. }
  507. return true;
  508. } else if (t.isBinary(node)) {
  509. return this.isPure(node.left, constantsOnly) && this.isPure(node.right, constantsOnly);
  510. } else if (t.isArrayExpression(node)) {
  511. for (const elem of node.elements) {
  512. if (!this.isPure(elem, constantsOnly)) return false;
  513. }
  514. return true;
  515. } else if (t.isObjectExpression(node)) {
  516. for (const prop of node.properties) {
  517. if (!this.isPure(prop, constantsOnly)) return false;
  518. }
  519. return true;
  520. } else if (t.isMethod(node)) {
  521. if (node.computed && !this.isPure(node.key, constantsOnly)) return false;
  522. if (node.kind === "get" || node.kind === "set") return false;
  523. return true;
  524. } else if (t.isProperty(node)) {
  525. if (node.computed && !this.isPure(node.key, constantsOnly)) return false;
  526. return this.isPure(node.value, constantsOnly);
  527. } else if (t.isUnaryExpression(node)) {
  528. return this.isPure(node.argument, constantsOnly);
  529. } else if (t.isTaggedTemplateExpression(node)) {
  530. return t.matchesPattern(node.tag, "String.raw") && !this.hasBinding("String", true) && this.isPure(node.quasi, constantsOnly);
  531. } else if (t.isTemplateLiteral(node)) {
  532. for (const expression of node.expressions) {
  533. if (!this.isPure(expression, constantsOnly)) return false;
  534. }
  535. return true;
  536. } else {
  537. return t.isPureish(node);
  538. }
  539. }
  540. setData(key, val) {
  541. return this.data[key] = val;
  542. }
  543. getData(key) {
  544. let scope = this;
  545. do {
  546. const data = scope.data[key];
  547. if (data != null) return data;
  548. } while (scope = scope.parent);
  549. }
  550. removeData(key) {
  551. let scope = this;
  552. do {
  553. const data = scope.data[key];
  554. if (data != null) scope.data[key] = null;
  555. } while (scope = scope.parent);
  556. }
  557. init() {
  558. if (!this.inited) {
  559. this.inited = true;
  560. this.crawl();
  561. }
  562. }
  563. crawl() {
  564. const path = this.path;
  565. this.references = Object.create(null);
  566. this.bindings = Object.create(null);
  567. this.globals = Object.create(null);
  568. this.uids = Object.create(null);
  569. this.data = Object.create(null);
  570. if (path.isFunction()) {
  571. if (path.isFunctionExpression() && path.has("id") && !path.get("id").node[t.NOT_LOCAL_BINDING]) {
  572. this.registerBinding("local", path.get("id"), path);
  573. }
  574. const params = path.get("params");
  575. for (const param of params) {
  576. this.registerBinding("param", param);
  577. }
  578. }
  579. const programParent = this.getProgramParent();
  580. if (programParent.crawling) return;
  581. const state = {
  582. references: [],
  583. constantViolations: [],
  584. assignments: []
  585. };
  586. this.crawling = true;
  587. path.traverse(collectorVisitor, state);
  588. this.crawling = false;
  589. for (const path of state.assignments) {
  590. const ids = path.getBindingIdentifiers();
  591. for (const name of Object.keys(ids)) {
  592. if (path.scope.getBinding(name)) continue;
  593. programParent.addGlobal(ids[name]);
  594. }
  595. path.scope.registerConstantViolation(path);
  596. }
  597. for (const ref of state.references) {
  598. const binding = ref.scope.getBinding(ref.node.name);
  599. if (binding) {
  600. binding.reference(ref);
  601. } else {
  602. programParent.addGlobal(ref.node);
  603. }
  604. }
  605. for (const path of state.constantViolations) {
  606. path.scope.registerConstantViolation(path);
  607. }
  608. }
  609. push(opts) {
  610. let path = this.path;
  611. if (!path.isBlockStatement() && !path.isProgram()) {
  612. path = this.getBlockParent().path;
  613. }
  614. if (path.isSwitchStatement()) {
  615. path = (this.getFunctionParent() || this.getProgramParent()).path;
  616. }
  617. if (path.isLoop() || path.isCatchClause() || path.isFunction()) {
  618. path.ensureBlock();
  619. path = path.get("body");
  620. }
  621. const unique = opts.unique;
  622. const kind = opts.kind || "var";
  623. const blockHoist = opts._blockHoist == null ? 2 : opts._blockHoist;
  624. const dataKey = `declaration:${kind}:${blockHoist}`;
  625. let declarPath = !unique && path.getData(dataKey);
  626. if (!declarPath) {
  627. const declar = t.variableDeclaration(kind, []);
  628. declar._blockHoist = blockHoist;
  629. [declarPath] = path.unshiftContainer("body", [declar]);
  630. if (!unique) path.setData(dataKey, declarPath);
  631. }
  632. const declarator = t.variableDeclarator(opts.id, opts.init);
  633. declarPath.node.declarations.push(declarator);
  634. this.registerBinding(kind, declarPath.get("declarations").pop());
  635. }
  636. getProgramParent() {
  637. let scope = this;
  638. do {
  639. if (scope.path.isProgram()) {
  640. return scope;
  641. }
  642. } while (scope = scope.parent);
  643. throw new Error("Couldn't find a Program");
  644. }
  645. getFunctionParent() {
  646. let scope = this;
  647. do {
  648. if (scope.path.isFunctionParent()) {
  649. return scope;
  650. }
  651. } while (scope = scope.parent);
  652. return null;
  653. }
  654. getBlockParent() {
  655. let scope = this;
  656. do {
  657. if (scope.path.isBlockParent()) {
  658. return scope;
  659. }
  660. } while (scope = scope.parent);
  661. throw new Error("We couldn't find a BlockStatement, For, Switch, Function, Loop or Program...");
  662. }
  663. getAllBindings() {
  664. const ids = Object.create(null);
  665. let scope = this;
  666. do {
  667. (0, _defaults.default)(ids, scope.bindings);
  668. scope = scope.parent;
  669. } while (scope);
  670. return ids;
  671. }
  672. getAllBindingsOfKind() {
  673. const ids = Object.create(null);
  674. for (const kind of arguments) {
  675. let scope = this;
  676. do {
  677. for (const name of Object.keys(scope.bindings)) {
  678. const binding = scope.bindings[name];
  679. if (binding.kind === kind) ids[name] = binding;
  680. }
  681. scope = scope.parent;
  682. } while (scope);
  683. }
  684. return ids;
  685. }
  686. bindingIdentifierEquals(name, node) {
  687. return this.getBindingIdentifier(name) === node;
  688. }
  689. getBinding(name) {
  690. let scope = this;
  691. let previousPath;
  692. do {
  693. const binding = scope.getOwnBinding(name);
  694. if (binding) {
  695. if (previousPath && previousPath.isPattern() && previousPath.parentPath.isFunction() && binding.kind !== "param") {} else {
  696. return binding;
  697. }
  698. }
  699. previousPath = scope.path;
  700. } while (scope = scope.parent);
  701. }
  702. getOwnBinding(name) {
  703. return this.bindings[name];
  704. }
  705. getBindingIdentifier(name) {
  706. const info = this.getBinding(name);
  707. return info && info.identifier;
  708. }
  709. getOwnBindingIdentifier(name) {
  710. const binding = this.bindings[name];
  711. return binding && binding.identifier;
  712. }
  713. hasOwnBinding(name) {
  714. return !!this.getOwnBinding(name);
  715. }
  716. hasBinding(name, noGlobals) {
  717. if (!name) return false;
  718. if (this.hasOwnBinding(name)) return true;
  719. if (this.parentHasBinding(name, noGlobals)) return true;
  720. if (this.hasUid(name)) return true;
  721. if (!noGlobals && (0, _includes.default)(Scope.globals, name)) return true;
  722. if (!noGlobals && (0, _includes.default)(Scope.contextVariables, name)) return true;
  723. return false;
  724. }
  725. parentHasBinding(name, noGlobals) {
  726. return this.parent && this.parent.hasBinding(name, noGlobals);
  727. }
  728. moveBindingTo(name, scope) {
  729. const info = this.getBinding(name);
  730. if (info) {
  731. info.scope.removeOwnBinding(name);
  732. info.scope = scope;
  733. scope.bindings[name] = info;
  734. }
  735. }
  736. removeOwnBinding(name) {
  737. delete this.bindings[name];
  738. }
  739. removeBinding(name) {
  740. const info = this.getBinding(name);
  741. if (info) {
  742. info.scope.removeOwnBinding(name);
  743. }
  744. let scope = this;
  745. do {
  746. if (scope.uids[name]) {
  747. scope.uids[name] = false;
  748. }
  749. } while (scope = scope.parent);
  750. }
  751. }
  752. exports.default = Scope;
  753. Scope.globals = Object.keys(_globals.default.builtin);
  754. Scope.contextVariables = ["arguments", "undefined", "Infinity", "NaN"];