Skip to content

Commit 5096af6

Browse files
committed
Add caveat section on promise execution order
1 parent 113bf30 commit 5096af6

File tree

1 file changed

+33
-0
lines changed

1 file changed

+33
-0
lines changed

Diff for: docs/caveats.md

+33
Original file line numberDiff line numberDiff line change
@@ -209,3 +209,36 @@ for (const featureClass of FEATURE_CLASSES) {
209209
```
210210

211211
Importatly, once we have a barrel file, we do not have to artificially split up the number of classes. This is because TSTL does not transpile exports with any local variables at all. Thus, we can have an unlimited number of exports inside of the barrel file without ever hitting the Lua local variable limit.
212+
213+
### Promises & Async/Await execution order
214+
215+
There is a very subtle difference in behaviour of promises and async/await (which is based on promises) between ECMAScript and TSTL's implementation. In the [ECMAScript specification](https://tc39.es/ecma262/#sec-triggerpromisereactions), resolving or rejecting of promises is deferred until any other user code has finished running. See the following example showing how this affects execution order:
216+
217+
```ts
218+
const p = new Promise((resolve) => {
219+
console.log("construct");
220+
resolve("done");
221+
});
222+
p.then((r) => console.log(r));
223+
console.log("after");
224+
```
225+
226+
ECMAScript JS output:
227+
228+
```
229+
promise construct
230+
after promise
231+
done <-- note that even though resolve was called synchronously after 'construct', it is deferred until after 'done'
232+
```
233+
234+
Due to technical constraints (TSTL does not implement [a task queue](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await#control_flow_effects_of_await) because it would be environment specific), TSTL promises will simply immediately resolve or reject promises as soon as the resolve or reject function is called. This means that for the above code, TSTL will instead produce:
235+
236+
TSTL output:
237+
238+
```
239+
construct
240+
done <-- promise already resolved during construction
241+
after
242+
```
243+
244+
In practice, this difference should rarely make any difference. TSTL's behaviour is consistent and predictable, and totally follows the Promise abstraction, aside from the ECMAScript 'implementation choice' to defer resolves/rejects. Still, it is a difference to keep in mind if you are comparing `tsc` vs `tstl` output runtime behaviour.

0 commit comments

Comments
 (0)