Skip to content

Fix: prevent unnecessary property change notifications for NaN - #21171

Closed
Karthikeya1500 wants to merge 1 commit into
emberjs:mainfrom
Karthikeya1500:fix/prevent-unnecessary-property-change-notifications-for-nan
Closed

Karthikeya1500 wants to merge 1 commit into
emberjs:mainfrom
Karthikeya1500:fix/prevent-unnecessary-property-change-notifications-for-nan

Conversation

@Karthikeya1500

Copy link
Copy Markdown

Fix: Correct equality check for NaN in property change detection

Problem

Currently, both _setProp (property_set.ts) and the computed property caching logic (computed.ts) use strict equality (=== / !==) to determine whether a property value has changed.

However, in JavaScript NaN !== NaN always evaluates to true. Because of this, updating a property from NaN to NaN is incorrectly treated as a change. This bypasses Ember’s early-return optimizations and triggers notifyPropertyChange, even though the value has not actually changed.

In larger applications, this can lead to unnecessary observer executions, reactive updates, and avoidable DOM re-renders.

Solution

Replace strict equality checks with Object.is() when comparing the new value with the cached value. Object.is() correctly handles edge cases such as NaN and distinguishes between +0 and -0.

With this change, setting a property from NaN to NaN will be correctly recognized as an unchanged value, preventing unnecessary reactive updates.

Impact

This improves the correctness of Ember’s change detection and avoids false-positive property change notifications in the core reactivity loop. Although small, this fix helps eliminate potential performance overhead caused by redundant updates.

When setting a property to NaN, if its current value is already NaN, `currentValue !== value` evaluates to `true` (since `NaN !== NaN` in JS). This triggers false positive property change notifications and unnecessary reactivity recalculations. Using `!Object.is(currentValue, value)` correctly checks for value equivalence.
@NullVoxPopuli

Copy link
Copy Markdown
Contributor

Do you have a test that recreates this NaN !== NaN situation?

@kategengler

Copy link
Copy Markdown
Member

set and computed are slated for deprecation as soon as we can manage it (See emberjs/rfcs#1129). For that reason, we don't want to change any of the internal code, even for a bugfix. Any change could break someone and cause upgrade pain/effort that would be better spent in moving off of computed and to @tracked.

@Karthikeya1500

Copy link
Copy Markdown
Author

@NullVoxPopuli @kategengler

Thank you for the context, @kategengler! I wasn't aware of the upcoming deprecation in RFC #1129. I completely understand the reasoning behind freezing the internal code for set and computed to avoid any unintended breaking changes or upgrade friction.

@NullVoxPopuli Given the feedback above and the decision not to merge fixes in this area, I'll hold off on writing a test for this edge case unless you feel it would still be useful to have for posterity.

I'll go ahead and close this PR. Thanks both for your time reviewing it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants