@@ -3,6 +3,7 @@ const {OrderedMap} = require('immutable');
33
44const ArgumentType = require ( '../extension-support/argument-type' ) ;
55const Blocks = require ( './blocks' ) ;
6+ const BlocksRuntimeCache = require ( './blocks-runtime-cache' ) ;
67const BlockType = require ( '../extension-support/block-type' ) ;
78const Profiler = require ( './profiler' ) ;
89const Sequencer = require ( './sequencer' ) ;
@@ -1434,16 +1435,11 @@ class Runtime extends EventEmitter {
14341435 * @return {!Thread } The newly created thread.
14351436 */
14361437 _pushThread ( id , target , opts ) {
1437- opts = Object . assign ( {
1438- stackClick : false ,
1439- updateMonitor : false
1440- } , opts ) ;
1441-
14421438 const thread = new Thread ( id ) ;
14431439 thread . target = target ;
1444- thread . stackClick = opts . stackClick ;
1445- thread . updateMonitor = opts . updateMonitor ;
1446- thread . blockContainer = opts . updateMonitor ?
1440+ thread . stackClick = Boolean ( opts && opts . stackClick ) ;
1441+ thread . updateMonitor = Boolean ( opts && opts . updateMonitor ) ;
1442+ thread . blockContainer = thread . updateMonitor ?
14471443 this . monitorBlocks :
14481444 target . blocks ;
14491445
@@ -1586,6 +1582,20 @@ class Runtime extends EventEmitter {
15861582 }
15871583 }
15881584
1585+ allScriptsByOpcodeDo ( opcode , f , optTarget ) {
1586+ let targets = this . executableTargets ;
1587+ if ( optTarget ) {
1588+ targets = [ optTarget ] ;
1589+ }
1590+ for ( let t = targets . length - 1 ; t >= 0 ; t -- ) {
1591+ const target = targets [ t ] ;
1592+ const scripts = BlocksRuntimeCache . getScripts ( target . blocks , opcode ) ;
1593+ for ( let j = 0 ; j < scripts . length ; j ++ ) {
1594+ f ( scripts [ j ] , target ) ;
1595+ }
1596+ }
1597+ }
1598+
15891599 /**
15901600 * Start all relevant hats.
15911601 * @param {!string } requestedHatOpcode Opcode of hats to start.
@@ -1610,71 +1620,52 @@ class Runtime extends EventEmitter {
16101620 }
16111621
16121622 // Consider all scripts, looking for hats with opcode `requestedHatOpcode`.
1613- this . allScriptsDo ( ( topBlockId , target ) => {
1614- const blocks = target . blocks ;
1615- const block = blocks . getBlock ( topBlockId ) ;
1616- const potentialHatOpcode = block . opcode ;
1617- if ( potentialHatOpcode !== requestedHatOpcode ) {
1618- // Not the right hat.
1619- return ;
1620- }
1623+ this . allScriptsByOpcodeDo ( requestedHatOpcode , ( script , target ) => {
1624+ const {
1625+ blockId : topBlockId ,
1626+ fieldsOfInputs : hatFields
1627+ } = script ;
16211628
16221629 // Match any requested fields.
16231630 // For example: ensures that broadcasts match.
16241631 // This needs to happen before the block is evaluated
16251632 // (i.e., before the predicate can be run) because "broadcast and wait"
16261633 // needs to have a precise collection of started threads.
1627- let hatFields = blocks . getFields ( block ) ;
1628-
1629- // If no fields are present, check inputs (horizontal blocks)
1630- if ( Object . keys ( hatFields ) . length === 0 ) {
1631- hatFields = { } ; // don't overwrite the block's actual fields list
1632- const hatInputs = blocks . getInputs ( block ) ;
1633- for ( const input in hatInputs ) {
1634- if ( ! hatInputs . hasOwnProperty ( input ) ) continue ;
1635- const id = hatInputs [ input ] . block ;
1636- const inpBlock = blocks . getBlock ( id ) ;
1637- const fields = blocks . getFields ( inpBlock ) ;
1638- Object . assign ( hatFields , fields ) ;
1639- }
1640- }
1641-
1642- if ( optMatchFields ) {
1643- for ( const matchField in optMatchFields ) {
1644- if ( hatFields [ matchField ] . value . toUpperCase ( ) !==
1645- optMatchFields [ matchField ] ) {
1646- // Field mismatch.
1647- return ;
1648- }
1634+ for ( const matchField in optMatchFields ) {
1635+ if ( hatFields [ matchField ] . value !== optMatchFields [ matchField ] ) {
1636+ // Field mismatch.
1637+ return ;
16491638 }
16501639 }
16511640
16521641 if ( hatMeta . restartExistingThreads ) {
16531642 // If `restartExistingThreads` is true, we should stop
16541643 // any existing threads starting with the top block.
1655- for ( let i = 0 ; i < instance . threads . length ; i ++ ) {
1656- if ( instance . threads [ i ] . topBlock === topBlockId &&
1657- ! instance . threads [ i ] . stackClick && // stack click threads and hat threads can coexist
1658- instance . threads [ i ] . target === target ) {
1659- newThreads . push ( instance . _restartThread ( instance . threads [ i ] ) ) ;
1644+ for ( let i = 0 ; i < this . threads . length ; i ++ ) {
1645+ if ( this . threads [ i ] . target === target &&
1646+ this . threads [ i ] . topBlock === topBlockId &&
1647+ // stack click threads and hat threads can coexist
1648+ ! this . threads [ i ] . stackClick ) {
1649+ newThreads . push ( this . _restartThread ( this . threads [ i ] ) ) ;
16601650 return ;
16611651 }
16621652 }
16631653 } else {
16641654 // If `restartExistingThreads` is false, we should
16651655 // give up if any threads with the top block are running.
1666- for ( let j = 0 ; j < instance . threads . length ; j ++ ) {
1667- if ( instance . threads [ j ] . topBlock === topBlockId &&
1668- instance . threads [ j ] . target === target &&
1669- ! instance . threads [ j ] . stackClick && // stack click threads and hat threads can coexist
1670- instance . threads [ j ] . status !== Thread . STATUS_DONE ) {
1656+ for ( let j = 0 ; j < this . threads . length ; j ++ ) {
1657+ if ( this . threads [ j ] . target === target &&
1658+ this . threads [ j ] . topBlock === topBlockId &&
1659+ // stack click threads and hat threads can coexist
1660+ ! this . threads [ j ] . stackClick &&
1661+ this . threads [ j ] . status !== Thread . STATUS_DONE ) {
16711662 // Some thread is already running.
16721663 return ;
16731664 }
16741665 }
16751666 }
16761667 // Start the thread with this top block.
1677- newThreads . push ( instance . _pushThread ( topBlockId , target ) ) ;
1668+ newThreads . push ( this . _pushThread ( topBlockId , target ) ) ;
16781669 } , optTarget ) ;
16791670 // For compatibility with Scratch 2, edge triggered hats need to be processed before
16801671 // threads are stepped. See ScratchRuntime.as for original implementation
0 commit comments