diff --git a/src/blocks/scratch3_control.js b/src/blocks/scratch3_control.js index 15a43fb6..76d077b1 100644 --- a/src/blocks/scratch3_control.js +++ b/src/blocks/scratch3_control.js @@ -17,6 +17,7 @@ class Scratch3ControlBlocks { return { control_repeat: this.repeat, control_repeat_until: this.repeatUntil, + control_while: this.repeatWhile, control_for_each: this.forEach, control_forever: this.forever, control_wait: this.wait, @@ -56,12 +57,20 @@ class Scratch3ControlBlocks { repeatUntil (args, util) { const condition = Cast.toBoolean(args.CONDITION); - // If the condition is true, start the branch. + // If the condition is false (repeat UNTIL), start the branch. if (!condition) { util.startBranch(1, true); } } + repeatWhile (args, util) { + const condition = Cast.toBoolean(args.CONDITION); + // If the condition is true (repeat WHILE), start the branch. + if (condition) { + util.startBranch(1, true); + } + } + forEach (args, util) { const variable = util.target.lookupOrCreateVariable( args.VARIABLE.id, args.VARIABLE.name); diff --git a/src/serialization/sb2_specmap.js b/src/serialization/sb2_specmap.js index 93a26a8a..87527371 100644 --- a/src/serialization/sb2_specmap.js +++ b/src/serialization/sb2_specmap.js @@ -799,6 +799,19 @@ const specMap = { } ] }, + 'doWhile': { + opcode: 'control_while', + argMap: [ + { + type: 'input', + inputName: 'CONDITION' + }, + { + type: 'input', + inputName: 'SUBSTACK' + } + ] + }, 'doForLoop': { opcode: 'control_for_each', argMap: [ diff --git a/test/unit/blocks_control.js b/test/unit/blocks_control.js index 3e89ab95..9d46fc01 100644 --- a/test/unit/blocks_control.js +++ b/test/unit/blocks_control.js @@ -52,6 +52,28 @@ test('repeatUntil', t => { t.end(); }); +test('repeatWhile', t => { + const rt = new Runtime(); + const c = new Control(rt); + + // Test harness (mocks `util`) + let i = 0; + const repeat = 10; + const util = { + stackFrame: Object.create(null), + startBranch: function () { + i++; + // Note !== instead of === + c.repeatWhile({CONDITION: (i !== repeat)}, util); + } + }; + + // Execute test + c.repeatWhile({CONDITION: (i !== repeat)}, util); + t.strictEqual(i, repeat); + t.end(); +}); + test('forEach', t => { const rt = new Runtime(); const c = new Control(rt);