Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Commit

Permalink
fix(ngEventDirs): pass error in handler to $exceptionHandler when eve…
Browse files Browse the repository at this point in the history
…nt was triggered in a digest

This ensures that the error handling is the same for events triggered inside and outside a digest.
  • Loading branch information
Narretz committed Jul 25, 2018
1 parent 535ee32 commit 6882113
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 3 deletions.
9 changes: 7 additions & 2 deletions src/ng/directive/ngEventDirs.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ forEach(
'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '),
function(eventName) {
var directiveName = directiveNormalize('ng-' + eventName);
ngEventDirectives[directiveName] = ['$parse', '$rootScope', function($parse, $rootScope) {
ngEventDirectives[directiveName] = ['$parse', '$rootScope', '$exceptionHandler', function($parse, $rootScope, $exceptionHandler) {
return {
restrict: 'A',
compile: function($element, attr) {
Expand All @@ -64,12 +64,17 @@ forEach(
var callback = function() {
fn(scope, {$event: event});
};

if (!$rootScope.$$phase) {
scope.$apply(callback);
} else if (forceAsyncEvents[eventName]) {
scope.$evalAsync(callback);
} else {
callback();
try {
callback();
} catch (error) {
$exceptionHandler(error);
}
}
});
};
Expand Down
89 changes: 88 additions & 1 deletion test/ng/directive/ngEventDirsSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@ describe('event directives', function() {
expect($rootScope.blur).toHaveBeenCalledOnce();
expect(element.val()).toBe('newValue');
}));

});


Expand Down Expand Up @@ -190,4 +189,92 @@ describe('event directives', function() {
expect($rootScope.click).toHaveBeenCalledOnce();
expect(watchedVal).toEqual('newValue');
}));


describe('throwing errors in event handlers', function() {

it('should not stop execution if the event is triggered outside a digest', function() {

module(function($exceptionHandlerProvider) {
$exceptionHandlerProvider.mode('log');
});

inject(function($rootScope, $compile, $exceptionHandler, $log) {

element = $compile('<button ng-click="click()">Click</button>')($rootScope);
expect($log.assertEmpty());
$rootScope.click = function() {
throw new Error('listener error');
};

$rootScope.do = function() {
element.triggerHandler('click');
$log.log('done');
};

$rootScope.do();

expect($exceptionHandler.errors).toEqual([Error('listener error')]);
expect($log.log.logs).toEqual([['done']]);
$log.reset();
});
});


it('should not stop execution if the event is triggered inside a digest', function() {

module(function($exceptionHandlerProvider) {
$exceptionHandlerProvider.mode('log');
});

inject(function($rootScope, $compile, $exceptionHandler, $log) {

element = $compile('<button ng-click="click()">Click</button>')($rootScope);
expect($log.assertEmpty());
$rootScope.click = function() {
throw new Error('listener error');
};

$rootScope.do = function() {
element.triggerHandler('click');
$log.log('done');
};

$rootScope.$apply(function() {
$rootScope.do();
});

expect($exceptionHandler.errors).toEqual([Error('listener error')]);
expect($log.log.logs).toEqual([['done']]);
$log.reset();
});
});


it('should not stop execution if the event is triggered in a watch expression function', function() {

module(function($exceptionHandlerProvider) {
$exceptionHandlerProvider.mode('log');
});

inject(function($rootScope, $compile, $exceptionHandler, $log) {

element = $compile('<button ng-click="click()">Click</button>')($rootScope);
$rootScope.click = function() {
throw new Error('listener error');
};

$rootScope.$watch(function() {
element.triggerHandler('click');
$log.log('done');
});

$rootScope.$digest();

expect($exceptionHandler.errors).toEqual([Error('listener error'), Error('listener error')]);
expect($log.log.logs).toEqual([['done'], ['done']]);
$log.reset();
});
});
});
});

0 comments on commit 6882113

Please sign in to comment.