@@ -466,11 +466,19 @@ const visitors: EvaluateMap = {
466466 } ,
467467 // @es 2015 for of
468468 ForOfStatement ( path ) {
469- const { node, scope } = path ;
469+ const { node, scope, ctx } = path ;
470+ const labelName : string | void = ctx . labelName ;
470471 const entity = evaluate ( path . createChild ( node . right ) ) ;
472+ const SymbolConst : any =
473+ typeof Symbol !== "undefined"
474+ ? Symbol
475+ : ( ( ) => {
476+ const $var = scope . hasBinding ( "Symbol" ) ;
477+ return $var ? $var . value : undefined ;
478+ } ) ( ) ;
471479 // not support for of, it mean not support native for of
472- if ( typeof Symbol !== "undefined" ) {
473- if ( ! entity || ! entity [ Symbol . iterator ] ) {
480+ if ( SymbolConst ) {
481+ if ( ! entity || ! entity [ SymbolConst . iterator ] ) {
474482 // FIXME: how to get function name
475483 // for (let value of get()){}
476484 throw ErrInvalidIterable ( ( node . right as types . Identifier ) . name ) ;
@@ -490,7 +498,26 @@ const visitors: EvaluateMap = {
490498 forOfScope . invasive = true ;
491499 forOfScope . isolated = false ;
492500 forOfScope . declare ( node . left . kind , varName , value ) ; // define in current scope
493- evaluate ( path . createChild ( node . body , forOfScope ) ) ;
501+ const signal = evaluate ( path . createChild ( node . body , forOfScope ) ) ;
502+ if ( Signal . isBreak ( signal ) ) {
503+ if ( ! signal . value ) {
504+ break ;
505+ }
506+ if ( signal . value === labelName ) {
507+ break ;
508+ }
509+ return signal ;
510+ } else if ( Signal . isContinue ( signal ) ) {
511+ if ( ! signal . value ) {
512+ continue ;
513+ }
514+ if ( signal . value === labelName ) {
515+ continue ;
516+ }
517+ return signal ;
518+ } else if ( Signal . isReturn ( signal ) ) {
519+ return signal ;
520+ }
494521 }
495522 } else if ( isIdentifier ( node . left ) ) {
496523 /**
@@ -503,7 +530,26 @@ const visitors: EvaluateMap = {
503530 const forOfScope = scope . createChild ( "forOf" ) ;
504531 forOfScope . invasive = true ;
505532 scope . var ( varName , value ) ; // define in parent scope
506- evaluate ( path . createChild ( node . body , forOfScope ) ) ;
533+ const signal = evaluate ( path . createChild ( node . body , forOfScope ) ) ;
534+ if ( Signal . isBreak ( signal ) ) {
535+ if ( ! signal . value ) {
536+ break ;
537+ }
538+ if ( signal . value === labelName ) {
539+ break ;
540+ }
541+ return signal ;
542+ } else if ( Signal . isContinue ( signal ) ) {
543+ if ( ! signal . value ) {
544+ continue ;
545+ }
546+ if ( signal . value === labelName ) {
547+ continue ;
548+ }
549+ return signal ;
550+ } else if ( Signal . isReturn ( signal ) ) {
551+ return signal ;
552+ }
507553 }
508554 }
509555 } ,
0 commit comments