-
Notifications
You must be signed in to change notification settings - Fork 398
Description
This is a bit experimental and I'm not sure I fully understand the -Xasync FSM code generation, but while it works for Option and Future (via the tests) invalid code seems to be generated for scala.js+js.Promise because it is assumed you can extract the value out. A couple of notes from retronym on scala/contributors made me think this might work but I'm not sure it does under scala.js or any effect that cannot be queried.
Here's a repo with the code https://github.com/aappddeevv/scalajs-promise-async. The issue is that even for the simplest case (sbt tests/testOnly ttg.scalajs.async.SmokeTest
) the code generated would never work even if my implementation is wrong.
We can't extract a value directly from a js.Promise so the impl must always work with js.Promise
. However, the code generated in case 3
is clearly doing a cast via $uI
which will always fail.
It's highly likely the problem is my code, but at first blush it seems like this won't ever work for js.Promise.
// code for adding 3 Int js.Promises together.
class $c_Lttg_scalajs_async_SmokeTest$stateMachine$async$1 extends $c_Lttg_scalajs_async_PromiseStateMachine {
constructor() {
super();
this.Lttg_scalajs_async_SmokeTest$stateMachine$async$1__f_result1 = 0;
this.Lttg_scalajs_async_SmokeTest$stateMachine$async$1__f_result2 = 0;
$ct_Lttg_scalajs_async_PromiseStateMachine__(this)
};
apply__sjs_js_Thenable__V(tr$async) {
while (true) {
try {
switch (this.Lttg_scalajs_async_PromiseStateMachine__f_state$async) {
case 0: {
const awaitable$async = Promise.resolve(1);
tr$async = this.getCompleted__sjs_js_Promise__sjs_js_Promise(awaitable$async);
this.Lttg_scalajs_async_PromiseStateMachine__f_state$async = 1;
if ((tr$async !== null)) {
/*<skip>*/
} else {
this.onComplete__sjs_js_Thenable__V(awaitable$async);
return (void 0)
};
break
}
case 1: {
const tryGetResult$async = this.tryGet__sjs_js_Promise__O(tr$async);
if ((this === tryGetResult$async)) {
return (void 0)
};
this.Lttg_scalajs_async_SmokeTest$stateMachine$async$1__f_result1 = $uI(tryGetResult$async);
const awaitable$async$2 = Promise.resolve(2);
tr$async = this.getCompleted__sjs_js_Promise__sjs_js_Promise(awaitable$async$2);
this.Lttg_scalajs_async_PromiseStateMachine__f_state$async = 2;
if ((tr$async !== null)) {
/*<skip>*/
} else {
this.onComplete__sjs_js_Thenable__V(awaitable$async$2);
return (void 0)
};
break
}
case 2: {
const tryGetResult$async$2 = this.tryGet__sjs_js_Promise__O(tr$async);
if ((this === tryGetResult$async$2)) {
return (void 0)
};
this.Lttg_scalajs_async_SmokeTest$stateMachine$async$1__f_result2 = $uI(tryGetResult$async$2);
const awaitable$async$3 = Promise.resolve(3);
tr$async = this.getCompleted__sjs_js_Promise__sjs_js_Promise(awaitable$async$3);
this.Lttg_scalajs_async_PromiseStateMachine__f_state$async = 3;
if ((tr$async !== null)) {
/*<skip>*/
} else {
this.onComplete__sjs_js_Thenable__V(awaitable$async$3);
return (void 0)
};
break
}
case 3: {
const tryGetResult$async$3 = this.tryGet__sjs_js_Promise__O(tr$async);
if ((this === tryGetResult$async$3)) {
return (void 0)
};
$uI(tryGetResult$async$3);
this.completeSuccess__O__V(((this.Lttg_scalajs_async_SmokeTest$stateMachine$async$1__f_result1 + this.Lttg_scalajs_async_SmokeTest$stateMachine$async$1__f_result2) | 0));
return (void 0);
break
}
default: {
const i = this.Lttg_scalajs_async_PromiseStateMachine__f_state$async;
throw $ct_jl_IllegalStateException__T__(new $c_jl_IllegalStateException(), ("" + i))
}
}
} catch (e) {
const e$2 = $m_sjsr_package$().wrapJavaScriptException__O__jl_Throwable(e);
this.completeFailure__jl_Throwable__V(e$2);
return (void 0)
}
}
};
apply__O__O(v1) {
this.apply__sjs_js_Thenable__V(v1)
};
}