import { Syntax } from "estraverse" ; import { Scope } from "./scope" ; import { ScopeManager } from "../scopeManager" ; import * as assert from "assert" ; import { Variable } from "../variable" ; import { Reference } from "../reference" ; import * as ESTree from "estree" ; export class FunctionScope extends Scope < ESTree . Function | ESTree . Program > { public constructor ( scopeManager , upperScope , block , isMethodDefinition ) { super ( scopeManager , "function" , upperScope , block , isMethodDefinition ) ; if ( this . block . type !== Syntax . ArrowFunctionExpression ) { this . __defineArguments ( ) ; } } public isArgumentsMaterialized ( ) { if ( this . block . type === Syntax . ArrowFunctionExpression ) { return false ; } if ( ! this . isStatic ( ) ) { return true ; } const variable = this . set . get ( "arguments" ) ; assert ( typeof variable !== "undefined" , "Always have arguments variable." ) ; return ( variable ! . tainted || variable ! . references . length !== 0 ) ; } public isThisMaterialized ( ) { if ( ! this . isStatic ( ) ) { return true ; } return this . thisFound ; } public __defineArguments ( ) { this . __defineGeneric ( "arguments" , this . set , this . variables , null ) ; this . taints . set ( "arguments" , true ) ; } public __isValidResolution ( ref , variable ) { if ( this . block . type === "Program" ) { return true ; } const bodyStart = this . block . body . range ! [ 0 ] ; return ! ( variable . scope === this && ref . identifier . range ! [ 0 ] < bodyStart && variable . defs . every ( d => d . name ! . range ! [ 0 ] >= bodyStart ) ) ; } }