@samitouri / QOS-React / commits / bedf0cc6c5

[hir] Don't track ref.current as a valid dep

Sathya Gunasekaran committed May 31, 2023 at 13:54 UTC bedf0cc6c50b4d738f4022e48188c0166e63bed8
12 files changed +284
compiler/forget/src/HIR/HIR.ts
+8
@@ -979,6 +979,14 @@ export function isPrimitiveType(id: Identifier): boolean {
979 return id.type.kind === "Primitive";
980 }
981
982 +export function isRefValueType(id: Identifier): boolean {
983 + return id.type.kind === "Object" && id.type.shapeId === "BuiltInRefValue";
984 +}
985 +
986 +export function isUseRefType(id: Identifier): boolean {
987 + return id.type.kind === "Object" && id.type.shapeId === "BuiltInUseRefId";
988 +}
989 +
990 export function getHookKind(env: Environment, id: Identifier): HookKind | null {
991 const idType = id.type;
992 if (idType.kind === "Function") {
compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts
+9
@@ -11,6 +11,7 @@ import {
11 IdentifierId,
12 InstructionId,
13 InstructionKind,
14 + isUseRefType,
15 makeInstructionId,
16 Place,
17 ReactiveFunction,
@@ -314,6 +315,14 @@ class Context {
315
316 // Checks if identifier is a valid dependency in the current scope
317 #checkValidDependency(maybeDependency: ReactiveScopeDependency): boolean {
318 + // ref.current access is not a valid dep
319 + if (
320 + isUseRefType(maybeDependency.identifier) &&
321 + maybeDependency.path.at(0) === "current"
322 + ) {
323 + return false;
324 + }
325 +
326 const identifier = maybeDependency.identifier;
327 // If this operand is used in a scope, has a dynamic value, and was defined
328 // before this scope, then its a dependency of the scope.
compiler/forget/src/__tests__/fixtures/compiler/ref-current-field-not-added-to-dep.expect.md new
+46
@@ -0,0 +1,46 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function VideoTab() {
6 + const ref = useRef();
7 + let x = () => {
8 + ref.current.x;
9 + };
10 +
11 + return <VideoList videos={x} />;
12 +}
13 +
14 +```
15 +
16 +## Code
17 +
18 +```javascript
19 +import { unstable_useMemoCache as useMemoCache } from "react";
20 +function VideoTab() {
21 + const $ = useMemoCache(3);
22 + const ref = useRef();
23 + let t0;
24 + if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
25 + t0 = () => {
26 + ref.current.x;
27 + };
28 + $[0] = t0;
29 + } else {
30 + t0 = $[0];
31 + }
32 + const x = t0;
33 + const c_1 = $[1] !== x;
34 + let t1;
35 + if (c_1) {
36 + t1 = <VideoList videos={x} />;
37 + $[1] = x;
38 + $[2] = t1;
39 + } else {
40 + t1 = $[2];
41 + }
42 + return t1;
43 +}
44 +
45 +```
46 +
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/ref-current-field-not-added-to-dep.js new
+8
@@ -0,0 +1,8 @@
1 +function VideoTab() {
2 + const ref = useRef();
3 + let x = () => {
4 + ref.current.x;
5 + };
6 +
7 + return <VideoList videos={x} />;
8 +}
compiler/forget/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep-2.expect.md new
+45
@@ -0,0 +1,45 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function Foo({ a }) {
6 + const ref = useRef();
7 + const x = { a, val: ref.current };
8 +
9 + return <VideoList videos={x} />;
10 +}
11 +
12 +```
13 +
14 +## Code
15 +
16 +```javascript
17 +import { unstable_useMemoCache as useMemoCache } from "react";
18 +function Foo(t18) {
19 + const $ = useMemoCache(4);
20 + const { a } = t18;
21 + const ref = useRef();
22 + const c_0 = $[0] !== a;
23 + let t0;
24 + if (c_0) {
25 + t0 = { a, val: ref.current };
26 + $[0] = a;
27 + $[1] = t0;
28 + } else {
29 + t0 = $[1];
30 + }
31 + const x = t0;
32 + const c_2 = $[2] !== x;
33 + let t1;
34 + if (c_2) {
35 + t1 = <VideoList videos={x} />;
36 + $[2] = x;
37 + $[3] = t1;
38 + } else {
39 + t1 = $[3];
40 + }
41 + return t1;
42 +}
43 +
44 +```
45 +
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep-2.js new
+6
@@ -0,0 +1,6 @@
1 +function Foo({ a }) {
2 + const ref = useRef();
3 + const x = { a, val: ref.current };
4 +
5 + return <VideoList videos={x} />;
6 +}
compiler/forget/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep.expect.md new
+46
@@ -0,0 +1,46 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function VideoTab() {
6 + const ref = useRef();
7 + let x = () => {
8 + ref.current;
9 + };
10 +
11 + return <VideoList videos={x} />;
12 +}
13 +
14 +```
15 +
16 +## Code
17 +
18 +```javascript
19 +import { unstable_useMemoCache as useMemoCache } from "react";
20 +function VideoTab() {
21 + const $ = useMemoCache(3);
22 + const ref = useRef();
23 + let t0;
24 + if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
25 + t0 = () => {
26 + ref.current;
27 + };
28 + $[0] = t0;
29 + } else {
30 + t0 = $[0];
31 + }
32 + const x = t0;
33 + const c_1 = $[1] !== x;
34 + let t1;
35 + if (c_1) {
36 + t1 = <VideoList videos={x} />;
37 + $[1] = x;
38 + $[2] = t1;
39 + } else {
40 + t1 = $[2];
41 + }
42 + return t1;
43 +}
44 +
45 +```
46 +
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep.js new
+8
@@ -0,0 +1,8 @@
1 +function VideoTab() {
2 + const ref = useRef();
3 + let x = () => {
4 + ref.current;
5 + };
6 +
7 + return <VideoList videos={x} />;
8 +}
compiler/forget/src/__tests__/fixtures/compiler/ref-current-optional-field-no-added-to-dep.expect.md new
+46
@@ -0,0 +1,46 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function VideoTab() {
6 + const ref = useRef();
7 + let x = () => {
8 + ref.current?.x;
9 + };
10 +
11 + return <VideoList videos={x} />;
12 +}
13 +
14 +```
15 +
16 +## Code
17 +
18 +```javascript
19 +import { unstable_useMemoCache as useMemoCache } from "react";
20 +function VideoTab() {
21 + const $ = useMemoCache(3);
22 + const ref = useRef();
23 + let t0;
24 + if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
25 + t0 = () => {
26 + ref.current?.x;
27 + };
28 + $[0] = t0;
29 + } else {
30 + t0 = $[0];
31 + }
32 + const x = t0;
33 + const c_1 = $[1] !== x;
34 + let t1;
35 + if (c_1) {
36 + t1 = <VideoList videos={x} />;
37 + $[1] = x;
38 + $[2] = t1;
39 + } else {
40 + t1 = $[2];
41 + }
42 + return t1;
43 +}
44 +
45 +```
46 +
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/ref-current-optional-field-no-added-to-dep.js new
+8
@@ -0,0 +1,8 @@
1 +function VideoTab() {
2 + const ref = useRef();
3 + let x = () => {
4 + ref.current?.x;
5 + };
6 +
7 + return <VideoList videos={x} />;
8 +}
compiler/forget/src/__tests__/fixtures/compiler/ref-current-write-not-added-to-dep.expect.md new
+46
@@ -0,0 +1,46 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function VideoTab() {
6 + const ref = useRef();
7 + let x = () => {
8 + ref.current = 1;
9 + };
10 +
11 + return <VideoList videos={x} />;
12 +}
13 +
14 +```
15 +
16 +## Code
17 +
18 +```javascript
19 +import { unstable_useMemoCache as useMemoCache } from "react";
20 +function VideoTab() {
21 + const $ = useMemoCache(3);
22 + const ref = useRef();
23 + let t0;
24 + if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
25 + t0 = () => {
26 + ref.current = 1;
27 + };
28 + $[0] = t0;
29 + } else {
30 + t0 = $[0];
31 + }
32 + const x = t0;
33 + const c_1 = $[1] !== x;
34 + let t1;
35 + if (c_1) {
36 + t1 = <VideoList videos={x} />;
37 + $[1] = x;
38 + $[2] = t1;
39 + } else {
40 + t1 = $[2];
41 + }
42 + return t1;
43 +}
44 +
45 +```
46 +
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/ref-current-write-not-added-to-dep.js new
+8
@@ -0,0 +1,8 @@
1 +function VideoTab() {
2 + const ref = useRef();
3 + let x = () => {
4 + ref.current = 1;
5 + };
6 +
7 + return <VideoList videos={x} />;
8 +}