@@ -283,7 +283,7 @@ class Composer {
283283
284284 repeat ( count ) { // varargs, no options
285285 if ( typeof count !== 'number' ) throw new ComposerError ( 'Invalid argument' , count )
286- return this . let ( { count } , this . while ( this . function ( ( ) => count -- > 0 , { helper : 'repeat_1' } ) , this . seq ( ...Array . prototype . slice . call ( arguments , 1 ) ) ) )
286+ return this . let ( { count } , this . while ( this . function ( ( ) => count -- > 0 , { helper : 'repeat_1' } ) , this . mask ( this . seq ( ...Array . prototype . slice . call ( arguments , 1 ) ) ) ) )
287287 }
288288
289289 retry ( count ) { // varargs, no options
@@ -292,10 +292,15 @@ class Composer {
292292 return this . let ( { count } ,
293293 this . function ( params => ( { params } ) , { helper : 'retry_1' } ) ,
294294 this . dowhile (
295- this . finally ( this . function ( ( { params } ) => params , { helper : 'retry_2' } ) , attempt ) ,
295+ this . finally ( this . function ( ( { params } ) => params , { helper : 'retry_2' } ) , this . mask ( attempt ) ) ,
296296 this . function ( ( { result } ) => typeof result . error !== 'undefined' && count -- > 0 , { helper : 'retry_3' } ) ) ,
297297 this . function ( ( { result } ) => result , { helper : 'retry_4' } ) )
298298 }
299+
300+ mask ( body , options ) {
301+ if ( arguments . length > 2 ) throw new ComposerError ( 'Too many arguments' )
302+ return new Composition ( { type : 'mask' , body : this . task ( body ) } , options )
303+ }
299304}
300305
301306module . exports = new Composer ( )
@@ -333,6 +338,9 @@ function init(__eval__, composition) {
333338 case 'let' :
334339 var body = compile ( json . body , path + '.body' )
335340 return [ [ { type : 'let' , let : json . declarations , path } ] , body , [ { type : 'exit' , path } ] ] . reduce ( chain )
341+ case 'mask' :
342+ var body = compile ( json . body , path + '.body' )
343+ return [ [ { type : 'mask' , path } ] , body , [ { type : 'exit' , path } ] ] . reduce ( chain )
336344 case 'retain' :
337345 var body = compile ( json . body , path + '.body' )
338346 var fsm = [ [ { type : 'push' , path } ] , body , [ { type : 'pop' , collect : true , path } ] ] . reduce ( chain )
@@ -433,14 +441,29 @@ function init(__eval__, composition) {
433441
434442 // run function f on current stack
435443 function run ( f ) {
444+ // handle let/mask pairs
445+ const view = [ ]
446+ let n = 0
447+ for ( let i in stack ) {
448+ if ( typeof stack [ i ] . mask !== 'undefined' ) {
449+ n ++
450+ } else if ( typeof stack [ i ] . let !== 'undefined' ) {
451+ if ( n === 0 ) {
452+ view . push ( stack [ i ] )
453+ } else {
454+ n --
455+ }
456+ }
457+ }
458+
436459 // update value of topmost matching symbol on stack if any
437460 function set ( symbol , value ) {
438- const element = stack . find ( element => typeof element . let !== 'undefined' && typeof element . let [ symbol ] !== 'undefined' )
461+ const element = view . find ( element => typeof element . let !== 'undefined' && typeof element . let [ symbol ] !== 'undefined' )
439462 if ( typeof element !== 'undefined' ) element . let [ symbol ] = JSON . parse ( JSON . stringify ( value ) )
440463 }
441464
442465 // collapse stack for invocation
443- const env = stack . reduceRight ( ( acc , cur ) => typeof cur . let === 'object' ? Object . assign ( acc , cur . let ) : acc , { } )
466+ const env = view . reduceRight ( ( acc , cur ) => typeof cur . let === 'object' ? Object . assign ( acc , cur . let ) : acc , { } )
444467 let main = '(function(){try{'
445468 for ( const name in env ) main += `var ${ name } =arguments[1]['${ name } '];`
446469 main += `return eval((${ f } ))(arguments[0])}finally{`
@@ -476,6 +499,9 @@ function init(__eval__, composition) {
476499 case 'let' :
477500 stack . unshift ( { let : JSON . parse ( JSON . stringify ( json . let ) ) } )
478501 break
502+ case 'mask' :
503+ stack . unshift ( { mask : true } )
504+ break
479505 case 'exit' :
480506 if ( stack . length === 0 ) return internalError ( `State ${ current } attempted to pop from an empty stack` )
481507 stack . shift ( )
0 commit comments