From 3bfd755e6005fcf528a544548e517dce6122c8b0 Mon Sep 17 00:00:00 2001
From: Tim Mickel <tim.mickel@gmail.com>
Date: Thu, 13 Oct 2016 23:00:46 -0400
Subject: [PATCH] Complete implementation of stop block (#271)

* "Other scripts in stage" sb2

* Complete implementation of "stop" block
---
 src/blocks/scratch3_control.js | 13 ++++++++++---
 src/engine/execute.js          |  9 +++++++++
 src/engine/runtime.js          |  9 ++++++++-
 src/import/sb2import.js        |  3 ++-
 4 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/src/blocks/scratch3_control.js b/src/blocks/scratch3_control.js
index eab6c1a0f..efa0c2fb6 100644
--- a/src/blocks/scratch3_control.js
+++ b/src/blocks/scratch3_control.js
@@ -133,9 +133,16 @@ Scratch3ControlBlocks.prototype.ifElse = function(args, util) {
     }
 };
 
-Scratch3ControlBlocks.prototype.stop = function() {
-    // @todo - don't use this.runtime
-    this.runtime.stopAll();
+Scratch3ControlBlocks.prototype.stop = function(args, util) {
+    var option = args.STOP_OPTION;
+    if (option == 'all') {
+        util.stopAll();
+    } else if (option == 'other scripts in sprite' ||
+        option == 'other scripts in stage') {
+        util.stopOtherTargetThreads();
+    } else if (option == 'this script') {
+        util.stopThread();
+    }
 };
 
 // @todo (GH-146): remove.
diff --git a/src/engine/execute.js b/src/engine/execute.js
index f51c0acaa..c857b73d7 100644
--- a/src/engine/execute.js
+++ b/src/engine/execute.js
@@ -176,6 +176,15 @@ var execute = function (sequencer, thread) {
         startBranch: function (branchNum) {
             sequencer.stepToBranch(thread, branchNum);
         },
+        stopAll: function () {
+            runtime.stopAll();
+        },
+        stopOtherTargetThreads: function() {
+            runtime.stopForTarget(target, thread);
+        },
+        stopThread: function() {
+            sequencer.retireThread(thread);
+        },
         startProcedure: function (procedureName) {
             sequencer.stepToProcedure(thread, procedureName);
         },
diff --git a/src/engine/runtime.js b/src/engine/runtime.js
index f78424109..4a101147d 100644
--- a/src/engine/runtime.js
+++ b/src/engine/runtime.js
@@ -246,6 +246,9 @@ Runtime.prototype._pushThread = function (id, target) {
  * @param {?Thread} thread Thread object to remove from actives
  */
 Runtime.prototype._removeThread = function (thread) {
+    // Inform sequencer to stop executing that thread.
+    this.sequencer.retireThread(thread);
+    // Remove from the list.
     var i = this.threads.indexOf(thread);
     if (i > -1) {
         this.threads.splice(i, 1);
@@ -382,10 +385,14 @@ Runtime.prototype.disposeTarget = function (target) {
 /**
  * Stop any threads acting on the target.
  * @param {!Target} target Target to stop threads for.
+ * @param {Thread=} opt_threadException Optional thread to skip.
  */
-Runtime.prototype.stopForTarget = function (target) {
+Runtime.prototype.stopForTarget = function (target, opt_threadException) {
     // Stop any threads on the target.
     for (var i = 0; i < this.threads.length; i++) {
+        if (this.threads[i] === opt_threadException) {
+            continue;
+        }
         if (this.threads[i].target == target) {
             this._removeThread(this.threads[i]);
         }
diff --git a/src/import/sb2import.js b/src/import/sb2import.js
index 752e39298..b052a4ee9 100644
--- a/src/import/sb2import.js
+++ b/src/import/sb2import.js
@@ -369,7 +369,8 @@ function parseBlock (sb2block) {
     if (oldOpcode == 'stopScripts') {
         // Mutation for stop block: if the argument is 'other scripts',
         // the block needs a next connection.
-        if (sb2block[1] == 'other scripts in sprite') {
+        if (sb2block[1] == 'other scripts in sprite' ||
+            sb2block[1] == 'other scripts in stage') {
             activeBlock.mutation = {
                 tagName: 'mutation',
                 hasnext: 'true',