From f283c6860c7402f8d88addc2dcb0480738e1cf65 Mon Sep 17 00:00:00 2001 From: Joe Savona Date: Fri, 20 Feb 2026 17:24:38 -0800 Subject: [PATCH] [compiler] Remove local CompilerError accumulators, emit directly to env.recordError() Removes unnecessary indirection in 17 compiler passes that previously accumulated errors in a local `CompilerError` instance before flushing them to `env.recordErrors()` at the end of each pass. Errors are now emitted directly via `env.recordError()` as they're discovered. For passes with recursive error-detection patterns (ValidateNoRefAccessInRender, ValidateNoSetStateInRender), the internal accumulator is kept but flushed via individual `recordError()` calls. For InferMutationAliasingRanges, a `shouldRecordErrors` flag preserves the conditional suppression logic. For TransformFire, the throw-based error propagation is replaced with direct recording plus an early-exit check in Pipeline.ts. --- .../src/Entrypoint/Pipeline.ts | 3 + .../src/HIR/BuildHIR.ts | 1052 ++++++++++------- .../src/HIR/HIRBuilder.ts | 64 +- .../src/Inference/DropManualMemoization.ts | 17 +- .../Inference/InferMutationAliasingRanges.ts | 38 +- .../ReactiveScopes/CodegenReactiveFunction.ts | 103 +- .../src/Transform/TransformFire.ts | 18 +- .../ValidateExhaustiveDependencies.ts | 8 +- .../src/Validation/ValidateHooksUsage.ts | 32 +- .../ValidateMemoizedEffectDependencies.ts | 32 +- .../Validation/ValidateNoCapitalizedCalls.ts | 22 +- .../ValidateNoDerivedComputationsInEffects.ts | 28 +- ...ValidateNoFreezingKnownMutableFunctions.ts | 8 +- .../ValidateNoImpureFunctionsInRender.ts | 8 +- .../Validation/ValidateNoRefAccessInRender.ts | 4 +- .../Validation/ValidateNoSetStateInRender.ts | 4 +- .../ValidatePreservedManualMemoization.ts | 16 +- .../src/Validation/ValidateSourceLocations.ts | 10 +- .../src/Validation/ValidateUseMemo.ts | 15 +- .../bailout-capitalized-fn-call.expect.md | 2 +- ...-fire-todo-syntax-shouldnt-throw.expect.md | 4 +- ...ailout-validate-conditional-hook.expect.md | 6 +- ...ro-dont-add-hook-guards-on-retry.expect.md | 7 +- 23 files changed, 817 insertions(+), 684 deletions(-) diff --git a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts index 22cf8a93e3..26cc2871ef 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts @@ -220,6 +220,9 @@ function runWithEnvironment( if (env.config.enableFire) { transformFire(hir); log({kind: 'hir', name: 'TransformFire', value: hir}); + if (env.hasErrors()) { + return Err(env.aggregateErrors()); + } } if (env.config.lowerContextAccess) { diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts index 76fb0589c8..7e665aa279 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts @@ -11,6 +11,7 @@ import invariant from 'invariant'; import { CompilerDiagnostic, CompilerError, + CompilerErrorDetail, CompilerSuggestionOperation, ErrorCategory, } from '../CompilerError'; @@ -105,7 +106,7 @@ export function lower( if (param.isIdentifier()) { const binding = builder.resolveIdentifier(param); if (binding.kind !== 'Identifier') { - builder.errors.pushDiagnostic( + builder.recordError( CompilerDiagnostic.create({ category: ErrorCategory.Invariant, reason: 'Could not find binding', @@ -169,7 +170,7 @@ export function lower( 'Assignment', ); } else { - builder.errors.pushDiagnostic( + builder.recordError( CompilerDiagnostic.create({ category: ErrorCategory.Todo, reason: `Handle ${param.node.type} parameters`, @@ -200,7 +201,7 @@ export function lower( lowerStatement(builder, body); directives = body.get('directives').map(d => d.node.value.value); } else { - builder.errors.pushDiagnostic( + builder.recordError( CompilerDiagnostic.create({ category: ErrorCategory.Syntax, reason: `Unexpected function body kind`, @@ -217,7 +218,9 @@ export function lower( if (id != null) { const idResult = validateIdentifierName(id); if (idResult.isErr()) { - builder.errors.merge(idResult.unwrapErr()); + for (const detail of idResult.unwrapErr().details) { + builder.recordError(detail); + } } else { validatedId = idResult.unwrap().value; } @@ -241,11 +244,6 @@ export function lower( const hirBody = builder.build(); - // Record all accumulated errors (including any from build()) on env - if (builder.errors.hasAnyErrors()) { - env.recordErrors(builder.errors); - } - return { id: validatedId, nameHint: null, @@ -282,13 +280,15 @@ function lowerStatement( * for control-flow and is generally considered an anti-pattern. we can likely * just not support this pattern, unless it really becomes necessary for some reason. */ - builder.errors.push({ - reason: - '(BuildHIR::lowerStatement) Support ThrowStatement inside of try/catch', - category: ErrorCategory.Todo, - loc: stmt.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: + '(BuildHIR::lowerStatement) Support ThrowStatement inside of try/catch', + category: ErrorCategory.Todo, + loc: stmt.node.loc ?? null, + suggestions: null, + }), + ); } const terminal: ThrowTerminal = { kind: 'throw', @@ -470,22 +470,26 @@ function lowerStatement( } else if (binding.path.isFunctionDeclaration()) { kind = InstructionKind.HoistedFunction; } else if (!binding.path.isVariableDeclarator()) { - builder.errors.push({ - category: ErrorCategory.Todo, - reason: 'Unsupported declaration type for hoisting', - description: `variable "${binding.identifier.name}" declared with ${binding.path.type}`, - suggestions: null, - loc: id.parentPath.node.loc ?? GeneratedSource, - }); + builder.recordError( + new CompilerErrorDetail({ + category: ErrorCategory.Todo, + reason: 'Unsupported declaration type for hoisting', + description: `variable "${binding.identifier.name}" declared with ${binding.path.type}`, + suggestions: null, + loc: id.parentPath.node.loc ?? GeneratedSource, + }), + ); continue; } else { - builder.errors.push({ - category: ErrorCategory.Todo, - reason: 'Handle non-const declarations for hoisting', - description: `variable "${binding.identifier.name}" declared with ${binding.kind}`, - suggestions: null, - loc: id.parentPath.node.loc ?? GeneratedSource, - }); + builder.recordError( + new CompilerErrorDetail({ + category: ErrorCategory.Todo, + reason: 'Handle non-const declarations for hoisting', + description: `variable "${binding.identifier.name}" declared with ${binding.kind}`, + suggestions: null, + loc: id.parentPath.node.loc ?? GeneratedSource, + }), + ); continue; } @@ -573,13 +577,15 @@ function lowerStatement( }; } if (!init.isVariableDeclaration()) { - builder.errors.push({ - reason: - '(BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement', - category: ErrorCategory.Todo, - loc: stmt.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: + '(BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement', + category: ErrorCategory.Todo, + loc: stmt.node.loc ?? null, + suggestions: null, + }), + ); // Lower the init expression as best-effort and continue if (init.isExpression()) { lowerExpressionToTemporary(builder, init as NodePath); @@ -652,12 +658,14 @@ function lowerStatement( const test = stmt.get('test'); if (test.node == null) { - builder.errors.push({ - reason: `(BuildHIR::lowerStatement) Handle empty test in ForStatement`, - category: ErrorCategory.Todo, - loc: stmt.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerStatement) Handle empty test in ForStatement`, + category: ErrorCategory.Todo, + loc: stmt.node.loc ?? null, + suggestions: null, + }), + ); // Treat `for(;;)` as `while(true)` to keep the builder state consistent builder.terminateWithContinuation( { @@ -820,12 +828,14 @@ function lowerStatement( const testExpr = case_.get('test'); if (testExpr.node == null) { if (hasDefault) { - builder.errors.push({ - reason: `Expected at most one \`default\` branch in a switch statement, this code should have failed to parse`, - category: ErrorCategory.Syntax, - loc: case_.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `Expected at most one \`default\` branch in a switch statement, this code should have failed to parse`, + category: ErrorCategory.Syntax, + loc: case_.node.loc ?? null, + suggestions: null, + }), + ); break; } hasDefault = true; @@ -892,12 +902,14 @@ function lowerStatement( const stmt = stmtPath as NodePath; const nodeKind: t.VariableDeclaration['kind'] = stmt.node.kind; if (nodeKind === 'var') { - builder.errors.push({ - reason: `(BuildHIR::lowerStatement) Handle ${nodeKind} kinds in VariableDeclaration`, - category: ErrorCategory.Todo, - loc: stmt.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerStatement) Handle ${nodeKind} kinds in VariableDeclaration`, + category: ErrorCategory.Todo, + loc: stmt.node.loc ?? null, + suggestions: null, + }), + ); // Treat `var` as `let` so references to the variable don't break } const kind = @@ -922,12 +934,14 @@ function lowerStatement( } else if (id.isIdentifier()) { const binding = builder.resolveIdentifier(id); if (binding.kind !== 'Identifier') { - builder.errors.push({ - reason: `(BuildHIR::lowerAssignment) Could not find binding for declaration.`, - category: ErrorCategory.Invariant, - loc: id.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerAssignment) Could not find binding for declaration.`, + category: ErrorCategory.Invariant, + loc: id.node.loc ?? null, + suggestions: null, + }), + ); } else { const place: Place = { effect: Effect.Unknown, @@ -939,19 +953,21 @@ function lowerStatement( if (builder.isContextIdentifier(id)) { if (kind === InstructionKind.Const) { const declRangeStart = declaration.parentPath.node.start!; - builder.errors.push({ - reason: `Expect \`const\` declaration not to be reassigned`, - category: ErrorCategory.Syntax, - loc: id.node.loc ?? null, - suggestions: [ - { - description: 'Change to a `let` declaration', - op: CompilerSuggestionOperation.Replace, - range: [declRangeStart, declRangeStart + 5], // "const".length - text: 'let', - }, - ], - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `Expect \`const\` declaration not to be reassigned`, + category: ErrorCategory.Syntax, + loc: id.node.loc ?? null, + suggestions: [ + { + description: 'Change to a `let` declaration', + op: CompilerSuggestionOperation.Replace, + range: [declRangeStart, declRangeStart + 5], // "const".length + text: 'let', + }, + ], + }), + ); } lowerValueToTemporary(builder, { kind: 'DeclareContext', @@ -985,13 +1001,15 @@ function lowerStatement( } } } else { - builder.errors.push({ - reason: `Expected variable declaration to be an identifier if no initializer was provided`, - description: `Got a \`${id.type}\``, - category: ErrorCategory.Syntax, - loc: stmt.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `Expected variable declaration to be an identifier if no initializer was provided`, + description: `Got a \`${id.type}\``, + category: ErrorCategory.Syntax, + loc: stmt.node.loc ?? null, + suggestions: null, + }), + ); } } return; @@ -1092,12 +1110,14 @@ function lowerStatement( const testBlock = builder.reserve('loop'); if (stmt.node.await) { - builder.errors.push({ - reason: `(BuildHIR::lowerStatement) Handle for-await loops`, - category: ErrorCategory.Todo, - loc: stmt.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerStatement) Handle for-await loops`, + category: ErrorCategory.Todo, + loc: stmt.node.loc ?? null, + suggestions: null, + }), + ); return; } @@ -1320,21 +1340,25 @@ function lowerStatement( const handlerPath = stmt.get('handler'); if (!hasNode(handlerPath)) { - builder.errors.push({ - reason: `(BuildHIR::lowerStatement) Handle TryStatement without a catch clause`, - category: ErrorCategory.Todo, - loc: stmt.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerStatement) Handle TryStatement without a catch clause`, + category: ErrorCategory.Todo, + loc: stmt.node.loc ?? null, + suggestions: null, + }), + ); return; } if (hasNode(stmt.get('finalizer'))) { - builder.errors.push({ - reason: `(BuildHIR::lowerStatement) Handle TryStatement with a finalizer ('finally') clause`, - category: ErrorCategory.Todo, - loc: stmt.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerStatement) Handle TryStatement with a finalizer ('finally') clause`, + category: ErrorCategory.Todo, + loc: stmt.node.loc ?? null, + suggestions: null, + }), + ); } const handlerBindingPath = handlerPath.get('param'); @@ -1421,13 +1445,15 @@ function lowerStatement( return; } case 'WithStatement': { - builder.errors.push({ - reason: `JavaScript 'with' syntax is not supported`, - description: `'with' syntax is considered deprecated and removed from JavaScript standards, consider alternatives`, - category: ErrorCategory.UnsupportedSyntax, - loc: stmtPath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `JavaScript 'with' syntax is not supported`, + description: `'with' syntax is considered deprecated and removed from JavaScript standards, consider alternatives`, + category: ErrorCategory.UnsupportedSyntax, + loc: stmtPath.node.loc ?? null, + suggestions: null, + }), + ); lowerValueToTemporary(builder, { kind: 'UnsupportedNode', loc: stmtPath.node.loc ?? GeneratedSource, @@ -1441,13 +1467,15 @@ function lowerStatement( * and complex enough to support that we don't anticipate supporting anytime soon. Developers * are encouraged to lift classes out of component/hook declarations. */ - builder.errors.push({ - reason: 'Inline `class` declarations are not supported', - description: `Move class declarations outside of components/hooks`, - category: ErrorCategory.UnsupportedSyntax, - loc: stmtPath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: 'Inline `class` declarations are not supported', + description: `Move class declarations outside of components/hooks`, + category: ErrorCategory.UnsupportedSyntax, + loc: stmtPath.node.loc ?? null, + suggestions: null, + }), + ); lowerValueToTemporary(builder, { kind: 'UnsupportedNode', loc: stmtPath.node.loc ?? GeneratedSource, @@ -1470,13 +1498,15 @@ function lowerStatement( case 'ImportDeclaration': case 'TSExportAssignment': case 'TSImportEqualsDeclaration': { - builder.errors.push({ - reason: - 'JavaScript `import` and `export` statements may only appear at the top level of a module', - category: ErrorCategory.Syntax, - loc: stmtPath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: + 'JavaScript `import` and `export` statements may only appear at the top level of a module', + category: ErrorCategory.Syntax, + loc: stmtPath.node.loc ?? null, + suggestions: null, + }), + ); lowerValueToTemporary(builder, { kind: 'UnsupportedNode', loc: stmtPath.node.loc ?? GeneratedSource, @@ -1485,13 +1515,15 @@ function lowerStatement( return; } case 'TSNamespaceExportDeclaration': { - builder.errors.push({ - reason: - 'TypeScript `namespace` statements may only appear at the top level of a module', - category: ErrorCategory.Syntax, - loc: stmtPath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: + 'TypeScript `namespace` statements may only appear at the top level of a module', + category: ErrorCategory.Syntax, + loc: stmtPath.node.loc ?? null, + suggestions: null, + }), + ); lowerValueToTemporary(builder, { kind: 'UnsupportedNode', loc: stmtPath.node.loc ?? GeneratedSource, @@ -1572,12 +1604,14 @@ function lowerObjectPropertyKey( }; } - builder.errors.push({ - reason: `(BuildHIR::lowerExpression) Expected Identifier, got ${key.type} key in ObjectExpression`, - category: ErrorCategory.Todo, - loc: key.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerExpression) Expected Identifier, got ${key.type} key in ObjectExpression`, + category: ErrorCategory.Todo, + loc: key.node.loc ?? null, + suggestions: null, + }), + ); return null; } @@ -1629,12 +1663,14 @@ function lowerExpression( } const valuePath = propertyPath.get('value'); if (!valuePath.isExpression()) { - builder.errors.push({ - reason: `(BuildHIR::lowerExpression) Handle ${valuePath.type} values in ObjectExpression`, - category: ErrorCategory.Todo, - loc: valuePath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerExpression) Handle ${valuePath.type} values in ObjectExpression`, + category: ErrorCategory.Todo, + loc: valuePath.node.loc ?? null, + suggestions: null, + }), + ); continue; } const value = lowerExpressionToTemporary(builder, valuePath); @@ -1655,12 +1691,14 @@ function lowerExpression( }); } else if (propertyPath.isObjectMethod()) { if (propertyPath.node.kind !== 'method') { - builder.errors.push({ - reason: `(BuildHIR::lowerExpression) Handle ${propertyPath.node.kind} functions in ObjectExpression`, - category: ErrorCategory.Todo, - loc: propertyPath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerExpression) Handle ${propertyPath.node.kind} functions in ObjectExpression`, + category: ErrorCategory.Todo, + loc: propertyPath.node.loc ?? null, + suggestions: null, + }), + ); continue; } const method = lowerObjectMethod(builder, propertyPath); @@ -1676,12 +1714,14 @@ function lowerExpression( key: loweredKey, }); } else { - builder.errors.push({ - reason: `(BuildHIR::lowerExpression) Handle ${propertyPath.type} properties in ObjectExpression`, - category: ErrorCategory.Todo, - loc: propertyPath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerExpression) Handle ${propertyPath.type} properties in ObjectExpression`, + category: ErrorCategory.Todo, + loc: propertyPath.node.loc ?? null, + suggestions: null, + }), + ); continue; } } @@ -1709,12 +1749,14 @@ function lowerExpression( ); elements.push({kind: 'Spread', place}); } else { - builder.errors.push({ - reason: `(BuildHIR::lowerExpression) Handle ${element.type} elements in ArrayExpression`, - category: ErrorCategory.Todo, - loc: element.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerExpression) Handle ${element.type} elements in ArrayExpression`, + category: ErrorCategory.Todo, + loc: element.node.loc ?? null, + suggestions: null, + }), + ); continue; } } @@ -1728,13 +1770,15 @@ function lowerExpression( const expr = exprPath as NodePath; const calleePath = expr.get('callee'); if (!calleePath.isExpression()) { - builder.errors.push({ - reason: `Expected an expression as the \`new\` expression receiver (v8 intrinsics are not supported)`, - description: `Got a \`${calleePath.node.type}\``, - category: ErrorCategory.Syntax, - loc: calleePath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `Expected an expression as the \`new\` expression receiver (v8 intrinsics are not supported)`, + description: `Got a \`${calleePath.node.type}\``, + category: ErrorCategory.Syntax, + loc: calleePath.node.loc ?? null, + suggestions: null, + }), + ); return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc}; } const callee = lowerExpressionToTemporary(builder, calleePath); @@ -1755,12 +1799,14 @@ function lowerExpression( const expr = exprPath as NodePath; const calleePath = expr.get('callee'); if (!calleePath.isExpression()) { - builder.errors.push({ - reason: `Expected Expression, got ${calleePath.type} in CallExpression (v8 intrinsics not supported). This error is likely caused by a bug in React Compiler. Please file an issue`, - category: ErrorCategory.Todo, - loc: calleePath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `Expected Expression, got ${calleePath.type} in CallExpression (v8 intrinsics not supported). This error is likely caused by a bug in React Compiler. Please file an issue`, + category: ErrorCategory.Todo, + loc: calleePath.node.loc ?? null, + suggestions: null, + }), + ); return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc}; } if (calleePath.isMemberExpression()) { @@ -1789,24 +1835,28 @@ function lowerExpression( const expr = exprPath as NodePath; const leftPath = expr.get('left'); if (!leftPath.isExpression()) { - builder.errors.push({ - reason: `(BuildHIR::lowerExpression) Expected Expression, got ${leftPath.type} lval in BinaryExpression`, - category: ErrorCategory.Todo, - loc: leftPath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerExpression) Expected Expression, got ${leftPath.type} lval in BinaryExpression`, + category: ErrorCategory.Todo, + loc: leftPath.node.loc ?? null, + suggestions: null, + }), + ); return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc}; } const left = lowerExpressionToTemporary(builder, leftPath); const right = lowerExpressionToTemporary(builder, expr.get('right')); const operator = expr.node.operator; if (operator === '|>') { - builder.errors.push({ - reason: `(BuildHIR::lowerExpression) Pipe operator not supported`, - category: ErrorCategory.Todo, - loc: leftPath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerExpression) Pipe operator not supported`, + category: ErrorCategory.Todo, + loc: leftPath.node.loc ?? null, + suggestions: null, + }), + ); return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc}; } return { @@ -1830,12 +1880,14 @@ function lowerExpression( last = lowerExpressionToTemporary(builder, item); } if (last === null) { - builder.errors.push({ - reason: `Expected sequence expression to have at least one expression`, - category: ErrorCategory.Syntax, - loc: expr.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `Expected sequence expression to have at least one expression`, + category: ErrorCategory.Syntax, + loc: expr.node.loc ?? null, + suggestions: null, + }), + ); } else { lowerValueToTemporary(builder, { kind: 'StoreLocal', @@ -2041,13 +2093,15 @@ function lowerExpression( * OptionalMemberExpressions as the left side of an AssignmentExpression are Stage 1 and * not supported by React Compiler yet. */ - builder.errors.push({ - reason: `(BuildHIR::lowerExpression) Unsupported syntax on the left side of an AssignmentExpression`, - description: `Expected an LVal, got: ${left.type}`, - category: ErrorCategory.Todo, - loc: left.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerExpression) Unsupported syntax on the left side of an AssignmentExpression`, + description: `Expected an LVal, got: ${left.type}`, + category: ErrorCategory.Todo, + loc: left.node.loc ?? null, + suggestions: null, + }), + ); return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc}; } } @@ -2070,12 +2124,14 @@ function lowerExpression( }; const binaryOperator = operators[operator]; if (binaryOperator == null) { - builder.errors.push({ - reason: `(BuildHIR::lowerExpression) Handle ${operator} operators in AssignmentExpression`, - category: ErrorCategory.Todo, - loc: expr.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerExpression) Handle ${operator} operators in AssignmentExpression`, + category: ErrorCategory.Todo, + loc: expr.node.loc ?? null, + suggestions: null, + }), + ); return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc}; } const left = expr.get('left'); @@ -2169,12 +2225,14 @@ function lowerExpression( } } default: { - builder.errors.push({ - reason: `(BuildHIR::lowerExpression) Expected Identifier or MemberExpression, got ${expr.type} lval in AssignmentExpression`, - category: ErrorCategory.Todo, - loc: expr.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerExpression) Expected Identifier or MemberExpression, got ${expr.type} lval in AssignmentExpression`, + category: ErrorCategory.Todo, + loc: expr.node.loc ?? null, + suggestions: null, + }), + ); return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc}; } } @@ -2208,12 +2266,14 @@ function lowerExpression( continue; } if (!attribute.isJSXAttribute()) { - builder.errors.push({ - reason: `(BuildHIR::lowerExpression) Handle ${attribute.type} attributes in JSXElement`, - category: ErrorCategory.Todo, - loc: attribute.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerExpression) Handle ${attribute.type} attributes in JSXElement`, + category: ErrorCategory.Todo, + loc: attribute.node.loc ?? null, + suggestions: null, + }), + ); continue; } const namePath = attribute.get('name'); @@ -2221,12 +2281,14 @@ function lowerExpression( if (namePath.isJSXIdentifier()) { propName = namePath.node.name; if (propName.indexOf(':') !== -1) { - builder.errors.push({ - reason: `(BuildHIR::lowerExpression) Unexpected colon in attribute name \`${propName}\``, - category: ErrorCategory.Todo, - loc: namePath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerExpression) Unexpected colon in attribute name \`${propName}\``, + category: ErrorCategory.Todo, + loc: namePath.node.loc ?? null, + suggestions: null, + }), + ); } } else { CompilerError.invariant(namePath.isJSXNamespacedName(), { @@ -2249,22 +2311,26 @@ function lowerExpression( }); } else { if (!valueExpr.isJSXExpressionContainer()) { - builder.errors.push({ - reason: `(BuildHIR::lowerExpression) Handle ${valueExpr.type} attribute values in JSXElement`, - category: ErrorCategory.Todo, - loc: valueExpr.node?.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerExpression) Handle ${valueExpr.type} attribute values in JSXElement`, + category: ErrorCategory.Todo, + loc: valueExpr.node?.loc ?? null, + suggestions: null, + }), + ); continue; } const expression = valueExpr.get('expression'); if (!expression.isExpression()) { - builder.errors.push({ - reason: `(BuildHIR::lowerExpression) Handle ${expression.type} expressions in JSXExpressionContainer within JSXElement`, - category: ErrorCategory.Todo, - loc: valueExpr.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerExpression) Handle ${expression.type} expressions in JSXExpressionContainer within JSXElement`, + category: ErrorCategory.Todo, + loc: valueExpr.node.loc ?? null, + suggestions: null, + }), + ); continue; } value = lowerExpressionToTemporary(builder, expression); @@ -2315,7 +2381,7 @@ function lowerExpression( }); for (const [name, locations] of Object.entries(fbtLocations)) { if (locations.length > 1) { - builder.errors.pushDiagnostic( + builder.recordError( new CompilerDiagnostic({ category: ErrorCategory.Todo, reason: 'Support duplicate fbt tags', @@ -2376,13 +2442,15 @@ function lowerExpression( case 'TaggedTemplateExpression': { const expr = exprPath as NodePath; if (expr.get('quasi').get('expressions').length !== 0) { - builder.errors.push({ - reason: - '(BuildHIR::lowerExpression) Handle tagged template with interpolations', - category: ErrorCategory.Todo, - loc: exprPath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: + '(BuildHIR::lowerExpression) Handle tagged template with interpolations', + category: ErrorCategory.Todo, + loc: exprPath.node.loc ?? null, + suggestions: null, + }), + ); return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc}; } CompilerError.invariant(expr.get('quasi').get('quasis').length == 1, { @@ -2392,13 +2460,15 @@ function lowerExpression( }); const value = expr.get('quasi').get('quasis').at(0)!.node.value; if (value.raw !== value.cooked) { - builder.errors.push({ - reason: - '(BuildHIR::lowerExpression) Handle tagged template where cooked value is different from raw value', - category: ErrorCategory.Todo, - loc: exprPath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: + '(BuildHIR::lowerExpression) Handle tagged template where cooked value is different from raw value', + category: ErrorCategory.Todo, + loc: exprPath.node.loc ?? null, + suggestions: null, + }), + ); return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc}; } @@ -2415,22 +2485,26 @@ function lowerExpression( const quasis = expr.get('quasis'); if (subexprs.length !== quasis.length - 1) { - builder.errors.push({ - reason: `Unexpected quasi and subexpression lengths in template literal`, - category: ErrorCategory.Syntax, - loc: exprPath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `Unexpected quasi and subexpression lengths in template literal`, + category: ErrorCategory.Syntax, + loc: exprPath.node.loc ?? null, + suggestions: null, + }), + ); return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc}; } if (subexprs.some(e => !e.isExpression())) { - builder.errors.push({ - reason: `(BuildHIR::lowerAssignment) Handle TSType in TemplateLiteral.`, - category: ErrorCategory.Todo, - loc: exprPath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerAssignment) Handle TSType in TemplateLiteral.`, + category: ErrorCategory.Todo, + loc: exprPath.node.loc ?? null, + suggestions: null, + }), + ); return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc}; } @@ -2467,8 +2541,26 @@ function lowerExpression( }; } } else { - builder.errors.push({ - reason: `Only object properties can be deleted`, + builder.recordError( + new CompilerErrorDetail({ + reason: `Only object properties can be deleted`, + category: ErrorCategory.Syntax, + loc: expr.node.loc ?? null, + suggestions: [ + { + description: 'Remove this line', + range: [expr.node.start!, expr.node.end!], + op: CompilerSuggestionOperation.Remove, + }, + ], + }), + ); + return {kind: 'UnsupportedNode', node: expr.node, loc: exprLoc}; + } + } else if (expr.node.operator === 'throw') { + builder.recordError( + new CompilerErrorDetail({ + reason: `Throw expressions are not supported`, category: ErrorCategory.Syntax, loc: expr.node.loc ?? null, suggestions: [ @@ -2478,22 +2570,8 @@ function lowerExpression( op: CompilerSuggestionOperation.Remove, }, ], - }); - return {kind: 'UnsupportedNode', node: expr.node, loc: exprLoc}; - } - } else if (expr.node.operator === 'throw') { - builder.errors.push({ - reason: `Throw expressions are not supported`, - category: ErrorCategory.Syntax, - loc: expr.node.loc ?? null, - suggestions: [ - { - description: 'Remove this line', - range: [expr.node.start!, expr.node.end!], - op: CompilerSuggestionOperation.Remove, - }, - ], - }); + }), + ); return {kind: 'UnsupportedNode', node: expr.node, loc: exprLoc}; } else { return { @@ -2603,20 +2681,24 @@ function lowerExpression( }; } if (!argument.isIdentifier()) { - builder.errors.push({ - reason: `(BuildHIR::lowerExpression) Handle UpdateExpression with ${argument.type} argument`, - category: ErrorCategory.Todo, - loc: exprPath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerExpression) Handle UpdateExpression with ${argument.type} argument`, + category: ErrorCategory.Todo, + loc: exprPath.node.loc ?? null, + suggestions: null, + }), + ); return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc}; } else if (builder.isContextIdentifier(argument)) { - builder.errors.push({ - reason: `(BuildHIR::lowerExpression) Handle UpdateExpression to variables captured within lambdas.`, - category: ErrorCategory.Todo, - loc: exprPath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerExpression) Handle UpdateExpression to variables captured within lambdas.`, + category: ErrorCategory.Todo, + loc: exprPath.node.loc ?? null, + suggestions: null, + }), + ); return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc}; } const lvalue = lowerIdentifierForAssignment( @@ -2630,22 +2712,26 @@ function lowerExpression( * lowerIdentifierForAssignment should have already reported an error if it returned null, * we check here just in case */ - if (!builder.errors.hasAnyErrors()) { - builder.errors.push({ - reason: `(BuildHIR::lowerExpression) Found an invalid UpdateExpression without a previously reported error`, - category: ErrorCategory.Invariant, - loc: exprLoc, - suggestions: null, - }); + if (!builder.environment.hasErrors()) { + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerExpression) Found an invalid UpdateExpression without a previously reported error`, + category: ErrorCategory.Invariant, + loc: exprLoc, + suggestions: null, + }), + ); } return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc}; } else if (lvalue.kind === 'Global') { - builder.errors.push({ - reason: `(BuildHIR::lowerExpression) Support UpdateExpression where argument is a global`, - category: ErrorCategory.Todo, - loc: exprLoc, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerExpression) Support UpdateExpression where argument is a global`, + category: ErrorCategory.Todo, + loc: exprLoc, + suggestions: null, + }), + ); return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc}; } const value = lowerIdentifier(builder, argument); @@ -2695,21 +2781,25 @@ function lowerExpression( }; } - builder.errors.push({ - reason: `(BuildHIR::lowerExpression) Handle MetaProperty expressions other than import.meta`, - category: ErrorCategory.Todo, - loc: exprPath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerExpression) Handle MetaProperty expressions other than import.meta`, + category: ErrorCategory.Todo, + loc: exprPath.node.loc ?? null, + suggestions: null, + }), + ); return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc}; } default: { - builder.errors.push({ - reason: `(BuildHIR::lowerExpression) Handle ${exprPath.type} expressions`, - category: ErrorCategory.Todo, - loc: exprPath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerExpression) Handle ${exprPath.type} expressions`, + category: ErrorCategory.Todo, + loc: exprPath.node.loc ?? null, + suggestions: null, + }), + ); return {kind: 'UnsupportedNode', node: exprNode, loc: exprLoc}; } } @@ -2999,12 +3089,14 @@ function lowerReorderableExpression( expr: NodePath, ): Place { if (!isReorderableExpression(builder, expr, true)) { - builder.errors.push({ - reason: `(BuildHIR::node.lowerReorderableExpression) Expression type \`${expr.type}\` cannot be safely reordered`, - category: ErrorCategory.Todo, - loc: expr.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::node.lowerReorderableExpression) Expression type \`${expr.type}\` cannot be safely reordered`, + category: ErrorCategory.Todo, + loc: expr.node.loc ?? null, + suggestions: null, + }), + ); } return lowerExpressionToTemporary(builder, expr); } @@ -3201,12 +3293,14 @@ function lowerArguments( } else if (argPath.isExpression()) { args.push(lowerExpressionToTemporary(builder, argPath)); } else { - builder.errors.push({ - reason: `(BuildHIR::lowerExpression) Handle ${argPath.type} arguments in CallExpression`, - category: ErrorCategory.Todo, - loc: argPath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerExpression) Handle ${argPath.type} arguments in CallExpression`, + category: ErrorCategory.Todo, + loc: argPath.node.loc ?? null, + suggestions: null, + }), + ); } } return args; @@ -3236,12 +3330,14 @@ function lowerMemberExpression( } else if (propertyNode.isNumericLiteral()) { property = makePropertyLiteral(propertyNode.node.value); } else { - builder.errors.push({ - reason: `(BuildHIR::lowerMemberExpression) Handle ${propertyNode.type} property`, - category: ErrorCategory.Todo, - loc: propertyNode.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerMemberExpression) Handle ${propertyNode.type} property`, + category: ErrorCategory.Todo, + loc: propertyNode.node.loc ?? null, + suggestions: null, + }), + ); return { object, property: propertyNode.toString(), @@ -3257,12 +3353,14 @@ function lowerMemberExpression( return {object, property, value}; } else { if (!propertyNode.isExpression()) { - builder.errors.push({ - reason: `(BuildHIR::lowerMemberExpression) Expected Expression, got ${propertyNode.type} property`, - category: ErrorCategory.Todo, - loc: propertyNode.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerMemberExpression) Expected Expression, got ${propertyNode.type} property`, + category: ErrorCategory.Todo, + loc: propertyNode.node.loc ?? null, + suggestions: null, + }), + ); return { object, property: propertyNode.toString(), @@ -3315,13 +3413,15 @@ function lowerJsxElementName( const name = exprPath.node.name.name; const tag = `${namespace}:${name}`; if (namespace.indexOf(':') !== -1 || name.indexOf(':') !== -1) { - builder.errors.push({ - reason: `Expected JSXNamespacedName to have no colons in the namespace or name`, - description: `Got \`${namespace}\` : \`${name}\``, - category: ErrorCategory.Syntax, - loc: exprPath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `Expected JSXNamespacedName to have no colons in the namespace or name`, + description: `Got \`${namespace}\` : \`${name}\``, + category: ErrorCategory.Syntax, + loc: exprPath.node.loc ?? null, + suggestions: null, + }), + ); } const place = lowerValueToTemporary(builder, { kind: 'Primitive', @@ -3330,12 +3430,14 @@ function lowerJsxElementName( }); return place; } else { - builder.errors.push({ - reason: `(BuildHIR::lowerJsxElementName) Handle ${exprPath.type} tags`, - category: ErrorCategory.Todo, - loc: exprPath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerJsxElementName) Handle ${exprPath.type} tags`, + category: ErrorCategory.Todo, + loc: exprPath.node.loc ?? null, + suggestions: null, + }), + ); return lowerValueToTemporary(builder, { kind: 'UnsupportedNode', node: exprNode, @@ -3424,12 +3526,14 @@ function lowerJsxElement( }); return place; } else { - builder.errors.push({ - reason: `(BuildHIR::lowerJsxElement) Unhandled JsxElement, got: ${exprPath.type}`, - category: ErrorCategory.Todo, - loc: exprPath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerJsxElement) Unhandled JsxElement, got: ${exprPath.type}`, + category: ErrorCategory.Todo, + loc: exprPath.node.loc ?? null, + suggestions: null, + }), + ); const place = lowerValueToTemporary(builder, { kind: 'UnsupportedNode', node: exprNode, @@ -3596,14 +3700,16 @@ function lowerIdentifier( } default: { if (binding.kind === 'Global' && binding.name === 'eval') { - builder.errors.push({ - reason: `The 'eval' function is not supported`, - description: - 'Eval is an anti-pattern in JavaScript, and the code executed cannot be evaluated by React Compiler', - category: ErrorCategory.UnsupportedSyntax, - loc: exprPath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `The 'eval' function is not supported`, + description: + 'Eval is an anti-pattern in JavaScript, and the code executed cannot be evaluated by React Compiler', + category: ErrorCategory.UnsupportedSyntax, + loc: exprPath.node.loc ?? null, + suggestions: null, + }), + ); } return lowerValueToTemporary(builder, { kind: 'LoadGlobal', @@ -3654,27 +3760,31 @@ function lowerIdentifierForAssignment( return {kind: 'Global', name: path.node.name}; } else { // Else its an internal error bc we couldn't find the binding - builder.errors.push({ - reason: `(BuildHIR::lowerAssignment) Could not find binding for declaration.`, - category: ErrorCategory.Invariant, - loc: path.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerAssignment) Could not find binding for declaration.`, + category: ErrorCategory.Invariant, + loc: path.node.loc ?? null, + suggestions: null, + }), + ); return null; } } else if ( binding.bindingKind === 'const' && kind === InstructionKind.Reassign ) { - builder.errors.push({ - reason: `Cannot reassign a \`const\` variable`, - category: ErrorCategory.Syntax, - loc: path.node.loc ?? null, - description: - binding.identifier.name != null - ? `\`${binding.identifier.name.value}\` is declared as const` - : null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `Cannot reassign a \`const\` variable`, + category: ErrorCategory.Syntax, + loc: path.node.loc ?? null, + description: + binding.identifier.name != null + ? `\`${binding.identifier.name.value}\` is declared as const` + : null, + }), + ); return null; } @@ -3723,12 +3833,14 @@ function lowerAssignment( let temporary; if (builder.isContextIdentifier(lvalue)) { if (kind === InstructionKind.Const && !isHoistedIdentifier) { - builder.errors.push({ - reason: `Expected \`const\` declaration not to be reassigned`, - category: ErrorCategory.Syntax, - loc: lvalue.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `Expected \`const\` declaration not to be reassigned`, + category: ErrorCategory.Syntax, + loc: lvalue.node.loc ?? null, + suggestions: null, + }), + ); } if ( @@ -3737,12 +3849,14 @@ function lowerAssignment( kind !== InstructionKind.Let && kind !== InstructionKind.Function ) { - builder.errors.push({ - reason: `Unexpected context variable kind`, - category: ErrorCategory.Syntax, - loc: lvalue.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `Unexpected context variable kind`, + category: ErrorCategory.Syntax, + loc: lvalue.node.loc ?? null, + suggestions: null, + }), + ); temporary = lowerValueToTemporary(builder, { kind: 'UnsupportedNode', node: lvalueNode, @@ -3806,24 +3920,28 @@ function lowerAssignment( loc, }); } else { - builder.errors.push({ - reason: `(BuildHIR::lowerAssignment) Handle ${property.type} properties in MemberExpression`, - category: ErrorCategory.Todo, - loc: property.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerAssignment) Handle ${property.type} properties in MemberExpression`, + category: ErrorCategory.Todo, + loc: property.node.loc ?? null, + suggestions: null, + }), + ); return {kind: 'UnsupportedNode', node: lvalueNode, loc}; } return {kind: 'LoadLocal', place: temporary, loc: temporary.loc}; } else { if (!property.isExpression()) { - builder.errors.push({ - reason: - '(BuildHIR::lowerAssignment) Expected private name to appear as a non-computed property', - category: ErrorCategory.Todo, - loc: property.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: + '(BuildHIR::lowerAssignment) Expected private name to appear as a non-computed property', + category: ErrorCategory.Todo, + loc: property.node.loc ?? null, + suggestions: null, + }), + ); return {kind: 'UnsupportedNode', node: lvalueNode, loc}; } const propertyPlace = lowerExpressionToTemporary(builder, property); @@ -3884,12 +4002,14 @@ function lowerAssignment( if (identifier === null) { continue; } else if (identifier.kind === 'Global') { - builder.errors.push({ - category: ErrorCategory.Todo, - reason: - 'Expected reassignment of globals to enable forceTemporaries', - loc: element.node.loc ?? GeneratedSource, - }); + builder.recordError( + new CompilerErrorDetail({ + category: ErrorCategory.Todo, + reason: + 'Expected reassignment of globals to enable forceTemporaries', + loc: element.node.loc ?? GeneratedSource, + }), + ); continue; } items.push({ @@ -3923,12 +4043,14 @@ function lowerAssignment( if (identifier === null) { continue; } else if (identifier.kind === 'Global') { - builder.errors.push({ - category: ErrorCategory.Todo, - reason: - 'Expected reassignment of globals to enable forceTemporaries', - loc: element.node.loc ?? GeneratedSource, - }); + builder.recordError( + new CompilerErrorDetail({ + category: ErrorCategory.Todo, + reason: + 'Expected reassignment of globals to enable forceTemporaries', + loc: element.node.loc ?? GeneratedSource, + }), + ); continue; } items.push(identifier); @@ -3996,12 +4118,14 @@ function lowerAssignment( if (property.isRestElement()) { const argument = property.get('argument'); if (!argument.isIdentifier()) { - builder.errors.push({ - reason: `(BuildHIR::lowerAssignment) Handle ${argument.node.type} rest element in ObjectPattern`, - category: ErrorCategory.Todo, - loc: argument.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerAssignment) Handle ${argument.node.type} rest element in ObjectPattern`, + category: ErrorCategory.Todo, + loc: argument.node.loc ?? null, + suggestions: null, + }), + ); continue; } if ( @@ -4028,12 +4152,14 @@ function lowerAssignment( if (identifier === null) { continue; } else if (identifier.kind === 'Global') { - builder.errors.push({ - category: ErrorCategory.Todo, - reason: - 'Expected reassignment of globals to enable forceTemporaries', - loc: property.node.loc ?? GeneratedSource, - }); + builder.recordError( + new CompilerErrorDetail({ + category: ErrorCategory.Todo, + reason: + 'Expected reassignment of globals to enable forceTemporaries', + loc: property.node.loc ?? GeneratedSource, + }), + ); continue; } properties.push({ @@ -4044,21 +4170,25 @@ function lowerAssignment( } else { // TODO: this should always be true given the if/else if (!property.isObjectProperty()) { - builder.errors.push({ - reason: `(BuildHIR::lowerAssignment) Handle ${property.type} properties in ObjectPattern`, - category: ErrorCategory.Todo, - loc: property.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerAssignment) Handle ${property.type} properties in ObjectPattern`, + category: ErrorCategory.Todo, + loc: property.node.loc ?? null, + suggestions: null, + }), + ); continue; } if (property.node.computed) { - builder.errors.push({ - reason: `(BuildHIR::lowerAssignment) Handle computed properties in ObjectPattern`, - category: ErrorCategory.Todo, - loc: property.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerAssignment) Handle computed properties in ObjectPattern`, + category: ErrorCategory.Todo, + loc: property.node.loc ?? null, + suggestions: null, + }), + ); continue; } const loweredKey = lowerObjectPropertyKey(builder, property); @@ -4067,12 +4197,14 @@ function lowerAssignment( } const element = property.get('value'); if (!element.isLVal()) { - builder.errors.push({ - reason: `(BuildHIR::lowerAssignment) Expected object property value to be an LVal, got: ${element.type}`, - category: ErrorCategory.Todo, - loc: element.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerAssignment) Expected object property value to be an LVal, got: ${element.type}`, + category: ErrorCategory.Todo, + loc: element.node.loc ?? null, + suggestions: null, + }), + ); continue; } if ( @@ -4090,12 +4222,14 @@ function lowerAssignment( if (identifier === null) { continue; } else if (identifier.kind === 'Global') { - builder.errors.push({ - category: ErrorCategory.Todo, - reason: - 'Expected reassignment of globals to enable forceTemporaries', - loc: element.node.loc ?? GeneratedSource, - }); + builder.recordError( + new CompilerErrorDetail({ + category: ErrorCategory.Todo, + reason: + 'Expected reassignment of globals to enable forceTemporaries', + loc: element.node.loc ?? GeneratedSource, + }), + ); continue; } properties.push({ @@ -4239,12 +4373,14 @@ function lowerAssignment( ); } default: { - builder.errors.push({ - reason: `(BuildHIR::lowerAssignment) Handle ${lvaluePath.type} assignments`, - category: ErrorCategory.Todo, - loc: lvaluePath.node.loc ?? null, - suggestions: null, - }); + builder.recordError( + new CompilerErrorDetail({ + reason: `(BuildHIR::lowerAssignment) Handle ${lvaluePath.type} assignments`, + category: ErrorCategory.Todo, + loc: lvaluePath.node.loc ?? null, + suggestions: null, + }), + ); return {kind: 'UnsupportedNode', node: lvalueNode, loc}; } } diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/HIRBuilder.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/HIRBuilder.ts index d7c65c6564..71874b0afb 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/HIRBuilder.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/HIRBuilder.ts @@ -7,7 +7,12 @@ import {Binding, NodePath} from '@babel/traverse'; import * as t from '@babel/types'; -import {CompilerError, ErrorCategory} from '../CompilerError'; +import { + CompilerError, + CompilerDiagnostic, + CompilerErrorDetail, + ErrorCategory, +} from '../CompilerError'; import {Environment} from './Environment'; import { BasicBlock, @@ -110,7 +115,6 @@ export default class HIRBuilder { #bindings: Bindings; #env: Environment; #exceptionHandlerStack: Array = []; - errors: CompilerError = new CompilerError(); /** * Traversal context: counts the number of `fbt` tag parents * of the current babel node. @@ -148,6 +152,10 @@ export default class HIRBuilder { this.#current = newBlock(this.#entry, options?.entryBlockKind ?? 'block'); } + recordError(error: CompilerDiagnostic | CompilerErrorDetail): void { + this.#env.recordError(error); + } + currentBlockKind(): BlockKind { return this.#current.kind; } @@ -308,24 +316,28 @@ export default class HIRBuilder { resolveBinding(node: t.Identifier): Identifier { if (node.name === 'fbt') { - this.errors.push({ - category: ErrorCategory.Todo, - reason: 'Support local variables named `fbt`', - description: - 'Local variables named `fbt` may conflict with the fbt plugin and are not yet supported', - loc: node.loc ?? GeneratedSource, - suggestions: null, - }); + this.recordError( + new CompilerErrorDetail({ + category: ErrorCategory.Todo, + reason: 'Support local variables named `fbt`', + description: + 'Local variables named `fbt` may conflict with the fbt plugin and are not yet supported', + loc: node.loc ?? GeneratedSource, + suggestions: null, + }), + ); } if (node.name === 'this') { - this.errors.push({ - category: ErrorCategory.UnsupportedSyntax, - reason: '`this` is not supported syntax', - description: - 'React Compiler does not support compiling functions that use `this`', - loc: node.loc ?? GeneratedSource, - suggestions: null, - }); + this.recordError( + new CompilerErrorDetail({ + category: ErrorCategory.UnsupportedSyntax, + reason: '`this` is not supported syntax', + description: + 'React Compiler does not support compiling functions that use `this`', + loc: node.loc ?? GeneratedSource, + suggestions: null, + }), + ); } const originalName = node.name; let name = originalName; @@ -371,13 +383,15 @@ export default class HIRBuilder { instr => instr.value.kind === 'FunctionExpression', ) ) { - this.errors.push({ - reason: `Support functions with unreachable code that may contain hoisted declarations`, - loc: block.instructions[0]?.loc ?? block.terminal.loc, - description: null, - suggestions: null, - category: ErrorCategory.Todo, - }); + this.recordError( + new CompilerErrorDetail({ + reason: `Support functions with unreachable code that may contain hoisted declarations`, + loc: block.instructions[0]?.loc ?? block.terminal.loc, + description: null, + suggestions: null, + category: ErrorCategory.Todo, + }), + ); } } ir.blocks = rpoBlocks; diff --git a/compiler/packages/babel-plugin-react-compiler/src/Inference/DropManualMemoization.ts b/compiler/packages/babel-plugin-react-compiler/src/Inference/DropManualMemoization.ts index 2c2dfca7dd..90acd83ea5 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Inference/DropManualMemoization.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Inference/DropManualMemoization.ts @@ -293,7 +293,7 @@ function extractManualMemoizationArgs( instr: TInstruction | TInstruction, kind: 'useCallback' | 'useMemo', sidemap: IdentifierSidemap, - errors: CompilerError, + env: Environment, ): { fnPlace: Place; depsList: Array | null; @@ -303,7 +303,7 @@ function extractManualMemoizationArgs( Place | SpreadPattern | undefined >; if (fnPlace == null || fnPlace.kind !== 'Identifier') { - errors.pushDiagnostic( + env.recordError( CompilerDiagnostic.create({ category: ErrorCategory.UseMemo, reason: `Expected a callback function to be passed to ${kind}`, @@ -335,7 +335,7 @@ function extractManualMemoizationArgs( ? sidemap.maybeDepsLists.get(depsListPlace.identifier.id) : null; if (maybeDepsList == null) { - errors.pushDiagnostic( + env.recordError( CompilerDiagnostic.create({ category: ErrorCategory.UseMemo, reason: `Expected the dependency list for ${kind} to be an array literal`, @@ -354,7 +354,7 @@ function extractManualMemoizationArgs( for (const dep of maybeDepsList.deps) { const maybeDep = sidemap.maybeDeps.get(dep.identifier.id); if (maybeDep == null) { - errors.pushDiagnostic( + env.recordError( CompilerDiagnostic.create({ category: ErrorCategory.UseMemo, reason: `Expected the dependency list to be an array of simple expressions (e.g. \`x\`, \`x.y.z\`, \`x?.y?.z\`)`, @@ -389,7 +389,6 @@ function extractManualMemoizationArgs( * is only used for memoizing values and not for running arbitrary side effects. */ export function dropManualMemoization(func: HIRFunction): void { - const errors = new CompilerError(); const isValidationEnabled = func.env.config.validatePreserveExistingMemoizationGuarantees || func.env.config.validateNoSetStateInRender || @@ -436,7 +435,7 @@ export function dropManualMemoization(func: HIRFunction): void { instr as TInstruction | TInstruction, manualMemo.kind, sidemap, - errors, + func.env, ); if (memoDetails == null) { @@ -464,7 +463,7 @@ export function dropManualMemoization(func: HIRFunction): void { * is rare and likely sketchy. */ if (!sidemap.functions.has(fnPlace.identifier.id)) { - errors.pushDiagnostic( + func.env.recordError( CompilerDiagnostic.create({ category: ErrorCategory.UseMemo, reason: `Expected the first argument to be an inline function expression`, @@ -549,10 +548,6 @@ export function dropManualMemoization(func: HIRFunction): void { markInstructionIds(func.body); } } - - if (errors.hasAnyErrors()) { - func.env.recordErrors(errors); - } } function findOptionalPlaces(fn: HIRFunction): Set { diff --git a/compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutationAliasingRanges.ts b/compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutationAliasingRanges.ts index 142fa7155c..6d584806a4 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutationAliasingRanges.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutationAliasingRanges.ts @@ -20,6 +20,7 @@ import { Place, isPrimitiveType, } from '../HIR/HIR'; +import {Environment} from '../HIR/Environment'; import { eachInstructionLValue, eachInstructionValueOperand, @@ -107,7 +108,7 @@ export function inferMutationAliasingRanges( let index = 0; - const errors = new CompilerError(); + const shouldRecordErrors = !isFunctionExpression && fn.env.enableValidations; for (const param of [...fn.params, ...fn.context, fn.returns]) { const place = param.kind === 'Identifier' ? param : param.place; @@ -200,7 +201,9 @@ export function inferMutationAliasingRanges( effect.kind === 'MutateGlobal' || effect.kind === 'Impure' ) { - errors.pushDiagnostic(effect.error); + if (shouldRecordErrors) { + fn.env.recordError(effect.error); + } functionEffects.push(effect); } else if (effect.kind === 'Render') { renders.push({index: index++, place: effect.place}); @@ -245,11 +248,15 @@ export function inferMutationAliasingRanges( mutation.kind, mutation.place.loc, mutation.reason, - errors, + shouldRecordErrors ? fn.env : null, ); } for (const render of renders) { - state.render(render.index, render.place.identifier, errors); + state.render( + render.index, + render.place.identifier, + shouldRecordErrors ? fn.env : null, + ); } for (const param of [...fn.context, ...fn.params]) { const place = param.kind === 'Identifier' ? param : param.place; @@ -498,7 +505,6 @@ export function inferMutationAliasingRanges( * would be transitively mutated needs a capture relationship. */ const tracked: Array = []; - const ignoredErrors = new CompilerError(); for (const param of [...fn.params, ...fn.context, fn.returns]) { const place = param.kind === 'Identifier' ? param : param.place; tracked.push(place); @@ -513,7 +519,7 @@ export function inferMutationAliasingRanges( MutationKind.Conditional, into.loc, null, - ignoredErrors, + null, ); for (const from of tracked) { if ( @@ -547,23 +553,17 @@ export function inferMutationAliasingRanges( } } - if ( - errors.hasAnyErrors() && - !isFunctionExpression && - fn.env.enableValidations - ) { - fn.env.recordErrors(errors); - } return functionEffects; } -function appendFunctionErrors(errors: CompilerError, fn: HIRFunction): void { +function appendFunctionErrors(env: Environment | null, fn: HIRFunction): void { + if (env == null) return; for (const effect of fn.aliasingEffects ?? []) { switch (effect.kind) { case 'Impure': case 'MutateFrozen': case 'MutateGlobal': { - errors.pushDiagnostic(effect.error); + env.recordError(effect.error); break; } } @@ -664,7 +664,7 @@ class AliasingState { } } - render(index: number, start: Identifier, errors: CompilerError): void { + render(index: number, start: Identifier, env: Environment | null): void { const seen = new Set(); const queue: Array = [start]; while (queue.length !== 0) { @@ -678,7 +678,7 @@ class AliasingState { continue; } if (node.value.kind === 'Function') { - appendFunctionErrors(errors, node.value.function); + appendFunctionErrors(env, node.value.function); } for (const [alias, when] of node.createdFrom) { if (when >= index) { @@ -710,7 +710,7 @@ class AliasingState { startKind: MutationKind, loc: SourceLocation, reason: MutationReason | null, - errors: CompilerError, + env: Environment | null, ): void { const seen = new Map(); const queue: Array<{ @@ -742,7 +742,7 @@ class AliasingState { node.transitive == null && node.local == null ) { - appendFunctionErrors(errors, node.value.function); + appendFunctionErrors(env, node.value.function); } if (transitive) { if (node.transitive == null || node.transitive.kind < kind) { diff --git a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/CodegenReactiveFunction.ts b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/CodegenReactiveFunction.ts index 1e0e97d8c8..6795262e1a 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/CodegenReactiveFunction.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/CodegenReactiveFunction.ts @@ -13,7 +13,11 @@ import { pruneUnusedLabels, renameVariables, } from '.'; -import {CompilerError, ErrorCategory} from '../CompilerError'; +import { + CompilerError, + CompilerErrorDetail, + ErrorCategory, +} from '../CompilerError'; import {Environment, ExternalFunction} from '../HIR'; import { ArrayPattern, @@ -358,10 +362,6 @@ function codegenReactiveFunction( } } - if (cx.errors.hasAnyErrors()) { - fn.env.recordErrors(cx.errors); - } - const countMemoBlockVisitor = new CountMemoBlockVisitor(fn.env); visitReactiveFunction(fn, countMemoBlockVisitor, undefined); @@ -434,7 +434,6 @@ class Context { */ #declarations: Set = new Set(); temp: Temporaries; - errors: CompilerError = new CompilerError(); objectMethods: Map = new Map(); uniqueIdentifiers: Set; fbtOperands: Set; @@ -453,6 +452,10 @@ class Context { this.fbtOperands = fbtOperands; this.temp = temporaries !== null ? new Map(temporaries) : new Map(); } + + recordError(error: CompilerErrorDetail): void { + this.env.recordError(error); + } get nextCacheIndex(): number { return this.#nextCacheIndex++; } @@ -972,12 +975,14 @@ function codegenTerminal( loc: terminal.init.loc, }); if (terminal.init.instructions.length !== 2) { - cx.errors.push({ - reason: 'Support non-trivial for..in inits', - category: ErrorCategory.Todo, - loc: terminal.init.loc, - suggestions: null, - }); + cx.recordError( + new CompilerErrorDetail({ + reason: 'Support non-trivial for..in inits', + category: ErrorCategory.Todo, + loc: terminal.init.loc, + suggestions: null, + }), + ); return t.emptyStatement(); } const iterableCollection = terminal.init.instructions[0]; @@ -993,12 +998,14 @@ function codegenTerminal( break; } case 'StoreContext': { - cx.errors.push({ - reason: 'Support non-trivial for..in inits', - category: ErrorCategory.Todo, - loc: terminal.init.loc, - suggestions: null, - }); + cx.recordError( + new CompilerErrorDetail({ + reason: 'Support non-trivial for..in inits', + category: ErrorCategory.Todo, + loc: terminal.init.loc, + suggestions: null, + }), + ); return t.emptyStatement(); } default: @@ -1069,12 +1076,14 @@ function codegenTerminal( loc: terminal.test.loc, }); if (terminal.test.instructions.length !== 2) { - cx.errors.push({ - reason: 'Support non-trivial for..of inits', - category: ErrorCategory.Todo, - loc: terminal.init.loc, - suggestions: null, - }); + cx.recordError( + new CompilerErrorDetail({ + reason: 'Support non-trivial for..of inits', + category: ErrorCategory.Todo, + loc: terminal.init.loc, + suggestions: null, + }), + ); return t.emptyStatement(); } const iterableItem = terminal.test.instructions[1]; @@ -1089,12 +1098,14 @@ function codegenTerminal( break; } case 'StoreContext': { - cx.errors.push({ - reason: 'Support non-trivial for..of inits', - category: ErrorCategory.Todo, - loc: terminal.init.loc, - suggestions: null, - }); + cx.recordError( + new CompilerErrorDetail({ + reason: 'Support non-trivial for..of inits', + category: ErrorCategory.Todo, + loc: terminal.init.loc, + suggestions: null, + }), + ); return t.emptyStatement(); } default: @@ -2189,22 +2200,26 @@ function codegenInstructionValue( } else { if (t.isVariableDeclaration(stmt)) { const declarator = stmt.declarations[0]; - cx.errors.push({ - reason: `(CodegenReactiveFunction::codegenInstructionValue) Cannot declare variables in a value block, tried to declare '${ - (declarator.id as t.Identifier).name - }'`, - category: ErrorCategory.Todo, - loc: declarator.loc ?? null, - suggestions: null, - }); + cx.recordError( + new CompilerErrorDetail({ + reason: `(CodegenReactiveFunction::codegenInstructionValue) Cannot declare variables in a value block, tried to declare '${ + (declarator.id as t.Identifier).name + }'`, + category: ErrorCategory.Todo, + loc: declarator.loc ?? null, + suggestions: null, + }), + ); return t.stringLiteral(`TODO handle ${declarator.id}`); } else { - cx.errors.push({ - reason: `(CodegenReactiveFunction::codegenInstructionValue) Handle conversion of ${stmt.type} to expression`, - category: ErrorCategory.Todo, - loc: stmt.loc ?? null, - suggestions: null, - }); + cx.recordError( + new CompilerErrorDetail({ + reason: `(CodegenReactiveFunction::codegenInstructionValue) Handle conversion of ${stmt.type} to expression`, + category: ErrorCategory.Todo, + loc: stmt.loc ?? null, + suggestions: null, + }), + ); return t.stringLiteral(`TODO handle ${stmt.type}`); } } diff --git a/compiler/packages/babel-plugin-react-compiler/src/Transform/TransformFire.ts b/compiler/packages/babel-plugin-react-compiler/src/Transform/TransformFire.ts index 6793df5710..f118b70258 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Transform/TransformFire.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Transform/TransformFire.ts @@ -5,7 +5,11 @@ * LICENSE file in the root directory of this source tree. */ -import {CompilerError, CompilerErrorDetailOptions, SourceLocation} from '..'; +import { + CompilerErrorDetail, + CompilerErrorDetailOptions, + SourceLocation, +} from '..'; import { ArrayExpression, CallExpression, @@ -54,7 +58,6 @@ export function transformFire(fn: HIRFunction): void { if (!context.hasErrors()) { ensureNoMoreFireUses(fn, context); } - context.throwIfErrorsFound(); } function replaceFireFunctions(fn: HIRFunction, context: Context): void { @@ -526,7 +529,7 @@ type FireCalleesToFireFunctionBinding = Map< class Context { #env: Environment; - #errors: CompilerError = new CompilerError(); + #hasErrors: boolean = false; /* * Used to look up the call expression passed to a `fire(callExpr())`. Gives back @@ -589,7 +592,8 @@ class Context { #arrayExpressions = new Map(); pushError(error: CompilerErrorDetailOptions): void { - this.#errors.push(error); + this.#hasErrors = true; + this.#env.recordError(new CompilerErrorDetail(error)); } withFunctionScope(fn: () => void): FireCalleesToFireFunctionBinding { @@ -698,11 +702,7 @@ class Context { } hasErrors(): boolean { - return this.#errors.hasAnyErrors(); - } - - throwIfErrorsFound(): void { - if (this.hasErrors()) throw this.#errors; + return this.#hasErrors; } } diff --git a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateExhaustiveDependencies.ts b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateExhaustiveDependencies.ts index 89bcea69bf..263891ba96 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateExhaustiveDependencies.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateExhaustiveDependencies.ts @@ -100,7 +100,6 @@ export function validateExhaustiveDependencies(fn: HIRFunction): void { loc: place.loc, }); } - const error = new CompilerError(); let startMemo: StartMemoize | null = null; function onStartMemoize( @@ -141,7 +140,7 @@ export function validateExhaustiveDependencies(fn: HIRFunction): void { 'all', ); if (diagnostic != null) { - error.pushDiagnostic(diagnostic); + fn.env.recordError(diagnostic); } } @@ -206,15 +205,12 @@ export function validateExhaustiveDependencies(fn: HIRFunction): void { effectReportMode, ); if (diagnostic != null) { - error.pushDiagnostic(diagnostic); + fn.env.recordError(diagnostic); } }, }, false, // isFunctionExpression ); - if (error.hasAnyErrors()) { - fn.env.recordErrors(error); - } } function validateDependencies( diff --git a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateHooksUsage.ts b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateHooksUsage.ts index cb1ac68e61..a243929dde 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateHooksUsage.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateHooksUsage.ts @@ -6,13 +6,9 @@ */ import * as t from '@babel/types'; -import { - CompilerError, - CompilerErrorDetail, - ErrorCategory, -} from '../CompilerError'; +import {CompilerErrorDetail, ErrorCategory} from '../CompilerError'; import {computeUnconditionalBlocks} from '../HIR/ComputeUnconditionalBlocks'; -import {isHookName} from '../HIR/Environment'; +import {Environment, isHookName} from '../HIR/Environment'; import { HIRFunction, IdentifierId, @@ -90,15 +86,14 @@ function joinKinds(a: Kind, b: Kind): Kind { export function validateHooksUsage(fn: HIRFunction): void { const unconditionalBlocks = computeUnconditionalBlocks(fn); - const errors = new CompilerError(); const errorsByPlace = new Map(); - function recordError( + function trackError( loc: SourceLocation, errorDetail: CompilerErrorDetail, ): void { if (typeof loc === 'symbol') { - errors.pushErrorDetail(errorDetail); + fn.env.recordError(errorDetail); } else { errorsByPlace.set(loc, errorDetail); } @@ -118,7 +113,7 @@ export function validateHooksUsage(fn: HIRFunction): void { * If that same place is also used as a conditional call, upgrade the error to a conditonal hook error */ if (previousError === undefined || previousError.reason !== reason) { - recordError( + trackError( place.loc, new CompilerErrorDetail({ category: ErrorCategory.Hooks, @@ -134,7 +129,7 @@ export function validateHooksUsage(fn: HIRFunction): void { const previousError = typeof place.loc !== 'symbol' ? errorsByPlace.get(place.loc) : undefined; if (previousError === undefined) { - recordError( + trackError( place.loc, new CompilerErrorDetail({ category: ErrorCategory.Hooks, @@ -151,7 +146,7 @@ export function validateHooksUsage(fn: HIRFunction): void { const previousError = typeof place.loc !== 'symbol' ? errorsByPlace.get(place.loc) : undefined; if (previousError === undefined) { - recordError( + trackError( place.loc, new CompilerErrorDetail({ category: ErrorCategory.Hooks, @@ -396,7 +391,7 @@ export function validateHooksUsage(fn: HIRFunction): void { } case 'ObjectMethod': case 'FunctionExpression': { - visitFunctionExpression(errors, instr.value.loweredFunc.func); + visitFunctionExpression(fn.env, instr.value.loweredFunc.func); break; } default: { @@ -421,20 +416,17 @@ export function validateHooksUsage(fn: HIRFunction): void { } for (const [, error] of errorsByPlace) { - errors.pushErrorDetail(error); - } - if (errors.hasAnyErrors()) { - fn.env.recordErrors(errors); + fn.env.recordError(error); } } -function visitFunctionExpression(errors: CompilerError, fn: HIRFunction): void { +function visitFunctionExpression(env: Environment, fn: HIRFunction): void { for (const [, block] of fn.body.blocks) { for (const instr of block.instructions) { switch (instr.value.kind) { case 'ObjectMethod': case 'FunctionExpression': { - visitFunctionExpression(errors, instr.value.loweredFunc.func); + visitFunctionExpression(env, instr.value.loweredFunc.func); break; } case 'MethodCall': @@ -445,7 +437,7 @@ function visitFunctionExpression(errors: CompilerError, fn: HIRFunction): void { : instr.value.property; const hookKind = getHookKind(fn.env, callee.identifier); if (hookKind != null) { - errors.pushErrorDetail( + env.recordError( new CompilerErrorDetail({ category: ErrorCategory.Hooks, reason: diff --git a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateMemoizedEffectDependencies.ts b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateMemoizedEffectDependencies.ts index 7e07080a18..4efe4896da 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateMemoizedEffectDependencies.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateMemoizedEffectDependencies.ts @@ -5,8 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {CompilerError} from '..'; -import {ErrorCategory} from '../CompilerError'; +import {CompilerErrorDetail, ErrorCategory} from '../CompilerError'; import { Identifier, Instruction, @@ -18,6 +17,7 @@ import { isUseInsertionEffectHookType, isUseLayoutEffectHookType, } from '../HIR'; +import {Environment} from '../HIR/Environment'; import {isMutable} from '../ReactiveScopes/InferReactiveScopeVariables'; import { ReactiveFunctionVisitor, @@ -49,17 +49,15 @@ import { * ``` */ export function validateMemoizedEffectDependencies(fn: ReactiveFunction): void { - const errors = new CompilerError(); - visitReactiveFunction(fn, new Visitor(), errors); - fn.env.recordErrors(errors); + visitReactiveFunction(fn, new Visitor(), fn.env); } -class Visitor extends ReactiveFunctionVisitor { +class Visitor extends ReactiveFunctionVisitor { scopes: Set = new Set(); override visitScope( scopeBlock: ReactiveScopeBlock, - state: CompilerError, + state: Environment, ): void { this.traverseScope(scopeBlock, state); @@ -87,7 +85,7 @@ class Visitor extends ReactiveFunctionVisitor { override visitInstruction( instruction: ReactiveInstruction, - state: CompilerError, + state: Environment, ): void { this.traverseInstruction(instruction, state); if ( @@ -105,14 +103,16 @@ class Visitor extends ReactiveFunctionVisitor { (isMutable(instruction as Instruction, deps) || isUnmemoized(deps.identifier, this.scopes)) ) { - state.push({ - category: ErrorCategory.EffectDependencies, - reason: - 'React Compiler has skipped optimizing this component because the effect dependencies could not be memoized. Unmemoized effect dependencies can trigger an infinite loop or other unexpected behavior', - description: null, - loc: typeof instruction.loc !== 'symbol' ? instruction.loc : null, - suggestions: null, - }); + state.recordError( + new CompilerErrorDetail({ + category: ErrorCategory.EffectDependencies, + reason: + 'React Compiler has skipped optimizing this component because the effect dependencies could not be memoized. Unmemoized effect dependencies can trigger an infinite loop or other unexpected behavior', + description: null, + loc: typeof instruction.loc !== 'symbol' ? instruction.loc : null, + suggestions: null, + }), + ); } } } diff --git a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoCapitalizedCalls.ts b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoCapitalizedCalls.ts index 4347860489..e6cf9b1667 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoCapitalizedCalls.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoCapitalizedCalls.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {CompilerError, CompilerErrorDetail, EnvironmentConfig} from '..'; +import {CompilerErrorDetail, EnvironmentConfig} from '..'; import {ErrorCategory} from '../CompilerError'; import {HIRFunction, IdentifierId} from '../HIR'; import {DEFAULT_GLOBALS} from '../HIR/Globals'; @@ -28,7 +28,6 @@ export function validateNoCapitalizedCalls(fn: HIRFunction): void { ); }; - const errors = new CompilerError(); const capitalLoadGlobals = new Map(); const capitalizedProperties = new Map(); const reason = @@ -80,20 +79,19 @@ export function validateNoCapitalizedCalls(fn: HIRFunction): void { const propertyIdentifier = value.property.identifier.id; const propertyName = capitalizedProperties.get(propertyIdentifier); if (propertyName != null) { - errors.push({ - category: ErrorCategory.CapitalizedCalls, - reason, - description: `${propertyName} may be a component`, - loc: value.loc, - suggestions: null, - }); + fn.env.recordError( + new CompilerErrorDetail({ + category: ErrorCategory.CapitalizedCalls, + reason, + description: `${propertyName} may be a component`, + loc: value.loc, + suggestions: null, + }), + ); } break; } } } } - if (errors.hasAnyErrors()) { - fn.env.recordErrors(errors); - } } diff --git a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoDerivedComputationsInEffects.ts b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoDerivedComputationsInEffects.ts index 09c30a692a..380f244331 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoDerivedComputationsInEffects.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoDerivedComputationsInEffects.ts @@ -6,7 +6,7 @@ */ import {CompilerError, SourceLocation} from '..'; -import {ErrorCategory} from '../CompilerError'; +import {CompilerErrorDetail, ErrorCategory} from '../CompilerError'; import { ArrayExpression, BlockId, @@ -20,6 +20,7 @@ import { eachInstructionValueOperand, eachTerminalOperand, } from '../HIR/visitors'; +import {Environment} from '../HIR/Environment'; /** * Validates that useEffect is not used for derived computations which could/should @@ -49,8 +50,6 @@ export function validateNoDerivedComputationsInEffects(fn: HIRFunction): void { const functions: Map = new Map(); const locals: Map = new Map(); - const errors = new CompilerError(); - for (const block of fn.body.blocks.values()) { for (const instr of block.instructions) { const {lvalue, value} = instr; @@ -90,20 +89,19 @@ export function validateNoDerivedComputationsInEffects(fn: HIRFunction): void { validateEffect( effectFunction.loweredFunc.func, dependencies, - errors, + fn.env, ); } } } } } - fn.env.recordErrors(errors); } function validateEffect( effectFunction: HIRFunction, effectDeps: Array, - errors: CompilerError, + env: Environment, ): void { for (const operand of effectFunction.context) { if (isSetStateType(operand.identifier)) { @@ -217,13 +215,15 @@ function validateEffect( } for (const loc of setStateLocations) { - errors.push({ - category: ErrorCategory.EffectDerivationsOfState, - reason: - 'Values derived from props and state should be calculated during render, not in an effect. (https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state)', - description: null, - loc, - suggestions: null, - }); + env.recordError( + new CompilerErrorDetail({ + category: ErrorCategory.EffectDerivationsOfState, + reason: + 'Values derived from props and state should be calculated during render, not in an effect. (https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state)', + description: null, + loc, + suggestions: null, + }), + ); } } diff --git a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoFreezingKnownMutableFunctions.ts b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoFreezingKnownMutableFunctions.ts index d0a786c7b4..3fc28ffb9e 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoFreezingKnownMutableFunctions.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoFreezingKnownMutableFunctions.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {CompilerDiagnostic, CompilerError, Effect} from '..'; +import {CompilerDiagnostic, Effect} from '..'; import {ErrorCategory} from '../CompilerError'; import { HIRFunction, @@ -43,7 +43,6 @@ import {AliasingEffect} from '../Inference/AliasingEffects'; * that are passed where a frozen value is expected and rejects them. */ export function validateNoFreezingKnownMutableFunctions(fn: HIRFunction): void { - const errors = new CompilerError(); const contextMutationEffects: Map< IdentifierId, Extract @@ -60,7 +59,7 @@ export function validateNoFreezingKnownMutableFunctions(fn: HIRFunction): void { place.identifier.name.kind === 'named' ? `\`${place.identifier.name.value}\`` : 'a local variable'; - errors.pushDiagnostic( + fn.env.recordError( CompilerDiagnostic.create({ category: ErrorCategory.Immutability, reason: 'Cannot modify local variables after render completes', @@ -159,7 +158,4 @@ export function validateNoFreezingKnownMutableFunctions(fn: HIRFunction): void { visitOperand(operand); } } - if (errors.hasAnyErrors()) { - fn.env.recordErrors(errors); - } } diff --git a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoImpureFunctionsInRender.ts b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoImpureFunctionsInRender.ts index 3b89aaccfa..ba089fbd1b 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoImpureFunctionsInRender.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoImpureFunctionsInRender.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {CompilerDiagnostic, CompilerError} from '..'; +import {CompilerDiagnostic} from '..'; import {ErrorCategory} from '../CompilerError'; import {HIRFunction} from '../HIR'; import {getFunctionCallSignature} from '../Inference/InferMutationAliasingEffects'; @@ -20,7 +20,6 @@ import {getFunctionCallSignature} from '../Inference/InferMutationAliasingEffect * and use it here. */ export function validateNoImpureFunctionsInRender(fn: HIRFunction): void { - const errors = new CompilerError(); for (const [, block] of fn.body.blocks) { for (const instr of block.instructions) { const value = instr.value; @@ -32,7 +31,7 @@ export function validateNoImpureFunctionsInRender(fn: HIRFunction): void { callee.identifier.type, ); if (signature != null && signature.impure === true) { - errors.pushDiagnostic( + fn.env.recordError( CompilerDiagnostic.create({ category: ErrorCategory.Purity, reason: 'Cannot call impure function during render', @@ -52,7 +51,4 @@ export function validateNoImpureFunctionsInRender(fn: HIRFunction): void { } } } - if (errors.hasAnyErrors()) { - fn.env.recordErrors(errors); - } } diff --git a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoRefAccessInRender.ts b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoRefAccessInRender.ts index d59b9ee68e..d023a4e29b 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoRefAccessInRender.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoRefAccessInRender.ts @@ -126,8 +126,8 @@ export function validateNoRefAccessInRender(fn: HIRFunction): void { collectTemporariesSidemap(fn, env); const errors = new CompilerError(); validateNoRefAccessInRenderImpl(fn, env, errors); - if (errors.hasAnyErrors()) { - fn.env.recordErrors(errors); + for (const detail of errors.details) { + fn.env.recordError(detail); } } diff --git a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoSetStateInRender.ts b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoSetStateInRender.ts index 3fb6f1ad42..43db751107 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoSetStateInRender.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoSetStateInRender.ts @@ -48,8 +48,8 @@ export function validateNoSetStateInRender(fn: HIRFunction): void { fn, unconditionalSetStateFunctions, ); - if (errors.hasAnyErrors()) { - fn.env.recordErrors(errors); + for (const detail of errors.details) { + fn.env.recordError(detail); } } diff --git a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidatePreservedManualMemoization.ts b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidatePreservedManualMemoization.ts index 2434e25f01..f974cf2bb3 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidatePreservedManualMemoization.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidatePreservedManualMemoization.ts @@ -27,6 +27,7 @@ import { ScopeId, SourceLocation, } from '../HIR'; +import {Environment} from '../HIR/Environment'; import {printIdentifier, printManualMemoDependency} from '../HIR/PrintHIR'; import { eachInstructionValueLValue, @@ -48,11 +49,10 @@ import {getOrInsertDefault} from '../Utils/utils'; */ export function validatePreservedManualMemoization(fn: ReactiveFunction): void { const state = { - errors: new CompilerError(), + env: fn.env, manualMemoState: null, }; visitReactiveFunction(fn, new Visitor(), state); - fn.env.recordErrors(state.errors); } const DEBUG = false; @@ -110,7 +110,7 @@ type ManualMemoBlockState = { }; type VisitorState = { - errors: CompilerError; + env: Environment; manualMemoState: ManualMemoBlockState | null; }; @@ -230,7 +230,7 @@ function validateInferredDep( temporaries: Map, declsWithinMemoBlock: Set, validDepsInMemoBlock: Array, - errorState: CompilerError, + errorState: Environment, memoLocation: SourceLocation, ): void { let normalizedDep: ManualMemoDependency; @@ -280,7 +280,7 @@ function validateInferredDep( errorDiagnostic = merge(errorDiagnostic ?? compareResult, compareResult); } } - errorState.pushDiagnostic( + errorState.recordError( CompilerDiagnostic.create({ category: ErrorCategory.PreserveManualMemo, reason: 'Existing memoization could not be preserved', @@ -426,7 +426,7 @@ class Visitor extends ReactiveFunctionVisitor { this.temporaries, state.manualMemoState.decls, state.manualMemoState.depsFromSource, - state.errors, + state.env, state.manualMemoState.loc, ); } @@ -529,7 +529,7 @@ class Visitor extends ReactiveFunctionVisitor { !this.scopes.has(identifier.scope.id) && !this.prunedScopes.has(identifier.scope.id) ) { - state.errors.pushDiagnostic( + state.env.recordError( CompilerDiagnostic.create({ category: ErrorCategory.PreserveManualMemo, reason: 'Existing memoization could not be preserved', @@ -575,7 +575,7 @@ class Visitor extends ReactiveFunctionVisitor { for (const identifier of decls) { if (isUnmemoized(identifier, this.scopes)) { - state.errors.pushDiagnostic( + state.env.recordError( CompilerDiagnostic.create({ category: ErrorCategory.PreserveManualMemo, reason: 'Existing memoization could not be preserved', diff --git a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateSourceLocations.ts b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateSourceLocations.ts index a1ae4c55bd..50f4c0e160 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateSourceLocations.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateSourceLocations.ts @@ -7,7 +7,7 @@ import {NodePath} from '@babel/traverse'; import * as t from '@babel/types'; -import {CompilerDiagnostic, CompilerError, ErrorCategory} from '..'; +import {CompilerDiagnostic, ErrorCategory} from '..'; import {CodegenFunction} from '../ReactiveScopes'; import {Environment} from '../HIR/Environment'; @@ -125,8 +125,6 @@ export function validateSourceLocations( generatedAst: CodegenFunction, env: Environment, ): void { - const errors = new CompilerError(); - /* * Step 1: Collect important locations from the original source * Note: Multiple node types can share the same location (e.g. VariableDeclarator and Identifier) @@ -241,7 +239,7 @@ export function validateSourceLocations( loc: t.SourceLocation, nodeType: string, ): void => { - errors.pushDiagnostic( + env.recordError( CompilerDiagnostic.create({ category: ErrorCategory.Todo, reason: 'Important source location missing in generated code', @@ -261,7 +259,7 @@ export function validateSourceLocations( expectedType: string, actualTypes: Set, ): void => { - errors.pushDiagnostic( + env.recordError( CompilerDiagnostic.create({ category: ErrorCategory.Todo, reason: @@ -309,6 +307,4 @@ export function validateSourceLocations( } } } - - env.recordErrors(errors); } diff --git a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateUseMemo.ts b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateUseMemo.ts index b223fac523..87c6ebd1a2 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateUseMemo.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateUseMemo.ts @@ -16,13 +16,13 @@ import { IdentifierId, SourceLocation, } from '../HIR'; +import {Environment} from '../HIR/Environment'; import { eachInstructionValueOperand, eachTerminalOperand, } from '../HIR/visitors'; export function validateUseMemo(fn: HIRFunction): void { - const errors = new CompilerError(); const voidMemoErrors = new CompilerError(); const useMemos = new Set(); const react = new Set(); @@ -90,7 +90,7 @@ export function validateUseMemo(fn: HIRFunction): void { firstParam.kind === 'Identifier' ? firstParam.loc : firstParam.place.loc; - errors.pushDiagnostic( + fn.env.recordError( CompilerDiagnostic.create({ category: ErrorCategory.UseMemo, reason: 'useMemo() callbacks may not accept parameters', @@ -106,7 +106,7 @@ export function validateUseMemo(fn: HIRFunction): void { } if (body.loweredFunc.func.async || body.loweredFunc.func.generator) { - errors.pushDiagnostic( + fn.env.recordError( CompilerDiagnostic.create({ category: ErrorCategory.UseMemo, reason: @@ -122,7 +122,7 @@ export function validateUseMemo(fn: HIRFunction): void { ); } - validateNoContextVariableAssignment(body.loweredFunc.func, errors); + validateNoContextVariableAssignment(body.loweredFunc.func, fn.env); if (fn.env.config.validateNoVoidUseMemo) { if (!hasNonVoidReturn(body.loweredFunc.func)) { @@ -176,14 +176,11 @@ export function validateUseMemo(fn: HIRFunction): void { } } fn.env.logErrors(voidMemoErrors.asResult()); - if (errors.hasAnyErrors()) { - fn.env.recordErrors(errors); - } } function validateNoContextVariableAssignment( fn: HIRFunction, - errors: CompilerError, + env: Environment, ): void { const context = new Set(fn.context.map(place => place.identifier.id)); for (const block of fn.body.blocks.values()) { @@ -192,7 +189,7 @@ function validateNoContextVariableAssignment( switch (value.kind) { case 'StoreContext': { if (context.has(value.lvalue.place.identifier.id)) { - errors.pushDiagnostic( + env.recordError( CompilerDiagnostic.create({ category: ErrorCategory.UseMemo, reason: diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/bailout-capitalized-fn-call.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/bailout-capitalized-fn-call.expect.md index 5f02716d95..d1fd19c005 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/bailout-capitalized-fn-call.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/bailout-capitalized-fn-call.expect.md @@ -24,7 +24,7 @@ function Component({prop1, bar}) { ## Code ```javascript -import { c as _c, useFire } from "react/compiler-runtime"; // @validateNoCapitalizedCalls @enableFire @panicThreshold:"none" +import { useFire } from "react/compiler-runtime"; // @validateNoCapitalizedCalls @enableFire @panicThreshold:"none" import { fire } from "react"; const CapitalizedCall = require("shared-runtime").sum; diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/no-fire-todo-syntax-shouldnt-throw.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/no-fire-todo-syntax-shouldnt-throw.expect.md index 58a942b580..459e0becd1 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/no-fire-todo-syntax-shouldnt-throw.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/no-fire-todo-syntax-shouldnt-throw.expect.md @@ -68,7 +68,7 @@ function NonFireComponent({ prop1 }) { function FireComponent(props) { const $ = _c(3); - const foo = _temp3; + const foo = _temp; const t0 = useFire(foo); let t1; if ($[0] !== props || $[1] !== t0) { @@ -85,7 +85,7 @@ function FireComponent(props) { return null; } -function _temp3(props_0) { +function _temp(props_0) { console.log(props_0); } diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-validate-conditional-hook.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-validate-conditional-hook.expect.md index cdd56fe7af..0099c65c92 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-validate-conditional-hook.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-validate-conditional-hook.expect.md @@ -29,7 +29,7 @@ function Component(props) { ## Code ```javascript -import { c as _c, useFire } from "react/compiler-runtime"; // @enableFire @panicThreshold:"none" +import { useFire } from "react/compiler-runtime"; // @enableFire @panicThreshold:"none" import { fire, useEffect } from "react"; import { Stringify } from "shared-runtime"; @@ -38,7 +38,7 @@ import { Stringify } from "shared-runtime"; * hook usage) disabled */ function Component(props) { - const foo = _temp2; + const foo = _temp; if (props.cond) { const t0 = useFire(foo); @@ -49,7 +49,7 @@ function Component(props) { return ; } -function _temp2(props_0) { +function _temp(props_0) { console.log(props_0); } diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/repro-dont-add-hook-guards-on-retry.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/repro-dont-add-hook-guards-on-retry.expect.md index 2887c071ef..2ad6dea688 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/repro-dont-add-hook-guards-on-retry.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/repro-dont-add-hook-guards-on-retry.expect.md @@ -23,15 +23,14 @@ function Component(props, useDynamicHook) { ## Code ```javascript -import { $dispatcherGuard } from "react-compiler-runtime"; -import { c as _c, useFire } from "react/compiler-runtime"; +import { useFire } from "react/compiler-runtime"; import { useEffect, fire } from "react"; function Component(props, useDynamicHook) { "use memo"; useDynamicHook(); - const foo = _temp2; + const foo = _temp; const t0 = useFire(foo); useEffect(() => { @@ -40,7 +39,7 @@ function Component(props, useDynamicHook) { return
hello world
; } -function _temp2(props_0) { +function _temp(props_0) { console.log(props_0); }