Stringification is more likely to produce a helpful output than
JSON.stringify on error objects.
Old message:
Failed to refresh built-in extension primitives: {}
New message:
Failed to refresh built-in extension primitives: TypeError: Cannot destructure property 'provider' of ...
Also includes the appropriate can[Fetch|OpenWindow|Redirect] methods.
Fetching is always allowed. The other methods are always rejected.
The Worker-based sandbox does not have a window.open method and the
iframe-based sandbox has a feature policy that should prevent them from
opening windows already.
While this is not believed to cause security bugs as this is not
interpeted as HTML, the inconsistent/no escaping causes bugs such as:
https://github.com/TurboWarp/extensions/issues/241
To resolve this, we now fully escape (hopefully) every value from
extensions that makes its way into XML, so now the characters:
" ' < > &
can be used anywhere in extensions without issues, even opcodes,
argument names, field names, etc. Just not the extension ID.
Some parts of Scratch such as ExtensionManager._sanitizeID and
Runtime._convertPlaceholders tried to explicitly remove XML characters,
however the code was broken (they only removed the first occurrence) and
this seems like the wrong fix anyways. We can use XML characters, they just
need to be escaped.
Also includes a very comprehensive test.
The bug was that property keys that look like array indexes are always
enumerated by JS before other keys regardless of creation time. For now,
we will avoid using numbers when compressing projects.
This does negligibly increase the size of project.json.
Appel v1.4 went from 2257234 to 2260628 bytes, a 0.15% increase.
This is unfortunate. Ideally we would add some manual logic to follow
redirects ourselves, but it turns out fetch's redirect: 'manual' is
actually useless.
isWhiteSpace works by trimming the entire string. This works, but in the
context we use it, this is a lot of unnecessary work.
At this point we know that `+x === 0` and we want to know if that's
because x is empty or because it actually contains 0, hence we can use
a loop that just checks for a 0 existing in the string. This relies on
the assumption that there is no x such that:
+x === 0 && x.trim().length !== 0 && !x.includes('0')
In a very biased microbenchmark (https://scratch.mit.edu/projects/788352711)
this results in a 10% performance improvement.
This also will allow us to resolve https://github.com/TurboWarp/scratch-vm/issues/115
in a later commit.