@@ -1,5 +1,7 @@
|
||||
getJasmineRequireObj().ExceptionFormatter = function() {
|
||||
function ExceptionFormatter() {
|
||||
getJasmineRequireObj().ExceptionFormatter = function(j$) {
|
||||
|
||||
function ExceptionFormatter(options) {
|
||||
var jasmineFile = (options && options.jasmineFile) || j$.util.jasmineFile();
|
||||
this.message = function(error) {
|
||||
var message = '';
|
||||
|
||||
@@ -21,8 +23,34 @@ getJasmineRequireObj().ExceptionFormatter = function() {
|
||||
};
|
||||
|
||||
this.stack = function(error) {
|
||||
return error ? error.stack : null;
|
||||
if (!error || !error.stack) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var stackTrace = new j$.StackTrace(error.stack);
|
||||
var lines = filterJasmine(stackTrace);
|
||||
|
||||
if (stackTrace.message) {
|
||||
lines.unshift(stackTrace.message);
|
||||
}
|
||||
|
||||
return lines.join('\n');
|
||||
};
|
||||
|
||||
function filterJasmine(stackTrace) {
|
||||
var result = [],
|
||||
jasmineMarker = stackTrace.style === 'webkit' ? '<Jasmine>' : ' at <Jasmine>';
|
||||
|
||||
stackTrace.frames.forEach(function(frame) {
|
||||
if (frame.file && frame.file !== jasmineFile) {
|
||||
result.push(frame.raw);
|
||||
} else if (result[result.length - 1] !== jasmineMarker) {
|
||||
result.push(jasmineMarker);
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return ExceptionFormatter;
|
||||
|
||||
80
src/core/StackTrace.js
Normal file
80
src/core/StackTrace.js
Normal file
@@ -0,0 +1,80 @@
|
||||
getJasmineRequireObj().StackTrace = function(j$) {
|
||||
function StackTrace(rawTrace) {
|
||||
var lines = rawTrace
|
||||
.split('\n')
|
||||
.filter(function(line) { return line !== ''; });
|
||||
|
||||
if (lines[0].match(/^Error/)) {
|
||||
this.message = lines.shift();
|
||||
} else {
|
||||
this.message = undefined;
|
||||
}
|
||||
|
||||
var parseResult = tryParseFrames(lines);
|
||||
this.frames = parseResult.frames;
|
||||
this.style = parseResult.style;
|
||||
}
|
||||
|
||||
var framePatterns = [
|
||||
// PhantomJS on Linux, Node, Chrome, IE, Edge
|
||||
// e.g. " at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)"
|
||||
// Note that the "function name" can include a surprisingly large set of
|
||||
// characters, including angle brackets and square brackets.
|
||||
{ re: /^\s*at ([^\)]+) \(([^\)]+)\)$/, fnIx: 1, fileLineColIx: 2, style: 'v8' },
|
||||
|
||||
// NodeJS alternate form, often mixed in with the Chrome style
|
||||
// e.g. " at /some/path:4320:20
|
||||
{ re: /\s*at (.+)$/, fileLineColIx: 1, style: 'v8' },
|
||||
|
||||
// PhantomJS on OS X, Safari, Firefox
|
||||
// e.g. "run@http://localhost:8888/__jasmine__/jasmine.js:4320:27"
|
||||
// or "http://localhost:8888/__jasmine__/jasmine.js:4320:27"
|
||||
{ re: /^(([^@\s]+)@)?([^\s]+)$/, fnIx: 2, fileLineColIx: 3, style: 'webkit' }
|
||||
];
|
||||
|
||||
// regexes should capture the function name (if any) as group 1
|
||||
// and the file, line, and column as group 2.
|
||||
function tryParseFrames(lines) {
|
||||
var style = null;
|
||||
var frames = lines.map(function(line) {
|
||||
var convertedLine = first(framePatterns, function(pattern) {
|
||||
var overallMatch = line.match(pattern.re),
|
||||
fileLineColMatch;
|
||||
if (!overallMatch) { return null; }
|
||||
|
||||
fileLineColMatch = overallMatch[pattern.fileLineColIx].match(
|
||||
/^(.*):(\d+):\d+$/);
|
||||
if (!fileLineColMatch) { return null; }
|
||||
|
||||
style = style || pattern.style;
|
||||
return {
|
||||
raw: line,
|
||||
file: fileLineColMatch[1],
|
||||
line: parseInt(fileLineColMatch[2], 10),
|
||||
func: overallMatch[pattern.fnIx]
|
||||
};
|
||||
});
|
||||
|
||||
return convertedLine || { raw: line };
|
||||
});
|
||||
|
||||
return {
|
||||
style: style,
|
||||
frames: frames
|
||||
};
|
||||
}
|
||||
|
||||
function first(items, fn) {
|
||||
var i, result;
|
||||
|
||||
for (i = 0; i < items.length; i++) {
|
||||
result = fn(items[i]);
|
||||
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return StackTrace;
|
||||
};
|
||||
@@ -34,7 +34,8 @@ var getJasmineRequireObj = (function (jasmineGlobal) {
|
||||
j$.Clock = jRequire.Clock();
|
||||
j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler();
|
||||
j$.Env = jRequire.Env(j$);
|
||||
j$.ExceptionFormatter = jRequire.ExceptionFormatter();
|
||||
j$.StackTrace = jRequire.StackTrace(j$);
|
||||
j$.ExceptionFormatter = jRequire.ExceptionFormatter(j$);
|
||||
j$.Expectation = jRequire.Expectation();
|
||||
j$.buildExpectationResult = jRequire.buildExpectationResult();
|
||||
j$.JsApiReporter = jRequire.JsApiReporter();
|
||||
|
||||
@@ -100,5 +100,53 @@ getJasmineRequireObj().util = function(j$) {
|
||||
return Object.prototype.hasOwnProperty.call(obj, key);
|
||||
};
|
||||
|
||||
function anyMatch(pattern, lines) {
|
||||
var i;
|
||||
|
||||
for (i = 0; i < lines.length; i++) {
|
||||
if (lines[i].match(pattern)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function errorWithStack() {
|
||||
// Don't throw and catch if we don't have to, because it makes it harder
|
||||
// for users to debug their code with exception breakpoints.
|
||||
var error = new Error();
|
||||
|
||||
if (error.stack) {
|
||||
return error;
|
||||
}
|
||||
|
||||
// But some browsers (e.g. Phantom) only provide a stack trace if we throw.
|
||||
try {
|
||||
throw new Error();
|
||||
} catch (e) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
function callerFile() {
|
||||
var trace = new j$.StackTrace(errorWithStack().stack);
|
||||
return trace.frames[2].file;
|
||||
}
|
||||
|
||||
util.jasmineFile = (function() {
|
||||
var result;
|
||||
|
||||
return function() {
|
||||
var trace;
|
||||
|
||||
if (!result) {
|
||||
result = callerFile();
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
}());
|
||||
|
||||
return util;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user