Scratch-vm: The queueing of questions works differently from 2.0

Created on 13 Nov 2017  路  7Comments  路  Source: LLK/scratch-vm

Steps to Reproduce

  • Drag 3 'ask and wait' blocks to the workspace. Put 'answer' or 'timer' in the text field.
  • Click on all 3
    image
    Behavior in 2.0: The question is nothing, then your first answer, then your second answer
    Behavior in 3.0: The question is nothing all 3 times
    If you use timer, 3.0 uses time when you started the block, 2.0 uses time when it ran.
    You can also do this across sprites (if 2 sprites want to ask questions at the same time)

Operating System and Browser

Windows 10 Chrome

bug compatibility needs-triage

All 7 comments

I'll work on this.

I think I see the problem. Basically, whenever multiple question blocks are run at the same time, they get put on the queue. The queue stores the stingified question text.

Problem is, it stores the stringified text _at the time it was called_. Instead, we should store the argument to the block on the queue, and only cast it to string at the last minute.

I'll make a repo, and once I have this issue fixed, I'll make a pull request.

The relevant file is https://github.com/LLK/scratch-vm/blob/develop/src/blocks/scratch3_sensing.js, with the relevant code being around line 70 or so.

It turns out, we'd need to make somewhat major changes to make this work. Maybe we could make the ask block yield if a question is being asked?

Good repro project for this: https://scratch.mit.edu/projects/227391651

From what I can tell, this issue (both the original example and my repro project with the timer block) stems from differences in how 3.0 and 2.0 (and 1.4, which shares 2.0 behavior) queues up evaluation for ask and wait blocks. In 3.0, when two ask blocks are queued in different threads they immediately evaluate their inputs before waiting (relevant: execute.js lines 336-347, scratch3_sensing.js lines 138-147). In 2.0 and 1.x, ask and wait blocks appear to wait before evaluating their inputs.

I think this might be related to tmickel's comments at https://github.com/LLK/scratch-vm/issues/591

He mentions that the issue has come up before, in repeat blocks and in wait blocks (and potentially here now). We have always worked around the problem to avoid refactor, but the "underlying problem" is, currently in Scratch 3.0, input blocks are resolved and then the resulting value is passed to the parent block (no parent block code runs until the inputs are already evaluated). For instance, the issue with https://github.com/LLK/scratch-vm/pull/593/files was that wait was called every tick with a different args.DURATION. This could be solved by letting the parent block decide when its input blocks are evaluated, which would be a large VM change. From Tim:

...
"in the Scratch 2.0 interpreter, handling this was simplified because block implementations do "their own deciding" about when their inputs are evaluated. It's possible that the nicest solution could be to refactor the 3.0 interpreter to work similarly, it's a different abstraction (in 3.0 thus far, to the block implementation inputs are "ready-to-go" and evaluated at the start).
...
"could be worth trying :) also might have performance benefits. the original reason for this way was having a good API for Scratch extensions (which maybe shouldn't have to evaluate their own inputs) and have the default blocks use the same API. But maybe something could satisfy everything..."

(More relevant discussion in the linked issue)

Tough problem :) Another option for this particular case could be to create some kind of lock around all blocks of one type, so that you never enter into an ask-and-wait block until others complete (instead of enqueueing the ask blocks in Scratch3SensingBlocks).

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rasmushaglund picture rasmushaglund  路  4Comments

kchadha picture kchadha  路  6Comments

CatsAreFluffy picture CatsAreFluffy  路  6Comments

Micircle picture Micircle  路  5Comments

cwillisf picture cwillisf  路  4Comments