Permalink
Comparing changes
Open a pull request
- 2 commits
- 6 files changed
- 0 commit comments
- 2 contributors
Commits on May 27, 2016
Unified
Split
Showing
with
276 additions
and 121 deletions.
- +3 −0 angularFiles.js
- +19 −3 src/ng/compile.js
- +6 −1 test/helpers/matchers.js
- +127 −0 test/ng/compileSpec.js
- +117 −117 test/ngAnimate/animateCssSpec.js
- +4 −0 test/ngMessages/messagesSpec.js
| @@ -175,6 +175,7 @@ var angularFiles = { | ||
| 'test/auto/*.js', | ||
| 'test/ng/**/*.js', | ||
| 'test/ngAnimate/*.js', | ||
| 'test/ngMessageFormat/*.js', | ||
| 'test/ngMessages/*.js', | ||
| 'test/ngCookies/*.js', | ||
| 'test/ngResource/*.js', | ||
| @@ -212,7 +213,9 @@ var angularFiles = { | ||
| 'test/modules/no_bootstrap.js', | ||
| 'src/ngScenario/browserTrigger.js', | ||
| 'test/helpers/*.js', | ||
| 'test/ngAnimate/*.js', | ||
| 'test/ngMessageFormat/*.js', | ||
| 'test/ngMessages/*.js', | ||
| 'test/ngMock/*.js', | ||
| 'test/ngCookies/*.js', | ||
| 'test/ngRoute/**/*.js', | ||
| @@ -1311,11 +1311,19 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { | ||
| } | ||
| // We must run this hook in an apply since the $$postDigest runs outside apply | ||
| $rootScope.$apply(function() { | ||
| var errors = []; | ||
| for (var i = 0, ii = onChangesQueue.length; i < ii; ++i) { | ||
| onChangesQueue[i](); | ||
| try { | ||
| onChangesQueue[i](); | ||
| } catch (e) { | ||
| errors.push(e); | ||
| } | ||
| } | ||
| // Reset the queue to trigger a new schedule next time there is a change | ||
| onChangesQueue = undefined; | ||
| if (errors.length) { | ||
| throw errors; | ||
| } | ||
| }); | ||
| } finally { | ||
| onChangesTtl++; | ||
| @@ -2491,10 +2499,18 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { | ||
| forEach(elementControllers, function(controller) { | ||
| var controllerInstance = controller.instance; | ||
| if (isFunction(controllerInstance.$onChanges)) { | ||
| controllerInstance.$onChanges(controller.bindingInfo.initialChanges); | ||
| try { | ||
| controllerInstance.$onChanges(controller.bindingInfo.initialChanges); | ||
| } catch (e) { | ||
| $exceptionHandler(e); | ||
| } | ||
| } | ||
| if (isFunction(controllerInstance.$onInit)) { | ||
| controllerInstance.$onInit(); | ||
| try { | ||
| controllerInstance.$onInit(); | ||
| } catch (e) { | ||
| $exceptionHandler(e); | ||
| } | ||
| } | ||
| if (isFunction(controllerInstance.$onDestroy)) { | ||
| controllerScope.$on('$destroy', function callOnDestroyHook() { | ||
| @@ -233,14 +233,19 @@ beforeEach(function() { | ||
| compare: generateCompare(false), | ||
| negativeCompare: generateCompare(true) | ||
| }; | ||
| function hasClass(element, selector) { | ||
| if (!element.getAttribute) return false; | ||
| return ((" " + (element.getAttribute('class') || '') + " ").replace(/[\n\t]/g, " "). | ||
| indexOf(" " + selector + " ") > -1); | ||
| } | ||
| function generateCompare(isNot) { | ||
| return function(actual, clazz) { | ||
| var message = function() { | ||
| return "Expected '" + angular.mock.dump(actual) + "'" + (isNot ? " not " : "") + " to have class '" + clazz + "'."; | ||
| }; | ||
| var classes = clazz.trim().split(/\s+/); | ||
| for (var i = 0; i < classes.length; ++i) { | ||
| if (!jqLiteHasClass(actual[0], classes[i])) { | ||
| if (!hasClass(actual[0], classes[i])) { | ||
| return { pass: isNot }; | ||
| } | ||
| } | ||
| @@ -3650,6 +3650,46 @@ describe('$compile', function() { | ||
| expect(Controller2.prototype.$onInit).toHaveBeenCalledOnce(); | ||
| }); | ||
| }); | ||
|
|
||
| it('should continue to trigger other `$onInit` hooks if one throws an error', function() { | ||
| function ThrowingController() { | ||
| this.$onInit = function() { | ||
| throw new Error('bad hook'); | ||
| }; | ||
| } | ||
| function LoggingController($log) { | ||
| this.$onInit = function() { | ||
| $log.info('onInit'); | ||
| }; | ||
| } | ||
|
|
||
| angular.module('my', []) | ||
| .component('c1', { | ||
| controller: ThrowingController, | ||
| bindings: {'prop': '<'} | ||
| }) | ||
| .component('c2', { | ||
| controller: LoggingController, | ||
| bindings: {'prop': '<'} | ||
| }) | ||
| .config(function($exceptionHandlerProvider) { | ||
| // We need to test with the exceptionHandler not rethrowing... | ||
| $exceptionHandlerProvider.mode('log'); | ||
| }); | ||
|
|
||
| module('my'); | ||
| inject(function($compile, $rootScope, $exceptionHandler, $log) { | ||
|
|
||
| // Setup the directive with bindings that will keep updating the bound value forever | ||
| element = $compile('<div><c1 prop="a"></c1><c2 prop="a"></c2>')($rootScope); | ||
|
|
||
| // The first component's error should be logged | ||
| expect($exceptionHandler.errors.pop()).toEqual(new Error('bad hook')); | ||
|
|
||
| // The second component's hook should still be called | ||
| expect($log.info.logs.pop()).toEqual(['onInit']); | ||
| }); | ||
| }); | ||
| }); | ||
|
|
||
|
|
||
| @@ -4121,6 +4161,93 @@ describe('$compile', function() { | ||
| expect($exceptionHandler.errors[0].toString()).toContain('[$compile:infchng] 10 $onChanges() iterations reached.'); | ||
| }); | ||
| }); | ||
|
|
||
|
|
||
| it('should continue to trigger other `$onChanges` hooks if one throws an error', function() { | ||
| function ThrowingController() { | ||
| this.$onChanges = function(change) { | ||
| throw new Error('bad hook'); | ||
| }; | ||
| } | ||
| function LoggingController($log) { | ||
| this.$onChanges = function(change) { | ||
| $log.info('onChange'); | ||
| }; | ||
| } | ||
|
|
||
| angular.module('my', []) | ||
| .component('c1', { | ||
| controller: ThrowingController, | ||
| bindings: {'prop': '<'} | ||
| }) | ||
| .component('c2', { | ||
| controller: LoggingController, | ||
| bindings: {'prop': '<'} | ||
| }) | ||
| .config(function($exceptionHandlerProvider) { | ||
| // We need to test with the exceptionHandler not rethrowing... | ||
| $exceptionHandlerProvider.mode('log'); | ||
| }); | ||
|
|
||
| module('my'); | ||
| inject(function($compile, $rootScope, $exceptionHandler, $log) { | ||
|
|
||
| // Setup the directive with bindings that will keep updating the bound value forever | ||
| element = $compile('<div><c1 prop="a"></c1><c2 prop="a"></c2>')($rootScope); | ||
|
|
||
| // The first component's error should be logged | ||
| expect($exceptionHandler.errors.pop()).toEqual(new Error('bad hook')); | ||
|
|
||
| // The second component's changes should still be called | ||
| expect($log.info.logs.pop()).toEqual(['onChange']); | ||
|
|
||
| $rootScope.$apply('a = 42'); | ||
|
|
||
| // The first component's error should be logged | ||
| var errors = $exceptionHandler.errors.pop(); | ||
| expect(errors[0]).toEqual(new Error('bad hook')); | ||
|
|
||
| // The second component's changes should still be called | ||
| expect($log.info.logs.pop()).toEqual(['onChange']); | ||
| }); | ||
| }); | ||
|
|
||
|
|
||
| it('should collect up all `$onChanges` errors into one throw', function() { | ||
| function ThrowingController() { | ||
| this.$onChanges = function(change) { | ||
| throw new Error('bad hook: ' + this.prop); | ||
| }; | ||
| } | ||
|
|
||
| angular.module('my', []) | ||
| .component('c1', { | ||
| controller: ThrowingController, | ||
| bindings: {'prop': '<'} | ||
| }) | ||
| .config(function($exceptionHandlerProvider) { | ||
| // We need to test with the exceptionHandler not rethrowing... | ||
| $exceptionHandlerProvider.mode('log'); | ||
| }); | ||
|
|
||
| module('my'); | ||
| inject(function($compile, $rootScope, $exceptionHandler, $log) { | ||
|
|
||
| // Setup the directive with bindings that will keep updating the bound value forever | ||
| element = $compile('<div><c1 prop="a"></c1><c1 prop="a * 2"></c1>')($rootScope); | ||
|
|
||
| // Both component's errors should be logged | ||
| expect($exceptionHandler.errors.pop()).toEqual(new Error('bad hook: NaN')); | ||
| expect($exceptionHandler.errors.pop()).toEqual(new Error('bad hook: undefined')); | ||
|
|
||
| $rootScope.$apply('a = 42'); | ||
|
|
||
| // Both component's error should be logged | ||
| var errors = $exceptionHandler.errors.pop(); | ||
| expect(errors.pop()).toEqual(new Error('bad hook: 84')); | ||
| expect(errors.pop()).toEqual(new Error('bad hook: 42')); | ||
| }); | ||
| }); | ||
| }); | ||
| }); | ||
|
|
||
Oops, something went wrong.