@samitouri / QOS-React-2 / commits / 0bfa404bac

[compiler] More precise errors for invalid import/export/namespace statements (#33748)

import, export, and TS namespace statements can only be used at the top-level of a module, which is enforced by parsers already. Here we add a backup validation of that. As of this PR, we now have only major statement type (class declarations) listed as a todo. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33748). * #33753 * #33752 * #33751 * #33750 * __->__ #33748

Joseph Savona committed Jul 9, 2025 at 22:24 UTC 0bfa404bacbad78af5b39c080ba67535f2e53044
1 file changed +36 -21
compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts
+36 -21
@@ -1397,6 +1397,41 @@ function lowerStatement(
1397 });
1398 return;
1399 }
1400 + case 'ExportAllDeclaration':
1401 + case 'ExportDefaultDeclaration':
1402 + case 'ExportNamedDeclaration':
1403 + case 'ImportDeclaration':
1404 + case 'TSExportAssignment':
1405 + case 'TSImportEqualsDeclaration': {
1406 + builder.errors.push({
1407 + reason:
1408 + 'JavaScript `import` and `export` statements may only appear at the top level of a module',
1409 + severity: ErrorSeverity.InvalidJS,
1410 + loc: stmtPath.node.loc ?? null,
1411 + suggestions: null,
1412 + });
1413 + lowerValueToTemporary(builder, {
1414 + kind: 'UnsupportedNode',
1415 + loc: stmtPath.node.loc ?? GeneratedSource,
1416 + node: stmtPath.node,
1417 + });
1418 + return;
1419 + }
1420 + case 'TSNamespaceExportDeclaration': {
1421 + builder.errors.push({
1422 + reason:
1423 + 'TypeScript `namespace` statements may only appear at the top level of a module',
1424 + severity: ErrorSeverity.InvalidJS,
1425 + loc: stmtPath.node.loc ?? null,
1426 + suggestions: null,
1427 + });
1428 + lowerValueToTemporary(builder, {
1429 + kind: 'UnsupportedNode',
1430 + loc: stmtPath.node.loc ?? GeneratedSource,
1431 + node: stmtPath.node,
1432 + });
1433 + return;
1434 + }
1435 case 'DeclareClass':
1436 case 'DeclareExportAllDeclaration':
1437 case 'DeclareExportDeclaration':
@@ -1411,32 +1446,12 @@ function lowerStatement(
1446 case 'OpaqueType':
1447 case 'TSDeclareFunction':
1448 case 'TSInterfaceDeclaration':
1449 + case 'TSModuleDeclaration':
1450 case 'TSTypeAliasDeclaration':
1451 case 'TypeAlias': {
1452 // We do not preserve type annotations/syntax through transformation
1453 return;
1454 }
1419 - case 'ExportAllDeclaration':
1420 - case 'ExportDefaultDeclaration':
1421 - case 'ExportNamedDeclaration':
1422 - case 'ImportDeclaration':
1423 - case 'TSExportAssignment':
1424 - case 'TSImportEqualsDeclaration':
1425 - case 'TSModuleDeclaration':
1426 - case 'TSNamespaceExportDeclaration': {
1427 - builder.errors.push({
1428 - reason: `(BuildHIR::lowerStatement) Handle ${stmtPath.type} statements`,
1429 - severity: ErrorSeverity.Todo,
1430 - loc: stmtPath.node.loc ?? null,
1431 - suggestions: null,
1432 - });
1433 - lowerValueToTemporary(builder, {
1434 - kind: 'UnsupportedNode',
1435 - loc: stmtPath.node.loc ?? GeneratedSource,
1436 - node: stmtPath.node,
1437 - });
1438 - return;
1439 - }
1455 default: {
1456 return assertExhaustive(
1457 stmtNode,