@@ -498,3 +498,99 @@ test('expandSwitches lowers nested switches innermost-first', t => {
498498 t . notOk ( opcodes . includes ( 'control_case' ) , 'no cases left' ) ;
499499 t . end ( ) ;
500500} ) ;
501+
502+ test ( 'collapseSwitches folds a variadic operator_or into every case' , t => {
503+ const eqBlock = ( id , value , parent ) => ( {
504+ id,
505+ opcode : 'operator_equals' ,
506+ next : null ,
507+ parent,
508+ inputs : {
509+ OPERAND1 : { name : 'OPERAND1' , block : `${ id } var` , shadow : null } ,
510+ OPERAND2 : { name : 'OPERAND2' , block : `${ id } val` , shadow : `${ id } val` }
511+ } ,
512+ fields : { } ,
513+ shadow : false ,
514+ topLevel : false
515+ } ) ;
516+ const varReporter = ( id , parent ) => ( {
517+ id,
518+ opcode : 'data_variable' ,
519+ next : null ,
520+ parent,
521+ inputs : { } ,
522+ fields : { VARIABLE : { name : 'VARIABLE' , value : 'switch value' , id : 'svid' } } ,
523+ shadow : false ,
524+ topLevel : false
525+ } ) ;
526+
527+ const values = [ '5' , '4' , '2' , '3' ] ;
528+ const orInputs = { } ;
529+ const blocks = {
530+ top : {
531+ id : 'top' ,
532+ opcode : 'event_whenflagclicked' ,
533+ next : 'if' ,
534+ parent : null ,
535+ inputs : { } ,
536+ fields : { } ,
537+ shadow : false ,
538+ topLevel : true ,
539+ x : 0 ,
540+ y : 0
541+ } ,
542+ if : {
543+ id : 'if' ,
544+ opcode : 'control_if_else' ,
545+ next : null ,
546+ parent : 'top' ,
547+ inputs : {
548+ CONDITION : { name : 'CONDITION' , block : 'or' , shadow : null } ,
549+ SUBSTACK : { name : 'SUBSTACK' , block : 'body' , shadow : null } ,
550+ SUBSTACK2 : { name : 'SUBSTACK2' , block : 'defbody' , shadow : null }
551+ } ,
552+ fields : { } ,
553+ shadow : false ,
554+ topLevel : false
555+ } ,
556+ body : stackBlock ( 'body' , 'looks_show' , 'if' , null ) ,
557+ defbody : stackBlock ( 'defbody' , 'looks_hide' , 'if' , null )
558+ } ;
559+ values . forEach ( ( value , i ) => {
560+ const eqId = `eq${ i } ` ;
561+ orInputs [ `OPERAND${ i + 1 } ` ] = { name : `OPERAND${ i + 1 } ` , block : eqId , shadow : null } ;
562+ blocks [ eqId ] = eqBlock ( eqId , value , 'or' ) ;
563+ blocks [ `${ eqId } var` ] = varReporter ( `${ eqId } var` , eqId ) ;
564+ blocks [ `${ eqId } val` ] = textShadow ( `${ eqId } val` , value , eqId ) ;
565+ } ) ;
566+ blocks . or = {
567+ id : 'or' ,
568+ opcode : 'operator_or' ,
569+ next : null ,
570+ parent : 'if' ,
571+ inputs : orInputs ,
572+ fields : { } ,
573+ shadow : false ,
574+ topLevel : false ,
575+ mutation : { tagName : 'mutation' , children : [ ] , itemcount : '4' }
576+ } ;
577+
578+ const collapsed = sb3 . collapseSwitches ( blocks , { } ) ;
579+ const switchId = Object . keys ( collapsed ) . find ( id => collapsed [ id ] . opcode === 'control_switch' ) ;
580+ t . ok ( switchId , 'switch created' ) ;
581+
582+ const caseValues = [ ] ;
583+ let cur = collapsed [ switchId ] . inputs . SUBSTACK . block ;
584+ while ( cur ) {
585+ const block = collapsed [ cur ] ;
586+ if ( block . opcode === 'control_case' || block . opcode === 'control_case_fallthrough' ) {
587+ const valInput = block . inputs . VALUE ;
588+ const valBlock = collapsed [ valInput . block || valInput . shadow ] ;
589+ caseValues . push ( valBlock . fields . TEXT . value ) ;
590+ }
591+ cur = block . next ;
592+ }
593+ t . same ( caseValues , [ '5' , '4' , '2' , '3' ] , 'all four operands became cases' ) ;
594+ t . notOk ( Object . values ( collapsed ) . some ( b => b . opcode === 'operator_or' ) , 'variadic or consumed' ) ;
595+ t . end ( ) ;
596+ } ) ;
0 commit comments