fix(react_compiler): track catch block declarations (#25067)

Tracks declarations introduced by catch bindings in React Compiler HIR.

AI-assisted.
This commit is contained in:
Boshen committed 2026-07-29 12:29:08 +00:00
1 parent e8c4c05fba
commit 0dc16ba3a0
3 files changed
+60 -4

No files matched your search

@@ -0,0 +1,15 @@
function Component({nodes}) {
try {
doSomething();
} catch {
const paragraphNode = createParagraphNode();
nodes.forEach(node => paragraphNode.append(node));
return paragraphNode;
}
return null;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{nodes: []}],
};
@@ -149,7 +149,20 @@ fn statement_end(stmt: &oxc::Statement) -> Option<u32> {
Some(stmt.span().end)
}
/// Collect binding names from a pattern that are declared in the given scope.
/// Resolve a declaration identifier to its symbol.
///
/// Prefer the identifier's semantic identity because function and catch bodies
/// may store direct lexical declarations in a child block scope. Fall back to
/// the current scope's binding map if semantic identity is unavailable.
fn resolve_declared_binding(
id: &oxc::BindingIdentifier,
scope_id: ScopeId,
scope: &ScopeResolver<'_, '_>,
) -> Option<SymbolId> {
id.symbol_id.get().or_else(|| scope.get_binding(scope_id, id.name.as_str()))
}
/// Collect symbols declared by a binding pattern.
fn collect_binding_names_from_pattern(
pattern: &oxc::BindingPattern,
scope_id: ScopeId,
@@ -158,7 +171,7 @@ fn collect_binding_names_from_pattern(
) {
match pattern {
oxc::BindingPattern::BindingIdentifier(id) => {
if let Some(symbol_id) = scope.get_binding(scope_id, id.name.as_str()) {
if let Some(symbol_id) = resolve_declared_binding(id, scope_id, scope) {
out.insert(symbol_id);
}
}
@@ -482,7 +495,7 @@ fn lower_block_statement_inner<'a>(
match body_stmt {
oxc::Statement::FunctionDeclaration(func) => {
if let Some(id) = &func.id
&& let Some(symbol_id) = scope.get_binding(scope_id, id.name.as_str())
&& let Some(symbol_id) = resolve_declared_binding(id, scope_id, scope)
{
declared.insert(symbol_id);
}
@@ -494,7 +507,7 @@ fn lower_block_statement_inner<'a>(
}
oxc::Statement::ClassDeclaration(cls) => {
if let Some(id) = &cls.id
&& let Some(symbol_id) = scope.get_binding(scope_id, id.name.as_str())
&& let Some(symbol_id) = resolve_declared_binding(id, scope_id, scope)
{
declared.insert(symbol_id);
}
@@ -0,0 +1,28 @@
---
source: crates/oxc_react_compiler/tests/snapshot.rs
input_file: crates/oxc_react_compiler/fixtures/try-catch-local-captured-by-nested-arrow.js
---
import { c as _c } from "react/compiler-runtime";
function Component(t0) {
const $ = _c(2);
const { nodes } = t0;
try {
doSomething();
} catch {
let paragraphNode;
if ($[0] !== nodes) {
paragraphNode = createParagraphNode();
nodes.forEach((node) => paragraphNode.append(node));
$[0] = nodes;
$[1] = paragraphNode;
} else {
paragraphNode = $[1];
}
return paragraphNode;
}
return null;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{ nodes: [] }]
};