Skip to content

[JSC] ModuleAnalyzer keeps the attributes list of the declaration behind each requested module - #670

Open
dylan-conway wants to merge 2 commits into
mainfrom
claude/module-analyzer-request-attributes-lists
Open

dylan-conway wants to merge 2 commits into
mainfrom
claude/module-analyzer-request-attributes-lists

Conversation

@dylan-conway

Copy link
Copy Markdown
Member

What

ModuleAnalyzer::appendRequestedModule takes the declaration's ImportAttributesListNode*. Under BUN_JSC_ADDITIONS it records that pointer when the request is new, and requestedModuleAttributesLists() exposes the result: a vector index-aligned with the module record's requestedModules().

Why

requestedModules() is deduplicated by (specifier, ScriptFetchParameters::Type) per phase, first declaration wins, and a request keeps only the parsed type. node:vm's SourceTextModule reports every attribute of each request (moduleRequests, and the extra.attributes argument of the link() callback), so Bun walks the AST again to find them. It paired the i-th import declaration with the i-th request, which is wrong as soon as a specifier repeats (oven-sh/bun#41654). Re-deriving JSC's dedup key from outside to fix that needs a copy of tryCreateAttributes, a way to read ImportDeclarationNode's private phase, and still cannot cover export * from / export { } from, because ModuleDeclarationNode has no way to tell those two apart.

The analyzer already knows, at the moment it deduplicates, which declaration created the request. Recording it there makes the pairing correct by construction for import and both export-from forms.

Notes

  • The nodes belong to the ModuleProgramNode being analyzed; the vector is only meaningful while that node is alive, which is how Bun uses it (analyzer and node are both locals of one function).
  • No behaviour change without BUN_JSC_ADDITIONS; the new parameter is unused there.
  • JSWebAssemblyInstance calls AbstractModuleRecord::appendRequestedModule directly and is not affected.

…ind each requested module

requestedModules() is deduplicated by (specifier, type) per phase, and a request
keeps only the parsed type. An embedder that reports every import attribute of a
request, such as node:vm's SourceTextModule.moduleRequests, had to find the
declaration again by re-deriving that key from the AST.

appendRequestedModule now takes the declaration's ImportAttributesListNode and,
under BUN_JSC_ADDITIONS, records it when the request is new.
requestedModuleAttributesLists() is index-aligned with requestedModules() and
covers import, export * from and export { } from alike.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed this PR and didn't find any bugs; since it changes the signature of a parser entry point in JavaScriptCore proper (a path listed under CODEOWNERS), a human look is still worthwhile before merging.

What was reviewed:

  • Index alignment of requestedModuleAttributesLists() with requestedModules(): the JSModuleRecord is created fresh in ModuleAnalyzer's constructor and, during analysis, only ModuleAnalyzer::appendRequestedModule appends to it, in the same isNewEntry branch as the new vector, so the two cannot diverge (the JSWebAssemblyInstance direct call is on a different record).
  • Both ModuleAnalyzer use sites (JSModuleLoader.cpp and Completion.cpp) keep the analyzer and ModuleProgramNode as locals of one function, and the header comment documents the arena lifetime of the stored node pointers.
  • All three in-tree callers were updated for the new positional parameter; without BUN_JSC_ADDITIONS the parameter is only UNUSED_PARAM-ed, so upstream behaviour is unchanged.
Extended reasoning...

Overview

The PR touches three parser files in JavaScriptCore: Source/JavaScriptCore/parser/ModuleAnalyzer.h, ModuleAnalyzer.cpp, and NodesAnalyzeModule.cpp. ModuleAnalyzer::appendRequestedModule gains an ImportAttributesListNode* parameter, and under USE(BUN_JSC_ADDITIONS) the analyzer stores that pointer in a new vector whenever a request is new, exposed via requestedModuleAttributesLists(). The three analyzeModule callers (import, export * from, export {} from) pass their node's attributesList(). No consumer is in this diff; the stated consumer is Bun's node:vm SourceTextModule implementation.

Security risks

