There is a non-reentrancy requirement stated in Evaluate() as:
1. [Assert](https://tc39.es/ecma262/#assert): This call to Evaluate is not happening at the same time as another call to Evaluate within the [surrounding agent](https://tc39.es/ecma262/#surrounding-agent).
It is possible to violate this invariant with the current specification as written, by importing and evaluating a deferred module within the top-level evaluation of another module's execution.
For example:
main.mjs
import './dep.mjs';
console.log('main');
dep.mjs
import defer * as lazy from './lazy.mjs';
lazy.breakInvariant;
console.log('dep');
lazy.mjs
console.log('lazy');
The evaluation of main.mjs will result in lazy being executed between dep.mjs and main.mjs via a new top-level execution interleaved during the top-level execution of main, breaking the invariant of main being the only top-level execution.
We could:
Relax the invariant to allow for disjoint graph evaluations to more carefully distinguish partial evaluating graphs, then only throwing specifically for the case where we hit modules already in the evaluating phase/
Harden this invariant more explicitly by treating it as an explicit check with a real value.
I can try to work on a PR for a more relaxed invariant here if it would be useful.
There is a non-reentrancy requirement stated in
Evaluate()
as:It is possible to violate this invariant with the current specification as written, by importing and evaluating a deferred module within the top-level evaluation of another module's execution.
For example:
main.mjs
dep.mjs
lazy.mjs
The evaluation of
main.mjs
will result inlazy
being executed betweendep.mjs
andmain.mjs
via a new top-level execution interleaved during the top-level execution of main, breaking the invariant of main being the only top-level execution.We could:
I can try to work on a PR for a more relaxed invariant here if it would be useful.