Skip to content

Commit ee7252e

Browse files
fix($compile): cope with $onInit hooks throwing
Previously, if one of these hooks threw an error, then the compilation was terminated unceremoniously. Closes angular#14444
1 parent 0400b63 commit ee7252e

File tree

2 files changed

+47
-2
lines changed

2 files changed

+47
-2
lines changed

src/ng/compile.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -2476,7 +2476,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
24762476
}
24772477
}
24782478
if (isFunction(controllerInstance.$onInit)) {
2479-
controllerInstance.$onInit();
2479+
try {
2480+
controllerInstance.$onInit();
2481+
} catch(e) {
2482+
$exceptionHandler(e);
2483+
}
24802484
}
24812485
if (isFunction(controllerInstance.$onDestroy)) {
24822486
controllerScope.$on('$destroy', function callOnDestroyHook() {

test/ng/compileSpec.js

+42-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
fdescribe('$compile', function() {
3+
describe('$compile', function() {
44
function isUnknownElement(el) {
55
return !!el.toString().match(/Unknown/);
66
}
@@ -4034,6 +4034,47 @@ fdescribe('$compile', function() {
40344034
});
40354035

40364036

4037+
it('should continue to trigger other `$onInit` hooks if one throws an error', function() {
4038+
function ThrowingController() {
4039+
this.$onInit = function() {
4040+
throw new Error('bad hook');
4041+
};
4042+
}
4043+
function LoggingController($log) {
4044+
this.$onInit = function() {
4045+
$log.info('onInit');
4046+
};
4047+
}
4048+
4049+
angular.module('my', [])
4050+
.component('c1', {
4051+
controller: ThrowingController,
4052+
bindings: {'prop': '<'}
4053+
})
4054+
.component('c2', {
4055+
controller: LoggingController,
4056+
bindings: {'prop': '<'}
4057+
})
4058+
.config(function($exceptionHandlerProvider) {
4059+
// We need to test with the exceptionHandler not rethrowing...
4060+
$exceptionHandlerProvider.mode('log');
4061+
});
4062+
4063+
module('my');
4064+
inject(function($compile, $rootScope, $exceptionHandler, $log) {
4065+
4066+
// Setup the directive with bindings that will keep updating the bound value forever
4067+
element = $compile('<div><c1 prop="a"></c1><c2 prop="a"></c2>')($rootScope);
4068+
4069+
// The first component's error should be logged
4070+
expect($exceptionHandler.errors.pop().toString()).toEqual('Error: bad hook');
4071+
4072+
// The second component's hook should still be called
4073+
expect($log.info.logs.pop()).toEqual(['onInit']);
4074+
});
4075+
});
4076+
4077+
40374078
it('should continue to trigger other `$onChanges` hooks if one throws an error', function() {
40384079
function ThrowingController() {
40394080
this.$onChanges = function(change) {

0 commit comments

Comments
 (0)