None identified. The change stores raw parser-arena pointers, which could dangle if an embedder held them past the ModuleProgramNode's lifetime, but that is a lifetime contract for the embedder and is documented in the header; the two in-tree constructions of ModuleAnalyzer (JSModuleLoader.cpp:1507 and Completion.cpp:94) keep the analyzer and the node as locals of the same function. No parsing, dedup, or module-record behaviour changes when the flag is off.

Level of scrutiny

Low to moderate. The diff is +22/-6, mechanical, and correctly gated. The one property that matters, index alignment with requestedModules(), holds by construction: JSModuleRecord is created inside ModuleAnalyzer's constructor, and within analysis the only appends to its m_requestedModules come through ModuleAnalyzer::appendRequestedModule, in the same isNewEntry branch that appends to the new vector. AbstractModuleRecord::appendRequestedModule is also called from JSWebAssemblyInstance.cpp, but on a different record that no analyzer touches. The dedup key ignoring non-type attributes ("first declaration wins") matches the existing requestedModules() semantics and is what the PR sets out to mirror. I did not approve outright because the repository's CODEOWNERS covers all of Source/JavaScriptCore, and the change alters a public signature of a parser class that upstream syncs will have to carry.

Other factors

There are no tests in this diff; the behaviour is only observable from Bun's embedder, so coverage would live in oven-sh/bun rather than here. The #if !USE(BUN_JSC_ADDITIONS) / UNUSED_PARAM split is slightly unusual stylistically but compiles cleanly under both configurations. The bug hunt exited on a dry streak after the four listed candidates were ruled out.

@github-actions

github-actions Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

Preview build of df5b071: autobuild-preview-pr-670-df5b071d

dylan-conway added a commit to oven-sh/bun that referenced this pull request Sep 15, 2026
oven-sh/WebKit#670: ModuleAnalyzer records, for every requested module, the
attributes list of the declaration that created it. createModuleRecord reads
that list by index instead of searching the AST for a matching import.

A request created by export ... from now reports that declaration's
attributes, custom keys included, and not a later import's. An index-like
attribute key no longer asserts.
@coderabbitai

coderabbitai Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Essentials

Run ID: 96b42c6f-0272-4651-ab83-09a1cd238442

📥 Commits

Reviewing files that changed from the base of the PR and between c775a5d and 06d01c5.

📒 Files selected for processing (3)
  • Source/JavaScriptCore/parser/ModuleAnalyzer.cpp
  • Source/JavaScriptCore/parser/ModuleAnalyzer.h
  • Source/JavaScriptCore/parser/NodesAnalyzeModule.cpp

Included review availability: 0 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 5 reviews per hour.


Walkthrough

ModuleAnalyzer::appendRequestedModule now accepts import attributes. Import, export-all, and named re-export analysis forwards declaration attributes. Bun additions store attribute lists aligned with requested modules.

Changes

Module attribute propagation

Layer / File(s) Summary
Module analyzer contract and storage
Source/JavaScriptCore/parser/ModuleAnalyzer.h, Source/JavaScriptCore/parser/ModuleAnalyzer.cpp
The analyzer accepts an ImportAttributesListNode*. Bun additions store aligned attribute lists for newly requested modules. Duplicate requests remain unchanged.
Declaration attribute forwarding
Source/JavaScriptCore/parser/NodesAnalyzeModule.cpp
Import, export-all, and named re-export declarations pass their attributesList() to appendRequestedModule.

Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to df5b0

No actionable merge-blocking risk is identified in this change.

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the change, motivation, affected behavior, and compatibility notes. It does not follow the repository template because it omits the bug title, Bugzilla URL, review status, and… Add the bug title and Bugzilla URL, include the required “Reviewed by NOBODY (OOPS!).” line or actual review status, provide the template-formatted explanation, and list each changed file with its affected functions or classes.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the primary change: retaining each declaration's import attributes list for requested modules.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description explains the change, motivation, affected behavior, and compatibility notes. It does not follow the repository template because it omits the bug title, Bugzilla URL, review status, and changed-file/function list.

Warning

Git: CodeRabbit could not clone the repository, so clone-backed analysis was skipped and this review may be incomplete. Verify repository clone access, such as SSH credentials, before requesting another full review. If clone access is intentionally unavailable, use path_filters to narrow the review scope.


Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant