refactor: identify AST nodes by NodeId instead of Span/Address#9609
refactor: identify AST nodes by NodeId instead of Span/Address#9609IWANABETHATGUY wants to merge 2 commits into
Conversation
How to use the Graphite Merge QueueAdd the label graphite: merge-when-ready to this PR to add it to the merge queue. You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
✅ Deploy Preview for rolldown-rs canceled.
|
698e338 to
77574a0
Compare
77574a0 to
5a92de4
Compare
|
@overlookmotel Thanks for the review. However, I still prefer using NodeId to identify nodes, for the following reasons: Address is more error-prone. I know it is safe to use in most cases, but it can still potentially introduce bugs when unstable_address is involved. Overall, I would prefer to use NodeId consistently for all AST node identification. |
Merging this PR will not alter performance
Comparing Footnotes
|
|
OK, fair enough. I tend towards prioritising perf myself, but obviously simplicity has large advantages - your rationale makes total sense. My understanding of where we're at with
We need to fix the 2nd, but it wasn't on immediate roadmap. We'll likely need to have 2 x This PR: What I haven't figured out yet is whether it's going to hit problems due to the dummy So... would you like to wait for me to do that and then review this PR (likely next week)? Or would you like to assess yourselves and get this merged earlier? Sorry, I had hoped to get into it properly this week, but... other stuff has been going on. |
No rush. I’ll wait until you finish the review before merging it. |
## Summary Adds `meta/design/ast-construction.md` documenting how rolldown should construct oxc AST, and cross-links it from `ast-mutation.md`. The convention: - **Generic nodes → oxc's `AstBuilder` directly** (handle named `ast`). - **Rolldown-specific patterns → an `AstBuilderExt` extension trait**, methods prefixed `make_` and named after the operation (e.g. `make_to_esm_wrapper`), mirroring oxc's builder signature style. The call site self-identifies (bare node name = oxc; `make_*` = rolldown) and avoids inherent-vs-trait method shadowing. - **Build programmatically by default; parsing source is an exception.** Direct construction has no runtime cost; parsing pays lexing+parsing overhead every build. Authoring code as JS and parsing it (`EcmaCompiler::parse`) is reserved for a large fixed blob — in practice just the runtime module. - The `AstSnippet` facade is retired over time (its author already noted the name was a compromise for `AstBuilder`). ## Background oxc made `AstBuilder` the single sanctioned construction path (`#[non_exhaustive]` on `NodeId`-bearing nodes, oxc#23046, handled in #9670) and is redesigning it further (oxc#23043, which cites #9609). This doc aligns rolldown with that direction instead of growing a divergent local layer. ## Notes - **Docs-only; no code changes.** - The `## Plan` section is **temporary** and will be removed once the migration it describes is implemented. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
There isn't really a hurry for this, but I also get sometimes we want things to get too pefect to be done. If you could finish the review in time that's good, if you can't that's fine too. On the other hands, merging this would be also a way of getting feedbacks for the node id design. Will plan to merge this after this weeks' release, so we get a full week time to revert this PR if you find some significant downsides. I wanna push this forward, because I'm looking at the some internal improvement/refactor. I want the future refactor can build on top of the new basis. It might not be perfect, but we still want to fix bugs on top of the new basis instead of the old one. |

Summary
Replaces the two ad-hoc cross-pass AST-node identity keys — oxc
Span(deduped byPreProcessor) and arenaAddress— with oxc's post-semanticNodeIdfor every side table threaded from scan → link → finalize:EcmaView::imports,dummy_record_set,new_url_references,this_expr_replace_mapMemberExprRef::node_id/LinkingMetadata::resolved_member_expr_refsDynamicImportExprInfo::node_id/EntryPoint::related_stmt_infosCross-module tables are keyed by
(ModuleIdx, NodeId)because node ids are unique only within a single AST.Spanis retained purely as source-location metadata (diagnostics, source maps, generated replacement spans); import records now carry an explicitimporter_spanso the TLA import-chain diagnostic no longer needs a reverse lookup over the (formerly span-keyed)importsmap.This removes the implicit "spans are stable and unique within a module" contract along with the
PreProcessorsynthetic-span workaround: finalizer-generated nodes keepNodeId::DUMMYand can no longer collide with scan-time records.Notes
make_copy) and HMR paths finalize a clone of the scanned AST; they rely onclone_in_with_semantic_ids(viaEcmaAst::clone_with_another_arena) to preserve node ids across the arena boundary, where plainclone_inwould reset them toNodeId::DUMMY.meta/design/ast-mutation.mdis rewritten to document the newNodeIdcontract.🤖 Generated with Claude Code