From 302ca326597bc0cb1e529bfe40424475c6216444 Mon Sep 17 00:00:00 2001 From: Joe Savona Date: Fri, 16 Aug 2024 11:17:37 -0700 Subject: [PATCH 1/2] [compiler] Validate against JSX in try statements Per comments on the new validation pass, this disallows creating JSX (expression/fragment) within a try statement. Developers sometimes use this pattern thinking that they can catch errors during the rendering of the element, without realizing that rendering is lazy. The validation allows us to teach developers about the error boundary pattern. [ghstack-poisoned] --- .../src/Entrypoint/Pipeline.ts | 3 + .../Validation/ValidateNoJSXInTryStatement.ts | 52 ++++++++++++++++++ ...in-catch-in-outer-try-with-catch.expect.md | 37 +++++++++++++ ...id-jsx-in-catch-in-outer-try-with-catch.js | 16 ++++++ ...or.invalid-jsx-in-try-with-catch.expect.md | 30 ++++++++++ .../error.invalid-jsx-in-try-with-catch.js | 9 +++ ...-catch-in-outer-try-with-finally.expect.md | 55 +++++++++++++++++++ ...-jsx-in-catch-in-outer-try-with-finally.js | 16 ++++++ ...-invalid-jsx-in-try-with-finally.expect.md | 38 +++++++++++++ ...or.todo-invalid-jsx-in-try-with-finally.js | 9 +++ 10 files changed, 265 insertions(+) create mode 100644 compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoJSXInTryStatement.ts create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-catch-in-outer-try-with-catch.expect.md create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-catch-in-outer-try-with-catch.js create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-try-with-catch.expect.md create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-try-with-catch.js create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-catch-in-outer-try-with-finally.expect.md create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-catch-in-outer-try-with-finally.js create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-try-with-finally.expect.md create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-try-with-finally.js diff --git a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts index 590aba2fdc0c4..3926f9d66761b 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts @@ -105,6 +105,7 @@ import {outlineFunctions} from '../Optimization/OutlineFunctions'; import {propagatePhiTypes} from '../TypeInference/PropagatePhiTypes'; import {lowerContextAccess} from '../Optimization/LowerContextAccess'; import {validateNoSetStateInPassiveEffects} from '../Validation/ValidateNoSetStateInPassiveEffects'; +import {validateNoJSXInTryStatement} from '../Validation/ValidateNoJSXInTryStatement'; export type CompilerPipelineValue = | {kind: 'ast'; name: string; value: CodegenFunction} @@ -249,6 +250,8 @@ function* runWithEnvironment( validateNoSetStateInPassiveEffects(hir); } + validateNoJSXInTryStatement(hir); + inferReactivePlaces(hir); yield log({kind: 'hir', name: 'InferReactivePlaces', value: hir}); diff --git a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoJSXInTryStatement.ts b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoJSXInTryStatement.ts new file mode 100644 index 0000000000000..b92a89d764301 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoJSXInTryStatement.ts @@ -0,0 +1,52 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import {CompilerError, ErrorSeverity} from '..'; +import {BlockId, HIRFunction} from '../HIR'; +import {retainWhere} from '../Utils/utils'; + +/** + * Developers may not be aware of error boundaries and lazy evaluation of JSX, leading them + * to use patterns such as `let el; try { el = } catch { ... }` to attempt to + * catch rendering errors. Such code will fail to catch errors in rendering, but developers + * may not realize this right away. + * + * This validation pass validates against this pattern: specifically, it errors for JSX + * created within a try block. JSX is allowed within a catch statement, unless that catch + * is itself nested inside an outer try. + */ +export function validateNoJSXInTryStatement(fn: HIRFunction): void { + const activeTryBlocks: Array = []; + const errors = new CompilerError(); + for (const [, block] of fn.body.blocks) { + retainWhere(activeTryBlocks, id => id !== block.id); + + if (activeTryBlocks.length !== 0) { + for (const instr of block.instructions) { + const {value} = instr; + switch (value.kind) { + case 'JsxExpression': + case 'JsxFragment': { + errors.push({ + severity: ErrorSeverity.InvalidReact, + reason: `Unexpected JSX element within a try statement. 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)`, + loc: value.loc, + }); + break; + } + } + } + } + + if (block.terminal.kind === 'try') { + activeTryBlocks.push(block.terminal.handler); + } + } + if (errors.hasErrors()) { + throw errors; + } +} diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-catch-in-outer-try-with-catch.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-catch-in-outer-try-with-catch.expect.md new file mode 100644 index 0000000000000..579f4b5229408 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-catch-in-outer-try-with-catch.expect.md @@ -0,0 +1,37 @@ + +## Input + +```javascript +import {identity} from 'shared-runtime'; + +function Component(props) { + let el; + try { + let value; + try { + value = identity(props.foo); + } catch { + el =
; + } + } catch { + return null; + } + return el; +} + +``` + + +## Error + +``` + 8 | value = identity(props.foo); + 9 | } catch { +> 10 | el =
; + | ^^^^^^^^^^^^^^^^^^^^^ InvalidReact: Unexpected JSX element within a try statement. 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) (10:10) + 11 | } + 12 | } catch { + 13 | return null; +``` + + \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-catch-in-outer-try-with-catch.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-catch-in-outer-try-with-catch.js new file mode 100644 index 0000000000000..62c2137af5736 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-catch-in-outer-try-with-catch.js @@ -0,0 +1,16 @@ +import {identity} from 'shared-runtime'; + +function Component(props) { + let el; + try { + let value; + try { + value = identity(props.foo); + } catch { + el =
; + } + } catch { + return null; + } + return el; +} diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-try-with-catch.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-try-with-catch.expect.md new file mode 100644 index 0000000000000..e8e630961cef1 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-try-with-catch.expect.md @@ -0,0 +1,30 @@ + +## Input + +```javascript +function Component(props) { + let el; + try { + el =
; + } catch { + return null; + } + return el; +} + +``` + + +## Error + +``` + 2 | let el; + 3 | try { +> 4 | el =
; + | ^^^^^^^ InvalidReact: Unexpected JSX element within a try statement. 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) (4:4) + 5 | } catch { + 6 | return null; + 7 | } +``` + + \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-try-with-catch.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-try-with-catch.js new file mode 100644 index 0000000000000..dedf0acfef3a8 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-try-with-catch.js @@ -0,0 +1,9 @@ +function Component(props) { + let el; + try { + el =
; + } catch { + return null; + } + return el; +} diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-catch-in-outer-try-with-finally.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-catch-in-outer-try-with-finally.expect.md new file mode 100644 index 0000000000000..67e425f135117 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-catch-in-outer-try-with-finally.expect.md @@ -0,0 +1,55 @@ + +## Input + +```javascript +import {identity} from 'shared-runtime'; + +function Component(props) { + let el; + try { + let value; + try { + value = identity(props.foo); + } catch { + el =
; + } + } finally { + console.log(el); + } + return el; +} + +``` + + +## Error + +``` + 3 | function Component(props) { + 4 | let el; +> 5 | try { + | ^^^^^ +> 6 | let value; + | ^^^^^^^^^^^^^^ +> 7 | try { + | ^^^^^^^^^^^^^^ +> 8 | value = identity(props.foo); + | ^^^^^^^^^^^^^^ +> 9 | } catch { + | ^^^^^^^^^^^^^^ +> 10 | el =
; + | ^^^^^^^^^^^^^^ +> 11 | } + | ^^^^^^^^^^^^^^ +> 12 | } finally { + | ^^^^^^^^^^^^^^ +> 13 | console.log(el); + | ^^^^^^^^^^^^^^ +> 14 | } + | ^^^^ Todo: (BuildHIR::lowerStatement) Handle TryStatement without a catch clause (5:14) + 15 | return el; + 16 | } + 17 | +``` + + \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-catch-in-outer-try-with-finally.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-catch-in-outer-try-with-finally.js new file mode 100644 index 0000000000000..362b78f3834fa --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-catch-in-outer-try-with-finally.js @@ -0,0 +1,16 @@ +import {identity} from 'shared-runtime'; + +function Component(props) { + let el; + try { + let value; + try { + value = identity(props.foo); + } catch { + el =
; + } + } finally { + console.log(el); + } + return el; +} diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-try-with-finally.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-try-with-finally.expect.md new file mode 100644 index 0000000000000..beb15d1722b3a --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-try-with-finally.expect.md @@ -0,0 +1,38 @@ + +## Input + +```javascript +function Component(props) { + let el; + try { + el =
; + } finally { + console.log(el); + } + return el; +} + +``` + + +## Error + +``` + 1 | function Component(props) { + 2 | let el; +> 3 | try { + | ^^^^^ +> 4 | el =
; + | ^^^^^^^^^^^^^^^^^ +> 5 | } finally { + | ^^^^^^^^^^^^^^^^^ +> 6 | console.log(el); + | ^^^^^^^^^^^^^^^^^ +> 7 | } + | ^^^^ Todo: (BuildHIR::lowerStatement) Handle TryStatement without a catch clause (3:7) + 8 | return el; + 9 | } + 10 | +``` + + \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-try-with-finally.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-try-with-finally.js new file mode 100644 index 0000000000000..5766b3a1e1e2b --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-try-with-finally.js @@ -0,0 +1,9 @@ +function Component(props) { + let el; + try { + el =
; + } finally { + console.log(el); + } + return el; +} From 1a37c1ef2f1cb07c7c3b434584b88c80a485bcb8 Mon Sep 17 00:00:00 2001 From: Joe Savona Date: Fri, 16 Aug 2024 11:22:52 -0700 Subject: [PATCH 2/2] Update on "[compiler] Validate against JSX in try statements" Per comments on the new validation pass, this disallows creating JSX (expression/fragment) within a try statement. Developers sometimes use this pattern thinking that they can catch errors during the rendering of the element, without realizing that rendering is lazy. The validation allows us to teach developers about the error boundary pattern. [ghstack-poisoned] --- .../src/Entrypoint/Pipeline.ts | 4 ++- .../src/HIR/Environment.ts | 6 ++++ ...in-catch-in-outer-try-with-catch.expect.md | 15 +++++---- ...id-jsx-in-catch-in-outer-try-with-catch.js | 1 + ...or.invalid-jsx-in-try-with-catch.expect.md | 15 +++++---- .../error.invalid-jsx-in-try-with-catch.js | 1 + ...-catch-in-outer-try-with-finally.expect.md | 33 ++++++++++--------- ...-jsx-in-catch-in-outer-try-with-finally.js | 1 + ...-invalid-jsx-in-try-with-finally.expect.md | 23 ++++++------- ...or.todo-invalid-jsx-in-try-with-finally.js | 1 + 10 files changed, 58 insertions(+), 42 deletions(-) diff --git a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts index 3926f9d66761b..8307e8817b4f9 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts @@ -250,7 +250,9 @@ function* runWithEnvironment( validateNoSetStateInPassiveEffects(hir); } - validateNoJSXInTryStatement(hir); + if (env.config.validateNoJSXInTryStatements) { + validateNoJSXInTryStatement(hir); + } inferReactivePlaces(hir); yield log({kind: 'hir', name: 'InferReactivePlaces', value: hir}); 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 ca03b8a7b1e39..a5614ac244a14 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts @@ -237,6 +237,12 @@ const EnvironmentConfigSchema = z.object({ */ validateNoSetStateInPassiveEffects: z.boolean().default(false), + /** + * Validates against creating JSX within a try block and recommends using an error boundary + * instead. + */ + validateNoJSXInTryStatements: z.boolean().default(false), + /** * Validates that the dependencies of all effect hooks are memoized. This helps ensure * that Forget does not introduce infinite renders caused by a dependency changing, diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-catch-in-outer-try-with-catch.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-catch-in-outer-try-with-catch.expect.md index 579f4b5229408..40cebff89a75e 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-catch-in-outer-try-with-catch.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-catch-in-outer-try-with-catch.expect.md @@ -2,6 +2,7 @@ ## Input ```javascript +// @validateNoJSXInTryStatements import {identity} from 'shared-runtime'; function Component(props) { @@ -25,13 +26,13 @@ function Component(props) { ## Error ``` - 8 | value = identity(props.foo); - 9 | } catch { -> 10 | el =
; - | ^^^^^^^^^^^^^^^^^^^^^ InvalidReact: Unexpected JSX element within a try statement. 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) (10:10) - 11 | } - 12 | } catch { - 13 | return null; + 9 | value = identity(props.foo); + 10 | } catch { +> 11 | el =
; + | ^^^^^^^^^^^^^^^^^^^^^ InvalidReact: Unexpected JSX element within a try statement. 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) (11:11) + 12 | } + 13 | } catch { + 14 | return null; ``` \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-catch-in-outer-try-with-catch.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-catch-in-outer-try-with-catch.js index 62c2137af5736..0935a1a63cd83 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-catch-in-outer-try-with-catch.js +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-catch-in-outer-try-with-catch.js @@ -1,3 +1,4 @@ +// @validateNoJSXInTryStatements import {identity} from 'shared-runtime'; function Component(props) { diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-try-with-catch.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-try-with-catch.expect.md index e8e630961cef1..ee1f5335ef624 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-try-with-catch.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-try-with-catch.expect.md @@ -2,6 +2,7 @@ ## Input ```javascript +// @validateNoJSXInTryStatements function Component(props) { let el; try { @@ -18,13 +19,13 @@ function Component(props) { ## Error ``` - 2 | let el; - 3 | try { -> 4 | el =
; - | ^^^^^^^ InvalidReact: Unexpected JSX element within a try statement. 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) (4:4) - 5 | } catch { - 6 | return null; - 7 | } + 3 | let el; + 4 | try { +> 5 | el =
; + | ^^^^^^^ InvalidReact: Unexpected JSX element within a try statement. 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) (5:5) + 6 | } catch { + 7 | return null; + 8 | } ``` \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-try-with-catch.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-try-with-catch.js index dedf0acfef3a8..3e7747c875b3c 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-try-with-catch.js +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-in-try-with-catch.js @@ -1,3 +1,4 @@ +// @validateNoJSXInTryStatements function Component(props) { let el; try { diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-catch-in-outer-try-with-finally.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-catch-in-outer-try-with-finally.expect.md index 67e425f135117..a7ea7b7739c6a 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-catch-in-outer-try-with-finally.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-catch-in-outer-try-with-finally.expect.md @@ -2,6 +2,7 @@ ## Input ```javascript +// @validateNoJSXInTryStatements import {identity} from 'shared-runtime'; function Component(props) { @@ -25,31 +26,31 @@ function Component(props) { ## Error ``` - 3 | function Component(props) { - 4 | let el; -> 5 | try { + 4 | function Component(props) { + 5 | let el; +> 6 | try { | ^^^^^ -> 6 | let value; +> 7 | let value; | ^^^^^^^^^^^^^^ -> 7 | try { +> 8 | try { | ^^^^^^^^^^^^^^ -> 8 | value = identity(props.foo); +> 9 | value = identity(props.foo); | ^^^^^^^^^^^^^^ -> 9 | } catch { +> 10 | } catch { | ^^^^^^^^^^^^^^ -> 10 | el =
; +> 11 | el =
; | ^^^^^^^^^^^^^^ -> 11 | } +> 12 | } | ^^^^^^^^^^^^^^ -> 12 | } finally { +> 13 | } finally { | ^^^^^^^^^^^^^^ -> 13 | console.log(el); +> 14 | console.log(el); | ^^^^^^^^^^^^^^ -> 14 | } - | ^^^^ Todo: (BuildHIR::lowerStatement) Handle TryStatement without a catch clause (5:14) - 15 | return el; - 16 | } - 17 | +> 15 | } + | ^^^^ Todo: (BuildHIR::lowerStatement) Handle TryStatement without a catch clause (6:15) + 16 | return el; + 17 | } + 18 | ``` \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-catch-in-outer-try-with-finally.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-catch-in-outer-try-with-finally.js index 362b78f3834fa..9db091a2fb7ed 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-catch-in-outer-try-with-finally.js +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-catch-in-outer-try-with-finally.js @@ -1,3 +1,4 @@ +// @validateNoJSXInTryStatements import {identity} from 'shared-runtime'; function Component(props) { diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-try-with-finally.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-try-with-finally.expect.md index beb15d1722b3a..a6a85d4519bcb 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-try-with-finally.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-try-with-finally.expect.md @@ -2,6 +2,7 @@ ## Input ```javascript +// @validateNoJSXInTryStatements function Component(props) { let el; try { @@ -18,21 +19,21 @@ function Component(props) { ## Error ``` - 1 | function Component(props) { - 2 | let el; -> 3 | try { + 2 | function Component(props) { + 3 | let el; +> 4 | try { | ^^^^^ -> 4 | el =
; +> 5 | el =
; | ^^^^^^^^^^^^^^^^^ -> 5 | } finally { +> 6 | } finally { | ^^^^^^^^^^^^^^^^^ -> 6 | console.log(el); +> 7 | console.log(el); | ^^^^^^^^^^^^^^^^^ -> 7 | } - | ^^^^ Todo: (BuildHIR::lowerStatement) Handle TryStatement without a catch clause (3:7) - 8 | return el; - 9 | } - 10 | +> 8 | } + | ^^^^ Todo: (BuildHIR::lowerStatement) Handle TryStatement without a catch clause (4:8) + 9 | return el; + 10 | } + 11 | ``` \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-try-with-finally.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-try-with-finally.js index 5766b3a1e1e2b..f0a17391c0eef 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-try-with-finally.js +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-try-with-finally.js @@ -1,3 +1,4 @@ +// @validateNoJSXInTryStatements function Component(props) { let el; try {