You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

422 lines
12 KiB

4 years ago
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.matchesPattern = matchesPattern;
  6. exports.has = has;
  7. exports.isStatic = isStatic;
  8. exports.isnt = isnt;
  9. exports.equals = equals;
  10. exports.isNodeType = isNodeType;
  11. exports.canHaveVariableDeclarationOrExpression = canHaveVariableDeclarationOrExpression;
  12. exports.canSwapBetweenExpressionAndStatement = canSwapBetweenExpressionAndStatement;
  13. exports.isCompletionRecord = isCompletionRecord;
  14. exports.isStatementOrBlock = isStatementOrBlock;
  15. exports.referencesImport = referencesImport;
  16. exports.getSource = getSource;
  17. exports.willIMaybeExecuteBefore = willIMaybeExecuteBefore;
  18. exports._guessExecutionStatusRelativeTo = _guessExecutionStatusRelativeTo;
  19. exports._guessExecutionStatusRelativeToDifferentFunctions = _guessExecutionStatusRelativeToDifferentFunctions;
  20. exports.resolve = resolve;
  21. exports._resolve = _resolve;
  22. exports.isConstantExpression = isConstantExpression;
  23. exports.isInStrictMode = isInStrictMode;
  24. exports.is = void 0;
  25. var _includes = _interopRequireDefault(require("lodash/includes"));
  26. var t = _interopRequireWildcard(require("@babel/types"));
  27. function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
  28. 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; }
  29. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  30. function matchesPattern(pattern, allowPartial) {
  31. return t.matchesPattern(this.node, pattern, allowPartial);
  32. }
  33. function has(key) {
  34. const val = this.node && this.node[key];
  35. if (val && Array.isArray(val)) {
  36. return !!val.length;
  37. } else {
  38. return !!val;
  39. }
  40. }
  41. function isStatic() {
  42. return this.scope.isStatic(this.node);
  43. }
  44. const is = has;
  45. exports.is = is;
  46. function isnt(key) {
  47. return !this.has(key);
  48. }
  49. function equals(key, value) {
  50. return this.node[key] === value;
  51. }
  52. function isNodeType(type) {
  53. return t.isType(this.type, type);
  54. }
  55. function canHaveVariableDeclarationOrExpression() {
  56. return (this.key === "init" || this.key === "left") && this.parentPath.isFor();
  57. }
  58. function canSwapBetweenExpressionAndStatement(replacement) {
  59. if (this.key !== "body" || !this.parentPath.isArrowFunctionExpression()) {
  60. return false;
  61. }
  62. if (this.isExpression()) {
  63. return t.isBlockStatement(replacement);
  64. } else if (this.isBlockStatement()) {
  65. return t.isExpression(replacement);
  66. }
  67. return false;
  68. }
  69. function isCompletionRecord(allowInsideFunction) {
  70. let path = this;
  71. let first = true;
  72. do {
  73. const container = path.container;
  74. if (path.isFunction() && !first) {
  75. return !!allowInsideFunction;
  76. }
  77. first = false;
  78. if (Array.isArray(container) && path.key !== container.length - 1) {
  79. return false;
  80. }
  81. } while ((path = path.parentPath) && !path.isProgram());
  82. return true;
  83. }
  84. function isStatementOrBlock() {
  85. if (this.parentPath.isLabeledStatement() || t.isBlockStatement(this.container)) {
  86. return false;
  87. } else {
  88. return (0, _includes.default)(t.STATEMENT_OR_BLOCK_KEYS, this.key);
  89. }
  90. }
  91. function referencesImport(moduleSource, importName) {
  92. if (!this.isReferencedIdentifier()) return false;
  93. const binding = this.scope.getBinding(this.node.name);
  94. if (!binding || binding.kind !== "module") return false;
  95. const path = binding.path;
  96. const parent = path.parentPath;
  97. if (!parent.isImportDeclaration()) return false;
  98. if (parent.node.source.value === moduleSource) {
  99. if (!importName) return true;
  100. } else {
  101. return false;
  102. }
  103. if (path.isImportDefaultSpecifier() && importName === "default") {
  104. return true;
  105. }
  106. if (path.isImportNamespaceSpecifier() && importName === "*") {
  107. return true;
  108. }
  109. if (path.isImportSpecifier() && path.node.imported.name === importName) {
  110. return true;
  111. }
  112. return false;
  113. }
  114. function getSource() {
  115. const node = this.node;
  116. if (node.end) {
  117. const code = this.hub.getCode();
  118. if (code) return code.slice(node.start, node.end);
  119. }
  120. return "";
  121. }
  122. function willIMaybeExecuteBefore(target) {
  123. return this._guessExecutionStatusRelativeTo(target) !== "after";
  124. }
  125. function getOuterFunction(path) {
  126. return (path.scope.getFunctionParent() || path.scope.getProgramParent()).path;
  127. }
  128. function isExecutionUncertain(type, key) {
  129. switch (type) {
  130. case "LogicalExpression":
  131. return key === "right";
  132. case "ConditionalExpression":
  133. case "IfStatement":
  134. return key === "consequent" || key === "alternate";
  135. case "WhileStatement":
  136. case "DoWhileStatement":
  137. case "ForInStatement":
  138. case "ForOfStatement":
  139. return key === "body";
  140. case "ForStatement":
  141. return key === "body" || key === "update";
  142. case "SwitchStatement":
  143. return key === "cases";
  144. case "TryStatement":
  145. return key === "handler";
  146. case "AssignmentPattern":
  147. return key === "right";
  148. case "OptionalMemberExpression":
  149. return key === "property";
  150. case "OptionalCallExpression":
  151. return key === "arguments";
  152. default:
  153. return false;
  154. }
  155. }
  156. function isExecutionUncertainInList(paths, maxIndex) {
  157. for (let i = 0; i < maxIndex; i++) {
  158. const path = paths[i];
  159. if (isExecutionUncertain(path.parent.type, path.parentKey)) {
  160. return true;
  161. }
  162. }
  163. return false;
  164. }
  165. function _guessExecutionStatusRelativeTo(target) {
  166. const funcParent = {
  167. this: getOuterFunction(this),
  168. target: getOuterFunction(target)
  169. };
  170. if (funcParent.target.node !== funcParent.this.node) {
  171. return this._guessExecutionStatusRelativeToDifferentFunctions(funcParent.target);
  172. }
  173. const paths = {
  174. target: target.getAncestry(),
  175. this: this.getAncestry()
  176. };
  177. if (paths.target.indexOf(this) >= 0) return "after";
  178. if (paths.this.indexOf(target) >= 0) return "before";
  179. let commonPath;
  180. const commonIndex = {
  181. target: 0,
  182. this: 0
  183. };
  184. while (!commonPath && commonIndex.this < paths.this.length) {
  185. const path = paths.this[commonIndex.this];
  186. commonIndex.target = paths.target.indexOf(path);
  187. if (commonIndex.target >= 0) {
  188. commonPath = path;
  189. } else {
  190. commonIndex.this++;
  191. }
  192. }
  193. if (!commonPath) {
  194. throw new Error("Internal Babel error - The two compared nodes" + " don't appear to belong to the same program.");
  195. }
  196. if (isExecutionUncertainInList(paths.this, commonIndex.this - 1) || isExecutionUncertainInList(paths.target, commonIndex.target - 1)) {
  197. return "unknown";
  198. }
  199. const divergence = {
  200. this: paths.this[commonIndex.this - 1],
  201. target: paths.target[commonIndex.target - 1]
  202. };
  203. if (divergence.target.listKey && divergence.this.listKey && divergence.target.container === divergence.this.container) {
  204. return divergence.target.key > divergence.this.key ? "before" : "after";
  205. }
  206. const keys = t.VISITOR_KEYS[commonPath.type];
  207. const keyPosition = {
  208. this: keys.indexOf(divergence.this.parentKey),
  209. target: keys.indexOf(divergence.target.parentKey)
  210. };
  211. return keyPosition.target > keyPosition.this ? "before" : "after";
  212. }
  213. const executionOrderCheckedNodes = new WeakSet();
  214. function _guessExecutionStatusRelativeToDifferentFunctions(target) {
  215. if (!target.isFunctionDeclaration() || target.parentPath.isExportDeclaration()) {
  216. return "unknown";
  217. }
  218. const binding = target.scope.getBinding(target.node.id.name);
  219. if (!binding.references) return "before";
  220. const referencePaths = binding.referencePaths;
  221. let allStatus;
  222. for (const path of referencePaths) {
  223. const childOfFunction = !!path.find(path => path.node === target.node);
  224. if (childOfFunction) continue;
  225. if (path.key !== "callee" || !path.parentPath.isCallExpression()) {
  226. return "unknown";
  227. }
  228. if (executionOrderCheckedNodes.has(path.node)) continue;
  229. executionOrderCheckedNodes.add(path.node);
  230. const status = this._guessExecutionStatusRelativeTo(path);
  231. executionOrderCheckedNodes.delete(path.node);
  232. if (allStatus && allStatus !== status) {
  233. return "unknown";
  234. } else {
  235. allStatus = status;
  236. }
  237. }
  238. return allStatus;
  239. }
  240. function resolve(dangerous, resolved) {
  241. return this._resolve(dangerous, resolved) || this;
  242. }
  243. function _resolve(dangerous, resolved) {
  244. if (resolved && resolved.indexOf(this) >= 0) return;
  245. resolved = resolved || [];
  246. resolved.push(this);
  247. if (this.isVariableDeclarator()) {
  248. if (this.get("id").isIdentifier()) {
  249. return this.get("init").resolve(dangerous, resolved);
  250. } else {}
  251. } else if (this.isReferencedIdentifier()) {
  252. const binding = this.scope.getBinding(this.node.name);
  253. if (!binding) return;
  254. if (!binding.constant) return;
  255. if (binding.kind === "module") return;
  256. if (binding.path !== this) {
  257. const ret = binding.path.resolve(dangerous, resolved);
  258. if (this.find(parent => parent.node === ret.node)) return;
  259. return ret;
  260. }
  261. } else if (this.isTypeCastExpression()) {
  262. return this.get("expression").resolve(dangerous, resolved);
  263. } else if (dangerous && this.isMemberExpression()) {
  264. const targetKey = this.toComputedKey();
  265. if (!t.isLiteral(targetKey)) return;
  266. const targetName = targetKey.value;
  267. const target = this.get("object").resolve(dangerous, resolved);
  268. if (target.isObjectExpression()) {
  269. const props = target.get("properties");
  270. for (const prop of props) {
  271. if (!prop.isProperty()) continue;
  272. const key = prop.get("key");
  273. let match = prop.isnt("computed") && key.isIdentifier({
  274. name: targetName
  275. });
  276. match = match || key.isLiteral({
  277. value: targetName
  278. });
  279. if (match) return prop.get("value").resolve(dangerous, resolved);
  280. }
  281. } else if (target.isArrayExpression() && !isNaN(+targetName)) {
  282. const elems = target.get("elements");
  283. const elem = elems[targetName];
  284. if (elem) return elem.resolve(dangerous, resolved);
  285. }
  286. }
  287. }
  288. function isConstantExpression() {
  289. if (this.isIdentifier()) {
  290. const binding = this.scope.getBinding(this.node.name);
  291. if (!binding) return false;
  292. return binding.constant;
  293. }
  294. if (this.isLiteral()) {
  295. if (this.isRegExpLiteral()) {
  296. return false;
  297. }
  298. if (this.isTemplateLiteral()) {
  299. return this.get("expressions").every(expression => expression.isConstantExpression());
  300. }
  301. return true;
  302. }
  303. if (this.isUnaryExpression()) {
  304. if (this.get("operator").node !== "void") {
  305. return false;
  306. }
  307. return this.get("argument").isConstantExpression();
  308. }
  309. if (this.isBinaryExpression()) {
  310. return this.get("left").isConstantExpression() && this.get("right").isConstantExpression();
  311. }
  312. return false;
  313. }
  314. function isInStrictMode() {
  315. const start = this.isProgram() ? this : this.parentPath;
  316. const strictParent = start.find(path => {
  317. if (path.isProgram({
  318. sourceType: "module"
  319. })) return true;
  320. if (path.isClass()) return true;
  321. if (!path.isProgram() && !path.isFunction()) return false;
  322. if (path.isArrowFunctionExpression() && !path.get("body").isBlockStatement()) {
  323. return false;
  324. }
  325. let {
  326. node
  327. } = path;
  328. if (path.isFunction()) node = node.body;
  329. for (const directive of node.directives) {
  330. if (directive.value.value === "use strict") {
  331. return true;
  332. }
  333. }
  334. });
  335. return !!strictParent;
  336. }