Skip to content

Commit bbad60d

Browse files
committed
Fix: use Object.is for dependency comparison to handle NaN correctly
Previously, the React Compiler generated code using !== for dependency comparison, which doesn't match React's Object.is semantics. This caused NaN in dependency arrays to always trigger re-evaluation since NaN !== NaN is true, but Object.is(NaN, NaN) is true. This fix changes the generated code to use !Object.is() for dependency comparison, which correctly handles NaN and other edge cases like -0. Fixes #35854
1 parent 1bb234c commit bbad60d

1 file changed

Lines changed: 15 additions & 7 deletions

File tree

compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/CodegenReactiveFunction.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -574,14 +574,22 @@ function codegenReactiveScope(
574574

575575
for (const dep of [...scope.dependencies].sort(compareScopeDependency)) {
576576
const index = cx.nextCacheIndex;
577-
const comparison = t.binaryExpression(
578-
'!==',
579-
t.memberExpression(
580-
t.identifier(cx.synthesizeName('$')),
581-
t.numericLiteral(index),
582-
true,
577+
// Use Object.is for dependency comparison to match React's equality semantics.
578+
// This correctly handles NaN (NaN !== NaN is true, but Object.is(NaN, NaN) is true).
579+
// We negate Object.is since we want to detect changes (inequality).
580+
const comparison = t.unaryExpression(
581+
'!',
582+
t.callExpression(
583+
t.memberExpression(t.identifier('Object'), t.identifier('is')),
584+
[
585+
t.memberExpression(
586+
t.identifier(cx.synthesizeName('$')),
587+
t.numericLiteral(index),
588+
true,
589+
),
590+
codegenDependency(cx, dep),
591+
],
583592
),
584-
codegenDependency(cx, dep),
585593
);
586594
changeExpressions.push(comparison);
587595
/*

0 commit comments

Comments
 (0)