[hir] Bailout when reading from React namespace

Forget doesn't understand the React namespace object and generates incorrect 
code when compiling code that loads props from this namespace object. 

This PR makes Forget bailout when we see a property load from React namespace 
object.
This commit is contained in:
Sathya Gunasekaran
2023-07-25 16:08:32 +01:00
parent 3f0afcbe47
commit dcb6549dda
9 changed files with 106 additions and 155 deletions
@@ -2215,6 +2215,20 @@ function lowerMemberExpression(
const object =
loweredObject ?? lowerExpressionToTemporary(builder, objectNode);
if (objectNode.isIdentifier() && objectNode.node.name === "React") {
builder.errors.push({
reason: `(BuildHIR::lowerMemberExpression) Handle loading properties from React namespace`,
severity: ErrorSeverity.Todo,
loc: propertyNode.node.loc ?? null,
suggestions: null,
});
return {
object,
property: propertyNode.toString(),
value: { kind: "UnsupportedNode", node: exprNode, loc: exprLoc },
};
}
if (!expr.node.computed) {
if (!propertyNode.isIdentifier()) {
builder.errors.push({
@@ -1,30 +0,0 @@
## Input
```javascript
function Foo() {
const [x, setX] = React.useState(1);
return x;
}
```
## Code
```javascript
import { unstable_useMemoCache as useMemoCache } from "react";
function Foo() {
const $ = useMemoCache(1);
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = React.useState(1);
$[0] = t0;
} else {
t0 = $[0];
}
const [x] = t0;
return x;
}
```
@@ -3,18 +3,18 @@
```javascript
import * as React from "react";
import { useState } from "react";
import { useState, useMemo } from "react";
function Component(props) {
const [x] = useState(0);
const expensiveNumber = React.useMemo(() => calculateExpensiveNumber(x), [x]);
const expensiveNumber = useMemo(() => calculateExpensiveNumber(x), [x]);
return <div>{expensiveNumber}</div>;
}
function Component2(props) {
const [x] = useState(0);
const expensiveNumber = React.useMemo(() => calculateExpensiveNumber(x), [x]);
const expensiveNumber = useMemo(() => calculateExpensiveNumber(x), [x]);
return <div>{expensiveNumber}</div>;
}
@@ -25,74 +25,62 @@ function Component2(props) {
```javascript
import * as React from "react";
import { useState, unstable_useMemoCache as useMemoCache } from "react";
import {
useState,
useMemo,
unstable_useMemoCache as useMemoCache,
} from "react";
function Component(props) {
const $ = useMemoCache(6);
const $ = useMemoCache(4);
const [x] = useState(0);
const c_0 = $[0] !== x;
let t1;
let t0;
if (c_0) {
const c_2 = $[2] !== x;
let t0;
if (c_2) {
t0 = () => calculateExpensiveNumber(x);
$[2] = x;
$[3] = t0;
} else {
t0 = $[3];
}
t1 = React.useMemo(t0, [x]);
t0 = calculateExpensiveNumber(x);
$[0] = x;
$[1] = t1;
$[1] = t0;
} else {
t1 = $[1];
t0 = $[1];
}
const expensiveNumber = t1;
const c_4 = $[4] !== expensiveNumber;
let t2;
if (c_4) {
t2 = <div>{expensiveNumber}</div>;
$[4] = expensiveNumber;
$[5] = t2;
const t15 = t0;
const expensiveNumber = t15;
const c_2 = $[2] !== expensiveNumber;
let t1;
if (c_2) {
t1 = <div>{expensiveNumber}</div>;
$[2] = expensiveNumber;
$[3] = t1;
} else {
t2 = $[5];
t1 = $[3];
}
return t2;
return t1;
}
function Component2(props) {
const $ = useMemoCache(6);
const $ = useMemoCache(4);
const [x] = useState(0);
const c_0 = $[0] !== x;
let t1;
let t0;
if (c_0) {
const c_2 = $[2] !== x;
let t0;
if (c_2) {
t0 = () => calculateExpensiveNumber(x);
$[2] = x;
$[3] = t0;
} else {
t0 = $[3];
}
t1 = React.useMemo(t0, [x]);
t0 = calculateExpensiveNumber(x);
$[0] = x;
$[1] = t1;
$[1] = t0;
} else {
t1 = $[1];
t0 = $[1];
}
const expensiveNumber = t1;
const c_4 = $[4] !== expensiveNumber;
let t2;
if (c_4) {
t2 = <div>{expensiveNumber}</div>;
$[4] = expensiveNumber;
$[5] = t2;
const t15 = t0;
const expensiveNumber = t15;
const c_2 = $[2] !== expensiveNumber;
let t1;
if (c_2) {
t1 = <div>{expensiveNumber}</div>;
$[2] = expensiveNumber;
$[3] = t1;
} else {
t2 = $[5];
t1 = $[3];
}
return t2;
return t1;
}
```
@@ -1,16 +1,16 @@
import * as React from "react";
import { useState } from "react";
import { useState, useMemo } from "react";
function Component(props) {
const [x] = useState(0);
const expensiveNumber = React.useMemo(() => calculateExpensiveNumber(x), [x]);
const expensiveNumber = useMemo(() => calculateExpensiveNumber(x), [x]);
return <div>{expensiveNumber}</div>;
}
function Component2(props) {
const [x] = useState(0);
const expensiveNumber = React.useMemo(() => calculateExpensiveNumber(x), [x]);
const expensiveNumber = useMemo(() => calculateExpensiveNumber(x), [x]);
return <div>{expensiveNumber}</div>;
}
@@ -1,72 +0,0 @@
## Input
```javascript
import * as React from "react";
function Component(props) {
const [x] = React.useState(0);
const expensiveNumber = React.useMemo(() => calculateExpensiveNumber(x), [x]);
return <div>{expensiveNumber}</div>;
}
function Component2(props) {
const [x] = React.useState(0);
const expensiveNumber = React.useMemo(() => calculateExpensiveNumber(x), [x]);
return <div>{expensiveNumber}</div>;
}
```
## Code
```javascript
import { unstable_useMemoCache as useMemoCache } from "react";
import * as React from "react";
function Component(props) {
const $ = useMemoCache(2);
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
const [x] = React.useState(0);
t0 = React.useMemo(() => calculateExpensiveNumber(x), [x]);
$[0] = t0;
} else {
t0 = $[0];
}
const expensiveNumber = t0;
let t1;
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
t1 = <div>{expensiveNumber}</div>;
$[1] = t1;
} else {
t1 = $[1];
}
return t1;
}
function Component2(props) {
const $ = useMemoCache(2);
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
const [x] = React.useState(0);
t0 = React.useMemo(() => calculateExpensiveNumber(x), [x]);
$[0] = t0;
} else {
t0 = $[0];
}
const expensiveNumber = t0;
let t1;
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
t1 = <div>{expensiveNumber}</div>;
$[1] = t1;
} else {
t1 = $[1];
}
return t1;
}
```
@@ -0,0 +1,32 @@
## Input
```javascript
import * as React from "react";
function Component(props) {
const [x] = React.useState(0);
const expensiveNumber = React.useMemo(() => calculateExpensiveNumber(x), [x]);
return <div>{expensiveNumber}</div>;
}
function Component2(props) {
const [x] = React.useState(0);
const expensiveNumber = React.useMemo(() => calculateExpensiveNumber(x), [x]);
return <div>{expensiveNumber}</div>;
}
```
## Error
```
[ReactForget] Todo: (BuildHIR::lowerMemberExpression) Handle loading properties from React namespace (4:4)
[ReactForget] Todo: (BuildHIR::lowerMemberExpression) Handle loading properties from React namespace (5:5)
```
@@ -0,0 +1,19 @@
## Input
```javascript
function Foo() {
const [x, setX] = React.useState(1);
return x;
}
```
## Error
```
[ReactForget] Todo: (BuildHIR::lowerMemberExpression) Handle loading properties from React namespace (2:2)
```