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

Why "intentional break" the behaviour of getting content of list? #83

Closed 9-2-1 closed 2 years ago

9-2-1 commented 2 years ago

In compiler/jsexecute.js, line 501

/**
 * Get the stringified form of a list.
 * @param {import('../engine/variable')} list The list.
 * @returns {string} Stringified form of the list.
 */
runtimeFunctions.listContents = `const listContents = list => {
    for (let i = 0; i < list.value.length; i++) {
        const listItem = list.value[i];
        // this is an intentional break from what scratch 3 does to address our automatic string -> number conversions
        // it fixes more than it breaks
        if ((listItem + '').length !== 1) {
            return list.value.join(' ');
        }
    }
    return list.value.join('');
}`;

Could anyone tell me why there is an "intentional break"?

What will happen if I change it to:

        if (typeof listItem !== "string" || (listItem + '').length !== 1) {

It seems that this change was introduced in commit 20a60d8e1cdb184f988fd01e7ecc88ca8fc98565

GarboMuffin commented 2 years ago

The problem is scripts like this:

image

Scratch won't convert 1, 2, 3, etc. to numbers, so the list will contain three strings. In TurboWarp it will instead contain three numbers as the compiler will eagerly convert strings to numbers when it's probably safe, which usually improves performance significantly.

In Scratch that script outputs "123", but because of the automatic number conversion, it would instead output "1 2 3" if we used the same logic as Scratch because typeof listItem === 'string' is not true anymore. The fix was to remove the string type check. This has been found to fix a lot of projects. It breaks projects that do things like "add (1 + 2) to list", but that is much more rare and easier to work around.

9-2-1 commented 2 years ago

Thank you very much.

Is here anyway to disable complier by using comments in the project?

(Maybe you want to say "eagerly convert strings to numbers")

(One of my favourite scratch community use a modified version of TurboWarp's vm and my project went wrong here unfortunately because my project depends on the default behaviour, and I can't disable complier in player mode.)

GarboMuffin commented 2 years ago

(Maybe you want to say "eagerly convert strings to numbers")

My bad, yes

Is here anyway to disable complier by using comments in the project?

You have some options:

9-2-1 commented 2 years ago

Thank you very much.