diff --git a/compiler/forget/src/HIR/HIR.ts b/compiler/forget/src/HIR/HIR.ts
index 80d405268a..661187ed90 100644
--- a/compiler/forget/src/HIR/HIR.ts
+++ b/compiler/forget/src/HIR/HIR.ts
@@ -979,6 +979,14 @@ export function isPrimitiveType(id: Identifier): boolean {
return id.type.kind === "Primitive";
}
+export function isRefValueType(id: Identifier): boolean {
+ return id.type.kind === "Object" && id.type.shapeId === "BuiltInRefValue";
+}
+
+export function isUseRefType(id: Identifier): boolean {
+ return id.type.kind === "Object" && id.type.shapeId === "BuiltInUseRefId";
+}
+
export function getHookKind(env: Environment, id: Identifier): HookKind | null {
const idType = id.type;
if (idType.kind === "Function") {
diff --git a/compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts b/compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts
index 05bb66b133..460d630d2c 100644
--- a/compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts
+++ b/compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts
@@ -11,6 +11,7 @@ import {
IdentifierId,
InstructionId,
InstructionKind,
+ isUseRefType,
makeInstructionId,
Place,
ReactiveFunction,
@@ -314,6 +315,14 @@ class Context {
// Checks if identifier is a valid dependency in the current scope
#checkValidDependency(maybeDependency: ReactiveScopeDependency): boolean {
+ // ref.current access is not a valid dep
+ if (
+ isUseRefType(maybeDependency.identifier) &&
+ maybeDependency.path.at(0) === "current"
+ ) {
+ return false;
+ }
+
const identifier = maybeDependency.identifier;
// If this operand is used in a scope, has a dynamic value, and was defined
// before this scope, then its a dependency of the scope.
diff --git a/compiler/forget/src/__tests__/fixtures/compiler/ref-current-field-not-added-to-dep.expect.md b/compiler/forget/src/__tests__/fixtures/compiler/ref-current-field-not-added-to-dep.expect.md
new file mode 100644
index 0000000000..7a630ff951
--- /dev/null
+++ b/compiler/forget/src/__tests__/fixtures/compiler/ref-current-field-not-added-to-dep.expect.md
@@ -0,0 +1,46 @@
+
+## Input
+
+```javascript
+function VideoTab() {
+ const ref = useRef();
+ let x = () => {
+ ref.current.x;
+ };
+
+ return ;
+}
+
+```
+
+## Code
+
+```javascript
+import { unstable_useMemoCache as useMemoCache } from "react";
+function VideoTab() {
+ const $ = useMemoCache(3);
+ const ref = useRef();
+ let t0;
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
+ t0 = () => {
+ ref.current.x;
+ };
+ $[0] = t0;
+ } else {
+ t0 = $[0];
+ }
+ const x = t0;
+ const c_1 = $[1] !== x;
+ let t1;
+ if (c_1) {
+ t1 = ;
+ $[1] = x;
+ $[2] = t1;
+ } else {
+ t1 = $[2];
+ }
+ return t1;
+}
+
+```
+
\ No newline at end of file
diff --git a/compiler/forget/src/__tests__/fixtures/compiler/ref-current-field-not-added-to-dep.js b/compiler/forget/src/__tests__/fixtures/compiler/ref-current-field-not-added-to-dep.js
new file mode 100644
index 0000000000..53d4489d8c
--- /dev/null
+++ b/compiler/forget/src/__tests__/fixtures/compiler/ref-current-field-not-added-to-dep.js
@@ -0,0 +1,8 @@
+function VideoTab() {
+ const ref = useRef();
+ let x = () => {
+ ref.current.x;
+ };
+
+ return ;
+}
diff --git a/compiler/forget/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep-2.expect.md b/compiler/forget/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep-2.expect.md
new file mode 100644
index 0000000000..3edc16158e
--- /dev/null
+++ b/compiler/forget/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep-2.expect.md
@@ -0,0 +1,45 @@
+
+## Input
+
+```javascript
+function Foo({ a }) {
+ const ref = useRef();
+ const x = { a, val: ref.current };
+
+ return ;
+}
+
+```
+
+## Code
+
+```javascript
+import { unstable_useMemoCache as useMemoCache } from "react";
+function Foo(t18) {
+ const $ = useMemoCache(4);
+ const { a } = t18;
+ const ref = useRef();
+ const c_0 = $[0] !== a;
+ let t0;
+ if (c_0) {
+ t0 = { a, val: ref.current };
+ $[0] = a;
+ $[1] = t0;
+ } else {
+ t0 = $[1];
+ }
+ const x = t0;
+ const c_2 = $[2] !== x;
+ let t1;
+ if (c_2) {
+ t1 = ;
+ $[2] = x;
+ $[3] = t1;
+ } else {
+ t1 = $[3];
+ }
+ return t1;
+}
+
+```
+
\ No newline at end of file
diff --git a/compiler/forget/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep-2.js b/compiler/forget/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep-2.js
new file mode 100644
index 0000000000..80ced49a9d
--- /dev/null
+++ b/compiler/forget/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep-2.js
@@ -0,0 +1,6 @@
+function Foo({ a }) {
+ const ref = useRef();
+ const x = { a, val: ref.current };
+
+ return ;
+}
diff --git a/compiler/forget/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep.expect.md b/compiler/forget/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep.expect.md
new file mode 100644
index 0000000000..9f8e8a776d
--- /dev/null
+++ b/compiler/forget/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep.expect.md
@@ -0,0 +1,46 @@
+
+## Input
+
+```javascript
+function VideoTab() {
+ const ref = useRef();
+ let x = () => {
+ ref.current;
+ };
+
+ return ;
+}
+
+```
+
+## Code
+
+```javascript
+import { unstable_useMemoCache as useMemoCache } from "react";
+function VideoTab() {
+ const $ = useMemoCache(3);
+ const ref = useRef();
+ let t0;
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
+ t0 = () => {
+ ref.current;
+ };
+ $[0] = t0;
+ } else {
+ t0 = $[0];
+ }
+ const x = t0;
+ const c_1 = $[1] !== x;
+ let t1;
+ if (c_1) {
+ t1 = ;
+ $[1] = x;
+ $[2] = t1;
+ } else {
+ t1 = $[2];
+ }
+ return t1;
+}
+
+```
+
\ No newline at end of file
diff --git a/compiler/forget/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep.js b/compiler/forget/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep.js
new file mode 100644
index 0000000000..f3d6f574fe
--- /dev/null
+++ b/compiler/forget/src/__tests__/fixtures/compiler/ref-current-not-added-to-dep.js
@@ -0,0 +1,8 @@
+function VideoTab() {
+ const ref = useRef();
+ let x = () => {
+ ref.current;
+ };
+
+ return ;
+}
diff --git a/compiler/forget/src/__tests__/fixtures/compiler/ref-current-optional-field-no-added-to-dep.expect.md b/compiler/forget/src/__tests__/fixtures/compiler/ref-current-optional-field-no-added-to-dep.expect.md
new file mode 100644
index 0000000000..6fe9a28cbb
--- /dev/null
+++ b/compiler/forget/src/__tests__/fixtures/compiler/ref-current-optional-field-no-added-to-dep.expect.md
@@ -0,0 +1,46 @@
+
+## Input
+
+```javascript
+function VideoTab() {
+ const ref = useRef();
+ let x = () => {
+ ref.current?.x;
+ };
+
+ return ;
+}
+
+```
+
+## Code
+
+```javascript
+import { unstable_useMemoCache as useMemoCache } from "react";
+function VideoTab() {
+ const $ = useMemoCache(3);
+ const ref = useRef();
+ let t0;
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
+ t0 = () => {
+ ref.current?.x;
+ };
+ $[0] = t0;
+ } else {
+ t0 = $[0];
+ }
+ const x = t0;
+ const c_1 = $[1] !== x;
+ let t1;
+ if (c_1) {
+ t1 = ;
+ $[1] = x;
+ $[2] = t1;
+ } else {
+ t1 = $[2];
+ }
+ return t1;
+}
+
+```
+
\ No newline at end of file
diff --git a/compiler/forget/src/__tests__/fixtures/compiler/ref-current-optional-field-no-added-to-dep.js b/compiler/forget/src/__tests__/fixtures/compiler/ref-current-optional-field-no-added-to-dep.js
new file mode 100644
index 0000000000..92b26a8f9c
--- /dev/null
+++ b/compiler/forget/src/__tests__/fixtures/compiler/ref-current-optional-field-no-added-to-dep.js
@@ -0,0 +1,8 @@
+function VideoTab() {
+ const ref = useRef();
+ let x = () => {
+ ref.current?.x;
+ };
+
+ return ;
+}
diff --git a/compiler/forget/src/__tests__/fixtures/compiler/ref-current-write-not-added-to-dep.expect.md b/compiler/forget/src/__tests__/fixtures/compiler/ref-current-write-not-added-to-dep.expect.md
new file mode 100644
index 0000000000..6b6b95e201
--- /dev/null
+++ b/compiler/forget/src/__tests__/fixtures/compiler/ref-current-write-not-added-to-dep.expect.md
@@ -0,0 +1,46 @@
+
+## Input
+
+```javascript
+function VideoTab() {
+ const ref = useRef();
+ let x = () => {
+ ref.current = 1;
+ };
+
+ return ;
+}
+
+```
+
+## Code
+
+```javascript
+import { unstable_useMemoCache as useMemoCache } from "react";
+function VideoTab() {
+ const $ = useMemoCache(3);
+ const ref = useRef();
+ let t0;
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
+ t0 = () => {
+ ref.current = 1;
+ };
+ $[0] = t0;
+ } else {
+ t0 = $[0];
+ }
+ const x = t0;
+ const c_1 = $[1] !== x;
+ let t1;
+ if (c_1) {
+ t1 = ;
+ $[1] = x;
+ $[2] = t1;
+ } else {
+ t1 = $[2];
+ }
+ return t1;
+}
+
+```
+
\ No newline at end of file
diff --git a/compiler/forget/src/__tests__/fixtures/compiler/ref-current-write-not-added-to-dep.js b/compiler/forget/src/__tests__/fixtures/compiler/ref-current-write-not-added-to-dep.js
new file mode 100644
index 0000000000..00b85bb682
--- /dev/null
+++ b/compiler/forget/src/__tests__/fixtures/compiler/ref-current-write-not-added-to-dep.js
@@ -0,0 +1,8 @@
+function VideoTab() {
+ const ref = useRef();
+ let x = () => {
+ ref.current = 1;
+ };
+
+ return ;
+}