Expose browser errors uniformly outside of GlobalErrors
This commit is contained in:
@@ -67,14 +67,14 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
|
||||
if (!envOptions.suppressLoadErrors) {
|
||||
installGlobalErrors();
|
||||
globalErrors.pushListener(function loadtimeErrorHandler(error, event) {
|
||||
globalErrors.pushListener(function loadtimeErrorHandler(error) {
|
||||
topSuite.result.failedExpectations.push({
|
||||
passed: false,
|
||||
globalErrorType: 'load',
|
||||
message: error ? error.message : event.message,
|
||||
stack: error && error.stack,
|
||||
filename: event && event.filename,
|
||||
lineno: event && event.lineno
|
||||
message: error.message,
|
||||
stack: error.stack,
|
||||
filename: error.filename,
|
||||
lineno: error.lineno
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -40,13 +40,6 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
|
||||
this.#adapter.uninstall();
|
||||
}
|
||||
|
||||
// The listener at the top of the stack will be called with two arguments:
|
||||
// the error and the event. Either of them may be falsy.
|
||||
// The error will normally be provided, but will be falsy in the case of
|
||||
// some browser load-time errors. The event will normally be provided in
|
||||
// browsers but will be falsy in Node.
|
||||
// Listeners that are pushed after spec files have been loaded should be
|
||||
// able to just use the error parameter.
|
||||
pushListener(listener) {
|
||||
this.#handlers.push(listener);
|
||||
}
|
||||
@@ -78,29 +71,23 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
|
||||
}
|
||||
|
||||
reportUnhandledRejections() {
|
||||
for (const {
|
||||
reason,
|
||||
event
|
||||
} of this.#pendingUnhandledRejections.values()) {
|
||||
this.#dispatchError(reason, event);
|
||||
for (const { reason } of this.#pendingUnhandledRejections.values()) {
|
||||
this.#dispatchError(reason);
|
||||
}
|
||||
|
||||
this.#pendingUnhandledRejections.clear();
|
||||
}
|
||||
|
||||
// Either error or event may be undefined
|
||||
#onUncaughtException(error, event) {
|
||||
this.#dispatchError(error, event);
|
||||
#onUncaughtException(error) {
|
||||
this.#dispatchError(error);
|
||||
}
|
||||
|
||||
// event or promise may be undefined
|
||||
// event is passed through for backwards compatibility reasons. It's probably
|
||||
// unnecessary, but user code could depend on it.
|
||||
#onUnhandledRejection(reason, promise, event) {
|
||||
// promise may be undefined
|
||||
#onUnhandledRejection(reason, promise) {
|
||||
if (this.#detectLateRejectionHandling() && promise) {
|
||||
this.#pendingUnhandledRejections.set(promise, { reason, event });
|
||||
this.#pendingUnhandledRejections.set(promise, { reason });
|
||||
} else {
|
||||
this.#dispatchError(reason, event);
|
||||
this.#dispatchError(reason);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,8 +99,7 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
|
||||
this.#pendingUnhandledRejections.delete(promise);
|
||||
}
|
||||
|
||||
// Either error or event may be undefined
|
||||
#dispatchError(error, event) {
|
||||
#dispatchError(error) {
|
||||
if (this.#overrideHandler) {
|
||||
// See discussion of spyOnGlobalErrorsAsync in base.js
|
||||
this.#overrideHandler(error);
|
||||
@@ -123,7 +109,7 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
|
||||
const handler = this.#handlers[this.#handlers.length - 1];
|
||||
|
||||
if (handler) {
|
||||
handler(error, event);
|
||||
handler(error);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
@@ -140,7 +126,7 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
|
||||
constructor(global, dispatch) {
|
||||
this.#global = global;
|
||||
this.#dispatch = dispatch;
|
||||
this.#onError = event => dispatch.onUncaughtException(event.error, event);
|
||||
this.#onError = this.#errorHandler.bind(this);
|
||||
this.#onUnhandledRejection = this.#unhandledRejectionHandler.bind(this);
|
||||
this.#onRejectionHandled = this.#rejectionHandledHandler.bind(this);
|
||||
}
|
||||
@@ -169,6 +155,28 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
|
||||
);
|
||||
}
|
||||
|
||||
#errorHandler(event) {
|
||||
let error = event.error;
|
||||
|
||||
// event.error isn't guaranteed to be present in all browser load-time
|
||||
// error events.
|
||||
if (!error) {
|
||||
error = {
|
||||
message: event.message,
|
||||
stack: `@${event.filename}:${event.lineno}`
|
||||
};
|
||||
}
|
||||
|
||||
if (event.filename) {
|
||||
// filename and lineno can be more convenient than stack when reporting
|
||||
// things like syntax errors. Pass them along.
|
||||
error.filename = event.filename;
|
||||
error.lineno = event.lineno;
|
||||
}
|
||||
|
||||
this.#dispatch.onUncaughtException(error);
|
||||
}
|
||||
|
||||
#unhandledRejectionHandler(event) {
|
||||
const jasmineMessage = 'Unhandled promise rejection: ' + event.reason;
|
||||
let reason;
|
||||
@@ -180,7 +188,7 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
|
||||
reason = jasmineMessage;
|
||||
}
|
||||
|
||||
this.#dispatch.onUnhandledRejection(reason, event.promise, event);
|
||||
this.#dispatch.onUnhandledRejection(reason, event.promise);
|
||||
}
|
||||
|
||||
#rejectionHandledHandler(event) {
|
||||
|
||||
@@ -77,8 +77,8 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
||||
}
|
||||
|
||||
QueueRunner.prototype.execute = function() {
|
||||
this.handleFinalError = (error, event) => {
|
||||
this.onException(errorOrMsgForGlobalError(error, event));
|
||||
this.handleFinalError = error => {
|
||||
this.onException(error);
|
||||
};
|
||||
this.globalErrors.pushListener(this.handleFinalError);
|
||||
this.run(0);
|
||||
@@ -108,8 +108,8 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
||||
this.recordError_(iterativeIndex);
|
||||
};
|
||||
|
||||
function handleError(error, event) {
|
||||
onException(errorOrMsgForGlobalError(error, event));
|
||||
function handleError(error) {
|
||||
onException(error);
|
||||
}
|
||||
const cleanup = once(() => {
|
||||
if (timeoutId !== void 0) {
|
||||
@@ -296,16 +296,5 @@ getJasmineRequireObj().QueueRunner = function(j$) {
|
||||
};
|
||||
}
|
||||
|
||||
function errorOrMsgForGlobalError(error, event) {
|
||||
// TODO: In cases where error is a string or undefined, the error message
|
||||
// that gets sent to reporters will be `${message} thrown`, which could
|
||||
// be improved to not say "thrown" when the cause wasn't necessarily
|
||||
// an exception or to provide hints about throwing Errors rather than
|
||||
// strings.
|
||||
return (
|
||||
error || (event && event.message) || 'Global error event with no message'
|
||||
);
|
||||
}
|
||||
|
||||
return QueueRunner;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user