From 2d1c498fa8a2a2971a3dab33852910407be28f71 Mon Sep 17 00:00:00 2001 From: Karthikeya1500 Date: Thu, 5 Mar 2026 00:25:21 +0530 Subject: [PATCH] Fix: prevent unnecessary property change notifications for NaN 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. --- packages/@ember/-internals/metal/lib/computed.ts | 12 ++++++------ packages/@ember/-internals/metal/lib/property_set.ts | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/@ember/-internals/metal/lib/computed.ts b/packages/@ember/-internals/metal/lib/computed.ts index aac84147b84..6c30b855746 100644 --- a/packages/@ember/-internals/metal/lib/computed.ts +++ b/packages/@ember/-internals/metal/lib/computed.ts @@ -72,7 +72,7 @@ export type ComputedPropertyCallback = ComputedPropertyGetterFunction | Computed const DEEP_EACH_REGEX = /\.@each\.[^.]+\./; -function noop(): void {} +function noop(): void { } /** `@computed` is a decorator that turns a JavaScript getter and setter into a computed property, which is a _cached, trackable value_. By default the getter @@ -345,7 +345,7 @@ export class ComputedProperty extends ComputedDescriptor { assert( `Attempted to use @computed on ${keyName}, but it did not have a getter or a setter. You must either pass a get a function or getter/setter to @computed directly (e.g. \`@computed({ get() { ... } })\`) or apply @computed directly to a getter/setter`, propertyDesc && - (typeof propertyDesc.get === 'function' || typeof propertyDesc.set === 'function') + (typeof propertyDesc.get === 'function' || typeof propertyDesc.set === 'function') ); let { get, set } = propertyDesc; @@ -374,9 +374,9 @@ export class ComputedProperty extends ComputedDescriptor { function addArg(property: string): void { assert( `Dependent keys containing @each only work one level deep. ` + - `You used the key "${property}" which is invalid. ` + - `Please create an intermediary computed property or ` + - `switch to using tracked properties.`, + `You used the key "${property}" which is invalid. ` + + `Please create an intermediary computed property or ` + + `switch to using tracked properties.`, DEEP_EACH_REGEX.test(property) === false ); @@ -531,7 +531,7 @@ export class ComputedProperty extends ComputedDescriptor { } // allows setter to return the same value that is cached already - if (hadCachedValue && cachedValue === ret) { + if (hadCachedValue && Object.is(cachedValue, ret)) { return ret; } diff --git a/packages/@ember/-internals/metal/lib/property_set.ts b/packages/@ember/-internals/metal/lib/property_set.ts index 65b78f9c1ed..e84f9a247c1 100644 --- a/packages/@ember/-internals/metal/lib/property_set.ts +++ b/packages/@ember/-internals/metal/lib/property_set.ts @@ -95,7 +95,7 @@ export function _setProp(obj: object, keyName: string, value: any) { (obj as any)[keyName] = value; } - if (currentValue !== value) { + if (!Object.is(currentValue, value)) { notifyPropertyChange(obj, keyName); } }