Hidden Assumptions in rollup
13 assumptions this code never checks · 4 critical · spanning Shape, Ordering, Contract, Temporal, Resource, Domain, Scale, Environment
Every codebase relies on things it never checks. Most of them are routine. CodeSea looked at rollup/rollup and picked out the few most likely to cause trouble. The full list is just below.
Most of what this code assumes is routine. These 3 are the ones most likely to cause trouble here. The rest are minor; they're under "Show everything".
If the Rust parser changes its serialization format or the TypeScript deserializer misreads the buffer, nodes will be created with wrong types, corrupted positions, or malformed structures, causing silent AST corruption throughout the bundling process
If scope resolution fails (circular imports, temporal dead zones, complex destructuring), this.variable remains null but the code continues processing, leading to null pointer exceptions when the identifier is later used for tree-shaking or rendering
If plugins return inconsistent module IDs for the same import or return malformed objects instead of strings, the module cache becomes corrupted and the same module may be loaded multiple times with different IDs, breaking dependency analysis
Show everything (10 more)
The EntityPathTracker and DiscriminatedPathTracker instances created in HasEffectsContext remain valid for the entire tree-shaking analysis phase and aren't modified concurrently by other parts of the system
If this fails: If these trackers are mutated during analysis by parallel processing or plugin interference, the tree-shaking algorithm will make incorrect inclusion decisions, potentially including dead code or excluding live code
src/ast/ExecutionContext.ts:createHasEffectsContext
The Node.js event loop can handle the Rust async parsing tasks without blocking, and that system memory is sufficient to hold both the original source code string and the serialized AST buffer simultaneously
If this fails: For very large files, the system may run out of memory when both the input string and output buffer exist at the same time, or the event loop may be starved if too many parse tasks are queued, causing the bundler to hang or crash
rust/bindings_napi/src/lib.rs:parse_async
JavaScript well-known symbols (Symbol.toStringTag, Symbol.hasInstance, etc.) have stable identities across all environments and that future ECMAScript versions won't introduce conflicting symbol semantics
If this fails: If symbol behavior changes in newer JavaScript engines or if polyfills create different symbol instances, the symbol-based property tracking will fail to correctly identify well-known symbol accesses, breaking tree-shaking for code using these symbols
src/ast/utils/PathTracker.ts:WELL_KNOWN_SYMBOLS
The nested Map structure in EntityPathTracker can efficiently handle deeply nested object path tracking without hitting JavaScript's recursion limits or memory constraints, even for complex codebases with deep property access chains
If this fails: For extremely deep object property accesses (obj.a.b.c...z), the tracker's nested Map structure may consume excessive memory or hit stack overflow during traversal, causing tree-shaking to fail or produce incorrect results
src/ast/utils/PathTracker.ts:EntityPathTracker
The WebAssembly runtime environment supports the Rust-compiled parser with sufficient stack space and linear memory, and that WASM's memory model is compatible with the AST buffer serialization format
If this fails: If the WASM runtime has insufficient memory or stack space, or if the memory layout differs from native execution, the parser will crash or produce corrupted AST data, breaking the entire bundling process in browser environments
rust/bindings_wasm/src/lib.rs:parse
The scope.addDeclaration method correctly handles all variable kinds (var, let, const, parameter) and that treeshake options remain consistent throughout the declaration phase - specifically that treeshake.correctVarValueBeforeDeclaration doesn't change mid-build
If this fails: If treeshake options change during bundling or if scope.addDeclaration fails to properly handle certain variable kinds, variable hoisting and initialization timing will be incorrect, leading to wrong tree-shaking decisions and potentially broken output code
src/ast/nodes/Identifier.ts:declare
The includedCallArguments Set maintains insertion order for function call argument processing and that arguments are processed in the same order they appear in the source code
If this fails: If argument processing order is inconsistent, side effects from function calls may be analyzed in the wrong sequence, potentially marking pure functions as having effects or missing side effects from impure arguments
src/ast/ExecutionContext.ts:InclusionContext
The mem::take(&mut self.code) operation assumes that the code string won't be needed again after parsing and that the ParseTask instance lifecycle aligns with the async task completion
If this fails: If the parsing task needs to retry or if the code is accessed after mem::take, the operation will panic or produce empty results, but this is more of a design constraint than a hidden failure mode
rust/bindings_napi/src/lib.rs:ParseTask
The symbolic representation of unknown object keys (UnknownKey, UnknownInteger, etc.) covers all possible dynamic property access patterns in JavaScript code and that no new access patterns will emerge
If this fails: If new JavaScript features introduce property access patterns not covered by the existing unknown key symbols, those accesses won't be properly tracked during tree-shaking, potentially causing over-aggressive elimination of code that has dynamic dependencies
src/ast/utils/PathTracker.ts:UnknownKey
The mimalloc allocator is available and compatible with the target platform, and that it provides better performance than the system allocator for the AST parsing workload
If this fails: If mimalloc fails to initialize or has compatibility issues on certain platforms, the Rust parser will fall back to system allocation, which may cause performance degradation but shouldn't break functionality
rust/bindings_napi/src/lib.rs:ALLOC
See the full structural analysis of rollup: the pipeline, data models, and system behavior that put these assumptions in context.
Full analysis of rollup/rollup →Frequently Asked Questions
What does rollup assume that could break in production?
The one most likely to cause trouble: The Rust parser produces SerializedAstBuffer with a specific binary format that matches the TypeScript deserializer's expectations exactly - node type IDs, byte offsets, nested structure encoding, and string table layout must all align perfectly If this fails, If the Rust parser changes its serialization format or the TypeScript deserializer misreads the buffer, nodes will be created with wrong types, corrupted positions, or malformed structures, causing silent AST corruption throughout the bundling process
How many hidden assumptions does rollup have?
CodeSea found 13 assumptions rollup relies on but never validates, 4 of them critical, spanning Shape, Ordering, Contract, Temporal, Resource, Domain, Scale, Environment. Most are routine — the analysis flags the two or three most likely to actually bite.
What is a hidden assumption?
Something the code depends on but never checks: a data shape, an ordering, an environment condition, a scale limit, or a contract with another service. It holds until the world it runs in changes, then fails silently.