[babel] Inject React import if Forget compiled the function

Updates our Babel plugin to add an import to React if we succesfully compiled a 
function and cached one or more values. For now this logic is entirely in the 
Babel plugin itself, but long term we should move this into codegen and teach 
Forget to start the pipeline by lowering the whole Program node to an HIR (which 
would also allow us to understand imports and other module scope values being 
used). Right now it's not possible to add in codegen (without some ugly code) as 
a file containing multiple components would result in duplicate imports being 
generated
This commit is contained in:
Lauren Tan
2023-04-17 17:49:17 -04:00
parent 7c5e5eb30c
commit 0ddcaafd7c
274 changed files with 418 additions and 60 deletions
+49 -5
View File
@@ -191,11 +191,55 @@ export default function ReactForgetBabelPlugin(
opts: { ...pass.opts, ...options },
});
if (options.gating != null && hasForgetCompiledCode) {
path.unshiftContainer(
"body",
buildImportForGatingModule(options.gating)
);
// If there isn't already an import of * as React, insert it so React.useMemoCache doesn't
// throw
if (hasForgetCompiledCode) {
let didInsertUseMemoCache = false;
let hasExistingReactImport = false;
path.traverse({
MemberExpression(memberExprPath) {
const obj = memberExprPath.get("object");
const prop = memberExprPath.get("property");
if (
obj.isIdentifier() &&
obj.node.name === "React" &&
prop.isIdentifier() &&
prop.node.name === "unstable_useMemoCache"
) {
didInsertUseMemoCache = true;
memberExprPath.stop();
}
},
ImportDeclaration(importDeclPath) {
if (
importDeclPath.get("source").node.value === "react" &&
importDeclPath.get("specifiers").length === 1 &&
importDeclPath
.get("specifiers")[0]
.isImportNamespaceSpecifier() &&
importDeclPath.get("specifiers")[0].get("local").node.name ===
"React"
) {
hasExistingReactImport = true;
importDeclPath.stop();
}
},
});
if (didInsertUseMemoCache && !hasExistingReactImport) {
path.unshiftContainer(
"body",
t.importDeclaration(
[t.importNamespaceSpecifier(t.identifier("React"))],
t.stringLiteral("react")
)
);
}
if (options.gating != null) {
path.unshiftContainer(
"body",
buildImportForGatingModule(options.gating)
);
}
}
} catch (err) {
if (options.logger && err) {
@@ -23,7 +23,7 @@ function Component() {
## Code
```javascript
// Should print A, B, arg, original
import * as React from "react"; // Should print A, B, arg, original
function changeF(o) {
o.f = () => console.log("new");
return undefined;
@@ -19,6 +19,7 @@ function Component() {
## Code
```javascript
import * as React from "react";
function Component() {
const $ = React.unstable_useMemoCache(1);
let t0;
@@ -22,7 +22,7 @@ function Component() {
## Code
```javascript
// Should print A, arg, original
import * as React from "react"; // Should print A, arg, original
function changeF(o) {
o.f = () => console.log("new");
@@ -16,6 +16,7 @@ function component(a) {
## Code
```javascript
import * as React from "react";
function component(a) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== a;
@@ -17,6 +17,7 @@ function component() {
## Code
```javascript
import * as React from "react";
function component() {
const $ = React.unstable_useMemoCache(1);
let x;
@@ -16,6 +16,7 @@ function component() {
## Code
```javascript
import * as React from "react";
function component() {
const $ = React.unstable_useMemoCache(3);
let t0;
@@ -26,6 +26,7 @@ function mutate(x, y) {}
## Code
```javascript
import * as React from "react";
function foo(cond) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== cond;
@@ -19,7 +19,7 @@ function AllocatingPrimitiveAsDepNested(props) {
## Code
```javascript
// bar(props.b) is an allocating expression that produces a primitive, which means
import * as React from "react"; // bar(props.b) is an allocating expression that produces a primitive, which means
// that Forget should memoize it.
// Correctness:
// - y depends on either bar(props.b) or bar(props.b) + 1
@@ -16,7 +16,7 @@ function AllocatingPrimitiveAsDep(props) {
## Code
```javascript
// bar(props.b) is an allocating expression that produces a primitive, which means
import * as React from "react"; // bar(props.b) is an allocating expression that produces a primitive, which means
// that Forget should memoize it.
// Correctness:
// - y depends on either bar(props.b) or bar(props.b) + 1
@@ -16,6 +16,7 @@ function foo(a, b, c) {
## Code
```javascript
import * as React from "react";
function foo(a, b, c) {
const $ = React.unstable_useMemoCache(10);
const c_0 = $[0] !== a;
@@ -17,6 +17,7 @@ function Component(props) {
## Code
```javascript
import * as React from "react";
function Component(props) {
const $ = React.unstable_useMemoCache(7);
const c_0 = $[0] !== props.x;
@@ -17,7 +17,7 @@ function ArrayAtTest(props) {
## Code
```javascript
// arrayInstance.at should have the following effects:
import * as React from "react"; // arrayInstance.at should have the following effects:
// - read on arg0
// - read on receiver
// - mutate on lvalue
@@ -18,7 +18,7 @@ function Component(props) {
## Code
```javascript
// x's mutable range should extend to `mutate(y)`
import * as React from "react"; // x's mutable range should extend to `mutate(y)`
function Component(props) {
const $ = React.unstable_useMemoCache(2);
@@ -12,6 +12,7 @@ function Component(props) {
## Code
```javascript
import * as React from "react";
function Component(props) {
const $ = React.unstable_useMemoCache(3);
const c_0 = $[0] !== props.foo;
@@ -13,6 +13,7 @@ function component([a, b]) {
## Code
```javascript
import * as React from "react";
function component(t17) {
const $ = React.unstable_useMemoCache(7);
const [a, b] = t17;
@@ -14,6 +14,7 @@ function Component(props) {
## Code
```javascript
import * as React from "react";
function Component(props) {
const $ = React.unstable_useMemoCache(7);
const c_0 = $[0] !== props.a;
@@ -15,6 +15,7 @@ function Component(props) {
## Code
```javascript
import * as React from "react";
function Component(props) {
const $ = React.unstable_useMemoCache(11);
const c_0 = $[0] !== props.a;
@@ -19,7 +19,7 @@ function Component(props) {
## Code
```javascript
// arrayInstance.push should have the following effects:
import * as React from "react"; // arrayInstance.push should have the following effects:
// - read on all args (rest parameter)
// - mutate on receiver
function Component(props) {
@@ -12,7 +12,8 @@ export default ErrorView;
## Code
```javascript
import { isForgetEnabled_Fixtures } from "ReactForgetFeatureFlag"; // @gating
import { isForgetEnabled_Fixtures } from "ReactForgetFeatureFlag";
import * as React from "react"; // @gating
function ErrorView_uncompiled(error, _retry) {
return <MessageBox error={error}></MessageBox>;
}
@@ -15,6 +15,7 @@ function Component(props) {
## Code
```javascript
import * as React from "react";
function Component(props) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== props.x;
@@ -14,6 +14,7 @@ function g(props) {
## Code
```javascript
import * as React from "react";
function g(props) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== props.c;
@@ -19,6 +19,7 @@ function useBar(props) {
## Code
```javascript
import * as React from "react";
function useBar(props) {
const $ = React.unstable_useMemoCache(1);
let z;
@@ -14,6 +14,7 @@ function foo() {
## Code
```javascript
import * as React from "react";
function foo() {
const $ = React.unstable_useMemoCache(2);
let t0;
@@ -14,6 +14,7 @@ function g() {
## Code
```javascript
import * as React from "react";
function g() {
const $ = React.unstable_useMemoCache(1);
let x;
@@ -13,6 +13,7 @@ async function Component(props) {
## Code
```javascript
import * as React from "react";
async function Component(props) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== props.id;
@@ -12,6 +12,7 @@ async function Component(props) {
## Code
```javascript
import * as React from "react";
async function Component(props) {
const $ = React.unstable_useMemoCache(4);
const c_0 = $[0] !== props.id;
@@ -0,0 +1,75 @@
## Input
```javascript
import * as React from "react";
import { useMemo } from "react";
function Component(props) {
const [x] = React.useState(0);
const expensiveNumber = useMemo(() => calculateExpensiveNumber(x), [x]);
return <div>{expensiveNumber}</div>;
}
function Component2(props) {
const [x] = React.useState(0);
const expensiveNumber = useMemo(() => calculateExpensiveNumber(x), [x]);
return <div>{expensiveNumber}</div>;
}
```
## Code
```javascript
import * as React from "react";
import { useMemo } from "react";
function Component(props) {
const $ = React.unstable_useMemoCache(2);
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
const [x] = React.useState(0);
t0 = calculateExpensiveNumber(x);
$[0] = t0;
} else {
t0 = $[0];
}
const t17 = t0;
const expensiveNumber = t17;
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 $ = React.unstable_useMemoCache(2);
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
const [x] = React.useState(0);
t0 = calculateExpensiveNumber(x);
$[0] = t0;
} else {
t0 = $[0];
}
const t17 = t0;
const expensiveNumber = t17;
let t1;
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
t1 = <div>{expensiveNumber}</div>;
$[1] = t1;
} else {
t1 = $[1];
}
return t1;
}
```
@@ -0,0 +1,16 @@
import * as React from "react";
import { useMemo } from "react";
function Component(props) {
const [x] = React.useState(0);
const expensiveNumber = useMemo(() => calculateExpensiveNumber(x), [x]);
return <div>{expensiveNumber}</div>;
}
function Component2(props) {
const [x] = React.useState(0);
const expensiveNumber = useMemo(() => calculateExpensiveNumber(x), [x]);
return <div>{expensiveNumber}</div>;
}
@@ -13,6 +13,7 @@ function component(t) {
## Code
```javascript
import * as React from "react";
function component(t) {
const $ = React.unstable_useMemoCache(2);
const { a } = t;
@@ -13,6 +13,7 @@ function Component(props) {
## Code
```javascript
import * as React from "react";
function Component(props) {
const $ = React.unstable_useMemoCache(1);
let x;
@@ -13,6 +13,7 @@ function Component(props) {
## Code
```javascript
import * as React from "react";
function Component(props) {
const $ = React.unstable_useMemoCache(1);
let x;
@@ -12,6 +12,7 @@ function Component(props) {
## Code
```javascript
import * as React from "react";
function Component(props) {
const $ = React.unstable_useMemoCache(3);
const c_0 = $[0] !== props.a;
@@ -17,6 +17,7 @@ function Component(props) {
## Code
```javascript
import * as React from "react";
function Component(props) {
const $ = React.unstable_useMemoCache(6);
const c_0 = $[0] !== props;
@@ -18,6 +18,7 @@ function Component(props) {
## Code
```javascript
import * as React from "react";
function foo() {
return undefined;
}
@@ -19,6 +19,7 @@ function component(a, b) {
## Code
```javascript
import * as React from "react";
function component(a, b) {
const $ = React.unstable_useMemoCache(9);
const c_0 = $[0] !== b;
@@ -19,6 +19,7 @@ function component(a) {
## Code
```javascript
import * as React from "react";
function component(a) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== a;
@@ -45,6 +45,7 @@ function getNativeLogFunction(level) {
## Code
```javascript
import * as React from "react";
function getNativeLogFunction(level) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== level;
@@ -17,6 +17,7 @@ function component(a) {
## Code
```javascript
import * as React from "react";
function component(a) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== a;
@@ -15,6 +15,7 @@ function component(a) {
## Code
```javascript
import * as React from "react";
function component(a) {
const $ = React.unstable_useMemoCache(4);
const c_0 = $[0] !== a;
@@ -19,6 +19,7 @@ function component(foo, bar) {
## Code
```javascript
import * as React from "react";
function component(foo, bar) {
const $ = React.unstable_useMemoCache(3);
const c_0 = $[0] !== foo;
@@ -19,6 +19,7 @@ function component(foo, bar) {
## Code
```javascript
import * as React from "react";
function component(foo, bar) {
const $ = React.unstable_useMemoCache(3);
const c_0 = $[0] !== foo;
@@ -19,6 +19,7 @@ function component(foo, bar) {
## Code
```javascript
import * as React from "react";
function component(foo, bar) {
const $ = React.unstable_useMemoCache(3);
const c_0 = $[0] !== foo;
@@ -19,6 +19,7 @@ function component(foo, bar) {
## Code
```javascript
import * as React from "react";
function component(foo, bar) {
const $ = React.unstable_useMemoCache(3);
const c_0 = $[0] !== foo;
@@ -17,6 +17,7 @@ function component(a) {
## Code
```javascript
import * as React from "react";
function component(a) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== a;
@@ -17,6 +17,7 @@ function component(a) {
## Code
```javascript
import * as React from "react";
function component(a) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== a;
@@ -18,6 +18,7 @@ function component(a) {
## Code
```javascript
import * as React from "react";
function component(a) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== a;
@@ -18,6 +18,7 @@ function component(a) {
## Code
```javascript
import * as React from "react";
function component(a) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== a;
@@ -18,6 +18,7 @@ function component(a, b) {
## Code
```javascript
import * as React from "react";
function component(a, b) {
const $ = React.unstable_useMemoCache(5);
const c_0 = $[0] !== b;
@@ -17,6 +17,7 @@ function component(a, b) {
## Code
```javascript
import * as React from "react";
function component(a, b) {
const $ = React.unstable_useMemoCache(7);
const c_0 = $[0] !== b;
@@ -16,6 +16,7 @@ function component(a) {
## Code
```javascript
import * as React from "react";
function component(a) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== a;
@@ -18,6 +18,7 @@ function component(a, b) {
## Code
```javascript
import * as React from "react";
function component(a, b) {
const $ = React.unstable_useMemoCache(5);
const c_0 = $[0] !== a;
@@ -17,6 +17,7 @@ function component(a) {
## Code
```javascript
import * as React from "react";
function component(a) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== a;
@@ -15,6 +15,7 @@ function component(a) {
## Code
```javascript
import * as React from "react";
function component(a) {
const $ = React.unstable_useMemoCache(4);
const c_0 = $[0] !== a;
@@ -17,6 +17,7 @@ function bar(a) {
## Code
```javascript
import * as React from "react";
function bar(a) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== a;
@@ -19,6 +19,7 @@ function bar(a, b) {
## Code
```javascript
import * as React from "react";
function bar(a, b) {
const $ = React.unstable_useMemoCache(3);
const c_0 = $[0] !== a;
@@ -17,6 +17,7 @@ function bar(a) {
## Code
```javascript
import * as React from "react";
function bar(a) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== a;
@@ -17,6 +17,7 @@ function bar(a) {
## Code
```javascript
import * as React from "react";
function bar(a) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== a;
@@ -22,6 +22,7 @@ function component(a, b) {
## Code
```javascript
import * as React from "react";
function component(a, b) {
const $ = React.unstable_useMemoCache(7);
const c_0 = $[0] !== a;
@@ -18,6 +18,7 @@ function component(a, b) {
## Code
```javascript
import * as React from "react";
function component(a, b) {
const $ = React.unstable_useMemoCache(5);
const c_0 = $[0] !== a;
@@ -16,6 +16,7 @@ function component(a) {
## Code
```javascript
import * as React from "react";
function component(a) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== a;
@@ -18,6 +18,7 @@ function Foo(props) {
## Code
```javascript
import * as React from "react";
function Foo(props) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== props.router.location;
@@ -19,6 +19,7 @@ function component({ mutator }) {
## Code
```javascript
import * as React from "react";
function component(t27) {
const $ = React.unstable_useMemoCache(7);
const { mutator } = t27;
@@ -18,6 +18,7 @@ function component(a, b) {
## Code
```javascript
import * as React from "react";
function component(a, b) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== a;
@@ -13,6 +13,7 @@ function component(a, b) {
## Code
```javascript
import * as React from "react";
function component(a, b) {
const $ = React.unstable_useMemoCache(6);
const c_0 = $[0] !== a;
@@ -16,6 +16,7 @@ function component(a) {
## Code
```javascript
import * as React from "react";
function component(a) {
const $ = React.unstable_useMemoCache(1);
let t0;
@@ -12,6 +12,7 @@ function StoreLandingUnseenGiftModalContainer(a) {
## Code
```javascript
import * as React from "react";
function StoreLandingUnseenGiftModalContainer(a) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== a;
@@ -18,6 +18,7 @@ function component(a) {
## Code
```javascript
import * as React from "react";
function component(a) {
const $ = React.unstable_useMemoCache(4);
const c_0 = $[0] !== a;
@@ -15,6 +15,7 @@ function component(a) {
## Code
```javascript
import * as React from "react";
function component(a) {
const $ = React.unstable_useMemoCache(4);
const c_0 = $[0] !== a;
@@ -15,6 +15,7 @@ function component(a) {
## Code
```javascript
import * as React from "react";
function component(a) {
const $ = React.unstable_useMemoCache(6);
const c_0 = $[0] !== a;
@@ -17,6 +17,7 @@ function component(a) {
## Code
```javascript
import * as React from "react";
function component(a) {
const $ = React.unstable_useMemoCache(6);
const c_0 = $[0] !== a;
@@ -15,6 +15,7 @@ function component(a) {
## Code
```javascript
import * as React from "react";
function component(a) {
const $ = React.unstable_useMemoCache(6);
const c_0 = $[0] !== a;
@@ -17,6 +17,7 @@ function component(a) {
## Code
```javascript
import * as React from "react";
function component(a) {
const $ = React.unstable_useMemoCache(4);
const c_0 = $[0] !== a;
@@ -17,6 +17,7 @@ function component(a) {
## Code
```javascript
import * as React from "react";
function component(a) {
const $ = React.unstable_useMemoCache(4);
const c_0 = $[0] !== a;
@@ -16,6 +16,7 @@ function foo() {
## Code
```javascript
import * as React from "react";
function foo() {
const $ = React.unstable_useMemoCache(1);
let z;
@@ -34,6 +34,7 @@ function Component(props) {
## Code
```javascript
import * as React from "react";
function Component(props) {
const $ = React.unstable_useMemoCache(8);
const items = props.items;
@@ -12,6 +12,7 @@ function Component(props) {
## Code
```javascript
import * as React from "react";
function Component(props) {
const $ = React.unstable_useMemoCache(4);
const c_0 = $[0] !== props.method;
@@ -17,6 +17,7 @@ function Component(props) {
## Code
```javascript
import * as React from "react";
function Component(props) {
const $ = React.unstable_useMemoCache(2);
const a = foo();
@@ -15,6 +15,7 @@ function component(a, b) {
## Code
```javascript
import * as React from "react";
function component(a, b) {
const $ = React.unstable_useMemoCache(3);
const c_0 = $[0] !== a;
@@ -13,6 +13,7 @@ function component() {
## Code
```javascript
import * as React from "react";
function component() {
const $ = React.unstable_useMemoCache(4);
const [x, setX] = useState(0);
@@ -17,7 +17,7 @@ function Component(props) {
## Code
```javascript
// To preserve the nullthrows behavior and reactive deps of this code,
import * as React from "react"; // To preserve the nullthrows behavior and reactive deps of this code,
// Forget needs to add `props.a` as a dependency (since `props.a.b` is
// a conditional dependency, i.e. gated behind control flow)
@@ -23,6 +23,7 @@ function Component(props) {
## Code
```javascript
import * as React from "react";
/**
* props.b *does* influence `a`
*/
@@ -61,6 +61,7 @@ function ComponentD(props) {
## Code
```javascript
import * as React from "react";
/**
* props.b does *not* influence `a`
*/
@@ -34,6 +34,7 @@ function mayMutate() {}
## Code
```javascript
import * as React from "react";
function ComponentA(props) {
const $ = React.unstable_useMemoCache(6);
const c_0 = $[0] !== props;
@@ -15,6 +15,7 @@ function Component(props) {
## Code
```javascript
import * as React from "react";
function Component(props) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== props.foo;
@@ -18,6 +18,7 @@ function Component(props) {
## Code
```javascript
import * as React from "react";
function Foo() {
return undefined;
}
@@ -13,6 +13,7 @@ function component() {
## Code
```javascript
import * as React from "react";
function component() {
const $ = React.unstable_useMemoCache(5);
const [x, setX] = useState(0);
@@ -14,6 +14,7 @@ function Component(props) {
## Code
```javascript
import * as React from "react";
function Component(props) {
const $ = React.unstable_useMemoCache(3);
const c_0 = $[0] !== props.a;
@@ -13,6 +13,7 @@ function Component(props) {
## Code
```javascript
import * as React from "react";
function Component(props) {
const $ = React.unstable_useMemoCache(3);
const c_0 = $[0] !== props.a;
@@ -22,6 +22,7 @@ function foo(a, b) {
## Code
```javascript
import * as React from "react";
function foo(a, b) {
const $ = React.unstable_useMemoCache(5);
const c_0 = $[0] !== a;
@@ -23,6 +23,7 @@ function foo(x, y, z) {
## Code
```javascript
import * as React from "react";
function foo(x, y, z) {
const $ = React.unstable_useMemoCache(3);
const items = [z];
@@ -13,6 +13,7 @@ function component(a) {
## Code
```javascript
import * as React from "react";
let someGlobal = {};
function component(a) {
const $ = React.unstable_useMemoCache(2);
@@ -12,6 +12,7 @@ function Component(props) {
## Code
```javascript
import * as React from "react";
function Component(props) {
const $ = React.unstable_useMemoCache(2);
const [t0] = props.y;
@@ -17,6 +17,7 @@ function Component(props) {
## Code
```javascript
import * as React from "react";
function Component(props) {
const $ = React.unstable_useMemoCache(2);
let x = undefined;
@@ -26,6 +26,7 @@ function foo(a, b, c) {
## Code
```javascript
import * as React from "react";
function foo(a, b, c) {
const $ = React.unstable_useMemoCache(5);
@@ -12,6 +12,7 @@ function Component(props) {
## Code
```javascript
import * as React from "react";
function Component(props) {
const $ = React.unstable_useMemoCache(2);
const { x: t0 } = props.y;
@@ -27,6 +27,7 @@ function foo(a, b, c) {
## Code
```javascript
import * as React from "react";
function foo(a, b, c) {
const $ = React.unstable_useMemoCache(18);
const c_0 = $[0] !== a;
@@ -17,6 +17,7 @@ function Component(props) {
## Code
```javascript
import * as React from "react";
function Component(props) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== props;
@@ -18,6 +18,7 @@ function Component(props) {
## Code
```javascript
import * as React from "react";
function Component(props) {
const $ = React.unstable_useMemoCache(2);
const c_0 = $[0] !== props;
@@ -21,6 +21,7 @@ function Component() {
## Code
```javascript
import * as React from "react";
function Component() {
const $ = React.unstable_useMemoCache(1);
let ret;

Some files were not shown because too many files have changed in this diff Show More