TurboWarp / scratch-vm

Scratch VM with a JIT compiler and more features
https://turbowarp.org/
Mozilla Public License 2.0
75 stars 72 forks source link

fix promise rejection handling #207

Closed FurryR closed 5 months ago

FurryR commented 5 months ago

Resolves

N/A

Proposed Changes

Now waitPromise throws when promise rejected.

Reason for Changes

Already explained in Discord.

Test Coverage

Not ready yet.

FurryR commented 5 months ago

Extension for test unit:

class Test {
  getInfo() {
    return {
      id: 'test',
      name: 'test',
      blocks: [
        { blockType: 'command', opcode: 'test', arguments: {}, text: 'test' }
      ]
    };
  }
  async test() {
    throw new Error('test');
  }
}
Scratch.extensions.register(new Test());
GarboMuffin commented 5 months ago

This does not match interpreter behavior at all

image

Scratch.extensions.register({
    getInfo: () => ({
        id: 'test123',
        name: 'test123',
        blocks: [
            {
                blockType: Scratch.BlockType.COMMAND,
                opcode: 'thr',
                text: 'return rejected promise'
            }
        ]
    }),
    thr: () => Promise.reject(new Error('Test error'))
});

Interpreter handles rejected promise by popStack()ing and continuing (inside a loop it works like JS continue;)

Current compiler handles rejected promise by just continuing.

This PR handles rejected promise by making the sequencer throw an uncaught error, breaking execution script of threads after for 1 tick, and then the thread is permanently stuck in an error'd state where it is highlighted but not actually running until the user restarts it. This is not better.