Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b370db084e |
@@ -608,7 +608,7 @@ export const EnvironmentConfigSchema = z.object({
|
|||||||
*
|
*
|
||||||
* Here the variables `ref` and `myRef` will be typed as Refs.
|
* Here the variables `ref` and `myRef` will be typed as Refs.
|
||||||
*/
|
*/
|
||||||
enableTreatRefLikeIdentifiersAsRefs: z.boolean().default(false),
|
enableTreatRefLikeIdentifiersAsRefs: z.boolean().default(true),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If specified a value, the compiler lowers any calls to `useContext` to use
|
* If specified a value, the compiler lowers any calls to `useContext` to use
|
||||||
|
|||||||
@@ -432,15 +432,11 @@ function validateNoRefAccessInRenderImpl(
|
|||||||
* By default we check that function call operands are not refs,
|
* By default we check that function call operands are not refs,
|
||||||
* ref values, or functions that can access refs.
|
* ref values, or functions that can access refs.
|
||||||
*/
|
*/
|
||||||
if (
|
if (isRefLValue || hookKind != null) {
|
||||||
isRefLValue ||
|
|
||||||
interpolatedAsJsx.has(instr.lvalue.identifier.id) ||
|
|
||||||
hookKind != null
|
|
||||||
) {
|
|
||||||
/**
|
/**
|
||||||
* Special cases:
|
* Special cases:
|
||||||
*
|
*
|
||||||
* 1) the lvalue is a ref
|
* 1. the lvalue is a ref
|
||||||
* In general passing a ref to a function may access that ref
|
* In general passing a ref to a function may access that ref
|
||||||
* value during render, so we disallow it.
|
* value during render, so we disallow it.
|
||||||
*
|
*
|
||||||
@@ -452,31 +448,22 @@ function validateNoRefAccessInRenderImpl(
|
|||||||
*
|
*
|
||||||
* Eg `const mergedRef = mergeRefs(ref1, ref2)`
|
* Eg `const mergedRef = mergeRefs(ref1, ref2)`
|
||||||
*
|
*
|
||||||
* 2) the lvalue is passed as a jsx child
|
* 2. calling hooks
|
||||||
*
|
|
||||||
* For example `<Foo>{renderHelper(ref)}</Foo>`. Here we have more
|
|
||||||
* context and infer that the ref is being passed to a component-like
|
|
||||||
* render function which attempts to obey the rules.
|
|
||||||
*
|
|
||||||
* 3) hooks
|
|
||||||
*
|
*
|
||||||
* Hooks are independently checked to ensure they don't access refs
|
* Hooks are independently checked to ensure they don't access refs
|
||||||
* during render.
|
* during render.
|
||||||
*/
|
*/
|
||||||
validateNoDirectRefValueAccess(errors, operand, env);
|
validateNoDirectRefValueAccess(errors, operand, env);
|
||||||
} else if (!isRefLValue) {
|
} else if (interpolatedAsJsx.has(instr.lvalue.identifier.id)) {
|
||||||
/**
|
/**
|
||||||
* In general passing a ref to a function may access that ref
|
* Special case: the lvalue is passed as a jsx child
|
||||||
* value during render, so we disallow it.
|
|
||||||
*
|
*
|
||||||
* The main exception is the "mergeRefs" pattern, ie a function
|
* For example `<Foo>{renderHelper(ref)}</Foo>`. Here we have more
|
||||||
* that accepts multiple refs as arguments (or an array of refs)
|
* context and infer that the ref is being passed to a component-like
|
||||||
* and returns a new, aggregated ref. If the lvalue is a ref,
|
* render function which attempts to obey the rules.
|
||||||
* we assume that the user is doing this pattern and allow passing
|
|
||||||
* refs.
|
|
||||||
*
|
|
||||||
* Eg `const mergedRef = mergeRefs(ref1, ref2)`
|
|
||||||
*/
|
*/
|
||||||
|
validateNoRefValueAccess(errors, env, operand);
|
||||||
|
} else {
|
||||||
validateNoRefPassedToFunction(
|
validateNoRefPassedToFunction(
|
||||||
errors,
|
errors,
|
||||||
env,
|
env,
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ function Component() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Child({ref}) {
|
function Child({ref}) {
|
||||||
|
'use no memo';
|
||||||
// This violates the rules of React, so we access the ref in a child
|
// This violates the rules of React, so we access the ref in a child
|
||||||
// component
|
// component
|
||||||
return ref.current;
|
return ref.current;
|
||||||
@@ -100,8 +101,10 @@ function Component() {
|
|||||||
return t6;
|
return t6;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Child(t0) {
|
function Child({ ref }) {
|
||||||
const { ref } = t0;
|
"use no memo";
|
||||||
|
// This violates the rules of React, so we access the ref in a child
|
||||||
|
// component
|
||||||
return ref.current;
|
return ref.current;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ function Component() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Child({ref}) {
|
function Child({ref}) {
|
||||||
|
'use no memo';
|
||||||
// This violates the rules of React, so we access the ref in a child
|
// This violates the rules of React, so we access the ref in a child
|
||||||
// component
|
// component
|
||||||
return ref.current;
|
return ref.current;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ function Component() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Child({ref}) {
|
function Child({ref}) {
|
||||||
|
'use no memo';
|
||||||
// This violates the rules of React, so we access the ref in a child
|
// This violates the rules of React, so we access the ref in a child
|
||||||
// component
|
// component
|
||||||
return ref.current;
|
return ref.current;
|
||||||
@@ -86,8 +87,10 @@ function Component() {
|
|||||||
return t5;
|
return t5;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Child(t0) {
|
function Child({ ref }) {
|
||||||
const { ref } = t0;
|
"use no memo";
|
||||||
|
// This violates the rules of React, so we access the ref in a child
|
||||||
|
// component
|
||||||
return ref.current;
|
return ref.current;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ function Component() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Child({ref}) {
|
function Child({ref}) {
|
||||||
|
'use no memo';
|
||||||
// This violates the rules of React, so we access the ref in a child
|
// This violates the rules of React, so we access the ref in a child
|
||||||
// component
|
// component
|
||||||
return ref.current;
|
return ref.current;
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ function Component() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Child({ref}) {
|
function Child({ref}) {
|
||||||
|
'use no memo';
|
||||||
// This violates the rules of React, so we access the ref in a child
|
// This violates the rules of React, so we access the ref in a child
|
||||||
// component
|
// component
|
||||||
return ref.current;
|
return ref.current;
|
||||||
@@ -83,8 +84,10 @@ function Component() {
|
|||||||
}
|
}
|
||||||
function _temp() {}
|
function _temp() {}
|
||||||
|
|
||||||
function Child(t0) {
|
function Child({ ref }) {
|
||||||
const { ref } = t0;
|
"use no memo";
|
||||||
|
// This violates the rules of React, so we access the ref in a child
|
||||||
|
// component
|
||||||
return ref.current;
|
return ref.current;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ function Component() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Child({ref}) {
|
function Child({ref}) {
|
||||||
|
'use no memo';
|
||||||
// This violates the rules of React, so we access the ref in a child
|
// This violates the rules of React, so we access the ref in a child
|
||||||
// component
|
// component
|
||||||
return ref.current;
|
return ref.current;
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ error.invalid-aliased-ref-in-callback-invoked-during-render-.ts:9:33
|
|||||||
7 | return <Foo item={item} current={current} />;
|
7 | return <Foo item={item} current={current} />;
|
||||||
8 | };
|
8 | };
|
||||||
> 9 | return <Items>{props.items.map(item => renderItem(item))}</Items>;
|
> 9 | return <Items>{props.items.map(item => renderItem(item))}</Items>;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ Passing a ref to a function may read its value during render
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ Cannot access ref value during render
|
||||||
10 | }
|
10 | }
|
||||||
11 |
|
11 |
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ error.invalid-ref-in-callback-invoked-during-render.ts:8:33
|
|||||||
6 | return <Foo item={item} current={current} />;
|
6 | return <Foo item={item} current={current} />;
|
||||||
7 | };
|
7 | };
|
||||||
> 8 | return <Items>{props.items.map(item => renderItem(item))}</Items>;
|
> 8 | return <Items>{props.items.map(item => renderItem(item))}</Items>;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ Passing a ref to a function may read its value during render
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ Cannot access ref value during render
|
||||||
9 | }
|
9 | }
|
||||||
10 |
|
10 |
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
|
|
||||||
## Input
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
import {Stringify, identity, mutate, CONST_TRUE} from 'shared-runtime';
|
|
||||||
|
|
||||||
function Foo(props, ref) {
|
|
||||||
const value = {};
|
|
||||||
if (CONST_TRUE) {
|
|
||||||
mutate(value);
|
|
||||||
return <Stringify ref={ref} />;
|
|
||||||
}
|
|
||||||
mutate(value);
|
|
||||||
if (CONST_TRUE) {
|
|
||||||
return <Stringify ref={identity(ref)} />;
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const FIXTURE_ENTRYPOINT = {
|
|
||||||
fn: Foo,
|
|
||||||
params: [{}, {current: 'fake-ref-object'}],
|
|
||||||
};
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Error
|
|
||||||
|
|
||||||
```
|
|
||||||
Found 1 error:
|
|
||||||
|
|
||||||
Error: Cannot access refs during render
|
|
||||||
|
|
||||||
React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef)
|
|
||||||
|
|
||||||
error.repro-ref-mutable-range.ts:11:36
|
|
||||||
9 | mutate(value);
|
|
||||||
10 | if (CONST_TRUE) {
|
|
||||||
> 11 | return <Stringify ref={identity(ref)} />;
|
|
||||||
| ^^^ Passing a ref to a function may read its value during render
|
|
||||||
12 | }
|
|
||||||
13 | return value;
|
|
||||||
14 | }
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
## Logs
|
## Logs
|
||||||
|
|
||||||
```
|
```
|
||||||
{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":158},"end":{"line":11,"column":1,"index":331},"filename":"mutate-after-useeffect-ref-access.ts"},"detail":{"options":{"severity":"InvalidReact","category":"This value cannot be modified","description":"Modifying component props or hook arguments is not allowed. Consider using a local variable instead.","details":[{"kind":"error","loc":{"start":{"line":9,"column":2,"index":289},"end":{"line":9,"column":16,"index":303},"filename":"mutate-after-useeffect-ref-access.ts"},"message":"value cannot be modified"}]}}}
|
{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":158},"end":{"line":11,"column":1,"index":331},"filename":"mutate-after-useeffect-ref-access.ts"},"detail":{"options":{"severity":"InvalidReact","category":"Cannot access refs during render","description":"React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef)","details":[{"kind":"error","loc":{"start":{"line":9,"column":2,"index":289},"end":{"line":9,"column":16,"index":303},"filename":"mutate-after-useeffect-ref-access.ts"},"message":"Cannot update ref during render"}]}}}
|
||||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":8,"column":2,"index":237},"end":{"line":8,"column":50,"index":285},"filename":"mutate-after-useeffect-ref-access.ts"},"decorations":[{"start":{"line":8,"column":24,"index":259},"end":{"line":8,"column":30,"index":265},"filename":"mutate-after-useeffect-ref-access.ts","identifierName":"arrRef"}]}
|
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":8,"column":2,"index":237},"end":{"line":8,"column":50,"index":285},"filename":"mutate-after-useeffect-ref-access.ts"},"decorations":[{"start":{"line":8,"column":24,"index":259},"end":{"line":8,"column":30,"index":265},"filename":"mutate-after-useeffect-ref-access.ts","identifierName":"arrRef"}]}
|
||||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":6,"column":0,"index":158},"end":{"line":11,"column":1,"index":331},"filename":"mutate-after-useeffect-ref-access.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
{"kind":"CompileSuccess","fnLoc":{"start":{"line":6,"column":0,"index":158},"end":{"line":11,"column":1,"index":331},"filename":"mutate-after-useeffect-ref-access.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -51,12 +51,12 @@ function RefsInEffects() {
|
|||||||
const ref = useRefHelper();
|
const ref = useRefHelper();
|
||||||
const wrapped = useDeeperRefHelper();
|
const wrapped = useDeeperRefHelper();
|
||||||
let t0;
|
let t0;
|
||||||
if ($[0] !== ref.current || $[1] !== wrapped.foo.current) {
|
if ($[0] !== ref || $[1] !== wrapped.foo.current) {
|
||||||
t0 = () => {
|
t0 = () => {
|
||||||
print(ref.current);
|
print(ref.current);
|
||||||
print(wrapped.foo.current);
|
print(wrapped.foo.current);
|
||||||
};
|
};
|
||||||
$[0] = ref.current;
|
$[0] = ref;
|
||||||
$[1] = wrapped.foo.current;
|
$[1] = wrapped.foo.current;
|
||||||
$[2] = t0;
|
$[2] = t0;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export const FIXTURE_ENTRYPOINT = {
|
|||||||
## Logs
|
## Logs
|
||||||
|
|
||||||
```
|
```
|
||||||
{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":190},"end":{"line":11,"column":1,"index":363},"filename":"mutate-after-useeffect-ref-access.ts"},"detail":{"options":{"severity":"InvalidReact","category":"This value cannot be modified","description":"Modifying component props or hook arguments is not allowed. Consider using a local variable instead.","details":[{"kind":"error","loc":{"start":{"line":9,"column":2,"index":321},"end":{"line":9,"column":16,"index":335},"filename":"mutate-after-useeffect-ref-access.ts"},"message":"value cannot be modified"}]}}}
|
{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":190},"end":{"line":11,"column":1,"index":363},"filename":"mutate-after-useeffect-ref-access.ts"},"detail":{"options":{"severity":"InvalidReact","category":"Cannot access refs during render","description":"React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected (https://react.dev/reference/react/useRef)","details":[{"kind":"error","loc":{"start":{"line":9,"column":2,"index":321},"end":{"line":9,"column":16,"index":335},"filename":"mutate-after-useeffect-ref-access.ts"},"message":"Cannot update ref during render"}]}}}
|
||||||
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":8,"column":2,"index":269},"end":{"line":8,"column":50,"index":317},"filename":"mutate-after-useeffect-ref-access.ts"},"decorations":[{"start":{"line":8,"column":24,"index":291},"end":{"line":8,"column":30,"index":297},"filename":"mutate-after-useeffect-ref-access.ts","identifierName":"arrRef"}]}
|
{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":8,"column":2,"index":269},"end":{"line":8,"column":50,"index":317},"filename":"mutate-after-useeffect-ref-access.ts"},"decorations":[{"start":{"line":8,"column":24,"index":291},"end":{"line":8,"column":30,"index":297},"filename":"mutate-after-useeffect-ref-access.ts","identifierName":"arrRef"}]}
|
||||||
{"kind":"CompileSuccess","fnLoc":{"start":{"line":6,"column":0,"index":190},"end":{"line":11,"column":1,"index":363},"filename":"mutate-after-useeffect-ref-access.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
{"kind":"CompileSuccess","fnLoc":{"start":{"line":6,"column":0,"index":190},"end":{"line":11,"column":1,"index":363},"filename":"mutate-after-useeffect-ref-access.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
|
|
||||||
## Input
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// @validatePreserveExistingMemoizationGuarantees
|
|
||||||
import {useCallback} from 'react';
|
|
||||||
|
|
||||||
function useHook(maybeRef) {
|
|
||||||
return useCallback(() => {
|
|
||||||
return [maybeRef.current];
|
|
||||||
}, [maybeRef]);
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Error
|
|
||||||
|
|
||||||
```
|
|
||||||
Found 1 error:
|
|
||||||
|
|
||||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
|
||||||
|
|
||||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `maybeRef.current`, but the source dependencies were [maybeRef]. Differences in ref.current access.
|
|
||||||
|
|
||||||
error.maybe-invalid-useCallback-read-maybeRef.ts:5:21
|
|
||||||
3 |
|
|
||||||
4 | function useHook(maybeRef) {
|
|
||||||
> 5 | return useCallback(() => {
|
|
||||||
| ^^^^^^^
|
|
||||||
> 6 | return [maybeRef.current];
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
> 7 | }, [maybeRef]);
|
|
||||||
| ^^^^ Could not preserve existing manual memoization
|
|
||||||
8 | }
|
|
||||||
9 |
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
|
|
||||||
## Input
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// @validatePreserveExistingMemoizationGuarantees
|
|
||||||
import {useMemo} from 'react';
|
|
||||||
|
|
||||||
function useHook(maybeRef, shouldRead) {
|
|
||||||
return useMemo(() => {
|
|
||||||
return () => [maybeRef.current];
|
|
||||||
}, [shouldRead, maybeRef]);
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Error
|
|
||||||
|
|
||||||
```
|
|
||||||
Found 1 error:
|
|
||||||
|
|
||||||
Memoization: Compilation skipped because existing memoization could not be preserved
|
|
||||||
|
|
||||||
React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `maybeRef.current`, but the source dependencies were [shouldRead, maybeRef]. Differences in ref.current access.
|
|
||||||
|
|
||||||
error.maybe-invalid-useMemo-read-maybeRef.ts:5:17
|
|
||||||
3 |
|
|
||||||
4 | function useHook(maybeRef, shouldRead) {
|
|
||||||
> 5 | return useMemo(() => {
|
|
||||||
| ^^^^^^^
|
|
||||||
> 6 | return () => [maybeRef.current];
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
> 7 | }, [shouldRead, maybeRef]);
|
|
||||||
| ^^^^ Could not preserve existing manual memoization
|
|
||||||
8 | }
|
|
||||||
9 |
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
|
||||||
|
## Input
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// @validatePreserveExistingMemoizationGuarantees
|
||||||
|
import {useCallback} from 'react';
|
||||||
|
|
||||||
|
function useHook(maybeRef) {
|
||||||
|
return useCallback(() => {
|
||||||
|
return [maybeRef.current];
|
||||||
|
}, [maybeRef]);
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Code
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { c as _c } from "react/compiler-runtime"; // @validatePreserveExistingMemoizationGuarantees
|
||||||
|
import { useCallback } from "react";
|
||||||
|
|
||||||
|
function useHook(maybeRef) {
|
||||||
|
const $ = _c(2);
|
||||||
|
let t0;
|
||||||
|
if ($[0] !== maybeRef) {
|
||||||
|
t0 = () => [maybeRef.current];
|
||||||
|
$[0] = maybeRef;
|
||||||
|
$[1] = t0;
|
||||||
|
} else {
|
||||||
|
t0 = $[1];
|
||||||
|
}
|
||||||
|
return t0;
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Eval output
|
||||||
|
(kind: exception) Fixture not implemented
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
|
||||||
|
## Input
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// @validatePreserveExistingMemoizationGuarantees
|
||||||
|
import {useMemo} from 'react';
|
||||||
|
|
||||||
|
function useHook(maybeRef, shouldRead) {
|
||||||
|
return useMemo(() => {
|
||||||
|
return () => [maybeRef.current];
|
||||||
|
}, [shouldRead, maybeRef]);
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Code
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { c as _c } from "react/compiler-runtime"; // @validatePreserveExistingMemoizationGuarantees
|
||||||
|
import { useMemo } from "react";
|
||||||
|
|
||||||
|
function useHook(maybeRef, shouldRead) {
|
||||||
|
const $ = _c(2);
|
||||||
|
let t0;
|
||||||
|
if ($[0] !== maybeRef) {
|
||||||
|
t0 = () => [maybeRef.current];
|
||||||
|
$[0] = maybeRef;
|
||||||
|
$[1] = t0;
|
||||||
|
} else {
|
||||||
|
t0 = $[1];
|
||||||
|
}
|
||||||
|
return t0;
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Eval output
|
||||||
|
(kind: exception) Fixture not implemented
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
|
||||||
|
## Input
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import {Stringify, identity, mutate, CONST_TRUE} from 'shared-runtime';
|
||||||
|
|
||||||
|
function Foo(props, ref) {
|
||||||
|
const value = {};
|
||||||
|
if (CONST_TRUE) {
|
||||||
|
mutate(value);
|
||||||
|
return <Stringify ref={ref} />;
|
||||||
|
}
|
||||||
|
mutate(value);
|
||||||
|
if (CONST_TRUE) {
|
||||||
|
return <Stringify ref={identity(ref)} />;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Foo,
|
||||||
|
params: [{}, {current: 'fake-ref-object'}],
|
||||||
|
};
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Code
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { c as _c } from "react/compiler-runtime";
|
||||||
|
import { Stringify, identity, mutate, CONST_TRUE } from "shared-runtime";
|
||||||
|
|
||||||
|
function Foo(props, ref) {
|
||||||
|
const $ = _c(7);
|
||||||
|
let t0;
|
||||||
|
let value;
|
||||||
|
if ($[0] !== ref) {
|
||||||
|
t0 = Symbol.for("react.early_return_sentinel");
|
||||||
|
bb0: {
|
||||||
|
value = {};
|
||||||
|
if (CONST_TRUE) {
|
||||||
|
mutate(value);
|
||||||
|
t0 = <Stringify ref={ref} />;
|
||||||
|
break bb0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutate(value);
|
||||||
|
}
|
||||||
|
$[0] = ref;
|
||||||
|
$[1] = t0;
|
||||||
|
$[2] = value;
|
||||||
|
} else {
|
||||||
|
t0 = $[1];
|
||||||
|
value = $[2];
|
||||||
|
}
|
||||||
|
if (t0 !== Symbol.for("react.early_return_sentinel")) {
|
||||||
|
return t0;
|
||||||
|
}
|
||||||
|
if (CONST_TRUE) {
|
||||||
|
let t1;
|
||||||
|
if ($[3] !== ref) {
|
||||||
|
t1 = identity(ref);
|
||||||
|
$[3] = ref;
|
||||||
|
$[4] = t1;
|
||||||
|
} else {
|
||||||
|
t1 = $[4];
|
||||||
|
}
|
||||||
|
let t2;
|
||||||
|
if ($[5] !== t1) {
|
||||||
|
t2 = <Stringify ref={t1} />;
|
||||||
|
$[5] = t1;
|
||||||
|
$[6] = t2;
|
||||||
|
} else {
|
||||||
|
t2 = $[6];
|
||||||
|
}
|
||||||
|
return t2;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Foo,
|
||||||
|
params: [{}, { current: "fake-ref-object" }],
|
||||||
|
};
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Eval output
|
||||||
|
(kind: ok) <div>{"ref":{"current":"fake-ref-object"}}</div>
|
||||||
Reference in New Issue
Block a user