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.
		
		
		
		
		
			
		
			
				
					430 lines
				
				12 KiB
			
		
		
			
		
	
	
					430 lines
				
				12 KiB
			| 
											3 years ago
										 | "use strict"; | ||
|  | 
 | ||
|  | Object.defineProperty(exports, "__esModule", { | ||
|  |   value: true | ||
|  | }); | ||
|  | exports._guessExecutionStatusRelativeTo = _guessExecutionStatusRelativeTo; | ||
|  | exports._resolve = _resolve; | ||
|  | exports.canHaveVariableDeclarationOrExpression = canHaveVariableDeclarationOrExpression; | ||
|  | exports.canSwapBetweenExpressionAndStatement = canSwapBetweenExpressionAndStatement; | ||
|  | exports.equals = equals; | ||
|  | exports.getSource = getSource; | ||
|  | exports.has = has; | ||
|  | exports.is = void 0; | ||
|  | exports.isCompletionRecord = isCompletionRecord; | ||
|  | exports.isConstantExpression = isConstantExpression; | ||
|  | exports.isInStrictMode = isInStrictMode; | ||
|  | exports.isNodeType = isNodeType; | ||
|  | exports.isStatementOrBlock = isStatementOrBlock; | ||
|  | exports.isStatic = isStatic; | ||
|  | exports.isnt = isnt; | ||
|  | exports.matchesPattern = matchesPattern; | ||
|  | exports.referencesImport = referencesImport; | ||
|  | exports.resolve = resolve; | ||
|  | exports.willIMaybeExecuteBefore = willIMaybeExecuteBefore; | ||
|  | var _t = require("@babel/types"); | ||
|  | const { | ||
|  |   STATEMENT_OR_BLOCK_KEYS, | ||
|  |   VISITOR_KEYS, | ||
|  |   isBlockStatement, | ||
|  |   isExpression, | ||
|  |   isIdentifier, | ||
|  |   isLiteral, | ||
|  |   isStringLiteral, | ||
|  |   isType, | ||
|  |   matchesPattern: _matchesPattern | ||
|  | } = _t; | ||
|  | 
 | ||
|  | function matchesPattern(pattern, allowPartial) { | ||
|  |   return _matchesPattern(this.node, pattern, allowPartial); | ||
|  | } | ||
|  | 
 | ||
