mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
InferReferenceEffects uses function types for CallExpression
Updates the InferReferenceEffects logic for CallExpression to work similarly to MethodCall, where we take into account the function signature (if present) when inferring the effects and return kind.
This commit is contained in:
@@ -538,6 +538,13 @@ export type MethodCall = {
|
||||
loc: SourceLocation;
|
||||
};
|
||||
|
||||
export type CallExpression = {
|
||||
kind: "CallExpression";
|
||||
callee: Place;
|
||||
args: Array<Place | SpreadPattern>;
|
||||
loc: SourceLocation;
|
||||
};
|
||||
|
||||
/**
|
||||
* The value of a given instruction. Note that values are not recursive: complex
|
||||
* values such as objects or arrays are always defined by instructions to define
|
||||
@@ -605,12 +612,7 @@ export type InstructionValue =
|
||||
args: Array<Place | SpreadPattern>;
|
||||
loc: SourceLocation;
|
||||
}
|
||||
| {
|
||||
kind: "CallExpression";
|
||||
callee: Place;
|
||||
args: Array<Place | SpreadPattern>;
|
||||
loc: SourceLocation;
|
||||
}
|
||||
| CallExpression
|
||||
| MethodCall
|
||||
| {
|
||||
kind: "UnaryExpression";
|
||||
|
||||
@@ -11,6 +11,7 @@ import { Environment } from "../HIR";
|
||||
import {
|
||||
BasicBlock,
|
||||
BlockId,
|
||||
CallExpression,
|
||||
Effect,
|
||||
HIRFunction,
|
||||
IdentifierId,
|
||||
@@ -707,8 +708,6 @@ function inferBlock(
|
||||
continue;
|
||||
}
|
||||
case "CallExpression": {
|
||||
valueKind = ValueKind.Mutable;
|
||||
effectKind = Effect.Mutate;
|
||||
const hook =
|
||||
instrValue.callee.identifier.type.kind === "Hook"
|
||||
? instrValue.callee.identifier.type.definition
|
||||
@@ -716,8 +715,42 @@ function inferBlock(
|
||||
if (hook !== null) {
|
||||
effectKind = hook.effectKind;
|
||||
valueKind = hook.valueKind;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
const signature = getFunctionCallSignature(
|
||||
env,
|
||||
instrValue.callee.identifier.type
|
||||
);
|
||||
|
||||
const effects =
|
||||
signature !== null
|
||||
? getMethodCallEffects(instrValue, signature)
|
||||
: null;
|
||||
for (let i = 0; i < instrValue.args.length; i++) {
|
||||
const arg = instrValue.args[i];
|
||||
const place = arg.kind === "Identifier" ? arg : arg.place;
|
||||
if (effects !== null) {
|
||||
// If effects are inferred for an argument, we should fail invalid
|
||||
// mutating effects
|
||||
state.referenceAndCheckError(place, effects[i]);
|
||||
} else {
|
||||
state.reference(place, Effect.Mutate);
|
||||
}
|
||||
}
|
||||
if (signature !== null) {
|
||||
state.referenceAndCheckError(
|
||||
instrValue.callee,
|
||||
signature.calleeEffect
|
||||
);
|
||||
} else {
|
||||
state.reference(instrValue.callee, Effect.Mutate);
|
||||
}
|
||||
|
||||
state.initialize(instrValue, ValueKind.Mutable);
|
||||
state.define(instr.lvalue, instrValue);
|
||||
instr.lvalue.effect = Effect.Mutate;
|
||||
continue;
|
||||
}
|
||||
case "MethodCall": {
|
||||
invariant(
|
||||
@@ -1003,7 +1036,7 @@ function getFunctionCallSignature(
|
||||
* @returns Inferred effects of function arguments, or null if inference fails.
|
||||
*/
|
||||
function getMethodCallEffects(
|
||||
fn: MethodCall,
|
||||
fn: MethodCall | CallExpression,
|
||||
sig: FunctionSignature
|
||||
): Array<Effect> | null {
|
||||
const results = [];
|
||||
|
||||
@@ -17,25 +17,29 @@ import { unstable_useMemoCache as useMemoCache } from "react";
|
||||
function Component(props) {
|
||||
const $ = useMemoCache(3);
|
||||
let t0;
|
||||
let x;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
x = {};
|
||||
t0 = Boolean(x);
|
||||
t0 = {};
|
||||
$[0] = t0;
|
||||
$[1] = x;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
x = $[1];
|
||||
}
|
||||
const y = t0;
|
||||
const x = t0;
|
||||
let t1;
|
||||
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = [x, y];
|
||||
$[2] = t1;
|
||||
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = Boolean(x);
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[2];
|
||||
t1 = $[1];
|
||||
}
|
||||
return t1;
|
||||
const y = t1;
|
||||
let t2;
|
||||
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t2 = [x, y];
|
||||
$[2] = t2;
|
||||
} else {
|
||||
t2 = $[2];
|
||||
}
|
||||
return t2;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -17,25 +17,29 @@ import { unstable_useMemoCache as useMemoCache } from "react";
|
||||
function Component(props) {
|
||||
const $ = useMemoCache(3);
|
||||
let t0;
|
||||
let x;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
x = {};
|
||||
t0 = Number(x);
|
||||
t0 = {};
|
||||
$[0] = t0;
|
||||
$[1] = x;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
x = $[1];
|
||||
}
|
||||
const y = t0;
|
||||
const x = t0;
|
||||
let t1;
|
||||
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = [x, y];
|
||||
$[2] = t1;
|
||||
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = Number(x);
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[2];
|
||||
t1 = $[1];
|
||||
}
|
||||
return t1;
|
||||
const y = t1;
|
||||
let t2;
|
||||
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t2 = [x, y];
|
||||
$[2] = t2;
|
||||
} else {
|
||||
t2 = $[2];
|
||||
}
|
||||
return t2;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -17,25 +17,29 @@ import { unstable_useMemoCache as useMemoCache } from "react";
|
||||
function Component(props) {
|
||||
const $ = useMemoCache(3);
|
||||
let t0;
|
||||
let x;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
x = {};
|
||||
t0 = String(x);
|
||||
t0 = {};
|
||||
$[0] = t0;
|
||||
$[1] = x;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
x = $[1];
|
||||
}
|
||||
const y = t0;
|
||||
const x = t0;
|
||||
let t1;
|
||||
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = [x, y];
|
||||
$[2] = t1;
|
||||
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = String(x);
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[2];
|
||||
t1 = $[1];
|
||||
}
|
||||
return t1;
|
||||
const y = t1;
|
||||
let t2;
|
||||
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t2 = [x, y];
|
||||
$[2] = t2;
|
||||
} else {
|
||||
t2 = $[2];
|
||||
}
|
||||
return t2;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user