You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Scala.js: Support js.async and js.await, including JSPI on Wasm.
This is forward port of the compiler changes in the two commits of
the Scala.js PR scala-js/scala-js#5130
---
We add support for a new pair of primitive methods, `js.async` and
`js.await`. They correspond to JavaScript `async` functions and
`await` expressions.
`js.await(p)` awaits a `Promise`, but it must be directly scoped
within a `js.async { ... }` block.
At the IR level, `js.await(p)` directly translates to a dedicated
IR node `JSAwait(arg)`. `js.async` blocks don't have a direct
representation. Instead, the IR models `async function`s and
`async =>`functions, as `Closure`s with an additionnal `async`
flag. This corresponds to the JavaScript model for `async/await`.
A `js.async { body }` block therefore corresponds to an
immediately-applied `async Closure`, which in JavaScript would be
written as `(async () => body)()`.
---
We then optionally allow orphan `js.await(p)` on WebAssembly.
With the JavaScript Promise Integration (JSPI), there can be as
many frames as we want between a `WebAssembly.promising` function
and the corresponding `WebAssembly.Suspending` calls. The former
is introduced by our `js.async` blocks, and the latter by calls to
`js.await`.
Normally, `js.await` must be directly enclosed within a `js.async`
block. This ensures that it can be compiled to a JavaScript `async`
function and `await` expression.
We introduce a sort of "language import" to allow "orphan awaits".
This way, we can decouple the `js.await` calls from their
`js.async` blocks. The generated IR will then only link when
targeting WebAssembly. Technically, `js.await` requires an
implicit `js.AwaitPermit`. The default one only allows `js.await`
directly inside `js.async`, and we can import a stronger one that
allows orphan awaits.
There must still be a `js.async` block *dynamically* enclosing any
`js.await` call (on the call stack), without intervening JS frame.
If that dynamic property is not satisfied, a
`WebAssembly.SuspendError` gets thrown. This last point is not yet
implemented in Node.js at the time of this commit; instead such a
situation traps. The corresponding test is therefore currently
ignored.
---
Since these features fundamentally depend on a) the target ES
version and b) the WebAssembly backend, we add more configurations
of Scala.js to the Scala 3 CI.
0 commit comments