From 432fb866548da749779d63b13d47c6511d089cf6 Mon Sep 17 00:00:00 2001 From: Georgios Kalpakas Date: Tue, 6 Sep 2016 19:58:09 +0300 Subject: [PATCH] fix($compile): avoid calling `$onChanges()` twice for `NaN` initial values --- src/ng/compile.js | 4 +++- test/ng/compileSpec.js | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/ng/compile.js b/src/ng/compile.js index 30f40539a9bc..a20d1d170731 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -3500,7 +3500,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { }); function recordChanges(key, currentValue, previousValue) { - if (isFunction(destination.$onChanges) && currentValue !== previousValue) { + if (isFunction(destination.$onChanges) && currentValue !== previousValue && + // eslint-disable-next-line no-self-compare + (currentValue === currentValue || previousValue === previousValue)) { // If we have not already scheduled the top level onChangesQueue handler then do so now if (!onChangesQueue) { scope.$$postDigest(flushOnChangesQueue); diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index 72015a3559ad..77a72d24f5c0 100755 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -4327,6 +4327,40 @@ describe('$compile', function() { }); + it('should not call `$onChanges` twice even when the initial value is `NaN`', function() { + var onChangesSpy = jasmine.createSpy('$onChanges'); + + module(function($compileProvider) { + $compileProvider.component('test', { + bindings: {prop: '<', attr: '@'}, + controller: function TestController() { + this.$onChanges = onChangesSpy; + } + }); + }); + + inject(function($compile, $rootScope) { + var template = '' + + ''; + $rootScope.a = 'foo'; + $rootScope.b = NaN; + + element = $compile(template)($rootScope); + $rootScope.$digest(); + + expect(onChangesSpy).toHaveBeenCalledTimes(2); + expect(onChangesSpy.calls.argsFor(0)[0]).toEqual({ + prop: jasmine.objectContaining({currentValue: 'foo'}), + attr: jasmine.objectContaining({currentValue: 'foo'}) + }); + expect(onChangesSpy.calls.argsFor(1)[0]).toEqual({ + prop: jasmine.objectContaining({currentValue: NaN}), + attr: jasmine.objectContaining({currentValue: 'NaN'}) + }); + }); + }); + + it('should only trigger one extra digest however many controllers have changes', function() { var log = []; function TestController1() { }