diff --git a/compiler/packages/babel-plugin-react-compiler/src/CompilerError.ts b/compiler/packages/babel-plugin-react-compiler/src/CompilerError.ts index 52c06825d9bbc..9d34f4fc84263 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/CompilerError.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/CompilerError.ts @@ -37,7 +37,7 @@ export enum ErrorSeverity { export type CompilerDiagnosticOptions = { category: ErrorCategory; reason: string; - description: string; + description: string | null; details: Array; suggestions?: Array | null | undefined; }; @@ -49,7 +49,7 @@ export type CompilerDiagnosticDetail = | { kind: 'error'; loc: SourceLocation | null; - message: string; + message: string | null; } | { kind: 'hint'; @@ -126,8 +126,8 @@ export class CompilerDiagnostic { return this.options.category; } - withDetail(detail: CompilerDiagnosticDetail): CompilerDiagnostic { - this.options.details.push(detail); + withDetails(...details: Array): CompilerDiagnostic { + this.options.details.push(...details); return this; } @@ -155,9 +155,9 @@ export class CompilerDiagnostic { } let codeFrame: string; try { - codeFrame = printCodeFrame(source, loc, detail.message); + codeFrame = printCodeFrame(source, loc, detail.message ?? ''); } catch (e) { - codeFrame = detail.message; + codeFrame = detail.message ?? ''; } buffer.push('\n\n'); if (loc.filename != null) { @@ -284,15 +284,16 @@ export class CompilerError extends Error { static invariant( condition: unknown, - options: Omit, + options: Omit, ): asserts condition { if (!condition) { const errors = new CompilerError(); - errors.pushErrorDetail( - new CompilerErrorDetail({ - ...options, + errors.pushDiagnostic( + CompilerDiagnostic.create({ + reason: options.reason, + description: options.description, category: ErrorCategory.Invariant, - }), + }).withDetails(...options.details), ); throw errors; } diff --git a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Gating.ts b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Gating.ts index 679389277b59e..00b61e877fa3b 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Gating.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Gating.ts @@ -51,12 +51,26 @@ function insertAdditionalFunctionDeclaration( CompilerError.invariant(originalFnName != null && compiled.id != null, { reason: 'Expected function declarations that are referenced elsewhere to have a named identifier', - loc: fnPath.node.loc ?? null, + description: null, + details: [ + { + kind: 'error', + loc: fnPath.node.loc ?? null, + message: null, + }, + ], }); CompilerError.invariant(originalFnParams.length === compiledParams.length, { reason: 'Expected React Compiler optimized function declarations to have the same number of parameters as source', - loc: fnPath.node.loc ?? null, + description: null, + details: [ + { + kind: 'error', + loc: fnPath.node.loc ?? null, + message: null, + }, + ], }); const gatingCondition = t.identifier( @@ -140,7 +154,13 @@ export function insertGatedFunctionDeclaration( CompilerError.invariant(compiled.type === 'FunctionDeclaration', { reason: 'Expected compiled node type to match input type', description: `Got ${compiled.type} but expected FunctionDeclaration`, - loc: fnPath.node.loc ?? null, + details: [ + { + kind: 'error', + loc: fnPath.node.loc ?? null, + message: null, + }, + ], }); insertAdditionalFunctionDeclaration( fnPath, diff --git a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Imports.ts b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Imports.ts index 75f3d26ad0f33..7832143b66efd 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Imports.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Imports.ts @@ -257,7 +257,13 @@ export function addImportsToProgram( reason: 'Encountered conflicting import specifiers in generated program', description: `Conflict from import ${loweredImport.module}:(${loweredImport.imported} as ${loweredImport.name}).`, - loc: GeneratedSource, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], suggestions: null, }, ); @@ -268,7 +274,13 @@ export function addImportsToProgram( reason: 'Found inconsistent import specifier. This is an internal bug.', description: `Expected import ${moduleName}:${specifierName} but found ${loweredImport.module}:${loweredImport.imported}`, - loc: GeneratedSource, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], }, ); } diff --git a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts index f57ca5d33e9ea..dd4cfd819adf4 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts @@ -310,7 +310,13 @@ function insertNewOutlinedFunctionNode( CompilerError.invariant(insertedFuncDecl.isFunctionDeclaration(), { reason: 'Expected inserted function declaration', description: `Got: ${insertedFuncDecl}`, - loc: insertedFuncDecl.node?.loc ?? null, + details: [ + { + kind: 'error', + loc: insertedFuncDecl.node?.loc ?? null, + message: null, + }, + ], }); return insertedFuncDecl; } @@ -419,7 +425,14 @@ export function compileProgram( for (const outlined of compiled.outlined) { CompilerError.invariant(outlined.fn.outlined.length === 0, { reason: 'Unexpected nested outlined functions', - loc: outlined.fn.loc, + description: null, + details: [ + { + kind: 'error', + loc: outlined.fn.loc, + message: null, + }, + ], }); const fn = insertNewOutlinedFunctionNode( program, @@ -1407,7 +1420,13 @@ export function getReactCompilerRuntimeModule( { reason: 'Expected target to already be validated', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }, ); diff --git a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Suppression.ts b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Suppression.ts index d432714704918..509ed72966758 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Suppression.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Suppression.ts @@ -152,7 +152,14 @@ export function suppressionsToCompilerError( ): CompilerError { CompilerError.invariant(suppressionRanges.length !== 0, { reason: `Expected at least suppression comment source range`, - loc: GeneratedSource, + description: null, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], }); const error = new CompilerError(); for (const suppressionRange of suppressionRanges) { @@ -196,7 +203,7 @@ export function suppressionsToCompilerError( op: CompilerSuggestionOperation.Remove, }, ], - }).withDetail({ + }).withDetails({ kind: 'error', loc: suppressionRange.disableComment.loc ?? null, message: 'Found React rule suppression', diff --git a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/ValidateNoUntransformedReferences.ts b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/ValidateNoUntransformedReferences.ts index 4f0b80ca918c8..de66b834dfdb7 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/ValidateNoUntransformedReferences.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/ValidateNoUntransformedReferences.ts @@ -217,7 +217,14 @@ function validateImportSpecifier( const binding = local.scope.getBinding(local.node.name); CompilerError.invariant(binding != null, { reason: 'Expected binding to be found for import specifier', - loc: local.node.loc ?? null, + description: null, + details: [ + { + kind: 'error', + loc: local.node.loc ?? null, + message: null, + }, + ], }); checkFn(binding.referencePaths, state); } @@ -237,7 +244,14 @@ function validateNamespacedImport( CompilerError.invariant(binding != null, { reason: 'Expected binding to be found for import specifier', - loc: local.node.loc ?? null, + description: null, + details: [ + { + kind: 'error', + loc: local.node.loc ?? null, + message: null, + }, + ], }); const filteredReferences = new Map< CheckInvalidReferenceFn, diff --git a/compiler/packages/babel-plugin-react-compiler/src/Flood/TypeErrors.ts b/compiler/packages/babel-plugin-react-compiler/src/Flood/TypeErrors.ts index fa3f551ff5fc3..6f6b3d83915b6 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Flood/TypeErrors.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Flood/TypeErrors.ts @@ -46,7 +46,14 @@ export function raiseUnificationErrors( if (errs.length === 0) { CompilerError.invariant(false, { reason: 'Should not have array of zero errors', - loc, + description: null, + details: [ + { + kind: 'error', + loc, + message: null, + }, + ], }); } else if (errs.length === 1) { CompilerError.throwInvalidJS({ diff --git a/compiler/packages/babel-plugin-react-compiler/src/Flood/Types.ts b/compiler/packages/babel-plugin-react-compiler/src/Flood/Types.ts index 21391b197b798..bfe8f47a58e5b 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Flood/Types.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Flood/Types.ts @@ -152,7 +152,13 @@ export function makeLinearId(id: number): LinearId { CompilerError.invariant(id >= 0 && Number.isInteger(id), { reason: 'Expected LinearId id to be a non-negative integer', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); return id as LinearId; @@ -167,7 +173,13 @@ export function makeTypeParameterId(id: number): TypeParameterId { CompilerError.invariant(id >= 0 && Number.isInteger(id), { reason: 'Expected TypeParameterId to be a non-negative integer', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); return id as TypeParameterId; @@ -191,7 +203,13 @@ export function makeVariableId(id: number): VariableId { CompilerError.invariant(id >= 0 && Number.isInteger(id), { reason: 'Expected VariableId id to be a non-negative integer', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); return id as VariableId; @@ -399,7 +417,14 @@ function convertFlowType(flowType: FlowType, loc: string): ResolvedType { } else { CompilerError.invariant(false, { reason: `Unsupported property kind ${prop.kind}`, - loc: GeneratedSource, + description: null, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], }); } } @@ -468,7 +493,14 @@ function convertFlowType(flowType: FlowType, loc: string): ResolvedType { } else { CompilerError.invariant(false, { reason: `Unsupported property kind ${prop.kind}`, - loc: GeneratedSource, + description: null, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], }); } } @@ -487,7 +519,14 @@ function convertFlowType(flowType: FlowType, loc: string): ResolvedType { } else { CompilerError.invariant(false, { reason: `Unsupported property kind ${prop.kind}`, - loc: GeneratedSource, + description: null, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], }); } } @@ -500,7 +539,14 @@ function convertFlowType(flowType: FlowType, loc: string): ResolvedType { } CompilerError.invariant(false, { reason: `Unsupported class instance type ${flowType.def.type.kind}`, - loc: GeneratedSource, + description: null, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], }); } case 'Fun': @@ -559,7 +605,14 @@ function convertFlowType(flowType: FlowType, loc: string): ResolvedType { } else { CompilerError.invariant(false, { reason: `Unsupported component props type ${propsType.type.kind}`, - loc: GeneratedSource, + description: null, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], }); } @@ -712,7 +765,14 @@ export class FlowTypeEnv implements ITypeEnv { // TODO: use flow-js only for web environments (e.g. playground) CompilerError.invariant(env.config.flowTypeProvider != null, { reason: 'Expected flowDumpTypes to be defined in environment config', - loc: GeneratedSource, + description: null, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], }); let stdout: any; if (source === lastFlowSource) { diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/AssertConsistentIdentifiers.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/AssertConsistentIdentifiers.ts index 2588ee1f9a8da..68562f97b0a33 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/AssertConsistentIdentifiers.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/AssertConsistentIdentifiers.ts @@ -38,7 +38,13 @@ export function assertConsistentIdentifiers(fn: HIRFunction): void { CompilerError.invariant(instr.lvalue.identifier.name === null, { reason: `Expected all lvalues to be temporaries`, description: `Found named lvalue \`${instr.lvalue.identifier.name}\``, - loc: instr.lvalue.loc, + details: [ + { + kind: 'error', + loc: instr.lvalue.loc, + message: null, + }, + ], suggestions: null, }); CompilerError.invariant(!assignments.has(instr.lvalue.identifier.id), { @@ -46,7 +52,13 @@ export function assertConsistentIdentifiers(fn: HIRFunction): void { description: `Found duplicate assignment of '${printPlace( instr.lvalue, )}'`, - loc: instr.lvalue.loc, + details: [ + { + kind: 'error', + loc: instr.lvalue.loc, + message: null, + }, + ], suggestions: null, }); assignments.add(instr.lvalue.identifier.id); @@ -77,7 +89,13 @@ function validate( CompilerError.invariant(identifier === previous, { reason: `Duplicate identifier object`, description: `Found duplicate identifier object for id ${identifier.id}`, - loc: loc ?? GeneratedSource, + details: [ + { + kind: 'error', + loc: loc ?? GeneratedSource, + message: null, + }, + ], suggestions: null, }); } diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/AssertTerminalBlocksExist.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/AssertTerminalBlocksExist.ts index e696fddbdeb26..f42b5a17f114f 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/AssertTerminalBlocksExist.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/AssertTerminalBlocksExist.ts @@ -18,7 +18,13 @@ export function assertTerminalSuccessorsExist(fn: HIRFunction): void { description: `Block bb${successor} does not exist for terminal '${printTerminal( block.terminal, )}'`, - loc: (block.terminal as any).loc ?? GeneratedSource, + details: [ + { + kind: 'error', + loc: (block.terminal as any).loc ?? GeneratedSource, + message: null, + }, + ], suggestions: null, }); return successor; @@ -33,14 +39,26 @@ export function assertTerminalPredsExist(fn: HIRFunction): void { CompilerError.invariant(predBlock != null, { reason: 'Expected predecessor block to exist', description: `Block ${block.id} references non-existent ${pred}`, - loc: GeneratedSource, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], }); CompilerError.invariant( [...eachTerminalSuccessor(predBlock.terminal)].includes(block.id), { reason: 'Terminal successor does not reference correct predecessor', description: `Block bb${block.id} has bb${predBlock.id} as a predecessor, but bb${predBlock.id}'s successors do not include bb${block.id}`, - loc: GeneratedSource, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], }, ); } diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/AssertValidBlockNesting.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/AssertValidBlockNesting.ts index adfb0510582cd..bc6956b6461ac 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/AssertValidBlockNesting.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/AssertValidBlockNesting.ts @@ -131,7 +131,13 @@ export function recursivelyTraverseItems( CompilerError.invariant(disjoint || nested, { reason: 'Invalid nesting in program blocks or scopes', description: `Items overlap but are not nested: ${maybeParentRange.start}:${maybeParentRange.end}(${currRange.start}:${currRange.end})`, - loc: GeneratedSource, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], }); if (disjoint) { exit(maybeParent, context); diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/AssertValidMutableRanges.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/AssertValidMutableRanges.ts index 773986a1b5e77..0888f4ae7312a 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/AssertValidMutableRanges.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/AssertValidMutableRanges.ts @@ -57,7 +57,13 @@ function validateMutableRange( { reason: `Invalid mutable range: [${range.start}:${range.end}]`, description: `${printPlace(place)} in ${description}`, - loc: place.loc, + details: [ + { + kind: 'error', + loc: place.loc, + message: null, + }, + ], }, ); } 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 457f54495f647..9df7ce5c81968 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts @@ -110,7 +110,7 @@ export function lower( category: ErrorCategory.Invariant, reason: 'Could not find binding', description: `[BuildHIR] Could not find binding for param \`${param.node.name}\`.`, - }).withDetail({ + }).withDetails({ kind: 'error', loc: param.node.loc ?? null, message: 'Could not find binding', @@ -174,7 +174,7 @@ export function lower( category: ErrorCategory.Todo, reason: `Handle ${param.node.type} parameters`, description: `[BuildHIR] Add support for ${param.node.type} parameters.`, - }).withDetail({ + }).withDetails({ kind: 'error', loc: param.node.loc ?? null, message: 'Unsupported parameter type', @@ -205,7 +205,7 @@ export function lower( category: ErrorCategory.Syntax, reason: `Unexpected function body kind`, description: `Expected function body to be an expression or a block statement, got \`${body.type}\`.`, - }).withDetail({ + }).withDetails({ kind: 'error', loc: body.node.loc ?? null, message: 'Expected a block statement or expression', @@ -439,7 +439,13 @@ function lowerStatement( reason: 'Expected to find binding for hoisted identifier', description: `Could not find a binding for ${id.node.name}`, suggestions: null, - loc: id.node.loc ?? GeneratedSource, + details: [ + { + kind: 'error', + loc: id.node.loc ?? GeneratedSource, + message: null, + }, + ], }); if (builder.environment.isHoistedIdentifier(binding.identifier)) { // Already hoisted @@ -481,7 +487,14 @@ function lowerStatement( CompilerError.invariant(identifier.kind === 'Identifier', { reason: 'Expected hoisted binding to be a local identifier, not a global', - loc: id.node.loc ?? GeneratedSource, + description: null, + details: [ + { + kind: 'error', + loc: id.node.loc ?? GeneratedSource, + message: null, + }, + ], }); const place: Place = { effect: Effect.Unknown, @@ -1014,7 +1027,13 @@ function lowerStatement( CompilerError.invariant(stmt.get('id').type === 'Identifier', { reason: 'function declarations must have a name', description: null, - loc: stmt.node.loc ?? null, + details: [ + { + kind: 'error', + loc: stmt.node.loc ?? null, + message: null, + }, + ], suggestions: null, }); const id = stmt.get('id') as NodePath; @@ -1114,7 +1133,13 @@ function lowerStatement( CompilerError.invariant(declarations.length === 1, { reason: `Expected only one declaration in the init of a ForOfStatement, got ${declarations.length}`, description: null, - loc: left.node.loc ?? null, + details: [ + { + kind: 'error', + loc: left.node.loc ?? null, + message: null, + }, + ], suggestions: null, }); const id = declarations[0].get('id'); @@ -1129,8 +1154,15 @@ function lowerStatement( test = lowerValueToTemporary(builder, assign); } else { CompilerError.invariant(left.isLVal(), { - loc: leftLoc, reason: 'Expected ForOf init to be a variable declaration or lval', + description: null, + details: [ + { + kind: 'error', + loc: leftLoc, + message: null, + }, + ], }); const assign = lowerAssignment( builder, @@ -1207,7 +1239,13 @@ function lowerStatement( CompilerError.invariant(declarations.length === 1, { reason: `Expected only one declaration in the init of a ForInStatement, got ${declarations.length}`, description: null, - loc: left.node.loc ?? null, + details: [ + { + kind: 'error', + loc: left.node.loc ?? null, + message: null, + }, + ], suggestions: null, }); const id = declarations[0].get('id'); @@ -1222,8 +1260,15 @@ function lowerStatement( test = lowerValueToTemporary(builder, assign); } else { CompilerError.invariant(left.isLVal(), { - loc: leftLoc, reason: 'Expected ForIn init to be a variable declaration or lval', + description: null, + details: [ + { + kind: 'error', + loc: leftLoc, + message: null, + }, + ], }); const assign = lowerAssignment( builder, @@ -2202,7 +2247,13 @@ function lowerExpression( CompilerError.invariant(namePath.isJSXNamespacedName(), { reason: 'Refinement', description: null, - loc: namePath.node.loc ?? null, + details: [ + { + kind: 'error', + loc: namePath.node.loc ?? null, + message: null, + }, + ], suggestions: null, }); const namespace = namePath.node.namespace.name; @@ -2256,8 +2307,14 @@ function lowerExpression( // This is already checked in builder.resolveIdentifier CompilerError.invariant(tagIdentifier.kind !== 'Identifier', { reason: `<${tagName}> tags should be module-level imports`, - loc: openingIdentifier.node.loc ?? GeneratedSource, description: null, + details: [ + { + kind: 'error', + loc: openingIdentifier.node.loc ?? GeneratedSource, + message: null, + }, + ], suggestions: null, }); } @@ -2361,7 +2418,13 @@ function lowerExpression( reason: "there should be only one quasi as we don't support interpolations yet", description: null, - loc: expr.node.loc ?? null, + details: [ + { + kind: 'error', + loc: expr.node.loc ?? null, + message: null, + }, + ], suggestions: null, }); const value = expr.get('quasi').get('quasis').at(0)!.node.value; @@ -2759,7 +2822,13 @@ function lowerOptionalMemberExpression( CompilerError.invariant(object !== null, { reason: 'Satisfy type checker', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); @@ -3327,7 +3396,13 @@ function lowerJsxMemberExpression( CompilerError.invariant(object.isJSXIdentifier(), { reason: `TypeScript refinement fail: expected 'JsxIdentifier', got \`${object.node.type}\``, description: null, - loc: object.node.loc ?? null, + details: [ + { + kind: 'error', + loc: object.node.loc ?? null, + message: null, + }, + ], suggestions: null, }); @@ -3369,7 +3444,13 @@ function lowerJsxElement( CompilerError.invariant(expression.isExpression(), { reason: `(BuildHIR::lowerJsxElement) Expected Expression but found ${expression.type}!`, description: null, - loc: expression.node.loc ?? null, + details: [ + { + kind: 'error', + loc: expression.node.loc ?? null, + message: null, + }, + ], suggestions: null, }); return lowerExpressionToTemporary(builder, expression); @@ -3770,7 +3851,13 @@ function lowerAssignment( CompilerError.invariant(kind === InstructionKind.Reassign, { reason: 'MemberExpression may only appear in an assignment expression', description: null, - loc: lvaluePath.node.loc ?? null, + details: [ + { + kind: 'error', + loc: lvaluePath.node.loc ?? null, + message: null, + }, + ], suggestions: null, }); const lvalue = lvaluePath as NodePath; diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/BuildReactiveScopeTerminalsHIR.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/BuildReactiveScopeTerminalsHIR.ts index 6f69af4b4f2cd..423c046221c8d 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/BuildReactiveScopeTerminalsHIR.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/BuildReactiveScopeTerminalsHIR.ts @@ -234,7 +234,14 @@ function pushEndScopeTerminal( const fallthroughId = context.fallthroughs.get(scope.id); CompilerError.invariant(fallthroughId != null, { reason: 'Expected scope to exist', - loc: GeneratedSource, + description: null, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], }); context.rewrites.push({ kind: 'EndScope', diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/CollectHoistablePropertyLoads.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/CollectHoistablePropertyLoads.ts index a11822538f54f..f249466431d58 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/CollectHoistablePropertyLoads.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/CollectHoistablePropertyLoads.ts @@ -269,7 +269,14 @@ class PropertyPathRegistry { CompilerError.invariant(reactive === rootNode.fullPath.reactive, { reason: '[HoistablePropertyLoads] Found inconsistencies in `reactive` flag when deduping identifier reads within the same scope', - loc: identifier.loc, + description: null, + details: [ + { + kind: 'error', + loc: identifier.loc, + message: null, + }, + ], }); } return rootNode; @@ -498,7 +505,14 @@ function propagateNonNull( if (node == null) { CompilerError.invariant(false, { reason: `Bad node ${nodeId}, kind: ${direction}`, - loc: GeneratedSource, + description: null, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], }); } const neighbors = Array.from( @@ -570,7 +584,14 @@ function propagateNonNull( CompilerError.invariant(i++ < 100, { reason: '[CollectHoistablePropertyLoads] fixed point iteration did not terminate after 100 loops', - loc: GeneratedSource, + description: null, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], }); changed = false; @@ -602,7 +623,13 @@ export function assertNonNull, U>( CompilerError.invariant(value != null, { reason: 'Unexpected null', description: source != null ? `(from ${source})` : null, - loc: GeneratedSource, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], }); return value; } diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/CollectOptionalChainDependencies.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/CollectOptionalChainDependencies.ts index 75dad4c1bfe63..22e2a63964ab6 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/CollectOptionalChainDependencies.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/CollectOptionalChainDependencies.ts @@ -186,7 +186,13 @@ function matchOptionalTestBlock( reason: '[OptionalChainDeps] Inconsistent optional chaining property load', description: `Test=${printIdentifier(terminal.test.identifier)} PropertyLoad base=${printIdentifier(propertyLoad.value.object.identifier)}`, - loc: propertyLoad.loc, + details: [ + { + kind: 'error', + loc: propertyLoad.loc, + message: null, + }, + ], }, ); @@ -194,7 +200,14 @@ function matchOptionalTestBlock( storeLocal.value.identifier.id === propertyLoad.lvalue.identifier.id, { reason: '[OptionalChainDeps] Unexpected storeLocal', - loc: propertyLoad.loc, + description: null, + details: [ + { + kind: 'error', + loc: propertyLoad.loc, + message: null, + }, + ], }, ); if ( @@ -211,7 +224,14 @@ function matchOptionalTestBlock( alternate.instructions[1].value.kind === 'StoreLocal', { reason: 'Unexpected alternate structure', - loc: terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: terminal.loc, + message: null, + }, + ], }, ); @@ -247,7 +267,14 @@ function traverseOptionalBlock( if (maybeTest.terminal.kind === 'branch') { CompilerError.invariant(optional.terminal.optional, { reason: '[OptionalChainDeps] Expect base case to be always optional', - loc: optional.terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: optional.terminal.loc, + message: null, + }, + ], }); /** * Optional base expressions are currently within value blocks which cannot @@ -285,7 +312,14 @@ function traverseOptionalBlock( maybeTest.instructions.at(-1)!.lvalue.identifier.id, { reason: '[OptionalChainDeps] Unexpected test expression', - loc: maybeTest.terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: maybeTest.terminal.loc, + message: null, + }, + ], }, ); baseObject = { @@ -374,7 +408,14 @@ function traverseOptionalBlock( reason: '[OptionalChainDeps] Unexpected instructions an inner optional block. ' + 'This indicates that the compiler may be incorrectly concatenating two unrelated optional chains', - loc: optional.terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: optional.terminal.loc, + message: null, + }, + ], }); } const matchConsequentResult = matchOptionalTestBlock(test, context.blocks); @@ -387,7 +428,13 @@ function traverseOptionalBlock( { reason: '[OptionalChainDeps] Unexpected optional goto-fallthrough', description: `${matchConsequentResult.consequentGoto} != ${optional.terminal.fallthrough}`, - loc: optional.terminal.loc, + details: [ + { + kind: 'error', + loc: optional.terminal.loc, + message: null, + }, + ], }, ); const load = { diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/ComputeUnconditionalBlocks.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/ComputeUnconditionalBlocks.ts index 627686b4ecffe..e3582c675442c 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/ComputeUnconditionalBlocks.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/ComputeUnconditionalBlocks.ts @@ -24,7 +24,14 @@ export function computeUnconditionalBlocks(fn: HIRFunction): Set { CompilerError.invariant(!unconditionalBlocks.has(current), { reason: 'Internal error: non-terminating loop in ComputeUnconditionalBlocks', - loc: null, + description: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); unconditionalBlocks.add(current); diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/DeriveMinimalDependenciesHIR.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/DeriveMinimalDependenciesHIR.ts index 7819ab39b2c69..4cdd77f57ffdc 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/DeriveMinimalDependenciesHIR.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/DeriveMinimalDependenciesHIR.ts @@ -54,7 +54,14 @@ export class ReactiveScopeDependencyTreeHIR { prevAccessType == null || prevAccessType === accessType, { reason: 'Conflicting access types', - loc: GeneratedSource, + description: null, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], }, ); let nextNode = currNode.properties.get(path[i].property); @@ -90,7 +97,13 @@ export class ReactiveScopeDependencyTreeHIR { CompilerError.invariant(reactive === rootNode.reactive, { reason: '[DeriveMinimalDependenciesHIR] Conflicting reactive root flag', description: `Identifier ${printIdentifier(identifier)}`, - loc: GeneratedSource, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], }); } return rootNode; diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/Dominator.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/Dominator.ts index 13118621fe520..4cb79d2b370ef 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/Dominator.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/Dominator.ts @@ -89,7 +89,13 @@ export class Dominator { CompilerError.invariant(dominator !== undefined, { reason: 'Unknown node', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); return dominator === id ? null : dominator; @@ -130,7 +136,13 @@ export class PostDominator { CompilerError.invariant(dominator !== undefined, { reason: 'Unknown node', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); return dominator === id ? null : dominator; @@ -175,7 +187,13 @@ function computeImmediateDominators(graph: Graph): Map { CompilerError.invariant(newIdom !== null, { reason: `At least one predecessor must have been visited for block ${id}`, description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts index 421b204e655c7..e38a49cb56a06 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts @@ -750,7 +750,13 @@ export class Environment { CompilerError.invariant(!this.#globals.has(hookName), { reason: `[Globals] Found existing definition in global registry for custom hook ${hookName}`, description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); this.#globals.set( @@ -783,7 +789,14 @@ export class Environment { CompilerError.invariant(code != null, { reason: 'Expected Environment to be initialized with source code when a Flow type provider is specified', - loc: null, + description: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], }); this.#flowTypeEnvironment.init(this, code); } else { @@ -794,7 +807,14 @@ export class Environment { get typeContext(): FlowTypeEnv { CompilerError.invariant(this.#flowTypeEnvironment != null, { reason: 'Flow type environment not initialized', - loc: null, + description: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], }); return this.#flowTypeEnvironment; } @@ -1044,7 +1064,13 @@ export class Environment { CompilerError.invariant(shape !== undefined, { reason: `[HIR] Forget internal error: cannot resolve shape ${shapeId}`, description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); return shape.properties.get('*') ?? null; @@ -1069,7 +1095,13 @@ export class Environment { CompilerError.invariant(shape !== undefined, { reason: `[HIR] Forget internal error: cannot resolve shape ${shapeId}`, description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); if (typeof property === 'string') { @@ -1094,7 +1126,13 @@ export class Environment { CompilerError.invariant(shape !== undefined, { reason: `[HIR] Forget internal error: cannot resolve shape ${shapeId}`, description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); return shape.functionType; diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/FindContextIdentifiers.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/FindContextIdentifiers.ts index ecc534eb729ec..f079933c048ae 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/FindContextIdentifiers.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/FindContextIdentifiers.ts @@ -184,7 +184,13 @@ function handleAssignment( CompilerError.invariant(valuePath.isLVal(), { reason: `[FindContextIdentifiers] Expected object property value to be an LVal, got: ${valuePath.type}`, description: null, - loc: valuePath.node.loc ?? GeneratedSource, + details: [ + { + kind: 'error', + loc: valuePath.node.loc ?? GeneratedSource, + message: null, + }, + ], suggestions: null, }); handleAssignment(currentFn, identifiers, valuePath); @@ -192,7 +198,13 @@ function handleAssignment( CompilerError.invariant(property.isRestElement(), { reason: `[FindContextIdentifiers] Invalid assumptions for babel types.`, description: null, - loc: property.node.loc ?? GeneratedSource, + details: [ + { + kind: 'error', + loc: property.node.loc ?? GeneratedSource, + message: null, + }, + ], suggestions: null, }); handleAssignment(currentFn, identifiers, property); diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts index 6b3ba6f94c8ae..582ef93cf34f2 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts @@ -1314,8 +1314,14 @@ export function makeIdentifierName(name: string): ValidatedIdentifier { } else { CompilerError.invariant(t.isValidIdentifier(name), { reason: `Expected a valid identifier name`, - loc: GeneratedSource, description: `\`${name}\` is not a valid JavaScript identifier`, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], suggestions: null, }); } @@ -1334,8 +1340,14 @@ export function makeIdentifierName(name: string): ValidatedIdentifier { export function promoteTemporary(identifier: Identifier): void { CompilerError.invariant(identifier.name === null, { reason: `Expected a temporary (unnamed) identifier`, - loc: GeneratedSource, description: `Identifier already has a name, \`${identifier.name}\``, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], suggestions: null, }); identifier.name = { @@ -1358,8 +1370,14 @@ export function isPromotedTemporary(name: string): boolean { export function promoteTemporaryJsxTag(identifier: Identifier): void { CompilerError.invariant(identifier.name === null, { reason: `Expected a temporary (unnamed) identifier`, - loc: GeneratedSource, description: `Identifier already has a name, \`${identifier.name}\``, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], suggestions: null, }); identifier.name = { @@ -1527,7 +1545,13 @@ export function isMutableEffect( CompilerError.invariant(false, { reason: 'Unexpected unknown effect', description: null, - loc: location, + details: [ + { + kind: 'error', + loc: location, + message: null, + }, + ], suggestions: null, }); } @@ -1660,7 +1684,13 @@ export function makeBlockId(id: number): BlockId { CompilerError.invariant(id >= 0 && Number.isInteger(id), { reason: 'Expected block id to be a non-negative integer', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); return id as BlockId; @@ -1677,7 +1707,13 @@ export function makeScopeId(id: number): ScopeId { CompilerError.invariant(id >= 0 && Number.isInteger(id), { reason: 'Expected block id to be a non-negative integer', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); return id as ScopeId; @@ -1694,7 +1730,13 @@ export function makeIdentifierId(id: number): IdentifierId { CompilerError.invariant(id >= 0 && Number.isInteger(id), { reason: 'Expected identifier id to be a non-negative integer', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); return id as IdentifierId; @@ -1711,7 +1753,13 @@ export function makeDeclarationId(id: number): DeclarationId { CompilerError.invariant(id >= 0 && Number.isInteger(id), { reason: 'Expected declaration id to be a non-negative integer', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); return id as DeclarationId; @@ -1728,7 +1776,13 @@ export function makeInstructionId(id: number): InstructionId { CompilerError.invariant(id >= 0 && Number.isInteger(id), { reason: 'Expected instruction id to be a non-negative integer', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); return id as InstructionId; 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 f60f123fb63cc..d3ecb2abdcd7d 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/HIRBuilder.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/HIRBuilder.ts @@ -507,7 +507,13 @@ export default class HIRBuilder { { reason: 'Mismatched label', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }, ); @@ -530,7 +536,13 @@ export default class HIRBuilder { { reason: 'Mismatched label', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }, ); @@ -566,7 +578,13 @@ export default class HIRBuilder { { reason: 'Mismatched loops', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }, ); @@ -591,7 +609,13 @@ export default class HIRBuilder { CompilerError.invariant(false, { reason: 'Expected a loop or switch to be in scope', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); } @@ -612,7 +636,13 @@ export default class HIRBuilder { CompilerError.invariant(false, { reason: 'Continue may only refer to a labeled loop', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); } @@ -620,7 +650,13 @@ export default class HIRBuilder { CompilerError.invariant(false, { reason: 'Expected a loop to be in scope', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); } @@ -643,7 +679,13 @@ function _shrink(func: HIR): void { CompilerError.invariant(block != null, { reason: `expected block ${blockId} to exist`, description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); target = getTargetIfIndirection(block); @@ -775,7 +817,13 @@ function getReversePostorderedBlocks(func: HIR): HIR['blocks'] { CompilerError.invariant(block != null, { reason: '[HIRBuilder] Unexpected null block', description: `expected block ${blockId} to exist`, - loc: GeneratedSource, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], }); const successors = [...eachTerminalSuccessor(block.terminal)].reverse(); const fallthrough = terminalFallthrough(block.terminal); @@ -831,7 +879,13 @@ export function markInstructionIds(func: HIR): void { CompilerError.invariant(!visited.has(instr), { reason: `${printInstruction(instr)} already visited!`, description: null, - loc: instr.loc, + details: [ + { + kind: 'error', + loc: instr.loc, + message: null, + }, + ], suggestions: null, }); visited.add(instr); @@ -854,7 +908,13 @@ export function markPredecessors(func: HIR): void { CompilerError.invariant(block != null, { reason: 'unexpected missing block', description: `block ${blockId}`, - loc: GeneratedSource, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], }); if (prevBlock) { block.preds.add(prevBlock.id); diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/MergeConsecutiveBlocks.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/MergeConsecutiveBlocks.ts index 881e4e93ffcdb..da8a5a9f19292 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/MergeConsecutiveBlocks.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/MergeConsecutiveBlocks.ts @@ -61,7 +61,13 @@ export function mergeConsecutiveBlocks(fn: HIRFunction): void { CompilerError.invariant(predecessor !== undefined, { reason: `Expected predecessor ${predecessorId} to exist`, description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); if (predecessor.terminal.kind !== 'goto' || predecessor.kind !== 'block') { @@ -77,7 +83,13 @@ export function mergeConsecutiveBlocks(fn: HIRFunction): void { CompilerError.invariant(phi.operands.size === 1, { reason: `Found a block with a single predecessor but where a phi has multiple (${phi.operands.size}) operands`, description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); const operand = Array.from(phi.operands.values())[0]!; diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/ObjectShape.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/ObjectShape.ts index 2c626243e7075..beaff321e267d 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/ObjectShape.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/ObjectShape.ts @@ -119,7 +119,13 @@ function parseAliasingSignatureConfig( CompilerError.invariant(!lifetimes.has(temp), { reason: `Invalid type configuration for module`, description: `Expected aliasing signature to have unique names for receiver, params, rest, returns, and temporaries in module '${moduleName}'`, - loc, + details: [ + { + kind: 'error', + loc, + message: null, + }, + ], }); const place = signatureArgument(lifetimes.size); lifetimes.set(temp, place); @@ -130,7 +136,13 @@ function parseAliasingSignatureConfig( CompilerError.invariant(place != null, { reason: `Invalid type configuration for module`, description: `Expected aliasing signature effects to reference known names from receiver/params/rest/returns/temporaries, but '${temp}' is not a known name in '${moduleName}'`, - loc, + details: [ + { + kind: 'error', + loc, + message: null, + }, + ], }); return place; } @@ -265,7 +277,13 @@ function addShape( CompilerError.invariant(!registry.has(id), { reason: `[ObjectShape] Could not add shape to registry: name ${id} already exists.`, description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); registry.set(id, shape); diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/PrintHIR.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/PrintHIR.ts index a8fb837262e74..197e486e8af3b 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/PrintHIR.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/PrintHIR.ts @@ -596,7 +596,13 @@ export function printInstructionValue(instrValue: ReactiveValue): string { { reason: 'Bad assumption about quasi length.', description: null, - loc: instrValue.loc, + details: [ + { + kind: 'error', + loc: instrValue.loc, + message: null, + }, + ], suggestions: null, }, ); @@ -865,8 +871,15 @@ export function printManualMemoDependency( } else { CompilerError.invariant(val.root.value.identifier.name?.kind === 'named', { reason: 'DepsValidation: expected named local variable in depslist', + description: null, suggestions: null, - loc: val.root.value.loc, + details: [ + { + kind: 'error', + loc: val.root.value.loc, + message: null, + }, + ], }); rootStr = nameOnly ? val.root.value.identifier.name.value diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/PropagateScopeDependenciesHIR.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/PropagateScopeDependenciesHIR.ts index 91b7712b881fc..bfffd464eadd4 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/PropagateScopeDependenciesHIR.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/PropagateScopeDependenciesHIR.ts @@ -86,7 +86,14 @@ export function propagateScopeDependenciesHIR(fn: HIRFunction): void { const hoistables = hoistablePropertyLoads.get(scope.id); CompilerError.invariant(hoistables != null, { reason: '[PropagateScopeDependencies] Scope not found in tracked blocks', - loc: GeneratedSource, + description: null, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], }); /** * Step 2: Calculate hoistable dependencies. @@ -428,7 +435,14 @@ export class DependencyCollectionContext { const scopedDependencies = this.#dependencies.value; CompilerError.invariant(scopedDependencies != null, { reason: '[PropagateScopeDeps]: Unexpected scope mismatch', - loc: scope.loc, + description: null, + details: [ + { + kind: 'error', + loc: scope.loc, + message: null, + }, + ], }); // Restore context of previous scope diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/PruneUnusedLabelsHIR.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/PruneUnusedLabelsHIR.ts index f0c488c3e1ec7..6eedef7bba6d4 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/PruneUnusedLabelsHIR.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/PruneUnusedLabelsHIR.ts @@ -53,7 +53,14 @@ export function pruneUnusedLabelsHIR(fn: HIRFunction): void { next.phis.size === 0 && fallthrough.phis.size === 0, { reason: 'Unexpected phis when merging label blocks', - loc: label.terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: label.terminal.loc, + message: null, + }, + ], }, ); @@ -64,7 +71,14 @@ export function pruneUnusedLabelsHIR(fn: HIRFunction): void { fallthrough.preds.has(nextId), { reason: 'Unexpected block predecessors when merging label blocks', - loc: label.terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: label.terminal.loc, + message: null, + }, + ], }, ); diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/ScopeDependencyUtils.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/ScopeDependencyUtils.ts index 6e9ff08b86242..04afe390b0c45 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/ScopeDependencyUtils.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/ScopeDependencyUtils.ts @@ -202,8 +202,14 @@ function writeOptionalDependency( CompilerError.invariant(firstOptional !== -1, { reason: '[ScopeDependencyUtils] Internal invariant broken: expected optional path', - loc: dep.identifier.loc, description: null, + details: [ + { + kind: 'error', + loc: dep.identifier.loc, + message: null, + }, + ], suggestions: null, }); if (firstOptional === dep.path.length - 1) { @@ -239,7 +245,13 @@ function writeOptionalDependency( CompilerError.invariant(testIdentifier !== null, { reason: 'Satisfy type checker', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/Types.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/Types.ts index 53eb8a779d73a..cdb1a600c7913 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/Types.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/Types.ts @@ -87,7 +87,13 @@ export function makeTypeId(id: number): TypeId { CompilerError.invariant(id >= 0 && Number.isInteger(id), { reason: 'Expected instruction id to be a non-negative integer', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); return id as TypeId; diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/visitors.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/visitors.ts index 64702c8abcdb6..af1cffe85fd31 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/visitors.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/visitors.ts @@ -1233,7 +1233,14 @@ export class ScopeBlockTraversal { CompilerError.invariant(blockInfo.scope.id === top, { reason: 'Expected traversed block fallthrough to match top-most active scope', - loc: block.instructions[0]?.loc ?? block.terminal.id, + description: null, + details: [ + { + kind: 'error', + loc: block.instructions[0]?.loc ?? block.terminal.id, + message: null, + }, + ], }); this.#activeScopes.pop(); } @@ -1247,7 +1254,14 @@ export class ScopeBlockTraversal { !this.blockInfos.has(block.terminal.fallthrough), { reason: 'Expected unique scope blocks and fallthroughs', - loc: block.terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: block.terminal.loc, + message: null, + }, + ], }, ); this.blockInfos.set(block.terminal.block, { diff --git a/compiler/packages/babel-plugin-react-compiler/src/Inference/AnalyseFunctions.ts b/compiler/packages/babel-plugin-react-compiler/src/Inference/AnalyseFunctions.ts index 77a2bdcde596a..7c94d81b9bd69 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Inference/AnalyseFunctions.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Inference/AnalyseFunctions.ts @@ -78,7 +78,14 @@ function lowerWithMutationAliasing(fn: HIRFunction): void { case 'Apply': { CompilerError.invariant(false, { reason: `[AnalyzeFunctions] Expected Apply effects to be replaced with more precise effects`, - loc: effect.function.loc, + description: null, + details: [ + { + kind: 'error', + loc: effect.function.loc, + message: null, + }, + ], }); } case 'Mutate': 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 d17c754662dca..260df8d7eef69 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Inference/DropManualMemoization.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Inference/DropManualMemoization.ts @@ -300,7 +300,7 @@ function extractManualMemoizationArgs( reason: `Expected a callback function to be passed to ${kind}`, description: `Expected a callback function to be passed to ${kind}`, suggestions: null, - }).withDetail({ + }).withDetails({ kind: 'error', loc: instr.value.loc, message: `Expected a callback function to be passed to ${kind}`, @@ -315,7 +315,7 @@ function extractManualMemoizationArgs( reason: `Unexpected spread argument to ${kind}`, description: `Unexpected spread argument to ${kind}`, suggestions: null, - }).withDetail({ + }).withDetails({ kind: 'error', loc: instr.value.loc, message: `Unexpected spread argument to ${kind}`, @@ -335,7 +335,7 @@ function extractManualMemoizationArgs( reason: `Expected the dependency list for ${kind} to be an array literal`, description: `Expected the dependency list for ${kind} to be an array literal`, suggestions: null, - }).withDetail({ + }).withDetails({ kind: 'error', loc: depsListPlace.loc, message: `Expected the dependency list for ${kind} to be an array literal`, @@ -353,7 +353,7 @@ function extractManualMemoizationArgs( reason: `Expected the dependency list to be an array of simple expressions (e.g. \`x\`, \`x.y.z\`, \`x?.y?.z\`)`, description: `Expected the dependency list to be an array of simple expressions (e.g. \`x\`, \`x.y.z\`, \`x?.y?.z\`)`, suggestions: null, - }).withDetail({ + }).withDetails({ kind: 'error', loc: dep.loc, message: `Expected the dependency list to be an array of simple expressions (e.g. \`x\`, \`x.y.z\`, \`x?.y?.z\`)`, @@ -462,7 +462,7 @@ export function dropManualMemoization( : 'useMemo' } callback doesn't return a value. useMemo is for computing and caching values, not for arbitrary side effects.`, suggestions: null, - }).withDetail({ + }).withDetails({ kind: 'error', loc: instr.value.loc, message: 'useMemo() callbacks must return a value', @@ -498,7 +498,7 @@ export function dropManualMemoization( reason: `Expected the first argument to be an inline function expression`, description: `Expected the first argument to be an inline function expression`, suggestions: [], - }).withDetail({ + }).withDetails({ kind: 'error', loc: fnPlace.loc, message: `Expected the first argument to be an inline function expression`, @@ -613,7 +613,14 @@ function findOptionalPlaces(fn: HIRFunction): Set { default: { CompilerError.invariant(false, { reason: `Unexpected terminal in optional`, - loc: terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: terminal.loc, + message: `Unexpected ${terminal.kind} in optional`, + }, + ], }); } } diff --git a/compiler/packages/babel-plugin-react-compiler/src/Inference/InferEffectDependencies.ts b/compiler/packages/babel-plugin-react-compiler/src/Inference/InferEffectDependencies.ts index 2997a449dead3..999701c3255ae 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Inference/InferEffectDependencies.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Inference/InferEffectDependencies.ts @@ -438,7 +438,14 @@ function rewriteSplices( { reason: '[InferEffectDependencies] Internal invariant broken: expected block instructions to be sorted', - loc: originalInstrs[cursor].loc, + description: null, + details: [ + { + kind: 'error', + loc: originalInstrs[cursor].loc, + message: null, + }, + ], }, ); currBlock.instructions.push(originalInstrs[cursor]); @@ -447,7 +454,14 @@ function rewriteSplices( CompilerError.invariant(originalInstrs[cursor].id === rewrite.location, { reason: '[InferEffectDependencies] Internal invariant broken: splice location not found', - loc: originalInstrs[cursor].loc, + description: null, + details: [ + { + kind: 'error', + loc: originalInstrs[cursor].loc, + message: null, + }, + ], }); if (rewrite.kind === 'instr') { @@ -467,7 +481,14 @@ function rewriteSplices( { reason: '[InferEffectDependencies] Internal invariant broken: expected entry block to have a fallthrough', - loc: entryBlock.terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: entryBlock.terminal.loc, + message: null, + }, + ], }, ); const originalTerminal = currBlock.terminal; @@ -566,7 +587,14 @@ function inferMinimalDependencies( CompilerError.invariant(hoistableToFnEntry != null, { reason: '[InferEffectDependencies] Internal invariant broken: missing entry block', - loc: fnInstr.loc, + description: null, + details: [ + { + kind: 'error', + loc: fnInstr.loc, + message: null, + }, + ], }); const dependencies = inferDependencies( @@ -622,7 +650,14 @@ function inferDependencies( CompilerError.invariant(resultUnfiltered != null, { reason: '[InferEffectDependencies] Internal invariant broken: missing scope dependencies', - loc: fn.loc, + description: null, + details: [ + { + kind: 'error', + loc: fn.loc, + message: null, + }, + ], }); const fnContext = new Set(fn.context.map(dep => dep.identifier.id)); diff --git a/compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutationAliasingEffects.ts b/compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutationAliasingEffects.ts index 1f8db2c3c7dc3..eb7b4de27f0a0 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutationAliasingEffects.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutationAliasingEffects.ts @@ -58,7 +58,6 @@ import { printInstruction, printInstructionValue, printPlace, - printSourceLocation, } from '../HIR/PrintHIR'; import {FunctionSignature} from '../HIR/ObjectShape'; import prettyFormat from 'pretty-format'; @@ -135,7 +134,13 @@ export function inferMutationAliasingEffects( reason: 'Expected React component to have not more than two parameters: one for props and for ref', description: null, - loc: fn.loc, + details: [ + { + kind: 'error', + loc: fn.loc, + message: null, + }, + ], suggestions: null, }); const [props, ref] = fn.params; @@ -202,7 +207,13 @@ export function inferMutationAliasingEffects( CompilerError.invariant(false, { reason: `[InferMutationAliasingEffects] Potential infinite loop`, description: `A value, temporary place, or effect was not cached properly`, - loc: fn.loc, + details: [ + { + kind: 'error', + loc: fn.loc, + message: null, + }, + ], }); } for (const [blockId, block] of fn.body.blocks) { @@ -357,7 +368,14 @@ function inferBlock( CompilerError.invariant(state.kind(handlerParam) != null, { reason: 'Expected catch binding to be intialized with a DeclareLocal Catch instruction', - loc: terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: terminal.loc, + message: null, + }, + ], }); const effects: Array = []; for (const instr of block.instructions) { @@ -456,7 +474,7 @@ function applySignature( category: ErrorCategory.Immutability, reason: 'This value cannot be modified', description: `${reason}.`, - }).withDetail({ + }).withDetails({ kind: 'error', loc: effect.value.loc, message: `${variable} cannot be modified`, @@ -465,7 +483,7 @@ function applySignature( effect.kind === 'Mutate' && effect.reason?.kind === 'AssignCurrentProperty' ) { - diagnostic.withDetail({ + diagnostic.withDetails({ kind: 'hint', message: `Hint: If this value is a Ref (value returned by \`useRef()\`), rename the variable to end in "Ref".`, }); @@ -507,7 +525,14 @@ function applySignature( ) { CompilerError.invariant(false, { reason: `Expected instruction lvalue to be initialized`, - loc: instruction.loc, + description: null, + details: [ + { + kind: 'error', + loc: instruction.loc, + message: null, + }, + ], }); } return effects.length !== 0 ? effects : null; @@ -536,7 +561,13 @@ function applyEffect( CompilerError.invariant(!initialized.has(effect.into.identifier.id), { reason: `Cannot re-initialize variable within an instruction`, description: `Re-initialized ${printPlace(effect.into)} in ${printAliasingEffect(effect)}`, - loc: effect.into.loc, + details: [ + { + kind: 'error', + loc: effect.into.loc, + message: null, + }, + ], }); initialized.add(effect.into.identifier.id); @@ -575,7 +606,13 @@ function applyEffect( CompilerError.invariant(!initialized.has(effect.into.identifier.id), { reason: `Cannot re-initialize variable within an instruction`, description: `Re-initialized ${printPlace(effect.into)} in ${printAliasingEffect(effect)}`, - loc: effect.into.loc, + details: [ + { + kind: 'error', + loc: effect.into.loc, + message: null, + }, + ], }); initialized.add(effect.into.identifier.id); @@ -635,7 +672,13 @@ function applyEffect( CompilerError.invariant(!initialized.has(effect.into.identifier.id), { reason: `Cannot re-initialize variable within an instruction`, description: `Re-initialized ${printPlace(effect.into)} in ${printAliasingEffect(effect)}`, - loc: effect.into.loc, + details: [ + { + kind: 'error', + loc: effect.into.loc, + message: null, + }, + ], }); initialized.add(effect.into.identifier.id); @@ -709,7 +752,13 @@ function applyEffect( { reason: `Expected destination value to already be initialized within this instruction for Alias effect`, description: `Destination ${printPlace(effect.into)} is not initialized in this instruction`, - loc: effect.into.loc, + details: [ + { + kind: 'error', + loc: effect.into.loc, + message: null, + }, + ], }, ); /* @@ -768,7 +817,13 @@ function applyEffect( CompilerError.invariant(!initialized.has(effect.into.identifier.id), { reason: `Cannot re-initialize variable within an instruction`, description: `Re-initialized ${printPlace(effect.into)} in ${printAliasingEffect(effect)}`, - loc: effect.into.loc, + details: [ + { + kind: 'error', + loc: effect.into.loc, + message: null, + }, + ], }); initialized.add(effect.into.identifier.id); @@ -1042,13 +1097,13 @@ function applyEffect( description: `${variable ?? 'This variable'} is accessed before it is declared, which prevents the earlier access from updating when this value changes over time.`, }); if (hoistedAccess != null && hoistedAccess.loc != effect.value.loc) { - diagnostic.withDetail({ + diagnostic.withDetails({ kind: 'error', loc: hoistedAccess.loc, message: `${variable ?? 'variable'} accessed before it is declared`, }); } - diagnostic.withDetail({ + diagnostic.withDetails({ kind: 'error', loc: effect.value.loc, message: `${variable ?? 'variable'} is declared here`, @@ -1079,7 +1134,7 @@ function applyEffect( category: ErrorCategory.Immutability, reason: 'This value cannot be modified', description: `${reason}.`, - }).withDetail({ + }).withDetails({ kind: 'error', loc: effect.value.loc, message: `${variable} cannot be modified`, @@ -1088,7 +1143,7 @@ function applyEffect( effect.kind === 'Mutate' && effect.reason?.kind === 'AssignCurrentProperty' ) { - diagnostic.withDetail({ + diagnostic.withDetails({ kind: 'hint', message: `Hint: If this value is a Ref (value returned by \`useRef()\`), rename the variable to end in "Ref".`, }); @@ -1169,7 +1224,13 @@ class InferenceState { reason: '[InferMutationAliasingEffects] Expected all top-level identifiers to be defined as variables, not values', description: null, - loc: value.loc, + details: [ + { + kind: 'error', + loc: value.loc, + message: null, + }, + ], suggestions: null, }); this.#values.set(value, kind); @@ -1180,7 +1241,13 @@ class InferenceState { CompilerError.invariant(values != null, { reason: `[InferMutationAliasingEffects] Expected value kind to be initialized`, description: `${printPlace(place)}`, - loc: place.loc, + details: [ + { + kind: 'error', + loc: place.loc, + message: 'this is uninitialized', + }, + ], suggestions: null, }); return Array.from(values); @@ -1192,7 +1259,13 @@ class InferenceState { CompilerError.invariant(values != null, { reason: `[InferMutationAliasingEffects] Expected value kind to be initialized`, description: `${printPlace(place)}`, - loc: place.loc, + details: [ + { + kind: 'error', + loc: place.loc, + message: 'this is uninitialized', + }, + ], suggestions: null, }); let mergedKind: AbstractValue | null = null; @@ -1204,7 +1277,13 @@ class InferenceState { CompilerError.invariant(mergedKind !== null, { reason: `[InferMutationAliasingEffects] Expected at least one value`, description: `No value found at \`${printPlace(place)}\``, - loc: place.loc, + details: [ + { + kind: 'error', + loc: place.loc, + message: null, + }, + ], suggestions: null, }); return mergedKind; @@ -1216,7 +1295,13 @@ class InferenceState { CompilerError.invariant(values != null, { reason: `[InferMutationAliasingEffects] Expected value for identifier to be initialized`, description: `${printIdentifier(value.identifier)}`, - loc: value.loc, + details: [ + { + kind: 'error', + loc: value.loc, + message: 'Expected value for identifier to be initialized', + }, + ], suggestions: null, }); this.#variables.set(place.identifier.id, new Set(values)); @@ -1227,7 +1312,13 @@ class InferenceState { CompilerError.invariant(values != null, { reason: `[InferMutationAliasingEffects] Expected value for identifier to be initialized`, description: `${printIdentifier(value.identifier)}`, - loc: value.loc, + details: [ + { + kind: 'error', + loc: value.loc, + message: 'Expected value for identifier to be initialized', + }, + ], suggestions: null, }); const prevValues = this.values(place); @@ -1240,11 +1331,15 @@ class InferenceState { // Defines (initializing or updating) a variable with a specific kind of value. define(place: Place, value: InstructionValue): void { CompilerError.invariant(this.#values.has(value), { - reason: `[InferMutationAliasingEffects] Expected value to be initialized at '${printSourceLocation( - value.loc, - )}'`, + reason: `[InferMutationAliasingEffects] Expected value to be initialized`, description: printInstructionValue(value), - loc: value.loc, + details: [ + { + kind: 'error', + loc: value.loc, + message: 'Expected value for identifier to be initialized', + }, + ], suggestions: null, }); this.#variables.set(place.identifier.id, new Set([value])); @@ -2055,7 +2150,7 @@ function computeSignatureForInstruction( reason: 'Cannot reassign variables declared outside of the component/hook', description: `Variable ${variable} is declared outside of the component/hook. Reassigning this value during render is a form of side effect, which can cause unpredictable behavior depending on when the component happens to re-render. If this variable is used in rendering, use useState instead. Otherwise, consider updating it in an effect. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)`, - }).withDetail({ + }).withDetails({ kind: 'error', loc: instr.loc, message: `${variable} cannot be reassigned`, @@ -2157,7 +2252,7 @@ function computeEffectsForLegacySignature( ? `\`${signature.canonicalName}\` is an impure function. ` : '') + 'Calling an impure function can produce unstable results that update unpredictably when the component happens to re-render. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent)', - }).withDetail({ + }).withDetails({ kind: 'error', loc, message: 'Cannot call impure function', @@ -2176,7 +2271,7 @@ function computeEffectsForLegacySignature( 'However, you may see issues if values from this API are passed to other components/hooks that are ' + 'memoized.', ].join(''), - }).withDetail({ + }).withDetails({ kind: 'error', loc: receiver.loc, message: signature.knownIncompatible, @@ -2676,7 +2771,13 @@ export function isKnownMutableEffect(effect: Effect): boolean { CompilerError.invariant(false, { reason: 'Unexpected unknown effect', description: null, - loc: GeneratedSource, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], suggestions: null, }); } @@ -2785,7 +2886,13 @@ function mergeValueKinds(a: ValueKind, b: ValueKind): ValueKind { { reason: `Unexpected value kind in mergeValues()`, description: `Found kinds ${a} and ${b}`, - loc: GeneratedSource, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], }, ); return ValueKind.Primitive; 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 b53026a4d4b87..29f68a77aec7b 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutationAliasingRanges.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutationAliasingRanges.ts @@ -229,7 +229,14 @@ export function inferMutationAliasingRanges( } else { CompilerError.invariant(effect.kind === 'Freeze', { reason: `Unexpected '${effect.kind}' effect for MaybeThrow terminal`, - loc: block.terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: block.terminal.loc, + message: null, + }, + ], }); } } @@ -378,7 +385,14 @@ export function inferMutationAliasingRanges( case 'Apply': { CompilerError.invariant(false, { reason: `[AnalyzeFunctions] Expected Apply effects to be replaced with more precise effects`, - loc: effect.function.loc, + description: null, + details: [ + { + kind: 'error', + loc: effect.function.loc, + message: null, + }, + ], }); } case 'MutateTransitive': @@ -525,7 +539,14 @@ export function inferMutationAliasingRanges( const fromNode = state.nodes.get(from.identifier); CompilerError.invariant(fromNode != null, { reason: `Expected a node to exist for all parameters and context variables`, - loc: into.loc, + description: null, + details: [ + { + kind: 'error', + loc: into.loc, + message: null, + }, + ], }); if (fromNode.lastMutated === mutationIndex) { if (into.identifier.id === fn.returns.identifier.id) { diff --git a/compiler/packages/babel-plugin-react-compiler/src/Inference/InferReactivePlaces.ts b/compiler/packages/babel-plugin-react-compiler/src/Inference/InferReactivePlaces.ts index 19e220b235694..271a76e92c125 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Inference/InferReactivePlaces.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Inference/InferReactivePlaces.ts @@ -349,7 +349,13 @@ export function inferReactivePlaces(fn: HIRFunction): void { CompilerError.invariant(false, { reason: 'Unexpected unknown effect', description: null, - loc: operand.loc, + details: [ + { + kind: 'error', + loc: operand.loc, + message: null, + }, + ], suggestions: null, }); } diff --git a/compiler/packages/babel-plugin-react-compiler/src/Optimization/ConstantPropagation.ts b/compiler/packages/babel-plugin-react-compiler/src/Optimization/ConstantPropagation.ts index 4ad86abbe73cb..ca2f6e00a5d0b 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Optimization/ConstantPropagation.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Optimization/ConstantPropagation.ts @@ -191,7 +191,14 @@ function evaluatePhi(phi: Phi, constants: Constants): Constant | null { case 'Primitive': { CompilerError.invariant(value.kind === 'Primitive', { reason: 'value kind expected to be Primitive', - loc: null, + description: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); @@ -204,7 +211,14 @@ function evaluatePhi(phi: Phi, constants: Constants): Constant | null { case 'LoadGlobal': { CompilerError.invariant(value.kind === 'LoadGlobal', { reason: 'value kind expected to be LoadGlobal', - loc: null, + description: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); diff --git a/compiler/packages/babel-plugin-react-compiler/src/Optimization/InlineJsxTransform.ts b/compiler/packages/babel-plugin-react-compiler/src/Optimization/InlineJsxTransform.ts index 3588cf32f9f66..8970f2e07ff16 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Optimization/InlineJsxTransform.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Optimization/InlineJsxTransform.ts @@ -709,7 +709,14 @@ function createPropsProperties( const spreadProp = jsxSpreadAttributes[0]; CompilerError.invariant(spreadProp.kind === 'JsxSpreadAttribute', { reason: 'Spread prop attribute must be of kind JSXSpreadAttribute', - loc: instr.loc, + description: null, + details: [ + { + kind: 'error', + loc: instr.loc, + message: null, + }, + ], }); propsProperty = { kind: 'ObjectProperty', diff --git a/compiler/packages/babel-plugin-react-compiler/src/Optimization/InstructionReordering.ts b/compiler/packages/babel-plugin-react-compiler/src/Optimization/InstructionReordering.ts index 441ad837780bc..409c170027231 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Optimization/InstructionReordering.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Optimization/InstructionReordering.ts @@ -78,10 +78,17 @@ export function instructionReordering(fn: HIRFunction): void { } CompilerError.invariant(shared.size === 0, { reason: `InstructionReordering: expected all reorderable nodes to have been emitted`, - loc: - [...shared.values()] - .map(node => node.instruction?.loc) - .filter(loc => loc != null)[0] ?? GeneratedSource, + description: null, + details: [ + { + kind: 'error', + loc: + [...shared.values()] + .map(node => node.instruction?.loc) + .filter(loc => loc != null)[0] ?? GeneratedSource, + message: null, + }, + ], }); markInstructionIds(fn.body); } @@ -302,7 +309,13 @@ function reorderBlock( node.reorderability === Reorderability.Reorderable, { reason: `Expected all remaining instructions to be reorderable`, - loc: node.instruction?.loc ?? block.terminal.loc, + details: [ + { + kind: 'error', + loc: node.instruction?.loc ?? block.terminal.loc, + message: null, + }, + ], description: node.instruction != null ? `Instruction [${node.instruction.id}] was not emitted yet but is not reorderable` diff --git a/compiler/packages/babel-plugin-react-compiler/src/Optimization/PruneMaybeThrows.ts b/compiler/packages/babel-plugin-react-compiler/src/Optimization/PruneMaybeThrows.ts index 9175fbdd1af1b..ad0b63a1358cb 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Optimization/PruneMaybeThrows.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Optimization/PruneMaybeThrows.ts @@ -52,7 +52,13 @@ export function pruneMaybeThrows(fn: HIRFunction): void { const mappedTerminal = terminalMapping.get(predecessor); CompilerError.invariant(mappedTerminal != null, { reason: `Expected non-existing phi operand's predecessor to have been mapped to a new terminal`, - loc: GeneratedSource, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], description: `Could not find mapping for predecessor bb${predecessor} in block bb${ block.id } for phi ${printPlace(phi.place)}`, diff --git a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/AlignObjectMethodScopes.ts b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/AlignObjectMethodScopes.ts index d5b8f99591cfb..680fb78c40ad1 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/AlignObjectMethodScopes.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/AlignObjectMethodScopes.ts @@ -41,8 +41,15 @@ function findScopesToMerge(fn: HIRFunction): DisjointSet { { reason: 'Internal error: Expected all ObjectExpressions and ObjectMethods to have non-null scope.', + description: null, suggestions: null, - loc: GeneratedSource, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], }, ); mergeScopesBuilder.union([operandScope, lvalueScope]); diff --git a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/AlignReactiveScopesToBlockScopesHIR.ts b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/AlignReactiveScopesToBlockScopesHIR.ts index e440340bd29f3..4a562dffdcebc 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/AlignReactiveScopesToBlockScopesHIR.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/AlignReactiveScopesToBlockScopesHIR.ts @@ -170,7 +170,14 @@ export function alignReactiveScopesToBlockScopesHIR(fn: HIRFunction): void { CompilerError.invariant(!valueBlockNodes.has(fallthrough), { reason: 'Expect hir blocks to have unique fallthroughs', - loc: terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: terminal.loc, + message: null, + }, + ], }); if (node != null) { valueBlockNodes.set(fallthrough, node); @@ -252,7 +259,14 @@ export function alignReactiveScopesToBlockScopesHIR(fn: HIRFunction): void { // Transition from block->value block, derive the outer block range CompilerError.invariant(fallthrough !== null, { reason: `Expected a fallthrough for value block`, - loc: terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: terminal.loc, + message: null, + }, + ], }); const fallthroughBlock = fn.body.blocks.get(fallthrough)!; const nextId = diff --git a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/AssertScopeInstructionsWithinScope.ts b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/AssertScopeInstructionsWithinScope.ts index 718e28f6101d1..eec357770d5a6 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/AssertScopeInstructionsWithinScope.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/AssertScopeInstructionsWithinScope.ts @@ -81,10 +81,16 @@ class CheckInstructionsAgainstScopesVisitor extends ReactiveFunctionVisitor< !this.activeScopes.has(scope.id) ) { CompilerError.invariant(false, { - description: `Instruction [${id}] is part of scope @${scope.id}, but that scope has already completed.`, - loc: place.loc, reason: 'Encountered an instruction that should be part of a scope, but where that scope has already completed', + description: `Instruction [${id}] is part of scope @${scope.id}, but that scope has already completed.`, + details: [ + { + kind: 'error', + loc: place.loc, + message: null, + }, + ], suggestions: null, }); } diff --git a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/AssertWellFormedBreakTargets.ts b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/AssertWellFormedBreakTargets.ts index 9ce9b2f490664..d838fd4bfd4b2 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/AssertWellFormedBreakTargets.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/AssertWellFormedBreakTargets.ts @@ -28,7 +28,14 @@ class Visitor extends ReactiveFunctionVisitor> { if (terminal.kind === 'break' || terminal.kind === 'continue') { CompilerError.invariant(seenLabels.has(terminal.target), { reason: 'Unexpected break to invalid label', - loc: stmt.terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: stmt.terminal.loc, + message: null, + }, + ], }); } } diff --git a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/BuildReactiveFunction.ts b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/BuildReactiveFunction.ts index 03e06dd0a2408..b400bb349876a 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/BuildReactiveFunction.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/BuildReactiveFunction.ts @@ -70,7 +70,13 @@ class Driver { CompilerError.invariant(!this.cx.emitted.has(block.id), { reason: `Cannot emit the same block twice: bb${block.id}`, description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); this.cx.emitted.add(block.id); @@ -130,7 +136,14 @@ class Driver { if (this.cx.isScheduled(terminal.consequent)) { CompilerError.invariant(false, { reason: `Unexpected 'if' where the consequent is already scheduled`, - loc: terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: terminal.loc, + message: null, + }, + ], }); } else { consequent = this.traverseBlock( @@ -143,7 +156,14 @@ class Driver { if (this.cx.isScheduled(alternateId)) { CompilerError.invariant(false, { reason: `Unexpected 'if' where the alternate is already scheduled`, - loc: terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: terminal.loc, + message: null, + }, + ], }); } else { alternate = this.traverseBlock(this.cx.ir.blocks.get(alternateId)!); @@ -196,7 +216,14 @@ class Driver { if (this.cx.isScheduled(case_.block)) { CompilerError.invariant(case_.block === terminal.fallthrough, { reason: `Unexpected 'switch' where a case is already scheduled and block is not the fallthrough`, - loc: terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: terminal.loc, + message: null, + }, + ], }); return; } else { @@ -255,7 +282,14 @@ class Driver { } else { CompilerError.invariant(false, { reason: `Unexpected 'do-while' where the loop is already scheduled`, - loc: terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: terminal.loc, + message: null, + }, + ], }); } @@ -316,7 +350,14 @@ class Driver { } else { CompilerError.invariant(false, { reason: `Unexpected 'while' where the loop is already scheduled`, - loc: terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: terminal.loc, + message: null, + }, + ], }); } @@ -402,7 +443,14 @@ class Driver { } else { CompilerError.invariant(false, { reason: `Unexpected 'for' where the loop is already scheduled`, - loc: terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: terminal.loc, + message: null, + }, + ], }); } @@ -500,7 +548,14 @@ class Driver { } else { CompilerError.invariant(false, { reason: `Unexpected 'for-of' where the loop is already scheduled`, - loc: terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: terminal.loc, + message: null, + }, + ], }); } @@ -572,7 +627,14 @@ class Driver { } else { CompilerError.invariant(false, { reason: `Unexpected 'for-in' where the loop is already scheduled`, - loc: terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: terminal.loc, + message: null, + }, + ], }); } @@ -615,7 +677,14 @@ class Driver { if (this.cx.isScheduled(terminal.alternate)) { CompilerError.invariant(false, { reason: `Unexpected 'branch' where the alternate is already scheduled`, - loc: terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: terminal.loc, + message: null, + }, + ], }); } else { alternate = this.traverseBlock( @@ -653,7 +722,14 @@ class Driver { if (this.cx.isScheduled(terminal.block)) { CompilerError.invariant(false, { reason: `Unexpected 'label' where the block is already scheduled`, - loc: terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: terminal.loc, + message: null, + }, + ], }); } else { block = this.traverseBlock(this.cx.ir.blocks.get(terminal.block)!); @@ -811,7 +887,14 @@ class Driver { if (this.cx.isScheduled(terminal.block)) { CompilerError.invariant(false, { reason: `Unexpected 'scope' where the block is already scheduled`, - loc: terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: terminal.loc, + message: null, + }, + ], }); } else { block = this.traverseBlock(this.cx.ir.blocks.get(terminal.block)!); @@ -837,7 +920,13 @@ class Driver { CompilerError.invariant(false, { reason: 'Unexpected unsupported terminal', description: null, - loc: terminal.loc, + details: [ + { + kind: 'error', + loc: terminal.loc, + message: null, + }, + ], suggestions: null, }); } @@ -874,7 +963,13 @@ class Driver { reason: 'Expected branch block to end in an instruction that sets the test value', description: null, - loc: instr.lvalue.loc, + details: [ + { + kind: 'error', + loc: instr.lvalue.loc, + message: null, + }, + ], suggestions: null, }, ); @@ -906,7 +1001,13 @@ class Driver { CompilerError.invariant(false, { reason: 'Expected goto value block to have at least one instruction', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); } else if (defaultBlock.instructions.length === 1) { @@ -1191,14 +1292,27 @@ class Driver { CompilerError.invariant(false, { reason: 'Expected a break target', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); } if (this.cx.scopeFallthroughs.has(target.block)) { CompilerError.invariant(target.type === 'implicit', { reason: 'Expected reactive scope to implicitly break to fallthrough', - loc, + description: null, + details: [ + { + kind: 'error', + loc, + message: null, + }, + ], }); return null; } @@ -1224,7 +1338,13 @@ class Driver { CompilerError.invariant(target !== null, { reason: `Expected continue target to be scheduled for bb${block}`, description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); @@ -1299,7 +1419,13 @@ class Context { CompilerError.invariant(!this.#scheduled.has(block), { reason: `Break block is already scheduled: bb${block}`, description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); this.#scheduled.add(block); @@ -1318,7 +1444,13 @@ class Context { CompilerError.invariant(!this.#scheduled.has(continueBlock), { reason: `Continue block is already scheduled: bb${continueBlock}`, description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); this.#scheduled.add(continueBlock); @@ -1346,7 +1478,13 @@ class Context { CompilerError.invariant(last !== undefined && last.id === scheduleId, { reason: 'Can only unschedule the last target', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); if (last.type !== 'loop' || last.ownsBlock !== null) { @@ -1421,7 +1559,13 @@ class Context { CompilerError.invariant(false, { reason: 'Expected a break target', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); } 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 5423f04843ed1..894f6ce209ccf 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/CodegenReactiveFunction.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/CodegenReactiveFunction.ts @@ -296,7 +296,14 @@ export function codegenFunction( CompilerError.invariant(globalGating != null, { reason: 'Bad config not caught! Expected at least one of gating or globalGating', - loc: null, + description: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); ifTest = globalGating; @@ -499,10 +506,16 @@ function codegenBlock(cx: Context, block: ReactiveBlock): t.BlockStatement { continue; } CompilerError.invariant(temp.get(key)! === value, { - loc: null, reason: 'Expected temporary value to be unchanged', description: null, suggestions: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], }); } cx.temp = temp; @@ -670,7 +683,13 @@ function codegenReactiveScope( description: `Declaration \`${printIdentifier( identifier, )}\` is unnamed in scope @${scope.id}`, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); @@ -707,7 +726,13 @@ function codegenReactiveScope( CompilerError.invariant(firstOutputIndex !== null, { reason: `Expected scope to have at least one declaration`, description: `Scope '@${scope.id}' has no declarations`, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); testCondition = t.binaryExpression( @@ -730,7 +755,13 @@ function codegenReactiveScope( { reason: `Expected to not have both change detection enabled and memoization disabled`, description: `Incompatible config options`, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], }, ); testCondition = t.logicalExpression( @@ -914,8 +945,14 @@ function codegenReactiveScope( earlyReturnValue.value.name.kind === 'named', { reason: `Expected early return value to be promoted to a named variable`, - loc: earlyReturnValue.loc, description: null, + details: [ + { + kind: 'error', + loc: earlyReturnValue.loc, + message: null, + }, + ], suggestions: null, }, ); @@ -975,7 +1012,13 @@ function codegenTerminal( CompilerError.invariant(terminal.init.kind === 'SequenceExpression', { reason: `Expected a sequence expression init for for..in`, description: `Got \`${terminal.init.kind}\` expression instead`, - loc: terminal.init.loc, + details: [ + { + kind: 'error', + loc: terminal.init.loc, + message: null, + }, + ], suggestions: null, }); if (terminal.init.instructions.length !== 2) { @@ -1010,7 +1053,13 @@ function codegenTerminal( CompilerError.invariant(false, { reason: `Expected a StoreLocal or Destructure to be assigned to the collection`, description: `Found ${iterableItem.value.kind}`, - loc: iterableItem.value.loc, + details: [ + { + kind: 'error', + loc: iterableItem.value.loc, + message: null, + }, + ], suggestions: null, }); } @@ -1027,7 +1076,13 @@ function codegenTerminal( reason: 'Destructure should never be Reassign as it would be an Object/ArrayPattern', description: null, - loc: iterableItem.loc, + details: [ + { + kind: 'error', + loc: iterableItem.loc, + message: null, + }, + ], suggestions: null, }); case InstructionKind.Catch: @@ -1038,7 +1093,13 @@ function codegenTerminal( CompilerError.invariant(false, { reason: `Unexpected ${iterableItem.value.lvalue.kind} variable in for..in collection`, description: null, - loc: iterableItem.loc, + details: [ + { + kind: 'error', + loc: iterableItem.loc, + message: null, + }, + ], suggestions: null, }); default: @@ -1067,7 +1128,13 @@ function codegenTerminal( { reason: `Expected a single-expression sequence expression init for for..of`, description: `Got \`${terminal.init.kind}\` expression instead`, - loc: terminal.init.loc, + details: [ + { + kind: 'error', + loc: terminal.init.loc, + message: null, + }, + ], suggestions: null, }, ); @@ -1076,7 +1143,13 @@ function codegenTerminal( CompilerError.invariant(terminal.test.kind === 'SequenceExpression', { reason: `Expected a sequence expression test for for..of`, description: `Got \`${terminal.init.kind}\` expression instead`, - loc: terminal.test.loc, + details: [ + { + kind: 'error', + loc: terminal.test.loc, + message: null, + }, + ], suggestions: null, }); if (terminal.test.instructions.length !== 2) { @@ -1110,7 +1183,13 @@ function codegenTerminal( CompilerError.invariant(false, { reason: `Expected a StoreLocal or Destructure to be assigned to the collection`, description: `Found ${iterableItem.value.kind}`, - loc: iterableItem.value.loc, + details: [ + { + kind: 'error', + loc: iterableItem.value.loc, + message: null, + }, + ], suggestions: null, }); } @@ -1131,7 +1210,13 @@ function codegenTerminal( CompilerError.invariant(false, { reason: `Unexpected ${iterableItem.value.lvalue.kind} variable in for..of collection`, description: null, - loc: iterableItem.loc, + details: [ + { + kind: 'error', + loc: iterableItem.loc, + message: null, + }, + ], suggestions: null, }); default: @@ -1272,7 +1357,13 @@ function codegenInstructionNullable( reason: 'Encountered a destructuring operation where some identifiers are already declared (reassignments) but others are not (declarations)', description: null, - loc: instr.loc, + details: [ + { + kind: 'error', + loc: instr.loc, + message: null, + }, + ], suggestions: null, }); } else if (hasReassign) { @@ -1285,7 +1376,13 @@ function codegenInstructionNullable( CompilerError.invariant(instr.lvalue === null, { reason: `Const declaration cannot be referenced as an expression`, description: null, - loc: instr.value.loc, + details: [ + { + kind: 'error', + loc: instr.value.loc, + message: `this is ${kind}`, + }, + ], suggestions: null, }); return createVariableDeclaration(instr.loc, 'const', [ @@ -1296,20 +1393,38 @@ function codegenInstructionNullable( CompilerError.invariant(instr.lvalue === null, { reason: `Function declaration cannot be referenced as an expression`, description: null, - loc: instr.value.loc, + details: [ + { + kind: 'error', + loc: instr.value.loc, + message: `this is ${kind}`, + }, + ], suggestions: null, }); const genLvalue = codegenLValue(cx, lvalue); CompilerError.invariant(genLvalue.type === 'Identifier', { reason: 'Expected an identifier as a function declaration lvalue', description: null, - loc: instr.value.loc, + details: [ + { + kind: 'error', + loc: instr.value.loc, + message: null, + }, + ], suggestions: null, }); CompilerError.invariant(value?.type === 'FunctionExpression', { reason: 'Expected a function as a function declaration value', description: `Got ${value == null ? String(value) : value.type} at ${printInstruction(instr)}`, - loc: instr.value.loc, + details: [ + { + kind: 'error', + loc: instr.value.loc, + message: null, + }, + ], suggestions: null, }); return createFunctionDeclaration( @@ -1325,7 +1440,13 @@ function codegenInstructionNullable( CompilerError.invariant(instr.lvalue === null, { reason: `Const declaration cannot be referenced as an expression`, description: null, - loc: instr.value.loc, + details: [ + { + kind: 'error', + loc: instr.value.loc, + message: 'this is const', + }, + ], suggestions: null, }); return createVariableDeclaration(instr.loc, 'let', [ @@ -1336,7 +1457,13 @@ function codegenInstructionNullable( CompilerError.invariant(value !== null, { reason: 'Expected a value for reassignment', description: null, - loc: instr.value.loc, + details: [ + { + kind: 'error', + loc: instr.value.loc, + message: null, + }, + ], suggestions: null, }); const expr = t.assignmentExpression( @@ -1369,7 +1496,13 @@ function codegenInstructionNullable( CompilerError.invariant(false, { reason: `Expected ${kind} to have been pruned in PruneHoistedContexts`, description: null, - loc: instr.loc, + details: [ + { + kind: 'error', + loc: instr.loc, + message: null, + }, + ], suggestions: null, }); } @@ -1387,7 +1520,14 @@ function codegenInstructionNullable( } else if (instr.value.kind === 'ObjectMethod') { CompilerError.invariant(instr.lvalue, { reason: 'Expected object methods to have a temp lvalue', - loc: null, + description: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); cx.objectMethods.set(instr.lvalue.identifier.id, instr.value); @@ -1434,7 +1574,13 @@ function codegenForInit( (instr.kind === 'let' || instr.kind === 'const'), { reason: 'Expected a variable declaration', - loc: init.loc, + details: [ + { + kind: 'error', + loc: init.loc, + message: null, + }, + ], description: `Got ${instr.type}`, suggestions: null, }, @@ -1447,7 +1593,13 @@ function codegenForInit( }); CompilerError.invariant(declarators.length > 0, { reason: 'Expected a variable declaration', - loc: init.loc, + details: [ + { + kind: 'error', + loc: init.loc, + message: null, + }, + ], description: null, suggestions: null, }); @@ -1768,7 +1920,13 @@ function codegenInstructionValue( CompilerError.invariant(t.isExpression(optionalValue.callee), { reason: 'v8 intrinsics are validated during lowering', description: null, - loc: optionalValue.callee.loc ?? null, + details: [ + { + kind: 'error', + loc: optionalValue.callee.loc ?? null, + message: null, + }, + ], suggestions: null, }); value = t.optionalCallExpression( @@ -1784,7 +1942,13 @@ function codegenInstructionValue( CompilerError.invariant(t.isExpression(property), { reason: 'Private names are validated during lowering', description: null, - loc: property.loc ?? null, + details: [ + { + kind: 'error', + loc: property.loc ?? null, + message: null, + }, + ], suggestions: null, }); value = t.optionalMemberExpression( @@ -1800,7 +1964,13 @@ function codegenInstructionValue( reason: 'Expected an optional value to resolve to a call expression or member expression', description: `Got a \`${optionalValue.type}\``, - loc: instrValue.loc, + details: [ + { + kind: 'error', + loc: instrValue.loc, + message: null, + }, + ], suggestions: null, }); } @@ -1816,10 +1986,15 @@ function codegenInstructionValue( t.isOptionalMemberExpression(memberExpr), { reason: - '[Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression. ' + - `Got a \`${memberExpr.type}\``, + '[Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression', description: null, - loc: memberExpr.loc ?? null, + details: [ + { + kind: 'error', + loc: memberExpr.loc ?? null, + message: `Got: '${memberExpr.type}'`, + }, + ], suggestions: null, }, ); @@ -1833,7 +2008,13 @@ function codegenInstructionValue( '[Codegen] Internal error: Forget should always generate MethodCall::property ' + 'as a MemberExpression of MethodCall::receiver', description: null, - loc: memberExpr.loc ?? null, + details: [ + { + kind: 'error', + loc: memberExpr.loc ?? null, + message: null, + }, + ], suggestions: null, }, ); @@ -1878,7 +2059,14 @@ function codegenInstructionValue( const method = cx.objectMethods.get(property.place.identifier.id); CompilerError.invariant(method, { reason: 'Expected ObjectMethod instruction', - loc: null, + description: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); const loweredFunc = method.loweredFunc; @@ -1949,7 +2137,13 @@ function codegenInstructionValue( CompilerError.invariant(tagValue.type === 'StringLiteral', { reason: `Expected JSX tag to be an identifier or string, got \`${tagValue.type}\``, description: null, - loc: tagValue.loc ?? null, + details: [ + { + kind: 'error', + loc: tagValue.loc ?? null, + message: null, + }, + ], suggestions: null, }); if (tagValue.value.indexOf(':') >= 0) { @@ -1969,7 +2163,13 @@ function codegenInstructionValue( SINGLE_CHILD_FBT_TAGS.has(tagValue.value) ) { CompilerError.invariant(instrValue.children != null, { - loc: instrValue.loc, + details: [ + { + kind: 'error', + loc: instrValue.loc, + message: null, + }, + ], reason: 'Expected fbt element to have children', suggestions: null, description: null, @@ -2271,7 +2471,13 @@ function codegenInstructionValue( { reason: `Unexpected StoreLocal in codegenInstructionValue`, description: null, - loc: instrValue.loc, + details: [ + { + kind: 'error', + loc: instrValue.loc, + message: null, + }, + ], suggestions: null, }, ); @@ -2301,7 +2507,13 @@ function codegenInstructionValue( CompilerError.invariant(false, { reason: `Unexpected ${instrValue.kind} in codegenInstructionValue`, description: null, - loc: instrValue.loc, + details: [ + { + kind: 'error', + loc: instrValue.loc, + message: null, + }, + ], suggestions: null, }); } @@ -2447,7 +2659,13 @@ function convertMemberExpressionToJsx( CompilerError.invariant(expr.property.type === 'Identifier', { reason: 'Expected JSX member expression property to be a string', description: null, - loc: expr.loc ?? null, + details: [ + { + kind: 'error', + loc: expr.loc ?? null, + message: null, + }, + ], suggestions: null, }); const property = t.jsxIdentifier(expr.property.name); @@ -2458,7 +2676,13 @@ function convertMemberExpressionToJsx( reason: 'Expected JSX member expression to be an identifier or nested member expression', description: null, - loc: expr.object.loc ?? null, + details: [ + { + kind: 'error', + loc: expr.object.loc ?? null, + message: null, + }, + ], suggestions: null, }); const object = convertMemberExpressionToJsx(expr.object); @@ -2482,7 +2706,13 @@ function codegenObjectPropertyKey( CompilerError.invariant(t.isExpression(expr), { reason: 'Expected object property key to be an expression', description: null, - loc: key.name.loc, + details: [ + { + kind: 'error', + loc: key.name.loc, + message: null, + }, + ], suggestions: null, }); return expr; @@ -2629,7 +2859,13 @@ function codegenPlace(cx: Context, place: Place): t.Expression | t.JSXText { description: `Value for '${printPlace( place, )}' was not set in the codegen context`, - loc: place.loc, + details: [ + { + kind: 'error', + loc: place.loc, + message: null, + }, + ], suggestions: null, }); const identifier = convertIdentifier(place.identifier); @@ -2642,7 +2878,13 @@ function convertIdentifier(identifier: Identifier): t.Identifier { identifier.name !== null && identifier.name.kind === 'named', { reason: `Expected temporaries to be promoted to named identifiers in an earlier pass`, - loc: GeneratedSource, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], description: `identifier ${identifier.id} is unnamed`, suggestions: null, }, @@ -2658,7 +2900,14 @@ function compareScopeDependency( a.identifier.name?.kind === 'named' && b.identifier.name?.kind === 'named', { reason: '[Codegen] Expected named identifier for dependency', - loc: a.identifier.loc, + description: null, + details: [ + { + kind: 'error', + loc: a.identifier.loc, + message: null, + }, + ], }, ); const aName = [ @@ -2682,7 +2931,14 @@ function compareScopeDeclaration( a.identifier.name?.kind === 'named' && b.identifier.name?.kind === 'named', { reason: '[Codegen] Expected named identifier for declaration', - loc: a.identifier.loc, + description: null, + details: [ + { + kind: 'error', + loc: a.identifier.loc, + message: null, + }, + ], }, ); const aName = a.identifier.name.value; diff --git a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/FlattenScopesWithHooksOrUseHIR.ts b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/FlattenScopesWithHooksOrUseHIR.ts index 103923a2e4d5e..7f01bde4b2740 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/FlattenScopesWithHooksOrUseHIR.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/FlattenScopesWithHooksOrUseHIR.ts @@ -75,7 +75,13 @@ export function flattenScopesWithHooksOrUseHIR(fn: HIRFunction): void { CompilerError.invariant(terminal.kind === 'scope', { reason: `Expected block to have a scope terminal`, description: `Expected block bb${block.id} to end in a scope terminal`, - loc: terminal.loc, + details: [ + { + kind: 'error', + loc: terminal.loc, + message: null, + }, + ], }); const body = fn.body.blocks.get(terminal.block)!; if ( diff --git a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/InferReactiveScopeVariables.ts b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/InferReactiveScopeVariables.ts index 0c1fd759bd5b8..300115c04e4cb 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/InferReactiveScopeVariables.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/InferReactiveScopeVariables.ts @@ -162,7 +162,13 @@ export function inferReactiveScopeVariables(fn: HIRFunction): void { }); CompilerError.invariant(false, { reason: `Invalid mutable range for scope`, - loc: GeneratedSource, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], description: `Scope @${scope.id} has range [${scope.range.start}:${ scope.range.end }] but the valid range is [1:${maxInstruction + 1}]`, diff --git a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/MergeReactiveScopesThatInvalidateTogether.ts b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/MergeReactiveScopesThatInvalidateTogether.ts index a7acf5d66250f..a698e3bd2472d 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/MergeReactiveScopesThatInvalidateTogether.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/MergeReactiveScopesThatInvalidateTogether.ts @@ -159,11 +159,17 @@ class Transform extends ReactiveFunctionTransform = []; function reset(): void { CompilerError.invariant(current !== null, { - loc: null, reason: 'MergeConsecutiveScopes: expected current scope to be non-null if reset()', - suggestions: null, description: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], + suggestions: null, }); if (current.to > current.from + 1) { merged.push(current); @@ -375,10 +381,16 @@ class Transform extends ReactiveFunctionTransform { CompilerError.invariant(lval.identifier.name != null, { reason: 'PromoteInterposedTemporaries: Assignment targets not expected to be temporaries', - loc: instruction.loc, + description: null, + details: [ + { + kind: 'error', + loc: instruction.loc, + message: null, + }, + ], }); } @@ -454,7 +461,13 @@ function promoteIdentifier(identifier: Identifier, state: State): void { reason: 'promoteTemporary: Expected to be called only for temporary variables', description: null, - loc: GeneratedSource, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], suggestions: null, }); if (state.tags.has(identifier.declarationId)) { diff --git a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PruneHoistedContexts.ts b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PruneHoistedContexts.ts index ae3ff122a23a2..489b7aa42e5f7 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PruneHoistedContexts.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PruneHoistedContexts.ts @@ -145,7 +145,14 @@ class Visitor extends ReactiveFunctionTransform { if (maybeHoistedFn != null) { CompilerError.invariant(maybeHoistedFn.kind === 'func', { reason: '[PruneHoistedContexts] Unexpected hoisted function', - loc: instruction.loc, + description: null, + details: [ + { + kind: 'error', + loc: instruction.loc, + message: null, + }, + ], }); maybeHoistedFn.definition = instruction.value.lvalue.place; /** diff --git a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PruneInitializationDependencies.ts b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PruneInitializationDependencies.ts index 9ef9d382c2834..c8e14be19eb64 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PruneInitializationDependencies.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PruneInitializationDependencies.ts @@ -196,7 +196,14 @@ class Visitor extends ReactiveFunctionVisitor { ): void { CompilerError.invariant(state !== 'Create', { reason: "Visiting a terminal statement with state 'Create'", - loc: stmt.terminal.loc, + description: null, + details: [ + { + kind: 'error', + loc: stmt.terminal.loc, + message: null, + }, + ], }); super.visitTerminal(stmt, state); } diff --git a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PruneNonEscapingScopes.ts b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PruneNonEscapingScopes.ts index 5735f7e80115b..52efb92350c9c 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PruneNonEscapingScopes.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PruneNonEscapingScopes.ts @@ -264,7 +264,13 @@ class State { CompilerError.invariant(identifierNode !== undefined, { reason: 'Expected identifier to be initialized', description: `[${id}] operand=${printPlace(place)} for identifier declaration ${identifier}`, - loc: place.loc, + details: [ + { + kind: 'error', + loc: place.loc, + message: null, + }, + ], suggestions: null, }); identifierNode.scopes.add(scope.id); @@ -286,7 +292,13 @@ function computeMemoizedIdentifiers(state: State): Set { CompilerError.invariant(node !== undefined, { reason: `Expected a node for all identifiers, none found for \`${id}\``, description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); if (node.seen) { @@ -328,7 +340,13 @@ function computeMemoizedIdentifiers(state: State): Set { CompilerError.invariant(node !== undefined, { reason: 'Expected a node for all scopes', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); if (node.seen) { @@ -977,7 +995,13 @@ class CollectDependenciesVisitor extends ReactiveFunctionVisitor< CompilerError.invariant(identifierNode !== undefined, { reason: 'Expected identifier to be initialized', description: null, - loc: stmt.terminal.loc, + details: [ + { + kind: 'error', + loc: stmt.terminal.loc, + message: null, + }, + ], suggestions: null, }); for (const scope of scopes) { @@ -1002,7 +1026,13 @@ class CollectDependenciesVisitor extends ReactiveFunctionVisitor< CompilerError.invariant(identifierNode !== undefined, { reason: 'Expected identifier to be initialized', description: null, - loc: reassignment.loc, + details: [ + { + kind: 'error', + loc: reassignment.loc, + message: null, + }, + ], suggestions: null, }); for (const scope of scopes) { diff --git a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/RenameVariables.ts b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/RenameVariables.ts index 5b39055e7d61a..f7b76d4258fa1 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/RenameVariables.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/RenameVariables.ts @@ -186,7 +186,13 @@ class Scopes { CompilerError.invariant(last === next, { reason: 'Mismatch push/pop calls', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); } diff --git a/compiler/packages/babel-plugin-react-compiler/src/SSA/EliminateRedundantPhi.ts b/compiler/packages/babel-plugin-react-compiler/src/SSA/EliminateRedundantPhi.ts index 12c8c0e2e6221..afc1f479121e6 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/SSA/EliminateRedundantPhi.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/SSA/EliminateRedundantPhi.ts @@ -97,7 +97,13 @@ export function eliminateRedundantPhi( CompilerError.invariant(same !== null, { reason: 'Expected phis to be non-empty', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); rewrites.set(phi.place.identifier, same); @@ -149,12 +155,26 @@ export function eliminateRedundantPhi( for (const phi of block.phis) { CompilerError.invariant(!rewrites.has(phi.place.identifier), { reason: '[EliminateRedundantPhis]: rewrite not complete', - loc: phi.place.loc, + description: null, + details: [ + { + kind: 'error', + loc: phi.place.loc, + message: null, + }, + ], }); for (const [, operand] of phi.operands) { CompilerError.invariant(!rewrites.has(operand.identifier), { reason: '[EliminateRedundantPhis]: rewrite not complete', - loc: phi.place.loc, + description: null, + details: [ + { + kind: 'error', + loc: phi.place.loc, + message: null, + }, + ], }); } } diff --git a/compiler/packages/babel-plugin-react-compiler/src/SSA/EnterSSA.ts b/compiler/packages/babel-plugin-react-compiler/src/SSA/EnterSSA.ts index 820f7388dc41b..67b8e75eb20e7 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/SSA/EnterSSA.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/SSA/EnterSSA.ts @@ -70,7 +70,13 @@ class SSABuilder { CompilerError.invariant(this.#current !== null, { reason: 'we need to be in a block to access state!', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); return this.#states.get(this.#current)!; @@ -253,7 +259,13 @@ function enterSSAImpl( CompilerError.invariant(!visitedBlocks.has(block), { reason: `found a cycle! visiting bb${block.id} again`, description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); @@ -266,7 +278,13 @@ function enterSSAImpl( CompilerError.invariant(func.context.length === 0, { reason: `Expected function context to be empty for outer function declarations`, description: null, - loc: func.loc, + details: [ + { + kind: 'error', + loc: func.loc, + message: null, + }, + ], suggestions: null, }); func.params = func.params.map(param => { @@ -295,7 +313,13 @@ function enterSSAImpl( reason: 'Expected function expression entry block to have zero predecessors', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); entry.preds.add(blockId); diff --git a/compiler/packages/babel-plugin-react-compiler/src/SSA/RewriteInstructionKindsBasedOnReassignment.ts b/compiler/packages/babel-plugin-react-compiler/src/SSA/RewriteInstructionKindsBasedOnReassignment.ts index 0af28e0d12596..3f1e663b21e7c 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/SSA/RewriteInstructionKindsBasedOnReassignment.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/SSA/RewriteInstructionKindsBasedOnReassignment.ts @@ -59,7 +59,13 @@ export function rewriteInstructionKindsBasedOnReassignment( { reason: `Expected variable not to be defined prior to declaration`, description: `${printPlace(lvalue.place)} was already defined`, - loc: lvalue.place.loc, + details: [ + { + kind: 'error', + loc: lvalue.place.loc, + message: null, + }, + ], }, ); declarations.set(lvalue.place.identifier.declarationId, lvalue); @@ -77,7 +83,13 @@ export function rewriteInstructionKindsBasedOnReassignment( { reason: `Expected variable not to be defined prior to declaration`, description: `${printPlace(lvalue.place)} was already defined`, - loc: lvalue.place.loc, + details: [ + { + kind: 'error', + loc: lvalue.place.loc, + message: null, + }, + ], }, ); declarations.set(lvalue.place.identifier.declarationId, lvalue); @@ -101,7 +113,13 @@ export function rewriteInstructionKindsBasedOnReassignment( description: `other places were \`${kind}\` but '${printPlace( place, )}' is const`, - loc: place.loc, + details: [ + { + kind: 'error', + loc: place.loc, + message: 'Expected consistent kind for destructuring', + }, + ], suggestions: null, }, ); @@ -114,7 +132,13 @@ export function rewriteInstructionKindsBasedOnReassignment( CompilerError.invariant(block.kind !== 'value', { reason: `TODO: Handle reassignment in a value block where the original declaration was removed by dead code elimination (DCE)`, description: null, - loc: place.loc, + details: [ + { + kind: 'error', + loc: place.loc, + message: null, + }, + ], suggestions: null, }); declarations.set(place.identifier.declarationId, lvalue); @@ -125,7 +149,13 @@ export function rewriteInstructionKindsBasedOnReassignment( description: `Other places were \`${kind}\` but '${printPlace( place, )}' is const`, - loc: place.loc, + details: [ + { + kind: 'error', + loc: place.loc, + message: 'Expected consistent kind for destructuring', + }, + ], suggestions: null, }, ); @@ -138,7 +168,13 @@ export function rewriteInstructionKindsBasedOnReassignment( description: `Other places were \`${kind}\` but '${printPlace( place, )}' is reassigned`, - loc: place.loc, + details: [ + { + kind: 'error', + loc: place.loc, + message: 'Expected consistent kind for destructuring', + }, + ], suggestions: null, }, ); @@ -150,7 +186,13 @@ export function rewriteInstructionKindsBasedOnReassignment( CompilerError.invariant(kind !== null, { reason: 'Expected at least one operand', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); lvalue.kind = kind; @@ -163,7 +205,13 @@ export function rewriteInstructionKindsBasedOnReassignment( CompilerError.invariant(declaration !== undefined, { reason: `Expected variable to have been defined`, description: `No declaration for ${printPlace(lvalue)}`, - loc: lvalue.loc, + details: [ + { + kind: 'error', + loc: lvalue.loc, + message: null, + }, + ], }); declaration.kind = InstructionKind.Let; break; diff --git a/compiler/packages/babel-plugin-react-compiler/src/TypeInference/InferTypes.ts b/compiler/packages/babel-plugin-react-compiler/src/TypeInference/InferTypes.ts index d3a297e2e51c2..682195f8df624 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/TypeInference/InferTypes.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/TypeInference/InferTypes.ts @@ -616,7 +616,13 @@ class Unifier { CompilerError.invariant(type.operands.length > 0, { reason: 'there should be at least one operand', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); diff --git a/compiler/packages/babel-plugin-react-compiler/src/Utils/DisjointSet.ts b/compiler/packages/babel-plugin-react-compiler/src/Utils/DisjointSet.ts index 566732c2bb9fb..575a35821e7f6 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Utils/DisjointSet.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Utils/DisjointSet.ts @@ -21,7 +21,13 @@ export default class DisjointSet { CompilerError.invariant(first != null, { reason: 'Expected set to be non-empty', description: null, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); /* diff --git a/compiler/packages/babel-plugin-react-compiler/src/Utils/TestUtils.ts b/compiler/packages/babel-plugin-react-compiler/src/Utils/TestUtils.ts index 5188849f1e973..1c3552d44bf03 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Utils/TestUtils.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Utils/TestUtils.ts @@ -164,7 +164,13 @@ function parseConfigPragmaEnvironmentForTest( CompilerError.invariant(false, { reason: 'Internal error, could not parse config from pragma string', description: `${fromZodError(config.error)}`, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); } @@ -248,7 +254,13 @@ function parseConfigStringAsJS( CompilerError.invariant(false, { reason: 'Failed to parse config pragma as JavaScript object', description: `Could not parse: ${configString}. Error: ${error}`, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); } @@ -279,7 +291,13 @@ function parseConfigStringAsJS( CompilerError.invariant(false, { reason: 'Invalid environment configuration in config pragma', description: `${fromZodError(validatedEnvironment.error)}`, - loc: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], suggestions: null, }); } diff --git a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateContextVariableLValues.ts b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateContextVariableLValues.ts index b11bb9de1d2f7..563e3764093f1 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateContextVariableLValues.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateContextVariableLValues.ts @@ -106,12 +106,19 @@ function visit( } CompilerError.invariant(false, { - reason: `Expected all references to a variable to be consistently local or context references`, - loc: place.loc, + reason: + 'Expected all references to a variable to be consistently local or context references', description: `Identifier ${printPlace( place, - )} is referenced as a ${kind} variable, but was previously referenced as a ${prev} variable`, + )} is referenced as a ${kind} variable, but was previously referenced as a ${prev.kind} variable`, suggestions: null, + details: [ + { + kind: 'error', + loc: place.loc, + message: `this is ${prev.kind}`, + }, + ], }); } } diff --git a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateLocalsNotReassignedAfterRender.ts b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateLocalsNotReassignedAfterRender.ts index c70a2f0158c94..e60f9ab4bee31 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateLocalsNotReassignedAfterRender.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateLocalsNotReassignedAfterRender.ts @@ -40,7 +40,7 @@ export function validateLocalsNotReassignedAfterRender(fn: HIRFunction): void { category: ErrorCategory.Immutability, reason: 'Cannot reassign variable after render completes', description: `Reassigning ${variable} after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead.`, - }).withDetail({ + }).withDetails({ kind: 'error', loc: reassignment.loc, message: `Cannot reassign ${variable} after render completes`, @@ -96,7 +96,7 @@ function getContextReassignment( reason: 'Cannot reassign variable in async function', description: 'Reassigning a variable in an async function can cause inconsistent behavior on subsequent renders. Consider using state instead', - }).withDetail({ + }).withDetails({ kind: 'error', loc: reassignment.loc, message: `Cannot reassign ${variable}`, @@ -191,7 +191,14 @@ function getContextReassignment( for (const operand of operands) { CompilerError.invariant(operand.effect !== Effect.Unknown, { reason: `Expected effects to be inferred prior to ValidateLocalsNotReassignedAfterRender`, - loc: operand.loc, + description: null, + details: [ + { + kind: 'error', + loc: operand.loc, + message: '', + }, + ], }); const reassignment = reassigningFunctions.get( operand.identifier.id, 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 b911c0f4c7f24..0e30794f0bfd4 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoDerivedComputationsInEffects.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoDerivedComputationsInEffects.ts @@ -83,7 +83,14 @@ export function validateNoDerivedComputationsInEffects(fn: HIRFunction): void { const dependencies: Array = deps.elements.map(dep => { CompilerError.invariant(dep.kind === 'Identifier', { reason: `Dependency is checked as a place above`, - loc: value.loc, + description: null, + details: [ + { + kind: 'error', + loc: value.loc, + message: 'this is checked as a place above', + }, + ], }); return locals.get(dep.identifier.id) ?? dep.identifier.id; }); 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 286c976530905..2e5d5998707eb 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoFreezingKnownMutableFunctions.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoFreezingKnownMutableFunctions.ts @@ -69,12 +69,12 @@ export function validateNoFreezingKnownMutableFunctions( reason: 'Cannot modify local variables after render completes', description: `This argument is a function which may reassign or mutate ${variable} after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead.`, }) - .withDetail({ + .withDetails({ kind: 'error', loc: operand.loc, message: `This function may (indirectly) reassign or modify ${variable} after render`, }) - .withDetail({ + .withDetails({ kind: 'error', loc: effect.value.loc, message: `This modifies ${variable}`, 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 82a42ac725664..ca0612d80ce2f 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoImpureFunctionsInRender.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoImpureFunctionsInRender.ts @@ -45,7 +45,7 @@ export function validateNoImpureFunctionsInRender( : '') + 'Calling an impure function can produce unstable results that update unpredictably when the component happens to re-render. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent)', suggestions: null, - }).withDetail({ + }).withDetails({ kind: 'error', loc: callee.loc, message: 'Cannot call impure function', diff --git a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoJSXInTryStatement.ts b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoJSXInTryStatement.ts index 8c9aaa8205337..00ffca556f45a 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoJSXInTryStatement.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoJSXInTryStatement.ts @@ -40,7 +40,7 @@ export function validateNoJSXInTryStatement( category: ErrorCategory.ErrorBoundaries, reason: 'Avoid constructing JSX within try/catch', description: `React does not immediately render components when JSX is rendered, so any errors from this component will not be caught by the try/catch. To catch errors in rendering a given component, wrap that component in an error boundary. (https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary)`, - }).withDetail({ + }).withDetails({ kind: 'error', loc: value.loc, message: 'Avoid constructing JSX within try/catch', 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 2e2742611a65f..de415881d61cc 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoRefAccessInRender.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoRefAccessInRender.ts @@ -57,8 +57,14 @@ function makeRefId(id: number): RefId { CompilerError.invariant(id >= 0 && Number.isInteger(id), { reason: 'Expected identifier id to be a non-negative integer', description: null, - loc: null, suggestions: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], }); return id as RefId; } @@ -191,19 +197,40 @@ function tyEqual(a: RefAccessType, b: RefAccessType): boolean { case 'Guard': CompilerError.invariant(b.kind === 'Guard', { reason: 'Expected ref value', - loc: null, + description: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], }); return a.refId === b.refId; case 'RefValue': CompilerError.invariant(b.kind === 'RefValue', { reason: 'Expected ref value', - loc: null, + description: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], }); return a.loc == b.loc; case 'Structure': { CompilerError.invariant(b.kind === 'Structure', { reason: 'Expected structure', - loc: null, + description: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], }); const fnTypesEqual = (a.fn === null && b.fn === null) || @@ -242,7 +269,14 @@ function joinRefAccessTypes(...types: Array): RefAccessType { a.kind === 'Structure' && b.kind === 'Structure', { reason: 'Expected structure', - loc: null, + description: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], }, ); const fn = @@ -471,7 +505,7 @@ function validateNoRefAccessInRenderImpl( category: ErrorCategory.Refs, reason: 'Cannot access refs during render', description: ERROR_DESCRIPTION, - }).withDetail({ + }).withDetails({ kind: 'error', loc: callee.loc, message: `This function accesses a ref value`, @@ -708,7 +742,14 @@ function validateNoRefAccessInRenderImpl( CompilerError.invariant(!env.hasChanged(), { reason: 'Ref type environment did not converge', - loc: null, + description: null, + details: [ + { + kind: 'error', + loc: null, + message: null, + }, + ], }); return Ok( @@ -734,7 +775,7 @@ function guardCheck(errors: CompilerError, operand: Place, env: Env): void { category: ErrorCategory.Refs, reason: 'Cannot access refs during render', description: ERROR_DESCRIPTION, - }).withDetail({ + }).withDetails({ kind: 'error', loc: operand.loc, message: `Cannot access ref value during render`, @@ -758,7 +799,7 @@ function validateNoRefValueAccess( category: ErrorCategory.Refs, reason: 'Cannot access refs during render', description: ERROR_DESCRIPTION, - }).withDetail({ + }).withDetails({ kind: 'error', loc: (type.kind === 'RefValue' && type.loc) || operand.loc, message: `Cannot access ref value during render`, @@ -784,7 +825,7 @@ function validateNoRefPassedToFunction( category: ErrorCategory.Refs, reason: 'Cannot access refs during render', description: ERROR_DESCRIPTION, - }).withDetail({ + }).withDetails({ kind: 'error', loc: (type.kind === 'RefValue' && type.loc) || loc, message: `Passing a ref to a function may read its value during render`, @@ -806,7 +847,7 @@ function validateNoRefUpdate( category: ErrorCategory.Refs, reason: 'Cannot access refs during render', description: ERROR_DESCRIPTION, - }).withDetail({ + }).withDetails({ kind: 'error', loc: (type.kind === 'RefValue' && type.loc) || loc, message: `Cannot update ref during render`, @@ -827,7 +868,7 @@ function validateNoDirectRefValueAccess( category: ErrorCategory.Refs, reason: 'Cannot access refs during render', description: ERROR_DESCRIPTION, - }).withDetail({ + }).withDetails({ kind: 'error', loc: type.loc ?? operand.loc, message: `Cannot access ref value during render`, diff --git a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoSetStateInEffects.ts b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoSetStateInEffects.ts index 32f49a5e31387..19c2e7bc5b9ab 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoSetStateInEffects.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoSetStateInEffects.ts @@ -107,7 +107,7 @@ export function validateNoSetStateInEffects( 'Calling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended. ' + '(https://react.dev/learn/you-might-not-need-an-effect)', suggestions: null, - }).withDetail({ + }).withDetails({ kind: 'error', loc: setState.loc, message: 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 dcd1882f198f4..a1a05b2e63c0a 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoSetStateInRender.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoSetStateInRender.ts @@ -102,7 +102,14 @@ function validateNoSetStateInRenderImpl( case 'StartMemoize': { CompilerError.invariant(activeManualMemoId === null, { reason: 'Unexpected nested StartMemoize instructions', - loc: instr.value.loc, + description: null, + details: [ + { + kind: 'error', + loc: instr.value.loc, + message: null, + }, + ], }); activeManualMemoId = instr.value.manualMemoId; break; @@ -113,7 +120,14 @@ function validateNoSetStateInRenderImpl( { reason: 'Expected FinishMemoize to align with previous StartMemoize instruction', - loc: instr.value.loc, + description: null, + details: [ + { + kind: 'error', + loc: instr.value.loc, + message: null, + }, + ], }, ); activeManualMemoId = null; @@ -134,7 +148,7 @@ function validateNoSetStateInRenderImpl( description: 'Each time the memo callback is evaluated it will change state. This can cause a memoization dependency to change, running the memo function again and causing an infinite loop. Instead of setting state in useMemo(), prefer deriving the value during render. (https://react.dev/reference/react/useState)', suggestions: null, - }).withDetail({ + }).withDetails({ kind: 'error', loc: callee.loc, message: 'Found setState() within useMemo()', @@ -149,7 +163,7 @@ function validateNoSetStateInRenderImpl( description: 'Calling setState during render will trigger another render, and can lead to infinite loops. (https://react.dev/reference/react/useState)', suggestions: null, - }).withDetail({ + }).withDetails({ kind: 'error', loc: callee.loc, message: 'Found setState() in render', 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 d6d52eda79f5e..0f5b40e8bcccc 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidatePreservedManualMemoization.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidatePreservedManualMemoization.ts @@ -245,7 +245,14 @@ function validateInferredDep( CompilerError.invariant(dep.identifier.name?.kind === 'named', { reason: 'ValidatePreservedManualMemoization: expected scope dependency to be named', - loc: GeneratedSource, + description: null, + details: [ + { + kind: 'error', + loc: GeneratedSource, + message: null, + }, + ], suggestions: null, }); normalizedDep = { @@ -303,7 +310,7 @@ function validateInferredDep( .join('') .trim(), suggestions: null, - }).withDetail({ + }).withDetails({ kind: 'error', loc: memoLocation, message: 'Could not preserve existing manual memoization', @@ -495,7 +502,13 @@ class Visitor extends ReactiveFunctionVisitor { CompilerError.invariant(state.manualMemoState == null, { reason: 'Unexpected nested StartMemoize instructions', description: `Bad manual memoization ids: ${state.manualMemoState?.manualMemoId}, ${value.manualMemoId}`, - loc: value.loc, + details: [ + { + kind: 'error', + loc: value.loc, + message: null, + }, + ], suggestions: null, }); @@ -540,7 +553,7 @@ class Visitor extends ReactiveFunctionVisitor { 'React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. ', 'This dependency may be mutated later, which could cause the value to change unexpectedly.', ].join(''), - }).withDetail({ + }).withDetails({ kind: 'error', loc, message: 'This dependency may be modified later', @@ -556,7 +569,13 @@ class Visitor extends ReactiveFunctionVisitor { { reason: 'Unexpected mismatch between StartMemoize and FinishMemoize', description: `Encountered StartMemoize id=${state.manualMemoState?.manualMemoId} followed by FinishMemoize id=${value.manualMemoId}`, - loc: value.loc, + details: [ + { + kind: 'error', + loc: value.loc, + message: null, + }, + ], suggestions: null, }, ); @@ -591,7 +610,7 @@ class Visitor extends ReactiveFunctionVisitor { ] .join('') .trim(), - }).withDetail({ + }).withDetails({ kind: 'error', loc, message: 'Could not preserve existing memoization', diff --git a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateStaticComponents.ts b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateStaticComponents.ts index 4d37febd47f75..1e0f6407bd91a 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateStaticComponents.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateStaticComponents.ts @@ -69,12 +69,12 @@ export function validateStaticComponents( reason: 'Cannot create components during render', description: `Components created during render will reset their state each time they are created. Declare components outside of render. `, }) - .withDetail({ + .withDetails({ kind: 'error', loc: value.tag.loc, message: 'This component is created during render', }) - .withDetail({ + .withDetails({ kind: 'error', loc: location, message: 'The component is created during render here', 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 f13c310354bd6..664ec606c1f23 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateUseMemo.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateUseMemo.ts @@ -79,7 +79,7 @@ export function validateUseMemo(fn: HIRFunction): Result { description: 'useMemo() callbacks are called by React to cache calculations across re-renders. They should not take parameters. Instead, directly reference the props, state, or local variables needed for the computation.', suggestions: null, - }).withDetail({ + }).withDetails({ kind: 'error', loc, message: 'Callbacks with parameters are not supported', @@ -96,7 +96,7 @@ export function validateUseMemo(fn: HIRFunction): Result { description: 'useMemo() callbacks are called once and must synchronously return a value.', suggestions: null, - }).withDetail({ + }).withDetails({ kind: 'error', loc: body.loc, message: 'Async and generator functions are not supported', diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-infer-mutation-aliasing-effects.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-infer-mutation-aliasing-effects.expect.md index a1c64e50483f8..ef3ba9d2bb6e7 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-infer-mutation-aliasing-effects.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-infer-mutation-aliasing-effects.expect.md @@ -31,13 +31,13 @@ Found 1 error: Invariant: [InferMutationAliasingEffects] Expected value kind to be initialized - thunk$14. + thunk$14 error.bug-infer-mutation-aliasing-effects.ts:10:22 8 | function thunk(action) { 9 | if (typeof action === 'function') { > 10 | return action(thunk, () => stateRef.current, extraArg); - | ^^^^^ [InferMutationAliasingEffects] Expected value kind to be initialized + | ^^^^^ this is uninitialized 11 | } else { 12 | dispatch(action); 13 | return undefined; diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-codegen-methodcall.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-codegen-methodcall.expect.md index 4ea831de8751e..7118601f88072 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-codegen-methodcall.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-codegen-methodcall.expect.md @@ -16,13 +16,15 @@ const YearsAndMonthsSince = () => { ``` Found 1 error: -Invariant: [Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression. Got a `Identifier` +Invariant: [Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression + + error.bug-invariant-codegen-methodcall.ts:3:17 1 | const YearsAndMonthsSince = () => { 2 | const diff = foo(); > 3 | const months = Math.floor(diff.bar()); - | ^^^^^^^^^^ [Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression. Got a `Identifier` + | ^^^^^^^^^^ Got: 'Identifier' 4 | return <>{months}; 5 | }; 6 | diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-expected-consistent-destructuring.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-expected-consistent-destructuring.expect.md index a30ccffcd7bd0..2adb62ebc560e 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-expected-consistent-destructuring.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-expected-consistent-destructuring.expect.md @@ -29,7 +29,7 @@ Found 1 error: Invariant: Expected consistent kind for destructuring -Other places were `Reassign` but 'mutate? #t8$46[7:9]{reactive}' is const. +Other places were `Reassign` but 'mutate? #t8$46[7:9]{reactive}' is const error.bug-invariant-expected-consistent-destructuring.ts:9:9 7 | diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-local-or-context-references.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-local-or-context-references.expect.md index bbf753f965091..86b7f85e450d6 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-local-or-context-references.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-local-or-context-references.expect.md @@ -31,13 +31,13 @@ Found 1 error: Invariant: Expected all references to a variable to be consistently local or context references -Identifier err$7 is referenced as a context variable, but was previously referenced as a [object Object] variable. +Identifier err$7 is referenced as a context variable, but was previously referenced as a local variable error.bug-invariant-local-or-context-references.ts:15:13 13 | setState(_prevState => ({ 14 | loading: false, > 15 | error: err, - | ^^^ Expected all references to a variable to be consistently local or context references + | ^^^ this is local 16 | })); 17 | } 18 | }; diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-unexpected-terminal-in-optional.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-unexpected-terminal-in-optional.expect.md index 743d2b9071e6a..c024342034701 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-unexpected-terminal-in-optional.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-unexpected-terminal-in-optional.expect.md @@ -21,11 +21,13 @@ Found 1 error: Invariant: Unexpected terminal in optional + + error.bug-invariant-unexpected-terminal-in-optional.ts:3:16 1 | const Foo = ({json}) => { 2 | try { > 3 | const foo = JSON.parse(json)?.foo; - | ^^^^ Unexpected terminal in optional + | ^^^^ Unexpected maybe-throw in optional 4 | return {foo}; 5 | } catch { 6 | return null; diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-unnamed-temporary.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-unnamed-temporary.expect.md index f8c46659bf7c2..8ea691f5866d8 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-unnamed-temporary.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-invariant-unnamed-temporary.expect.md @@ -24,7 +24,7 @@ Found 1 error: Invariant: Expected temporaries to be promoted to named identifiers in an earlier pass -identifier 15 is unnamed. +identifier 15 is unnamed ``` \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.call-args-destructuring-asignment-complex.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.call-args-destructuring-asignment-complex.expect.md index 624bc8b0b571c..9a5b4d7e8f007 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.call-args-destructuring-asignment-complex.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.call-args-destructuring-asignment-complex.expect.md @@ -18,11 +18,13 @@ Found 1 error: Invariant: Const declaration cannot be referenced as an expression + + error.call-args-destructuring-asignment-complex.ts:3:9 1 | function Component(props) { 2 | let x = makeObject(); > 3 | x.foo(([[x]] = makeObject())); - | ^^^^^ Const declaration cannot be referenced as an expression + | ^^^^^ this is Const 4 | return x; 5 | } 6 | diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-nested-method-calls-lower-property-load-into-temporary.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-nested-method-calls-lower-property-load-into-temporary.expect.md index 67d6c4f4e0549..5d34199894f04 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-nested-method-calls-lower-property-load-into-temporary.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-nested-method-calls-lower-property-load-into-temporary.expect.md @@ -24,13 +24,15 @@ export const FIXTURE_ENTRYPOINT = { ``` Found 1 error: -Invariant: [Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression. Got a `Identifier` +Invariant: [Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression + + error.todo-nested-method-calls-lower-property-load-into-temporary.ts:6:14 4 | function Component({}) { 5 | const items = makeArray(0, 1, 2, null, 4, false, 6); > 6 | const max = Math.max(2, items.push(5), ...other); - | ^^^^^^^^ [Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression. Got a `Identifier` + | ^^^^^^^^ Got: 'Identifier' 7 | return max; 8 | } 9 | diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-named-function-with-shadowed-local-same-name.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-named-function-with-shadowed-local-same-name.expect.md index 8b2bc0b2b6df6..7892cd232d08a 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-named-function-with-shadowed-local-same-name.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-named-function-with-shadowed-local-same-name.expect.md @@ -23,13 +23,13 @@ Found 1 error: Invariant: [InferMutationAliasingEffects] Expected value kind to be initialized - hasErrors_0$15:TFunction. + hasErrors_0$15:TFunction error.todo-repro-named-function-with-shadowed-local-same-name.ts:9:9 7 | return hasErrors; 8 | } > 9 | return hasErrors(); - | ^^^^^^^^^ [InferMutationAliasingEffects] Expected value kind to be initialized + | ^^^^^^^^^ this is uninitialized 10 | } 11 | ``` diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.todo-repro-named-function-with-shadowed-local-same-name.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.todo-repro-named-function-with-shadowed-local-same-name.expect.md index 092c895cc9812..06b960b366dc4 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.todo-repro-named-function-with-shadowed-local-same-name.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.todo-repro-named-function-with-shadowed-local-same-name.expect.md @@ -24,13 +24,13 @@ Found 1 error: Invariant: [InferMutationAliasingEffects] Expected value kind to be initialized - hasErrors_0$15:TFunction. + hasErrors_0$15:TFunction error.todo-repro-named-function-with-shadowed-local-same-name.ts:10:9 8 | return hasErrors; 9 | } > 10 | return hasErrors(); - | ^^^^^^^^^ [InferMutationAliasingEffects] Expected value kind to be initialized + | ^^^^^^^^^ this is uninitialized 11 | } 12 | ```