[config] Change compiler defaults to prepare for oss

This commit is contained in:
Mofei Zhang
2024-03-29 09:31:09 -04:00
parent 9d20aa2819
commit 5656d5f078
30 changed files with 163 additions and 132 deletions

View File

@@ -173,7 +173,7 @@ export type Logger = {
export const defaultOptions: PluginOptions = {
compilationMode: "infer",
panicThreshold: "CRITICAL_ERRORS",
panicThreshold: "NONE",
environment: {},
logger: null,
gating: null,

View File

@@ -156,7 +156,7 @@ const EnvironmentConfigSchema = z.object({
* that the memoization was preserved. This can be useful for determining where referential equalities
* may change under Forget.
*/
validatePreserveExistingMemoizationGuarantees: z.boolean().default(false),
validatePreserveExistingMemoizationGuarantees: z.boolean().default(true),
// 🌲
enableForest: z.boolean().default(false),
@@ -192,7 +192,7 @@ const EnvironmentConfigSchema = z.object({
* Validates that setState is not unconditionally called during render, as it can lead to
* infinite loops.
*/
validateNoSetStateInRender: z.boolean().default(false),
validateNoSetStateInRender: z.boolean().default(true),
/**
* Validates that the dependencies of all effect hooks are memoized. This helps ensure
@@ -214,7 +214,7 @@ const EnvironmentConfigSchema = z.object({
* in this allowlist. You can enable this validation with no additional allowlisted calls by setting
* this option to the empty array.
*/
validateNoCapitalizedCalls: z.nullable(z.array(z.string())).default(null),
validateNoCapitalizedCalls: z.nullable(z.array(z.string())).default([]),
/*
* When enabled, the compiler assumes that hooks follow the Rules of React:
@@ -223,7 +223,7 @@ const EnvironmentConfigSchema = z.object({
* - Hooks may memoize the result they return, thus the return value is
* assumed frozen.
*/
enableAssumeHooksFollowRulesOfReact: z.boolean().default(false),
enableAssumeHooksFollowRulesOfReact: z.boolean().default(true),
/**
* When enabled, the compiler assumes that any values are not subsequently
@@ -231,7 +231,7 @@ const EnvironmentConfigSchema = z.object({
* if a value `x` is referenced inside a function expression passed to `useEffect`,
* then this flag will assume that `x` is not subusequently modified.
*/
enableTransitivelyFreezeFunctionExpressions: z.boolean().default(false),
enableTransitivelyFreezeFunctionExpressions: z.boolean().default(true),
/*
* When enabled, removes *all* memoization from the function: this includes

View File

@@ -76,12 +76,12 @@ function ComponentA(props) {
let t0;
if ($[0] !== props) {
t0 = Symbol.for("react.early_return_sentinel");
bb7: {
bb8: {
a_DEBUG = [];
a_DEBUG.push(props.a);
if (props.b) {
t0 = null;
break bb7;
break bb8;
}
a_DEBUG.push(props.d);
@@ -130,13 +130,13 @@ function ComponentC(props) {
let t0;
if ($[0] !== props) {
t0 = Symbol.for("react.early_return_sentinel");
bb7: {
bb8: {
a = [];
a.push(props.a);
if (props.b) {
a.push(props.c);
t0 = null;
break bb7;
break bb8;
}
a.push(props.d);
@@ -163,13 +163,13 @@ function ComponentD(props) {
let t0;
if ($[0] !== props) {
t0 = Symbol.for("react.early_return_sentinel");
bb7: {
bb8: {
a = [];
a.push(props.a);
if (props.b) {
a.push(props.c);
t0 = a;
break bb7;
break bb8;
}
a.push(props.d);

View File

@@ -35,7 +35,7 @@ function Component(props) {
let t0;
if ($[0] !== props) {
t0 = Symbol.for("react.early_return_sentinel");
bb11: {
bb12: {
const x = [];
if (props.cond) {
x.push(props.a);
@@ -51,11 +51,11 @@ function Component(props) {
const y = t1;
x.push(y);
t0 = x;
break bb11;
break bb12;
}
t0 = x;
break bb11;
break bb12;
} else {
let t1;
if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
@@ -65,7 +65,7 @@ function Component(props) {
t1 = $[4];
}
t0 = t1;
break bb11;
break bb12;
}
}
$[0] = props;

View File

@@ -73,12 +73,12 @@ function Component(props) {
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = Symbol.for("react.early_return_sentinel");
bb8: {
bb9: {
const x = [];
if (ENABLE_FEATURE) {
x.push(42);
t0 = x;
break bb8;
break bb9;
} else {
console.log("fallthrough");
}

View File

@@ -49,12 +49,12 @@ function Component(props) {
let t0;
if ($[0] !== props) {
t0 = Symbol.for("react.early_return_sentinel");
bb8: {
bb9: {
const x = [];
if (props.cond) {
x.push(props.a);
t0 = x;
break bb8;
break bb9;
} else {
let t1;
if ($[2] !== props.b) {
@@ -65,7 +65,7 @@ function Component(props) {
t1 = $[3];
}
t0 = t1;
break bb8;
break bb9;
}
}
$[0] = props;

View File

@@ -2,19 +2,13 @@
## Input
```javascript
import {
makeObject_Primitives,
mutateAndReturn,
Stringify,
} from "shared-runtime";
import { makeObject_Primitives, mutateAndReturn, toJSON } from "shared-runtime";
function Component(_props) {
const collection = [makeObject_Primitives()];
const results = [];
for (const item of collection) {
results.push(
<div key={Stringify(item)}>{Stringify(mutateAndReturn(item))}</div>
);
results.push(<div key={toJSON(item)}>{toJSON(mutateAndReturn(item))}</div>);
}
return <div>{results}</div>;
}
@@ -31,11 +25,7 @@ export const FIXTURE_ENTRYPOINT = {
```javascript
import { unstable_useMemoCache as useMemoCache } from "react";
import {
makeObject_Primitives,
mutateAndReturn,
Stringify,
} from "shared-runtime";
import { makeObject_Primitives, mutateAndReturn, toJSON } from "shared-runtime";
function Component(_props) {
const $ = useMemoCache(1);
@@ -45,7 +35,7 @@ function Component(_props) {
const results = [];
for (const item of collection) {
results.push(
<div key={Stringify(item)}>{Stringify(mutateAndReturn(item))}</div>
<div key={toJSON(item)}>{toJSON(mutateAndReturn(item))}</div>
);
}
@@ -66,4 +56,4 @@ export const FIXTURE_ENTRYPOINT = {
```
### Eval output
(kind: ok) <div><div><div>{"a":0,"b":"value1","c":true,"wat0":"joe"}</div></div></div>
(kind: ok) <div><div>{"a":0,"b":"value1","c":true,"wat0":"joe"}</div></div>

View File

@@ -1,16 +1,10 @@
import {
makeObject_Primitives,
mutateAndReturn,
Stringify,
} from "shared-runtime";
import { makeObject_Primitives, mutateAndReturn, toJSON } from "shared-runtime";
function Component(_props) {
const collection = [makeObject_Primitives()];
const results = [];
for (const item of collection) {
results.push(
<div key={Stringify(item)}>{Stringify(mutateAndReturn(item))}</div>
);
results.push(<div key={toJSON(item)}>{toJSON(mutateAndReturn(item))}</div>);
}
return <div>{results}</div>;
}

View File

@@ -46,39 +46,47 @@ const React$useMemo = React.useMemo;
const Internal$Reassigned$useHook = useHook;
function Component() {
const $ = useMemoCache(6);
const $ = useMemoCache(8);
const [state] = React$useState(0);
const object = Internal$Reassigned$useHook();
const json = JSON.stringify(object);
let t0;
let t1;
if ($[0] !== state) {
t0 = makeArray(state);
const doubledArray = t0;
t1 = doubledArray.join("");
$[0] = state;
$[1] = t1;
$[2] = t0;
if ($[0] !== object) {
t0 = JSON.stringify(object);
$[0] = object;
$[1] = t0;
} else {
t1 = $[1];
t0 = $[2];
t0 = $[1];
}
const json = t0;
let t1;
let t2;
if ($[3] !== t1 || $[4] !== json) {
t2 = (
if ($[2] !== state) {
t1 = makeArray(state);
const doubledArray = t1;
t2 = doubledArray.join("");
$[2] = state;
$[3] = t2;
$[4] = t1;
} else {
t2 = $[3];
t1 = $[4];
}
let t3;
if ($[5] !== t2 || $[6] !== json) {
t3 = (
<div>
{t1}
{t2}
{json}
</div>
);
$[3] = t1;
$[4] = json;
$[5] = t2;
$[6] = json;
$[7] = t3;
} else {
t2 = $[5];
t3 = $[7];
}
return t2;
return t3;
}
export const FIXTURE_ENTRYPOINT = {

View File

@@ -15,8 +15,18 @@ function Foo(props) {
## Code
```javascript
import { unstable_useMemoCache as useMemoCache } from "react";
function Foo(props) {
const x = bar(props.a);
const $ = useMemoCache(2);
let t0;
if ($[0] !== props.a) {
t0 = bar(props.a);
$[0] = props.a;
$[1] = t0;
} else {
t0 = $[1];
}
const x = t0;
const y = x?.b;
const z = useBar(y);

View File

@@ -35,12 +35,12 @@ function Component(props) {
let t0;
if ($[0] !== props) {
t0 = Symbol.for("react.early_return_sentinel");
bb11: {
bb12: {
const x = [];
if (props.cond) {
x.push(props.a);
t0 = x;
break bb11;
break bb12;
} else {
let t1;
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
@@ -52,7 +52,7 @@ function Component(props) {
y = t1;
if (props.b) {
t0 = undefined;
break bb11;
break bb12;
}
}
}

View File

@@ -35,11 +35,11 @@ function useFoo(t0) {
let t1;
if ($[0] !== objIsNull || $[1] !== obj) {
t1 = Symbol.for("react.early_return_sentinel");
bb8: {
bb9: {
x = [];
if (objIsNull) {
t1 = undefined;
break bb8;
break bb9;
} else {
x.push(obj.a);
}

View File

@@ -46,12 +46,12 @@ function useFoo(t0) {
let t1;
if ($[0] !== cond || $[1] !== hasAB || $[2] !== input) {
t1 = Symbol.for("react.early_return_sentinel");
bb10: {
bb11: {
x = [];
if (cond) {
if (!hasAB) {
t1 = null;
break bb10;
break bb11;
}
let t2;
if ($[5] !== input.a.b) {

View File

@@ -47,12 +47,12 @@ function useFoo(t0) {
let t1;
if ($[0] !== cond || $[1] !== hasAB || $[2] !== input) {
t1 = Symbol.for("react.early_return_sentinel");
bb11: {
bb12: {
x = [];
if (cond) {
if (!hasAB) {
t1 = null;
break bb11;
break bb12;
} else {
let t2;
if ($[5] !== input.a.b) {

View File

@@ -37,11 +37,11 @@ function useFoo(t0) {
let t1;
if ($[0] !== objIsNull || $[1] !== obj) {
t1 = Symbol.for("react.early_return_sentinel");
bb7: {
bb8: {
x = [];
if (objIsNull) {
t1 = undefined;
break bb7;
break bb8;
}
x.push(obj.b);

View File

@@ -43,11 +43,11 @@ function useFoo(t0) {
let t1;
if ($[0] !== cond || $[1] !== input) {
t1 = Symbol.for("react.early_return_sentinel");
bb7: {
bb8: {
x = [];
if (cond) {
t1 = null;
break bb7;
break bb8;
}
let t2;
if ($[4] !== input.a.b) {

View File

@@ -37,7 +37,7 @@ function useFoo(t0) {
let t1;
if ($[0] !== hasAB || $[1] !== input.a || $[2] !== returnNull) {
t1 = Symbol.for("react.early_return_sentinel");
bb10: {
bb11: {
x = [];
if (!hasAB) {
let t2;
@@ -51,7 +51,7 @@ function useFoo(t0) {
x.push(t2);
if (!returnNull) {
t1 = null;
break bb10;
break bb11;
}
} else {
let t2;

View File

@@ -47,7 +47,7 @@ function useFoo(t0) {
let t1;
if ($[0] !== cond1 || $[1] !== cond2 || $[2] !== input.a.b) {
t1 = Symbol.for("react.early_return_sentinel");
bb11: {
bb12: {
x = [];
if (cond1) {
if (!cond2) {
@@ -61,7 +61,7 @@ function useFoo(t0) {
}
x.push(t2);
t1 = null;
break bb11;
break bb12;
} else {
let t2;
if ($[7] !== input.a.b) {

View File

@@ -38,7 +38,7 @@ function useFoo(t0) {
let t1;
if ($[0] !== inputHasABC || $[1] !== input.a || $[2] !== inputHasAB) {
t1 = Symbol.for("react.early_return_sentinel");
bb10: {
bb11: {
x = [];
if (!inputHasABC) {
let t2;
@@ -52,7 +52,7 @@ function useFoo(t0) {
x.push(t2);
if (!inputHasAB) {
t1 = null;
break bb10;
break bb11;
}
let t3;
if ($[7] !== input.a.b) {

View File

@@ -46,7 +46,7 @@ function Component() {
let t2;
if ($[0] !== items) {
t2 = Symbol.for("react.early_return_sentinel");
bb14: {
bb15: {
let t3;
if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
t3 = (t4) => {
@@ -72,7 +72,7 @@ function Component() {
t4 = $[5];
}
t2 = t4;
break bb14;
break bb15;
}
let t4;
if ($[6] === Symbol.for("react.memo_cache_sentinel")) {

View File

@@ -43,12 +43,12 @@ function Component(props) {
let t1;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t1 = Symbol.for("react.early_return_sentinel");
bb7: {
bb8: {
const object = makeObject_Primitives();
const cond = makeObject_Primitives();
if (!cond) {
t1 = null;
break bb7;
break bb8;
}
t0 = (

View File

@@ -51,12 +51,12 @@ function Component(props) {
let t2;
if ($[0] !== props) {
t2 = Symbol.for("react.early_return_sentinel");
bb10: {
bb11: {
t0 = toJSON(props);
const propsString = t0;
if (propsString.length <= 2) {
t2 = null;
break bb10;
break bb11;
}
t1 = identity(propsString);

View File

@@ -34,7 +34,7 @@ function Component(props) {
let t0;
if ($[0] !== props.y || $[1] !== props.e) {
t0 = Symbol.for("react.early_return_sentinel");
bb18: {
bb19: {
try {
const y = [];
y.push(props.y);
@@ -43,11 +43,11 @@ function Component(props) {
const e = t1;
e.push(props.e);
t0 = e;
break bb18;
break bb19;
}
t0 = null;
break bb18;
break bb19;
}
$[0] = props.y;
$[1] = props.e;

View File

@@ -35,7 +35,7 @@ function Component(props) {
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = Symbol.for("react.early_return_sentinel");
bb11: {
bb12: {
const x = [];
try {
throwInput(x);
@@ -43,11 +43,11 @@ function Component(props) {
const e = t1;
e.push(null);
t0 = e;
break bb11;
break bb12;
}
t0 = x;
break bb11;
break bb12;
}
$[0] = t0;
} else {

View File

@@ -37,19 +37,19 @@ function Component(props) {
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = Symbol.for("react.early_return_sentinel");
bb25: {
bb26: {
x = [];
try {
const y = shallowCopy({});
if (y == null) {
t0 = undefined;
break bb25;
break bb26;
}
x.push(throwInput(y));
} catch {
t0 = null;
break bb25;
break bb26;
}
}
$[0] = x;

View File

@@ -2,7 +2,7 @@
## Input
```javascript
// @enablePreserveExistingMemoizationGuarantees:false
// @enablePreserveExistingMemoizationGuarantees:false @enableTransitivelyFreezeFunctionExpressions:false
import { useCallback } from "react";
import {
identity,
@@ -39,7 +39,7 @@ export const FIXTURE_ENTRYPOINT = {
## Code
```javascript
// @enablePreserveExistingMemoizationGuarantees:false
// @enablePreserveExistingMemoizationGuarantees:false @enableTransitivelyFreezeFunctionExpressions:false
import { useCallback, unstable_useMemoCache as useMemoCache } from "react";
import {
identity,

View File

@@ -1,4 +1,4 @@
// @enablePreserveExistingMemoizationGuarantees:false
// @enablePreserveExistingMemoizationGuarantees:false @enableTransitivelyFreezeFunctionExpressions:false
import { useCallback } from "react";
import {
identity,

View File

@@ -2,6 +2,8 @@
## Input
```javascript
// @enableTransitivelyFreezeFunctionExpressions:false
function Component(props) {
const item = useMutable(props.itemId);
const dispatch = useDispatch();
@@ -30,9 +32,10 @@ function Component(props) {
## Code
```javascript
import { unstable_useMemoCache as useMemoCache } from "react";
import { unstable_useMemoCache as useMemoCache } from "react"; // @enableTransitivelyFreezeFunctionExpressions:false
function Component(props) {
const $ = useMemoCache(3);
const $ = useMemoCache(9);
const item = useMutable(props.itemId);
const dispatch = useDispatch();
useFreeze(dispatch);
@@ -47,25 +50,42 @@ function Component(props) {
t0 = $[1];
}
const exit = t0;
useEffect(() => {
const cleanup = GlobalEventEmitter.addListener("onInput", () => {
if (item.value) {
exit();
}
});
return () => cleanup.remove();
}, [exit, item]);
let t1;
if ($[2] !== item.value || $[3] !== exit) {
t1 = () => {
const cleanup = GlobalEventEmitter.addListener("onInput", () => {
if (item.value) {
exit();
}
});
return () => cleanup.remove();
};
$[2] = item.value;
$[3] = exit;
$[4] = t1;
} else {
t1 = $[4];
}
let t2;
if ($[5] !== exit || $[6] !== item) {
t2 = [exit, item];
$[5] = exit;
$[6] = item;
$[7] = t2;
} else {
t2 = $[7];
}
useEffect(t1, t2);
maybeMutate(item);
let t1;
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
t1 = <div />;
$[2] = t1;
let t3;
if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
t3 = <div />;
$[8] = t3;
} else {
t1 = $[2];
t3 = $[8];
}
return t1;
return t3;
}
```

View File

@@ -1,3 +1,5 @@
// @enableTransitivelyFreezeFunctionExpressions:false
function Component(props) {
const item = useMutable(props.itemId);
const dispatch = useDispatch();

View File

@@ -41,6 +41,8 @@ function makePluginOptions(
let enableUseMemoCachePolyfill = false;
let panicThreshold: PanicThresholdOptions = "ALL_ERRORS";
let hookPattern: string | null = null;
// TODO(@mofeiZ) rewrite snap fixtures to @validatePreserveExistingMemo:false
let validatePreserveExistingMemoizationGuarantees = false;
if (firstLine.indexOf("@compilationMode(annotation)") !== -1) {
assert(
@@ -113,6 +115,10 @@ function makePluginOptions(
ignoreUseNoForget = true;
}
if (firstLine.includes("@validatePreserveExistingMemoizationGuarantees")) {
validatePreserveExistingMemoizationGuarantees = true;
}
const hookPatternMatch = /@hookPattern:"([^"]+)"/.exec(firstLine);
if (
hookPatternMatch &&
@@ -164,6 +170,7 @@ function makePluginOptions(
enableEmitHookGuards,
assertValidMutableRanges: true,
hookPattern,
validatePreserveExistingMemoizationGuarantees,
},
compilationMode,
logger: null,
@@ -173,7 +180,7 @@ function makePluginOptions(
enableUseMemoCachePolyfill,
eslintSuppressionRules,
flowSuppressions,
ignoreUseNoForget
ignoreUseNoForget,
};
}
@@ -211,18 +218,18 @@ function getEvaluatorPresets(
presets.push(
language === "typescript"
? [
"@babel/preset-typescript",
{
/**
* onlyRemoveTypeImports needs to be set as fbt imports
* would otherwise be removed by this pass.
* https://github.com/facebook/fbt/issues/49
* https://github.com/facebook/sfbt/issues/72
* https://dev.to/retyui/how-to-add-support-typescript-for-fbt-an-internationalization-framework-3lo0
*/
onlyRemoveTypeImports: true,
},
]
"@babel/preset-typescript",
{
/**
* onlyRemoveTypeImports needs to be set as fbt imports
* would otherwise be removed by this pass.
* https://github.com/facebook/fbt/issues/49
* https://github.com/facebook/sfbt/issues/72
* https://dev.to/retyui/how-to-add-support-typescript-for-fbt-an-internationalization-framework-3lo0
*/
onlyRemoveTypeImports: true,
},
]
: "@babel/preset-flow"
);