|  | function has(key) { | ||
|  |   const val = this.node && this.node[key]; | ||
|  |   if (val && Array.isArray(val)) { | ||
|  |     return !!val.length; | ||
|  |   } else { | ||
|  |     return !!val; | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | function isStatic() { | ||
|  |   return this.scope.isStatic(this.node); | ||
|  | } | ||
|  | 
 | ||
|  | const is = has; | ||
|  | 
 | ||
|  | exports.is = is; | ||
|  | 
 | ||
|  | function isnt(key) { | ||
|  |   return !this.has(key); | ||
|  | } | ||
|  | 
 | ||
|  | function equals(key, value) { | ||
|  |   return this.node[key] === value; | ||
|  | } | ||
|  | 
 | ||
|  | function isNodeType(type) { | ||
|  |   return isType(this.type, type); | ||
|  | } | ||
|  | 
 | ||
|  | function canHaveVariableDeclarationOrExpression() { | ||
|  |   return (this.key === "init" || this.key === "left") && this.parentPath.isFor(); | ||
|  | } | ||
|  | 
 | ||
|  | function canSwapBetweenExpressionAndStatement(replacement) { | ||
|  |   if (this.key !== "body" || !this.parentPath.isArrowFunctionExpression()) { | ||
|  |     return false; | ||
|  |   } | ||
|  |   if (this.isExpression()) { | ||
|  |     return isBlockStatement(replacement); | ||
|  |   } else if (this.isBlockStatement()) { | ||
|  |     return isExpression(replacement); | ||
|  |   } | ||
|  |   return false; | ||
|  | } | ||
|  | 
 | ||
|  | function isCompletionRecord(allowInsideFunction) { | ||
|  |   let path = this; | ||
|  |   let first = true; | ||
|  |   do { | ||
|  |     const { | ||
|  |       type, | ||
|  |       container | ||
|  |     } = path; | ||
|  | 
 | ||
|  |     if (!first && (path.isFunction() || type === "StaticBlock")) { | ||
|  |       return !!allowInsideFunction; | ||
|  |     } | ||
|  |     first = false; | ||
|  | 
 | ||
|  |     if (Array.isArray(container) && path.key !== container.length - 1) { | ||
|  |       return false; | ||
|  |     } | ||
|  |   } while ((path = path.parentPath) && !path.isProgram() && !path.isDoExpression()); | ||
|  |   return true; | ||
|  | } | ||
|  | 
 | ||
|  | function isStatementOrBlock() { | ||
|  |   if (this.parentPath.isLabeledStatement() || isBlockStatement(this.container)) { | ||
|  |     return false; | ||
|  |   } else { | ||
|  |     return STATEMENT_OR_BLOCK_KEYS.includes(this.key); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | function referencesImport(moduleSource, importName) { | ||
|  |   if (!this.isReferencedIdentifier()) { | ||
|  |     if (this.isJSXMemberExpression() && this.node.property.name === importName || (this.isMemberExpression() || this.isOptionalMemberExpression()) && (this.node.computed ? isStringLiteral(this.node.property, { | ||
|  |       value: importName | ||
|  |     }) : this.node.property.name === importName)) { | ||
|  |       const object = this.get("object"); | ||
|  |       return object.isReferencedIdentifier() && object.referencesImport(moduleSource, "*"); | ||
|  |     } | ||
|  |     return false; | ||
|  |   } | ||
|  |   const binding = this.scope.getBinding(this.node.name); | ||
|  |   if (!binding || binding.kind !== "module") return false; | ||
|  |   const path = binding.path; | ||
|  |   const parent = path.parentPath; | ||
|  |   if (!parent.isImportDeclaration()) return false; | ||
|  | 
 | ||
|  |   if (parent.node.source.value === moduleSource) { | ||
|  |     if (!importName) return true; | ||
|  |   } else { | ||
|  |     return false; | ||
|  |   } | ||
|  |   if (path.isImportDefaultSpecifier() && importName === "default") { | ||
|  |     return true; | ||
|  |   } | ||
|  |   if (path.isImportNamespaceSpecifier() && importName === "*") { | ||
|  |     return true; | ||
|  |   } | ||
|  |   if (path.isImportSpecifier() && isIdentifier(path.node.imported, { | ||
|  |     name: importName | ||
|  |   })) { | ||
|  |     return true; | ||
|  |   } | ||
|  |   return false; | ||
|  | } | ||
|  | 
 | ||
|  | function getSource() { | ||
|  |   const node = this.node; | ||
|  |   if (node.end) { | ||
|  |     const code = this.hub.getCode(); | ||
|  |     if (code) return code.slice(node.start, node.end); | ||
|  |   } | ||
|  |   return ""; | ||
|  | } | ||
|  | function willIMaybeExecuteBefore(target) { | ||
|  |   return this._guessExecutionStatusRelativeTo(target) !== "after"; | ||
|  | } | ||
|  | function getOuterFunction(path) { | ||
|  |   return path.isProgram() ? path : (path.parentPath.scope.getFunctionParent() || path.parentPath.scope.getProgramParent()).path; | ||
|  | } | ||
|  | function isExecutionUncertain(type, key) { | ||
|  |   switch (type) { | ||
|  |     case "LogicalExpression": | ||
|  |       return key === "right"; | ||
|  | 
 | ||
|  |     case "ConditionalExpression": | ||
|  |     case "IfStatement": | ||
|  |       return key === "consequent" || key === "alternate"; | ||
|  | 
 | ||
|  |     case "WhileStatement": | ||
|  |     case "DoWhileStatement": | ||
|  |     case "ForInStatement": | ||
|  |     case "ForOfStatement": | ||
|  |       return key === "body"; | ||
|  | 
 | ||
|  |     case "ForStatement": | ||
|  |       return key === "body" || key === "update"; | ||
|  | 
 | ||
|  |     case "SwitchStatement": | ||
|  |       return key === "cases"; | ||
|  | 
 | ||
|  |     case "TryStatement": | ||
|  |       return key === "handler"; | ||
|  | 
 | ||
|  |     case "AssignmentPattern": | ||
|  |       return key === "right"; | ||
|  | 
 | ||
|  |     case "OptionalMemberExpression": | ||
|  |       return key === "property"; | ||
|  | 
 | ||
|  |     case "OptionalCallExpression": | ||
|  |       return key === "arguments"; | ||
|  |     default: | ||
|  |       return false; | ||
|  |   } | ||
|  | } | ||
|  | function isExecutionUncertainInList(paths, maxIndex) { | ||
|  |   for (let i = 0; i < maxIndex; i++) { | ||
|  |     const path = paths[i]; | ||
|  |     if (isExecutionUncertain(path.parent.type, path.parentKey)) { | ||
|  |       return true; | ||
|  |     } | ||
|  |   } | ||
|  |   return false; | ||
|  | } | ||
|  | 
 | ||
|  | const SYMBOL_CHECKING = Symbol(); | ||
|  | 
 | ||
|  | function _guessExecutionStatusRelativeTo(target) { | ||
|  |   return _guessExecutionStatusRelativeToCached(this, target, new Map()); | ||
|  | } | ||
|  | function _guessExecutionStatusRelativeToCached(base, target, cache) { | ||
|  |   const funcParent = { | ||
|  |     this: getOuterFunction(base), | ||
|  |     target: getOuterFunction(target) | ||
|  |   }; | ||
|  | 
 | ||
|  |   if (funcParent.target.node !== funcParent.this.node) { | ||
|  |     return _guessExecutionStatusRelativeToDifferentFunctionsCached(base, funcParent.target, cache); | ||
|  |   } | ||
|  |   const paths = { | ||
|  |     target: target.getAncestry(), | ||
|  |     this: base.getAncestry() | ||
|  |   }; | ||
|  | 
 | ||
|  |   if (paths.target.indexOf(base) >= 0) return "after"; | ||
|  |   if (paths.this.indexOf(target) >= 0) return "before"; | ||
|  | 
 | ||
|  |   let commonPath; | ||
|  |   const commonIndex = { | ||
|  |     target: 0, | ||
|  |     this: 0 | ||
|  |   }; | ||
|  |   while (!commonPath && commonIndex.this < paths.this.length) { | ||
|  |     const path = paths.this[commonIndex.this]; | ||
|  |     commonIndex.target = paths.target.indexOf(path); | ||
|  |     if (commonIndex.target >= 0) { | ||
|  |       commonPath = path; | ||
|  |     } else { | ||
|  |       commonIndex.this++; | ||
|  |     } | ||
|  |   } | ||
|  |   if (!commonPath) { | ||
|  |     throw new Error("Internal Babel error - The two compared nodes" + " don't appear to belong to the same program."); | ||
|  |   } | ||
|  |   if (isExecutionUncertainInList(paths.this, commonIndex.this - 1) || isExecutionUncertainInList(paths.target, commonIndex.target - 1)) { | ||
|  |     return "unknown"; | ||
|  |   } | ||
|  |   const divergence = { | ||
|  |     this: paths.this[commonIndex.this - 1], | ||
|  |     target: paths.target[commonIndex.target - 1] | ||
|  |   }; | ||
|  | 
 | ||
|  |   if (divergence.target.listKey && divergence.this.listKey && divergence.target.container === divergence.this.container) { | ||
|  |     return divergence.target.key > divergence.this.key ? "before" : "after"; | ||
|  |   } | ||
|  | 
 | ||
|  |   const keys = VISITOR_KEYS[commonPath.type]; | ||
|  |   const keyPosition = { | ||
|  |     this: keys.indexOf(divergence.this.parentKey), | ||
|  |     target: keys.indexOf(divergence.target.parentKey) | ||
|  |   }; | ||
|  |   return keyPosition.target > keyPosition.this ? "before" : "after"; | ||
|  | } | ||
|  | function _guessExecutionStatusRelativeToDifferentFunctionsInternal(base, target, cache) { | ||
|  |   if (!target.isFunctionDeclaration()) { | ||
|  |     if (_guessExecutionStatusRelativeToCached(base, target, cache) === "before") { | ||
|  |       return "before"; | ||
|  |     } | ||
|  |     return "unknown"; | ||
|  |   } else if (target.parentPath.isExportDeclaration()) { | ||
|  |     return "unknown"; | ||
|  |   } | ||
|  | 
 | ||
|  |   const binding = target.scope.getBinding(target.node.id.name); | ||
|  | 
 | ||
|  |   if (!binding.references) return "before"; | ||
|  |   const referencePaths = binding.referencePaths; | ||
|  |   let allStatus; | ||
|  | 
 | ||
|  |   for (const path of referencePaths) { | ||
|  |     const childOfFunction = !!path.find(path => path.node === target.node); | ||
|  |     if (childOfFunction) continue; | ||
|  |     if (path.key !== "callee" || !path.parentPath.isCallExpression()) { | ||
|  |       return "unknown"; | ||
|  |     } | ||
|  |     const status = _guessExecutionStatusRelativeToCached(base, path, cache); | ||
|  |     if (allStatus && allStatus !== status) { | ||
|  |       return "unknown"; | ||
|  |     } else { | ||
|  |       allStatus = status; | ||
|  |     } | ||
|  |   } | ||
|  |   return allStatus; | ||
|  | } | ||
|  | function _guessExecutionStatusRelativeToDifferentFunctionsCached(base, target, cache) { | ||
|  |   let nodeMap = cache.get(base.node); | ||
|  |   let cached; | ||
|  |   if (!nodeMap) { | ||
|  |     cache.set(base.node, nodeMap = new Map()); | ||
|  |   } else if (cached = nodeMap.get(target.node)) { | ||
|  |     if (cached === SYMBOL_CHECKING) { | ||
|  |       return "unknown"; | ||
|  |     } | ||
|  |     return cached; | ||
|  |   } | ||
|  |   nodeMap.set(target.node, SYMBOL_CHECKING); | ||
|  |   const result = _guessExecutionStatusRelativeToDifferentFunctionsInternal(base, target, cache); | ||
|  |   nodeMap.set(target.node, result); | ||
|  |   return result; | ||
|  | } | ||
|  | 
 | ||
|  | function resolve(dangerous, resolved) { | ||
|  |   return this._resolve(dangerous, resolved) || this; | ||
|  | } | ||
|  | function _resolve(dangerous, resolved) { | ||
|  |   if (resolved && resolved.indexOf(this) >= 0) return; | ||
|  | 
 | ||
|  |   resolved = resolved || []; | ||
|  |   resolved.push(this); | ||
|  |   if (this.isVariableDeclarator()) { | ||
|  |     if (this.get("id").isIdentifier()) { | ||
|  |       return this.get("init").resolve(dangerous, resolved); | ||
|  |     } else { | ||
|  |     } | ||
|  |   } else if (this.isReferencedIdentifier()) { | ||
|  |     const binding = this.scope.getBinding(this.node.name); | ||
|  |     if (!binding) return; | ||
|  | 
 | ||
|  |     if (!binding.constant) return; | ||
|  | 
 | ||
|  |     if (binding.kind === "module") return; | ||
|  |     if (binding.path !== this) { | ||
|  |       const ret = binding.path.resolve(dangerous, resolved); | ||
|  |       if (this.find(parent => parent.node === ret.node)) return; | ||
|  |       return ret; | ||
|  |     } | ||
|  |   } else if (this.isTypeCastExpression()) { | ||
|  |     return this.get("expression").resolve(dangerous, resolved); | ||
|  |   } else if (dangerous && this.isMemberExpression()) { | ||
|  | 
 | ||
|  |     const targetKey = this.toComputedKey(); | ||
|  |     if (!isLiteral(targetKey)) return; | ||
|  | 
 | ||
|  |     const targetName = targetKey.value; | ||
|  |     const target = this.get("object").resolve(dangerous, resolved); | ||
|  |     if (target.isObjectExpression()) { | ||
|  |       const props = target.get("properties"); | ||
|  |       for (const prop of props) { | ||
|  |         if (!prop.isProperty()) continue; | ||
|  |         const key = prop.get("key"); | ||
|  | 
 | ||
|  |         let match = prop.isnt("computed") && key.isIdentifier({ | ||
|  |           name: targetName | ||
|  |         }); | ||
|  | 
 | ||
|  |         match = match || key.isLiteral({ | ||
|  |           value: targetName | ||
|  |         }); | ||
|  |         if (match) return prop.get("value").resolve(dangerous, resolved); | ||
|  |       } | ||
|  |     } else if (target.isArrayExpression() && !isNaN(+targetName)) { | ||
|  |       const elems = target.get("elements"); | ||
|  |       const elem = elems[targetName]; | ||
|  |       if (elem) return elem.resolve(dangerous, resolved); | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | function isConstantExpression() { | ||
|  |   if (this.isIdentifier()) { | ||
|  |     const binding = this.scope.getBinding(this.node.name); | ||
|  |     if (!binding) return false; | ||
|  |     return binding.constant; | ||
|  |   } | ||
|  |   if (this.isLiteral()) { | ||
|  |     if (this.isRegExpLiteral()) { | ||
|  |       return false; | ||
|  |     } | ||
|  |     if (this.isTemplateLiteral()) { | ||
|  |       return this.get("expressions").every(expression => expression.isConstantExpression()); | ||
|  |     } | ||
|  |     return true; | ||
|  |   } | ||
|  |   if (this.isUnaryExpression()) { | ||
|  |     if (this.node.operator !== "void") { | ||
|  |       return false; | ||
|  |     } | ||
|  |     return this.get("argument").isConstantExpression(); | ||
|  |   } | ||
|  |   if (this.isBinaryExpression()) { | ||
|  |     const { | ||
|  |       operator | ||
|  |     } = this.node; | ||
|  |     return operator !== "in" && operator !== "instanceof" && this.get("left").isConstantExpression() && this.get("right").isConstantExpression(); | ||
|  |   } | ||
|  |   return false; | ||
|  | } | ||
|  | function isInStrictMode() { | ||
|  |   const start = this.isProgram() ? this : this.parentPath; | ||
|  |   const strictParent = start.find(path => { | ||
|  |     if (path.isProgram({ | ||
|  |       sourceType: "module" | ||
|  |     })) return true; | ||
|  |     if (path.isClass()) return true; | ||
|  |     if (path.isArrowFunctionExpression() && !path.get("body").isBlockStatement()) { | ||
|  |       return false; | ||
|  |     } | ||
|  |     let body; | ||
|  |     if (path.isFunction()) { | ||
|  |       body = path.node.body; | ||
|  |     } else if (path.isProgram()) { | ||
|  |       body = path.node; | ||
|  |     } else { | ||
|  |       return false; | ||
|  |     } | ||
|  |     for (const directive of body.directives) { | ||
|  |       if (directive.value.value === "use strict") { | ||
|  |         return true; | ||
|  |       } | ||
|  |     } | ||
|  |   }); | ||
|  |   return !!strictParent; | ||
|  | } | ||
|  | 
 | ||
|  | //# sourceMappingURL=introspection.js.map
 |