import { Node , ESTree } from "../../Node" ; import { BaseClosure , } from '../../Closure' ; import { Messages } from '../../Message' ; import { Interpreter } from '../../../interpreter/main' ; import { EmptyStatementReturn } from '../../Symbols' ; function detectVaiable ( this , node , varName , blockVariables ) { if ( node . kind == 'var' ) { /**
         * 如果var声明的scope中已经有同名的词法作用域的变量，这个var的声明需要报错：
         * Cannot redeclare block-scoped variable 'xxx'
         */ if ( this . collectDeclLex . some ( _ => _ [ varName ] ) ) { throw this . createInternalThrowError ( Messages . RedeclareBlockScopeVariableError , node . type , node ) ; } this . varDeclaration ( varName ) ; } else { let stackTop = this . collectDeclLex [ this . collectDeclLex . length - 1 ] ; stackTop && ( stackTop [ varName ] = { init : false , kind : node . kind } ) ; blockVariables . push ( varName ) ; } } export function variableDeclarationHandler ( this , node ) { let assignmentsClosure ; const assignments = [ ] ; let blockVariables = [ ] ; for ( let i = 0 ; i < node . declarations . length ; i ++ ) { const decl = node . declarations [ i ] ; if ( decl . id . type == 'ObjectPattern' ) { if ( ! decl . init ) { throw this . createInternalThrowError ( Messages . SpreadPatternVariableNoInit , '' , node ) ; } let properties = decl . id . properties ; let alreadyVars = [ ] ; properties . forEach ( item => { if ( item . type === 'Property' ) { let varName = this . getVariableName ( item . value ) ; alreadyVars . push ( varName ) ; detectVaiable . call ( this , node , varName , blockVariables ) ; assignments . push ( { type : 'ObjectPatternAssignExpression' , left : item . value , right : decl . init , } ) ; } else if ( item . type === 'RestElement' ) { let varName = item . argument . name ; detectVaiable . call ( this , node , varName , blockVariables ) ; assignments . push ( { type : "ObjectPatternAssignExpression" , left : item . argument , right : decl . init , rest : alreadyVars , } ) ; } else { throw this . createInternalThrowError ( Messages . UnknownVariableDeclTypeError , '' , node ) ; } } ) ; } else if ( decl . id . type == 'ArrayPattern' ) { if ( ! decl . init ) { throw this . createInternalThrowError ( Messages . SpreadPatternVariableNoInit , '' , node ) ; } let elements = decl . id . elements ; let alreadyVars = [ ] ; elements . forEach ( ( item , arr_ind ) => { if ( item . type === 'Identifier' ) { let varName = item . name ; alreadyVars . push ( varName ) ; detectVaiable . call ( this , node , varName , blockVariables ) ; assignments . push ( { type : 'ObjectPatternAssignExpression' , left : item , right : decl . init , index : arr_ind , } ) ; } else if ( item . type === 'RestElement' ) { let varName = item . argument . name ; detectVaiable . call ( this , node , varName , blockVariables ) ; assignments . push ( { type : "ObjectPatternAssignExpression" , left : item . argument , right : decl . init , index : arr_ind , arrRest : true , } ) ; } else { throw this . createInternalThrowError ( Messages . UnknownVariableDeclTypeError , '' , node ) ; } } ) ; } else { let variableName = this . getVariableName ( decl . id ) ; detectVaiable . call ( this , node , variableName , blockVariables ) ; if ( decl . init ) { assignments . push ( { type : "AssignmentExpression" , operator : "=" , left : decl . id , right : decl . init , } ) ; } } } if ( assignments . length ) { assignmentsClosure = this . createClosure ( { type : "GroupStatement" , body : ( assignments as unknown ) as ESTree . Statement [ ] , } ) ; } return ( ) => { if ( assignmentsClosure ) { if ( blockVariables . length ) { let scope = this . getCurrentScope ( ) ; blockVariables . forEach ( name => { if ( scope . lexDeclared [ name ] . kind === 'const' ) { } else if ( scope . lexDeclared [ name ] . kind === 'let' ) { scope . lexDeclared [ name ] . init = true ; } } ) ; } const oldValue = this . isVarDeclMode ; this . isVarDeclMode = true ; assignmentsClosure ( ) ; this . isVarDeclMode = oldValue ; } return EmptyStatementReturn ; } ; }