This issue tracks discovered strictExecutionOrder correctness bugs and architecture problems.
Bugs
onDemandWrapping does not account for top-level import-binding reads, so a pure-looking module can be moved across a mutation and capture the wrong live export value.
state.js export let n = 0; export function inc() { n++ }
mutate.js import { inc } from './state'; inc()
snap.js import { n } from './state'; export const snap = n
main.js import './mutate'; import { snap } from './snap' => snap must be 1
other.js import { snap } from './snap' => snap must be 0
- The current
ExecutionOrderSensitive check mostly asks whether a statement itself can do something observable, but misses reads whose observed value depends on earlier module execution.
earlier module evaluation changes exported binding
|
v
top-level import binding read observes a different value
Architecture Problems
StmtEvalAnalyzer short-circuits once it finds a tree-shaking side effect, so it cannot also be used as a complete collector of order facts.
statement: callWithSideEffect(); read(importedBinding)
current side-effect analysis:
callWithSideEffect() => stop
read(importedBinding) => never recorded
strictExecutionOrder + onDemandWrapping starts from wrapping almost everything and then tries to unwrap, instead of deriving wrapping obligations from execution-order-sensitive facts and graph dependencies.
current: wrap broadly -> optimize away wrappers -> correctness depends on exceptions
wanted: collect order facts -> propagate obligations -> wrap only required modules
This issue tracks discovered
strictExecutionOrdercorrectness bugs and architecture problems.Bugs
onDemandWrappingdoes not account for top-level import-binding reads, so a pure-looking module can be moved across a mutation and capture the wrong live export value.state.js export let n = 0; export function inc() { n++ } mutate.js import { inc } from './state'; inc() snap.js import { n } from './state'; export const snap = n main.js import './mutate'; import { snap } from './snap' => snap must be 1 other.js import { snap } from './snap' => snap must be 0ExecutionOrderSensitivecheck mostly asks whether a statement itself can do something observable, but misses reads whose observed value depends on earlier module execution.earlier module evaluation changes exported binding | v top-level import binding read observes a different valueArchitecture Problems
StmtEvalAnalyzershort-circuits once it finds a tree-shaking side effect, so it cannot also be used as a complete collector of order facts.strictExecutionOrder + onDemandWrappingstarts from wrapping almost everything and then tries to unwrap, instead of deriving wrapping obligations from execution-order-sensitive facts and graph dependencies.