diff --git a/src/engine/execute.js b/src/engine/execute.js
index a4bf76b2a..e0da40cc2 100644
--- a/src/engine/execute.js
+++ b/src/engine/execute.js
@@ -11,6 +11,62 @@ const isPromise = function (value) {
     return value && value.then && typeof value.then === 'function';
 };
 
+/**
+ * Handle any reported value from the primitive, either directly returned
+ * or after a promise resolves.
+ * @param {*} resolvedValue Value eventually returned from the primitive.
+ * @param {!Sequencer} sequencer Sequencer stepping the thread for the ran
+ * primitive.
+ * @param {!Thread} thread Thread containing the primitive.
+ * @param {!string} currentBlockId Id of the block in its thread for value from
+ * the primitive.
+ * @param {!boolean} isHat Is the current block a hat?
+ */
+// @todo move this to callback attached to the thread when we have performance
+// metrics (dd)
+const handleReport = function (
+    resolvedValue, sequencer, thread, currentBlockId, isHat) {
+    thread.pushReportedValue(resolvedValue);
+    if (isHat) {
+        // Hat predicate was evaluated.
+        if (sequencer.runtime.getIsEdgeActivatedHat(opcode)) {
+            // If this is an edge-activated hat, only proceed if the value is
+            // true and used to be false, or the stack was activated explicitly
+            // via stack click
+            if (!thread.stackClick) {
+                const oldEdgeValue = sequencer.runtime.updateEdgeActivatedValue(
+                    currentBlockId,
+                    resolvedValue
+                );
+                const edgeWasActivated = !oldEdgeValue && resolvedValue;
+                if (!edgeWasActivated) {
+                    sequencer.retireThread(thread);
+                }
+            }
+        } else if (!resolvedValue) {
+            // Not an edge-activated hat: retire the thread
+            // if predicate was false.
+            sequencer.retireThread(thread);
+        }
+    } else {
+        // In a non-hat, report the value visually if necessary if
+        // at the top of the thread stack.
+        if (typeof resolvedValue !== 'undefined' && thread.atStackTop()) {
+            if (thread.stackClick) {
+                sequencer.runtime.visualReport(currentBlockId, resolvedValue);
+            }
+            if (thread.updateMonitor) {
+                sequencer.runtime.requestUpdateMonitor(Map({
+                    id: currentBlockId,
+                    value: String(resolvedValue)
+                }));
+            }
+        }
+        // Finished any yields.
+        thread.status = Thread.STATUS_RUNNING;
+    }
+};
+
 /**
  * Execute a block.
  * @param {!Sequencer} sequencer Which sequencer is executing.
@@ -61,55 +117,6 @@ const execute = function (sequencer, thread) {
         return;
     }
 
-    /**
-     * Handle any reported value from the primitive, either directly returned
-     * or after a promise resolves.
-     * @param {*} resolvedValue Value eventually returned from the primitive.
-     */
-    // @todo move this to callback attached to the thread when we have performance
-    // metrics (dd)
-    const handleReport = function (resolvedValue) {
-        thread.pushReportedValue(resolvedValue);
-        if (isHat) {
-            // Hat predicate was evaluated.
-            if (runtime.getIsEdgeActivatedHat(opcode)) {
-                // If this is an edge-activated hat, only proceed if
-                // the value is true and used to be false, or the stack was activated
-                // explicitly via stack click
-                if (!thread.stackClick) {
-                    const oldEdgeValue = runtime.updateEdgeActivatedValue(
-                        currentBlockId,
-                        resolvedValue
-                    );
-                    const edgeWasActivated = !oldEdgeValue && resolvedValue;
-                    if (!edgeWasActivated) {
-                        sequencer.retireThread(thread);
-                    }
-                }
-            } else if (!resolvedValue) {
-                // Not an edge-activated hat: retire the thread
-                // if predicate was false.
-                sequencer.retireThread(thread);
-            }
-        } else {
-            // In a non-hat, report the value visually if necessary if
-            // at the top of the thread stack.
-            if (typeof resolvedValue !== 'undefined' && thread.atStackTop()) {
-                if (thread.stackClick) {
-                    runtime.visualReport(currentBlockId, resolvedValue);
-                }
-                if (thread.updateMonitor) {
-                    runtime.requestUpdateMonitor(Map({
-                        id: currentBlockId,
-                        value: String(resolvedValue)
-                    }));
-                }
-            }
-            // Finished any yields.
-            thread.status = Thread.STATUS_RUNNING;
-        }
-    };
-
     // Hats and single-field shadows are implemented slightly differently
     // from regular blocks.
     // For hats: if they have an associated block function,
@@ -124,7 +131,7 @@ const execute = function (sequencer, thread) {
         const keys = Object.keys(fields);
         if (keys.length === 1 && Object.keys(inputs).length === 0) {
             // One field and no inputs - treat as arg.
-            handleReport(fields[keys[0]].value);
+            handleReport(fields[keys[0]].value, sequencer, thread, currentBlockId, isHat);
         } else {
             log.warn(`Could not get implementation for opcode: ${opcode}`);
         }
@@ -244,7 +251,7 @@ const execute = function (sequencer, thread) {
         }
         // Promise handlers
         primitiveReportedValue.then(resolvedValue => {
-            handleReport(resolvedValue);
+            handleReport(resolvedValue, sequencer, thread, currentBlockId, isHat);
             if (typeof resolvedValue === 'undefined') {
                 let stackFrame;
                 let nextBlockId;
@@ -277,7 +284,7 @@ const execute = function (sequencer, thread) {
             thread.popStack();
         });
     } else if (thread.status === Thread.STATUS_RUNNING) {
-        handleReport(primitiveReportedValue);
+        handleReport(primitiveReportedValue, sequencer, thread, currentBlockId, isHat);
     }
 };