import { Node , ESTree } from "../../Node" ; import { BaseClosure , } from '../../Closure' ; import { Messages } from '../../Message' ; import { Interpreter } from '../../../interpreter/main' ; import { noop } from '../../../util' ; import { EmptyStatementReturn , Continue , Break , } from '../../Symbols' ; import { Return , BreakLabel , ContinueLabel } from '../../TokenClass' ; import Scope , { createScope } from "../../Scope" ; export function forStatementHandler ( this , node ) { let initClosure = noop ; let testClosure = node . test ? this . createClosure ( node . test ) : ( ) => true ; let updateClosure = noop ; let initLexDeclared ; let getBodyClosure = ( ) => { if ( node . body . type == 'BlockStatement' ) { return { needBlock : null , closure : this . createClosure ( node . body ) } ; } else { this . blockDeclareStart ( ) ; let closure = this . createClosure ( node . body ) ; let bodyLex = this . blockDeclareEnd ( ) ; return { needBlock : bodyLex , closure , } ; } } ; if ( node . type === "ForStatement" ) { if ( node . init ) { this . blockDeclareStart ( ) ; initClosure = this . createClosure ( node . init ) ; initLexDeclared = this . blockDeclareEnd ( ) ; } updateClosure = node . update ? this . createClosure ( node . update ) : noop ; } else { } return pNode => { let labelName ; let result = EmptyStatementReturn ; let shouldInitExec = node . type === "DoWhileStatement" ; if ( pNode && pNode . type === "LabeledStatement" ) { labelName = pNode . label . name ; } let prevScope ; let newScope ; if ( initLexDeclared ) { newScope = createScope ( this . getCurrentScope ( ) , `BScope(for-let)` , "block" ) ; newScope . lexDeclared = initLexDeclared ; prevScope = this . entryBlockScope ( newScope ) ; } for ( initClosure ( ) ; shouldInitExec || testClosure ( ) ; updateClosure ( ) ) { shouldInitExec = false ; let bodyClosure = getBodyClosure ( ) ; let bodyPrev ; let bodyScope ; if ( bodyClosure . needBlock ) { bodyScope = createScope ( this . getCurrentScope ( ) , `BScope(for-body)` , "block" ) ; bodyScope . lexDeclared = bodyClosure . needBlock ; bodyPrev = this . entryBlockScope ( bodyScope ) ; } const ret = this . setValue ( bodyClosure . closure ( ) ) ; if ( bodyClosure . needBlock ) { this . setCurrentScope ( bodyPrev ! ) ; } if ( ret === EmptyStatementReturn || ret === Continue ) continue ; if ( ret === Break ) { break ; } result = ret ; if ( result instanceof ContinueLabel && result . value === labelName ) { result = EmptyStatementReturn ; continue ; } if ( result instanceof Return || result instanceof BreakLabel || result instanceof ContinueLabel ) { break ; } } if ( initLexDeclared ) { this . setCurrentScope ( prevScope ! ) ; } return result ; } ; }