fix($log): don't parse error stacks manually outside of IE/Edge
IE/Edge display errors in such a way that it requires the user to click in 4 places to see the stack trace. There is no way to feature-detect it so there's a chance of the user agent sniffing to go wrong but since it's only about logging, this shouldn't break apps. Other browsers display errors in a sensible way and some of them map stack traces along source maps if available so it makes sense to let browsers display it as they want. Fixes #15590 Closes #15767
This commit is contained in:
+10
-1
@@ -67,6 +67,15 @@ function $LogProvider() {
|
||||
};
|
||||
|
||||
this.$get = ['$window', function($window) {
|
||||
// Support: IE 9-11, Edge 12-14+
|
||||
// IE/Edge display errors in such a way that it requires the user to click in 4 places
|
||||
// to see the stack trace. There is no way to feature-detect it so there's a chance
|
||||
// of the user agent sniffing to go wrong but since it's only about logging, this shouldn't
|
||||
// break apps. Other browsers display errors in a sensible way and some of them map stack
|
||||
// traces along source maps if available so it makes sense to let browsers display it
|
||||
// as they want.
|
||||
var formatStackTrace = msie || /\bEdge\//.test($window.navigator && $window.navigator.userAgent);
|
||||
|
||||
return {
|
||||
/**
|
||||
* @ngdoc method
|
||||
@@ -124,7 +133,7 @@ function $LogProvider() {
|
||||
|
||||
function formatError(arg) {
|
||||
if (arg instanceof Error) {
|
||||
if (arg.stack) {
|
||||
if (arg.stack && formatStackTrace) {
|
||||
arg = (arg.message && arg.stack.indexOf(arg.message) === -1)
|
||||
? 'Error: ' + arg.message + '\n' + arg.stack
|
||||
: arg.stack;
|
||||
|
||||
+39
-23
@@ -7,7 +7,10 @@ describe('$log', function() {
|
||||
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$window = {navigator: {}, document: {}};
|
||||
$window = {
|
||||
navigator: {userAgent: window.navigator.userAgent},
|
||||
document: {}
|
||||
};
|
||||
logger = '';
|
||||
log = function() { logger += 'log;'; };
|
||||
warn = function() { logger += 'warn;'; };
|
||||
@@ -64,6 +67,13 @@ describe('$log', function() {
|
||||
}
|
||||
));
|
||||
|
||||
it('should work if $window.navigator not defined', inject(
|
||||
function() {
|
||||
delete $window.navigator;
|
||||
},
|
||||
function($log) {}
|
||||
));
|
||||
|
||||
describe('IE logging behavior', function() {
|
||||
function removeApplyFunctionForIE() {
|
||||
log.apply = log.call =
|
||||
@@ -131,12 +141,12 @@ describe('$log', function() {
|
||||
$log.debug();
|
||||
expect(logger).toEqual('log;warn;info;error;');
|
||||
}
|
||||
));
|
||||
));
|
||||
|
||||
});
|
||||
|
||||
describe('$log.error', function() {
|
||||
var e, $log, errorArgs;
|
||||
var e, $log;
|
||||
|
||||
function TestError() {
|
||||
Error.prototype.constructor.apply(this, arguments);
|
||||
@@ -148,38 +158,44 @@ describe('$log', function() {
|
||||
TestError.prototype = Object.create(Error.prototype);
|
||||
TestError.prototype.constructor = TestError;
|
||||
|
||||
beforeEach(function() {
|
||||
e = new TestError('');
|
||||
var mockWindow = {
|
||||
console: {
|
||||
error: function() {
|
||||
errorArgs = [].slice.call(arguments, 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
$log = new $LogProvider().$get[1](mockWindow);
|
||||
});
|
||||
beforeEach(inject(
|
||||
function() {
|
||||
e = new TestError('');
|
||||
$window.console = {
|
||||
error: jasmine.createSpy('error')
|
||||
};
|
||||
},
|
||||
|
||||
function(_$log_) {
|
||||
$log = _$log_;
|
||||
}
|
||||
));
|
||||
|
||||
it('should pass error if does not have trace', function() {
|
||||
$log.error('abc', e);
|
||||
expect(errorArgs).toEqual(['abc', e]);
|
||||
});
|
||||
|
||||
|
||||
it('should print stack', function() {
|
||||
e.stack = 'stack';
|
||||
$log.error('abc', e);
|
||||
expect(errorArgs).toEqual(['abc', 'stack']);
|
||||
expect($window.console.error).toHaveBeenCalledWith('abc', e);
|
||||
});
|
||||
|
||||
if (msie || /\bEdge\//.test(window.navigator.userAgent)) {
|
||||
it('should print stack', function() {
|
||||
e.stack = 'stack';
|
||||
$log.error('abc', e);
|
||||
expect($window.console.error).toHaveBeenCalledWith('abc', 'stack');
|
||||
});
|
||||
} else {
|
||||
it('should print a raw error', function() {
|
||||
e.stack = 'stack';
|
||||
$log.error('abc', e);
|
||||
expect($window.console.error).toHaveBeenCalledWith('abc', e);
|
||||
});
|
||||
}
|
||||
|
||||
it('should print line', function() {
|
||||
e.message = 'message';
|
||||
e.sourceURL = 'sourceURL';
|
||||
e.line = '123';
|
||||
$log.error('abc', e);
|
||||
expect(errorArgs).toEqual(['abc', 'message\nsourceURL:123']);
|
||||
expect($window.console.error).toHaveBeenCalledWith('abc', 'message\nsourceURL:123');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user