resolvedAwaitResults property
Results of the await sites already resolved while resuming the statement
currently in flight, keyed by the AwaitExpression node itself.
SCC40: resuming a statement means re-evaluating it from the top, so every
await it contains is visited again. With only lastAwaitResult to consult,
each of those visits returned the same value — so (await a) + (await b)
evaluated to 'AA', a silent wrong answer rather than a crash. Keying by
node lets an already-resolved site replay its own value while a site that
has not been reached yet still suspends properly.
Scoped to one evaluation of one statement: resumingStatementHasMoreAwaits says whether that evaluation is still in progress, and the state machine clears this map as soon as it is not. A loop body re-enters the identical AST node on every iteration, so a map that outlived the statement would replay the previous iteration's value.
Keyed by IDENTITY, deliberately. SAstNode overrides == with
equals(), which serializes both sides via toJson() and deep-diffs
them. Under a plain map every lookup here would run that deep diff on a
hot path — and two await sites whose entire subtrees serialize
identically (await next() written twice) would fuse into one entry,
which is precisely what this map exists to prevent. Identity keying costs
a pointer compare. Note the fusing half is reasoned, not test-pinned: see
test/runtime/scc40_per_await_site_resumption_test.dart for why the case
cannot be written today.
Implementation
final Map<SAstNode, Object?> resolvedAwaitResults =
Map<SAstNode, Object?>.identity();