diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/disable-jsx-memoization.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/disable-jsx-memoization.expect.md index 223445d433..f08ff9d676 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/disable-jsx-memoization.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/disable-jsx-memoization.expect.md @@ -2,7 +2,7 @@ ## Input ```javascript -// @memoizeJsxElements false +// @memoizeJsxElements:false function Component(props) { const [name, setName] = useState(null); const onChange = function (e) { @@ -26,7 +26,7 @@ export const FIXTURE_ENTRYPOINT = { ## Code ```javascript -import { unstable_useMemoCache as useMemoCache } from "react"; // @memoizeJsxElements false +import { unstable_useMemoCache as useMemoCache } from "react"; // @memoizeJsxElements:false function Component(props) { const $ = useMemoCache(1); const [name, setName] = useState(null); diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/disable-jsx-memoization.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/disable-jsx-memoization.js index ef97791265..3cb4d05041 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/disable-jsx-memoization.js +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/disable-jsx-memoization.js @@ -1,4 +1,4 @@ -// @memoizeJsxElements false +// @memoizeJsxElements:false function Component(props) { const [name, setName] = useState(null); const onChange = function (e) { diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.bug-validate-no-set-state-not-all-mutable-range-extensions-are-bad.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.bug-validate-no-set-state-not-all-mutable-range-extensions-are-bad.expect.md index e23580622d..60eea597fb 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.bug-validate-no-set-state-not-all-mutable-range-extensions-are-bad.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.bug-validate-no-set-state-not-all-mutable-range-extensions-are-bad.expect.md @@ -2,6 +2,7 @@ ## Input ```javascript +// @validateNoSetStateInRender function Component(props) { const logEvent = useLogging(props.appId); const [currentStep, setCurrentStep] = useState(0); @@ -33,7 +34,7 @@ function Component(props) { ## Error ``` -[ReactForget] InvalidReact: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState) (11:11) +[ReactForget] InvalidReact: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState) (12:12) ``` \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.bug-validate-no-set-state-not-all-mutable-range-extensions-are-bad.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.bug-validate-no-set-state-not-all-mutable-range-extensions-are-bad.js index e8301cfd6e..2a4ce055cd 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.bug-validate-no-set-state-not-all-mutable-range-extensions-are-bad.js +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.bug-validate-no-set-state-not-all-mutable-range-extensions-are-bad.js @@ -1,3 +1,4 @@ +// @validateNoSetStateInRender function Component(props) { const logEvent = useLogging(props.appId); const [currentStep, setCurrentStep] = useState(0); diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-access-ref-during-render.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-access-ref-during-render.expect.md index b591fad42e..1e36f7c902 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-access-ref-during-render.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-access-ref-during-render.expect.md @@ -2,7 +2,7 @@ ## Input ```javascript -// @debug +// @validateRefAccessDuringRender function Component(props) { const ref = useRef(null); const value = ref.current; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-access-ref-during-render.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-access-ref-during-render.js index 0be1f1047a..4269fe4b86 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-access-ref-during-render.js +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-access-ref-during-render.js @@ -1,4 +1,4 @@ -// @debug +// @validateRefAccessDuringRender function Component(props) { const ref = useRef(null); const value = ref.current; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-capture-func-passed-to-jsx.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-capture-func-passed-to-jsx.expect.md index b52e8f693e..85a7e7f672 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-capture-func-passed-to-jsx.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-capture-func-passed-to-jsx.expect.md @@ -2,6 +2,7 @@ ## Input ```javascript +// @validateFrozenLambdas function component(a, b) { let y = { b }; let z = { a }; @@ -20,7 +21,7 @@ function component(a, b) { ## Error ``` -[ReactForget] InvalidReact: This mutates a variable that is managed by React, where an immutable value or a function was expected (8:8) +[ReactForget] InvalidReact: This mutates a variable that is managed by React, where an immutable value or a function was expected (9:9) ``` \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-capture-func-passed-to-jsx.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-capture-func-passed-to-jsx.js index 35357391f9..13841d6307 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-capture-func-passed-to-jsx.js +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-capture-func-passed-to-jsx.js @@ -1,3 +1,4 @@ +// @validateFrozenLambdas function component(a, b) { let y = { b }; let z = { a }; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-conditionally-mutable-lambda.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-conditionally-mutable-lambda.expect.md index 14b1666bde..6f62e04264 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-conditionally-mutable-lambda.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-conditionally-mutable-lambda.expect.md @@ -2,6 +2,7 @@ ## Input ```javascript +// @validateFrozenLambdas function Component(props) { const x = {}; let fn; @@ -25,7 +26,7 @@ function Component(props) { ## Error ``` -[ReactForget] InvalidReact: This mutates a variable that is managed by React, where an immutable value or a function was expected (15:15) +[ReactForget] InvalidReact: This mutates a variable that is managed by React, where an immutable value or a function was expected (16:16) ``` \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-conditionally-mutable-lambda.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-conditionally-mutable-lambda.js index 0ffb689787..076e9cd6cf 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-conditionally-mutable-lambda.js +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-conditionally-mutable-lambda.js @@ -1,3 +1,4 @@ +// @validateFrozenLambdas function Component(props) { const x = {}; let fn; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-mutable-lambda-mutate-local.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-mutable-lambda-mutate-local.expect.md index cc5e8b7d2f..a991205cf0 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-mutable-lambda-mutate-local.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-mutable-lambda-mutate-local.expect.md @@ -2,6 +2,7 @@ ## Input ```javascript +// @validateFrozenLambdas function Component(props) { const x = {}; const onChange = (e) => { @@ -18,7 +19,7 @@ function Component(props) { ## Error ``` -[ReactForget] InvalidReact: This mutates a variable that is managed by React, where an immutable value or a function was expected (8:8) +[ReactForget] InvalidReact: This mutates a variable that is managed by React, where an immutable value or a function was expected (9:9) ``` \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-mutable-lambda-mutate-local.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-mutable-lambda-mutate-local.js index 846b9df81a..9c830542c0 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-mutable-lambda-mutate-local.js +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-mutable-lambda-mutate-local.js @@ -1,3 +1,4 @@ +// @validateFrozenLambdas function Component(props) { const x = {}; const onChange = (e) => { diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-mutable-lambda-reassign-local.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-mutable-lambda-reassign-local.expect.md index 6725c866e4..1404800c4b 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-mutable-lambda-reassign-local.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-mutable-lambda-reassign-local.expect.md @@ -2,6 +2,7 @@ ## Input ```javascript +// @validateFrozenLambdas function Component(props) { let x = ""; const onChange = (e) => { @@ -16,7 +17,7 @@ function Component(props) { ## Error ``` -[ReactForget] InvalidReact: This mutates a variable that is managed by React, where an immutable value or a function was expected (6:6) +[ReactForget] InvalidReact: This mutates a variable that is managed by React, where an immutable value or a function was expected (7:7) ``` \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-mutable-lambda-reassign-local.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-mutable-lambda-reassign-local.js index b13ea05c67..f71882f091 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-mutable-lambda-reassign-local.js +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-freeze-mutable-lambda-reassign-local.js @@ -1,3 +1,4 @@ +// @validateFrozenLambdas function Component(props) { let x = ""; const onChange = (e) => { diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-pass-ref-to-function.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-pass-ref-to-function.expect.md index afd6b808f3..a2c7181cbc 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-pass-ref-to-function.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-pass-ref-to-function.expect.md @@ -2,6 +2,7 @@ ## Input ```javascript +// @validateRefAccessDuringRender function Component(props) { const ref = useRef(null); const x = foo(ref); @@ -14,7 +15,7 @@ function Component(props) { ## Error ``` -[ReactForget] InvalidReact: Ref values may not be passed to functions because they could read the ref value (`current` property) during render. (https://react.dev/reference/react/useRef). Cannot access ref object at mutate? $21[6:8]:TObject (3:3) +[ReactForget] InvalidReact: Ref values may not be passed to functions because they could read the ref value (`current` property) during render. (https://react.dev/reference/react/useRef). Cannot access ref object at mutate? $21[6:8]:TObject (4:4) ``` \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-pass-ref-to-function.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-pass-ref-to-function.js index ce93fc174c..bba228dfa4 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-pass-ref-to-function.js +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-pass-ref-to-function.js @@ -1,3 +1,4 @@ +// @validateRefAccessDuringRender function Component(props) { const ref = useRef(null); const x = foo(ref); diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-ref-in-callback-invoked-during-render.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-ref-in-callback-invoked-during-render.expect.md index 28e47ba6c4..f8d25f7b51 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-ref-in-callback-invoked-during-render.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-ref-in-callback-invoked-during-render.expect.md @@ -2,7 +2,7 @@ ## Input ```javascript -// @debug +// @validateRefAccessDuringRender function Component(props) { const ref = useRef(null); const renderItem = (item) => { diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-ref-in-callback-invoked-during-render.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-ref-in-callback-invoked-during-render.js index f400b30286..df786b271a 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-ref-in-callback-invoked-during-render.js +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-ref-in-callback-invoked-during-render.js @@ -1,4 +1,4 @@ -// @debug +// @validateRefAccessDuringRender function Component(props) { const ref = useRef(null); const renderItem = (item) => { diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-ref-value-as-props.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-ref-value-as-props.expect.md index b9aa2f0489..ad1e7a7ca0 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-ref-value-as-props.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-ref-value-as-props.expect.md @@ -2,6 +2,7 @@ ## Input ```javascript +// @validateRefAccessDuringRender function Component(props) { const ref = useRef(null); return ; @@ -13,7 +14,7 @@ function Component(props) { ## Error ``` -[ReactForget] InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef). Cannot access ref value at freeze $19:TObject (3:3) +[ReactForget] InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef). Cannot access ref value at freeze $19:TObject (4:4) ``` \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-ref-value-as-props.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-ref-value-as-props.js index 3cf0b2aaf8..0c8c1e65c8 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-ref-value-as-props.js +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-ref-value-as-props.js @@ -1,3 +1,4 @@ +// @validateRefAccessDuringRender function Component(props) { const ref = useRef(null); return ; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-set-and-read-ref-during-render.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-set-and-read-ref-during-render.expect.md index 727d52707d..c728ae32de 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-set-and-read-ref-during-render.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-set-and-read-ref-during-render.expect.md @@ -2,6 +2,7 @@ ## Input ```javascript +// @validateRefAccessDuringRender function Component(props) { const ref = useRef(null); ref.current = props.value; @@ -14,9 +15,9 @@ function Component(props) { ## Error ``` -[ReactForget] InvalidReact: Ref values may not be passed to functions because they could read the ref value (`current` property) during render. (https://react.dev/reference/react/useRef). Cannot access ref object at store $21[7:9]:TObject (3:3) +[ReactForget] InvalidReact: Ref values may not be passed to functions because they could read the ref value (`current` property) during render. (https://react.dev/reference/react/useRef). Cannot access ref object at store $21[7:9]:TObject (4:4) -[ReactForget] InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef). Cannot access ref value at freeze $24:TObject (4:4) +[ReactForget] InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef). Cannot access ref value at freeze $24:TObject (5:5) ``` \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-set-and-read-ref-during-render.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-set-and-read-ref-during-render.js index 97ce6931db..ef485e9005 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-set-and-read-ref-during-render.js +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-set-and-read-ref-during-render.js @@ -1,3 +1,4 @@ +// @validateRefAccessDuringRender function Component(props) { const ref = useRef(null); ref.current = props.value; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-unconditional-set-state-in-render.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-unconditional-set-state-in-render.expect.md index d17de1bd11..17428d98d5 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-unconditional-set-state-in-render.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-unconditional-set-state-in-render.expect.md @@ -2,6 +2,7 @@ ## Input ```javascript +// @validateNoSetStateInRender function Component(props) { const [x, setX] = useState(0); const aliased = setX; @@ -18,9 +19,9 @@ function Component(props) { ## Error ``` -[ReactForget] InvalidReact: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState) (5:5) - [ReactForget] InvalidReact: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState) (6:6) + +[ReactForget] InvalidReact: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState) (7:7) ``` \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-unconditional-set-state-in-render.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-unconditional-set-state-in-render.js index afef24308b..7e08cbe532 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-unconditional-set-state-in-render.js +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-unconditional-set-state-in-render.js @@ -1,3 +1,4 @@ +// @validateNoSetStateInRender function Component(props) { const [x, setX] = useState(0); const aliased = setX; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-use-ref-added-to-dep-without-type-info.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-use-ref-added-to-dep-without-type-info.expect.md index e189cb7d4a..6b40cae910 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-use-ref-added-to-dep-without-type-info.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-use-ref-added-to-dep-without-type-info.expect.md @@ -2,6 +2,7 @@ ## Input ```javascript +// @validateRefAccessDuringRender function Foo({ a }) { const ref = useRef(); // type information is lost here as we don't track types of fields @@ -21,7 +22,7 @@ function Foo({ a }) { ## Error ``` -[ReactForget] InvalidReact: Ref values may not be passed to functions because they could read the ref value (`current` property) during render. (https://react.dev/reference/react/useRef). Cannot access ref object at capture $29:TObject (4:4) +[ReactForget] InvalidReact: Ref values may not be passed to functions because they could read the ref value (`current` property) during render. (https://react.dev/reference/react/useRef). Cannot access ref object at capture $29:TObject (5:5) ``` \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-use-ref-added-to-dep-without-type-info.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-use-ref-added-to-dep-without-type-info.js index bbf5facc4a..c6c9228f9e 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-use-ref-added-to-dep-without-type-info.js +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-use-ref-added-to-dep-without-type-info.js @@ -1,3 +1,4 @@ +// @validateRefAccessDuringRender function Foo({ a }) { const ref = useRef(); // type information is lost here as we don't track types of fields diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-unconditional-set-state-lambda.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-unconditional-set-state-lambda.expect.md index 3159b7a33a..8d1e2600a6 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-unconditional-set-state-lambda.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-unconditional-set-state-lambda.expect.md @@ -2,6 +2,7 @@ ## Input ```javascript +// @validateNoSetStateInRender function Component(props) { let y = 0; const [x, setX] = useState(0); @@ -21,7 +22,7 @@ function Component(props) { ## Error ``` -[ReactForget] InvalidReact: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState) (6:6) +[ReactForget] InvalidReact: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState) (7:7) ``` \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-unconditional-set-state-lambda.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-unconditional-set-state-lambda.js index 8a89c2cbb1..8e7069b7c2 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-unconditional-set-state-lambda.js +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-unconditional-set-state-lambda.js @@ -1,3 +1,4 @@ +// @validateNoSetStateInRender function Component(props) { let y = 0; const [x, setX] = useState(0); diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/ref-current-aliased-not-added-to-dep-2.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/ref-current-aliased-not-added-to-dep-2.expect.md index 7054f3d815..caf1faa54f 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/ref-current-aliased-not-added-to-dep-2.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/ref-current-aliased-not-added-to-dep-2.expect.md @@ -2,7 +2,6 @@ ## Input ```javascript -// @validateRefAccessDuringRender false function Foo({ a }) { const ref = useRef(); const val = ref.current; @@ -16,7 +15,7 @@ function Foo({ a }) { ## Code ```javascript -import { unstable_useMemoCache as useMemoCache } from "react"; // @validateRefAccessDuringRender false +import { unstable_useMemoCache as useMemoCache } from "react"; function Foo(t20) { const $ = useMemoCache(4); const { a } = t20; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/ref-current-aliased-not-added-to-dep-2.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/ref-current-aliased-not-added-to-dep-2.js index 92d7decf20..1bdd040c67 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/ref-current-aliased-not-added-to-dep-2.js +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/ref-current-aliased-not-added-to-dep-2.js @@ -1,4 +1,3 @@ -// @validateRefAccessDuringRender false function Foo({ a }) { const ref = useRef(); const val = ref.current; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep-2.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep-2.expect.md index 83da9c0bed..5074bc6bd6 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep-2.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep-2.expect.md @@ -2,7 +2,6 @@ ## Input ```javascript -// @validateRefAccessDuringRender false function Foo({ a }) { const ref = useRef(); const x = { a, val: ref.current }; @@ -15,7 +14,7 @@ function Foo({ a }) { ## Code ```javascript -import { unstable_useMemoCache as useMemoCache } from "react"; // @validateRefAccessDuringRender false +import { unstable_useMemoCache as useMemoCache } from "react"; function Foo(t17) { const $ = useMemoCache(4); const { a } = t17; diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep-2.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep-2.js index a31a11fd3e..80ced49a9d 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep-2.js +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep-2.js @@ -1,4 +1,3 @@ -// @validateRefAccessDuringRender false function Foo({ a }) { const ref = useRef(); const x = { a, val: ref.current }; diff --git a/compiler/packages/fixture-test-utils/src/compiler-utils.ts b/compiler/packages/fixture-test-utils/src/compiler-utils.ts index e42ab8eced..618f974e8e 100644 --- a/compiler/packages/fixture-test-utils/src/compiler-utils.ts +++ b/compiler/packages/fixture-test-utils/src/compiler-utils.ts @@ -2,6 +2,7 @@ import assert from "assert"; import type { runReactForgetBabelPlugin as RunReactForgetBabelPlugin } from "babel-plugin-react-forget/src/Babel/RunReactForgetBabelPlugin"; import { CompilationMode } from "babel-plugin-react-forget/src/Entrypoint"; import type { Effect, ValueKind } from "babel-plugin-react-forget/src/HIR"; +import type { parseConfigPragma as ParseConfigPragma } from "babel-plugin-react-forget/src/HIR/Environment"; export function parseLanguage(source: string): "flow" | "typescript" { return source.indexOf("@flow") !== -1 ? "flow" : "typescript"; @@ -11,6 +12,7 @@ export function transformFixtureInput( input: string, basename: string, pluginFn: typeof RunReactForgetBabelPlugin, + parseConfigPragmaFn: typeof ParseConfigPragma, includeAst: boolean = false ) { // Extract the first line to quickly check for custom test directives @@ -19,16 +21,8 @@ export function transformFixtureInput( let language = parseLanguage(firstLine); let gating = null; let instrumentForget = null; - let memoizeJsxElements = true; - let enableAssumeHooksFollowRulesOfReact = false; - let disableAllMemoization = false; - let validateRefAccessDuringRender = true; - let validateNoSetStateInRender = true; let enableEmitFreeze = null; let compilationMode: CompilationMode = "all"; - let enableForest = false; - let enableMergeConsecutiveScopes = false; - let bailoutOnHoleyArrays = false; if (firstLine.indexOf("@compilationMode(annotation)") !== -1) { assert( @@ -57,37 +51,13 @@ export function transformFixtureInput( importSpecifierName: "useRenderCounter", }; } - if (firstLine.includes("@memoizeJsxElements false")) { - memoizeJsxElements = false; - } - if (firstLine.includes("@enableAssumeHooksFollowRulesOfReact true")) { - enableAssumeHooksFollowRulesOfReact = true; - } - if (firstLine.includes("@disableAllMemoization true")) { - disableAllMemoization = true; - } - if (firstLine.includes("@validateRefAccessDuringRender false")) { - validateRefAccessDuringRender = false; - } - if (firstLine.includes("@validateNoSetStateInRender false")) { - validateNoSetStateInRender = false; - } if (firstLine.includes("@enableEmitFreeze")) { enableEmitFreeze = { source: "react-forget-runtime", importSpecifierName: "makeReadOnly", }; } - if (firstLine.includes("@enableForest true")) { - enableForest = true; - } - if (firstLine.includes("@bailoutOnHoleyArrays")) { - bailoutOnHoleyArrays = true; - } - - if (firstLine.includes("@enableMergeConsecutiveScopes")) { - enableMergeConsecutiveScopes = true; - } + const config = parseConfigPragmaFn(firstLine); return pluginFn( input, @@ -95,6 +65,7 @@ export function transformFixtureInput( language, { environment: { + ...config, customHooks: new Map([ [ "useFreeze", @@ -124,17 +95,8 @@ export function transformFixtureInput( }, ], ]), - enableAssumeHooksFollowRulesOfReact, - disableAllMemoization, - memoizeJsxElements, - validateRefAccessDuringRender, - validateFrozenLambdas: true, - validateNoSetStateInRender, enableEmitFreeze, - enableMergeConsecutiveScopes, assertValidMutableRanges: true, - bailoutOnHoleyArrays, - enableForest, }, compilationMode, logger: null, diff --git a/compiler/packages/fixture-test-utils/src/constants.ts b/compiler/packages/fixture-test-utils/src/constants.ts index a55c2f1b23..36091aee78 100644 --- a/compiler/packages/fixture-test-utils/src/constants.ts +++ b/compiler/packages/fixture-test-utils/src/constants.ts @@ -13,6 +13,12 @@ export const LOGGER_PATH = path.join( "Utils", "logger.js" ); +export const PARSE_CONFIG_PRAGMA_PATH = path.join( + process.cwd(), + "dist", + "HIR", + "Environment.js" +); export const FIXTURES_PATH = path.join( process.cwd(), "src", diff --git a/compiler/packages/snap/src/compiler-worker.ts b/compiler/packages/snap/src/compiler-worker.ts index 5308bba0d5..81412ca108 100644 --- a/compiler/packages/snap/src/compiler-worker.ts +++ b/compiler/packages/snap/src/compiler-worker.ts @@ -6,6 +6,7 @@ */ import type { runReactForgetBabelPlugin as RunReactForgetBabelPlugin } from "babel-plugin-react-forget/src/Babel/RunReactForgetBabelPlugin"; +import type { parseConfigPragma as ParseConfigPragma } from "babel-plugin-react-forget/src/HIR/Environment"; import { TestFixture, transformFixtureInput, @@ -39,6 +40,7 @@ export type TestResult = { export async function compile( compilerPath: string, loggerPath: string, + parseConfigPragmaPath: string, fixture: TestFixture, compilerVersion: number, implicitDebugMode: boolean, @@ -78,6 +80,9 @@ export async function compile( runReactForgetBabelPlugin: typeof RunReactForgetBabelPlugin; }; const { toggleLogging } = require(loggerPath); + const { parseConfigPragma } = require(parseConfigPragmaPath) as { + parseConfigPragma: typeof ParseConfigPragma; + }; // only try logging if we filtered out all but one fixture, // since console log order is non-deterministic @@ -86,7 +91,8 @@ export async function compile( code = transformFixtureInput( input, basename, - runReactForgetBabelPlugin + runReactForgetBabelPlugin, + parseConfigPragma ).code; } catch (e) { e.message = e.message.replace(/\u001b[^m]*m/g, ""); diff --git a/compiler/packages/snap/src/runner.ts b/compiler/packages/snap/src/runner.ts index 1f95966ef5..7575c7b702 100644 --- a/compiler/packages/snap/src/runner.ts +++ b/compiler/packages/snap/src/runner.ts @@ -9,12 +9,14 @@ import watcher from "@parcel/watcher"; import chalk from "chalk"; import { COMPILER_PATH, - LOGGER_PATH, - FIXTURES_PATH, FILTER_FILENAME, FILTER_PATH, - readTestFilter, + FIXTURES_PATH, + LOGGER_PATH, + PARSE_CONFIG_PRAGMA_PATH, TestFilter, + getFixtures, + readTestFilter, } from "fixture-test-utils"; import fs from "fs"; import invariant from "invariant"; @@ -26,9 +28,8 @@ import * as readline from "readline"; import ts from "typescript"; import yargs from "yargs"; import { hideBin } from "yargs/helpers"; -import { TestResult } from "./compiler-worker"; import * as compiler from "./compiler-worker"; -import { getFixtures } from "fixture-test-utils"; +import { TestResult } from "./compiler-worker"; const WORKER_PATH = require.resolve("./compiler-worker.js"); @@ -126,6 +127,7 @@ async function run( .compile( COMPILER_PATH, LOGGER_PATH, + PARSE_CONFIG_PRAGMA_PATH, fixture, compilerVersion, filter?.debug ?? false, @@ -142,6 +144,7 @@ async function run( let output = await compiler.compile( COMPILER_PATH, LOGGER_PATH, + PARSE_CONFIG_PRAGMA_PATH, fixture, compilerVersion, filter?.debug ?? false, diff --git a/compiler/packages/sprout/src/runner-worker.ts b/compiler/packages/sprout/src/runner-worker.ts index 4585d047e5..1c1f2f504e 100644 --- a/compiler/packages/sprout/src/runner-worker.ts +++ b/compiler/packages/sprout/src/runner-worker.ts @@ -5,24 +5,30 @@ * LICENSE file in the root directory of this source tree. */ +import { NodePath, PluginItem, transformFromAstSync } from "@babel/core"; +import * as parser from "@babel/parser"; +import * as t from "@babel/types"; import type { runReactForgetBabelPlugin as RunReactForgetBabelPlugin } from "babel-plugin-react-forget/src/Babel/RunReactForgetBabelPlugin"; +import type { parseConfigPragma as ParseConfigPragma } from "babel-plugin-react-forget/src/HIR/Environment"; import { COMPILER_PATH, + PARSE_CONFIG_PRAGMA_PATH, parseLanguage, TestFixture, transformFixtureInput, } from "fixture-test-utils"; -import { NodePath, PluginItem, transformFromAstSync } from "@babel/core"; import fs from "fs/promises"; -import * as parser from "@babel/parser"; -import * as t from "@babel/types"; -import { doEval, EvaluatorResult } from "./runner-evaluator"; import path from "path"; +import { doEval, EvaluatorResult } from "./runner-evaluator"; const { runReactForgetBabelPlugin } = require(COMPILER_PATH) as { runReactForgetBabelPlugin: typeof RunReactForgetBabelPlugin; }; +const { parseConfigPragma } = require(PARSE_CONFIG_PRAGMA_PATH) as { + parseConfigPragma: typeof ParseConfigPragma; +}; + // TODO: save output in .sprout.md files export type TestResult = | { @@ -118,6 +124,7 @@ function transformFixtureForget( input, filename, runReactForgetBabelPlugin, + parseConfigPragma, true );