From bd76395676c3af1ad276c306b81fabe470088d19 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Mon, 13 Feb 2017 14:44:51 -0800 Subject: [PATCH 1/3] Minor cleanup around cloning methods --- src/sprites/rendered-target.js | 6 +++--- src/sprites/sprite.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sprites/rendered-target.js b/src/sprites/rendered-target.js index 9bbc20b2381..0a0a115f971 100644 --- a/src/sprites/rendered-target.js +++ b/src/sprites/rendered-target.js @@ -582,7 +582,7 @@ RenderedTarget.prototype.goBackLayers = function (nLayers) { /** * Move behind some other rendered target. - * @param {!Clone} other Other rendered target to move behind. + * @param {!RenderedTarget} other Other rendered target to move behind. */ RenderedTarget.prototype.goBehindOther = function (other) { if (this.renderer) { @@ -637,11 +637,11 @@ RenderedTarget.prototype.keepInFence = function (newX, newY, optFence) { /** * Make a clone, copying any run-time properties. * If we've hit the global clone limit, returns null. - * @return {!RenderedTarget} New clone. + * @return {RenderedTarget} New clone. */ RenderedTarget.prototype.makeClone = function () { if (!this.runtime.clonesAvailable() || this.isStage) { - return; // Hit max clone limit, or this is the stage. + return null; // Hit max clone limit, or this is the stage. } this.runtime.changeCloneCounter(1); var newClone = this.sprite.createClone(); diff --git a/src/sprites/sprite.js b/src/sprites/sprite.js index bccc5d90986..81626f3a721 100644 --- a/src/sprites/sprite.js +++ b/src/sprites/sprite.js @@ -46,7 +46,7 @@ var Sprite = function (blocks, runtime) { /** * Create a clone of this sprite. - * @returns {!Clone} Newly created clone. + * @returns {!RenderedTarget} Newly created clone. */ Sprite.prototype.createClone = function () { var newClone = new RenderedTarget(this, this.runtime); From 18107cde7b26ffe954e5a98ffc86e9ec655ec6c6 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Mon, 13 Feb 2017 14:35:50 -0800 Subject: [PATCH 2/3] Reverse target iteration in `allScriptsDo` The `allStacksAndOwnersDo` function in Scratch 2.0 runtime iterates targets in reverse and projects sometimes rely on that for correct initialization. If, for example, each sprite runs a "go back 999 layers" or "go to front" block as its first action, the order of execution will determine the ordering of the layers. This change makes Scratch 3.0 match the Scratch 2.0 execution order. --- src/engine/runtime.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index fc3b17a0687..d9e59d36ac4 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -414,7 +414,7 @@ Runtime.prototype.allScriptsDo = function (f, optTarget) { if (optTarget) { targets = [optTarget]; } - for (var t = 0; t < targets.length; t++) { + for (var t = targets.length - 1; t >= 0; t--) { var target = targets[t]; var scripts = target.blocks.getScripts(); for (var j = 0; j < scripts.length; j++) { From 3b3daf8aca77530823036a37fb45ca94755cf38d Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Tue, 14 Feb 2017 16:33:42 -0800 Subject: [PATCH 3/3] Add hat execution order test --- test/fixtures/hat-execution-order.sb2 | Bin 0 -> 4547 bytes test/integration/hat-execution-order.js | 39 ++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 test/fixtures/hat-execution-order.sb2 create mode 100644 test/integration/hat-execution-order.js diff --git a/test/fixtures/hat-execution-order.sb2 b/test/fixtures/hat-execution-order.sb2 new file mode 100644 index 0000000000000000000000000000000000000000..f9a7efdcc1583a0df68400c77cb46467fccf8841 GIT binary patch literal 4547 zcmeI0X;>528pnr(#1IIg$Rdkj-y2aj(NI9yLIlFDUJwFdUlJgK@W@((f(QjE)wW1M zx$FocDQXH_30{`UzAFkC4MqtjA*j{rorw2hxz6iCH{$C0C#ynM-bO?M>6r=0GrlBHPW zjD@Tgn;!`=#+|7=Z$?UND{3?_y{bcqy?3oA6>X`JIwqMFWxZ#|x2jfHI@96>PwA^N z7dxBF=tln>=9ucFvcWfbGDo70LK&m#Ra+&Dt^M)UTupP7|&9XW50N1H}!; z$|*28LThNqm$gKHOEj%4;$lLjLK3FcD(93dyOL_fN$ekWtXgIwWmc-=3Qf<^o3E3x z3C|W^JkF}e*Zbiazp;?AOfRD7_wc80u1U+~PU`MFaJjWL`ssDgf@zO>_Nl6Pqg}aV zn^C#wx#{Z=UvUGzl|4hENGCtm65o|k>Dm*@W+kSFZF^;qrxnqLrlkeB&wE6Xa!~=| z_(dwlMQ~}Epvv4%l~Da*#%MUcPLm_GRG1!)oc6`oJ`_y5g>oUg2nr)B;?H^anhK5- z!5z|nGtfD>Vt5I6tAc?~?!#LCXe7lb{%vu1K)CpYar2aCukmBtC7#69Dd_E6kdb}eDjC?gqmVsA#my2$>8#+{ z$Cn+l`|aMWaNN!wg5KjRbsrrs{^^ibI?;`%=k4=$PR+IZie;$1yRG3e!#wXQSwA8kL1kdFvz}z%*W$JZ(xGjW0gWX2EX?R}qWPWb?-=HX zD9}MCB=zTu<{X6^HLOlE4p(o|(MMDQK1KQjX@DFeA1If;{{M z_YIbRH5<8Fu}Zt&RlgN3c0u+V&ojJ8;+5k}w^IwAu++CwhkaPxKHFrUPFzpAqGS}4 zN_|XbmA@M?k0_R6oo}Bn%_R+Io*p=3)&NLCQ0Z_QGttB>dZtbOf`n_z9+}eWJxF*)-zFBgbz#jzh@#H@w{v(!6nEM5z<&y-zo`9@joE}`{@hpTbJQLH_;9h(xVh=v z{{s@sxThNpK_m-f&BrDXQV3Vg5#cy7}N05vZV-+&ZAB2tN> z;63926#C1SSk$tNyE0b&2aN@lI@vh5C)aPrpK-P&tfr{?QL}xw^*kT4q%~~sNK7WH zQ;@^~8@93@e`{}e)$fIxXF2E1TNh^+Bue+&_*3Fr6DvZeY(wN6nUSqYMfcMqvSP~e zdsN>n7$*BZNMxp(#nd>_lxkQmZFwcooUlTdM!~d?1b`*@EtBQKyqu95F}$PQA(v?9 zPF{FubyZM^eODnNsx*HmFt8TO?4mGV-?n<)kaqV-BuuMj?UX4zq zx1(vE?e*hyfu4MZk-$3B%3!yIv^TG8yroOfLGAzXVG<-sCC4<&a%A6rjV^c*OK~8p z1JNln==vlAk)o-xA7S0PuSDG)zI)MYQ12G|*0Et28@HucZPH{2`^>~q{g{|NM{z2l zAJrc`L1s5Yigp_5oiwb~$11NNNc@iZw#n6r`Ug_WcSLlhebCkF4(K}RD^NE+73vudO7O#(8 z!peLyxBTkm7z82iC{?s=TGC8xCnWK8>1xT!tYGpL`dz;0cL+ITF2Ylk_?CbdfgpiD z|4{)hpO21@e_O0qetKKAUX}+sgZG=PjU^j>$9l;{#0M9$v1FqUSTC^_```*TmTc6? ddWnamaA2Tn2zZ!qp9jha2Eaj|P$iTN@Gm;r?+O3_ literal 0 HcmV?d00001 diff --git a/test/integration/hat-execution-order.js b/test/integration/hat-execution-order.js new file mode 100644 index 00000000000..0a302624bbd --- /dev/null +++ b/test/integration/hat-execution-order.js @@ -0,0 +1,39 @@ +var path = require('path'); +var test = require('tap').test; +var extract = require('../fixtures/extract'); +var VirtualMachine = require('../../src/index'); + +var projectUri = path.resolve(__dirname, '../fixtures/hat-execution-order.sb2'); +var project = extract(projectUri); + +test('complex', function (t) { + var vm = new VirtualMachine(); + + // Evaluate playground data and exit + vm.on('playgroundData', function (e) { + var threads = JSON.parse(e.threads); + t.ok(threads.length === 0); + + var results = vm.runtime.targets[0].lists.results.contents; + t.deepEqual(results, ['3', '2', '1', 'stage']); + + t.end(); + process.nextTick(process.exit); + }); + + // Start VM, load project, and run + t.doesNotThrow(function () { + vm.start(); + vm.clear(); + vm.setCompatibilityMode(false); + vm.setTurboMode(false); + vm.loadProject(project); + vm.greenFlag(); + }); + + // After two seconds, get playground data and stop + setTimeout(function () { + vm.getPlaygroundData(); + vm.stopAll(); + }, 2000); +});