Open FurryR opened 9 months ago
I also noticed that there is an error in execute
function:
in
src/engine/execute.js
::handlePromise
, L516
if (isPromise(primitiveReportedValue)) {
handlePromise(primitiveReportedValue, sequencer, thread, opCached, lastOperation);
// Store the already reported values. They will be thawed into the
// future versions of the same operations by block id. The reporting
// operation if it is promise waiting will set its parent value at
// that time.
thread.justReported = null;
currentStackFrame.reporting = ops[i].id;
currentStackFrame.reported = ops.slice(0, i).map(reportedCached => {
const inputName = reportedCached._parentKey;
const reportedValues = reportedCached._parentValues;
if (inputName === 'BROADCAST_INPUT') {
return {
opCached: reportedCached.id,
inputValue: reportedValues[inputName].BROADCAST_OPTION.name
};
}
return {
opCached: reportedCached.id,
inputValue: reportedValues[inputName]
};
});
// We are waiting for a promise. Stop running this set of operations
// and continue them later after thawing the reported values.
break;
}
The result will be discarded if callback is already executed before thread.justReported = null;
.
I believe this is intentional. The threads are currently stepped in a specific order, and I'm not sure about the side effects of stepping threads "out of order". Even though promises can resolve at any point, their threads will be stepped in the original execution order.
In fact, one of my refactorings is to move all control flow handling out of the promise handler so that only Sequencer#stepThreads
does so.
I believe this is intentional. The threads are currently stepped in a specific order, and I'm not sure about the side effects of stepping threads "out of order". Even though promises can resolve at any point, their threads will be stepped in the original execution order.
so I made some experiments about executing the thread "out of order" (see https://github.com/FurryR/lpp-scratch/blob/main/src/impl/thread/helper.ts#L34) like synchronous one. It works pretty fine. Seems that everything will be fine if you just restore util.thread
after stepping the thread.
My point is, if an extension returns a synchronous value, it resumes immediately instead of yielding. Stepping the thread immediately after promise resolving makes blocks returning promise acts like synchronous and I think it is less confused. Thread execution order does not matter since Scratch users aren't required to learn about that, and few projects (FPS detection based on Promise and Turbowarp compiler detection based on reporter side-effect, both of them are cursed) are dependent on it.
Feature
In current implementation, we usually need at least 2 frames to handle a promise (that is returning from
blockFunction()
):However if we resume the thread on
then
handler, it will cost only 1 frame to do so:It is possible by stepping the thread immediately on
handlePromise()
: