Deprecate multiple calls to done callbacks

This commit is contained in:
Steve Gravrock
2021-09-08 20:44:27 -07:00
parent 7944250290
commit be23836c9d
12 changed files with 553 additions and 74 deletions

View File

@@ -5,10 +5,14 @@ getJasmineRequireObj().QueueRunner = function(j$) {
StopExecutionError.prototype = new Error();
j$.StopExecutionError = StopExecutionError;
function once(fn) {
function once(fn, onTwice) {
var called = false;
return function(arg) {
if (!called) {
if (called) {
if (onTwice) {
onTwice();
}
} else {
called = true;
// Direct call using single parameter, because cleanup/next does not need more
fn(arg);
@@ -17,6 +21,16 @@ getJasmineRequireObj().QueueRunner = function(j$) {
};
}
function fallbackOnMultipleDone() {
console.error(
new Error(
"An asynchronous function called its 'done' " +
'callback more than once, in a QueueRunner without a onMultipleDone ' +
'handler.'
)
);
}
function emptyFn() {}
function QueueRunner(attrs) {
@@ -31,6 +45,7 @@ getJasmineRequireObj().QueueRunner = function(j$) {
fn();
};
this.onException = attrs.onException || emptyFn;
this.onMultipleDone = attrs.onMultipleDone || fallbackOnMultipleDone;
this.userContext = attrs.userContext || new j$.UserContext();
this.timeout = attrs.timeout || {
setTimeout: setTimeout,
@@ -88,6 +103,8 @@ getJasmineRequireObj().QueueRunner = function(j$) {
var self = this,
completedSynchronously = true,
handleError = function handleError(error) {
// TODO probably shouldn't next() right away here.
// That makes debugging async failures much more confusing.
onException(error);
next(error);
},
@@ -97,37 +114,52 @@ getJasmineRequireObj().QueueRunner = function(j$) {
}
self.globalErrors.popListener(handleError);
}),
next = once(function next(err) {
cleanup();
next = once(
function next(err) {
cleanup();
if (j$.isError_(err)) {
if (!(err instanceof StopExecutionError) && !err.jasmineMessage) {
self.fail(err);
if (j$.isError_(err)) {
if (!(err instanceof StopExecutionError) && !err.jasmineMessage) {
self.fail(err);
}
self.errored = errored = true;
} else if (typeof err !== 'undefined' && !self.errored) {
self.deprecated(
'Any argument passed to a done callback will be treated as an ' +
'error in a future release. Call the done callback without ' +
"arguments if you don't want to trigger a spec failure."
);
}
self.errored = errored = true;
} else if (typeof err !== 'undefined' && !self.errored) {
self.deprecated(
'Any argument passed to a done callback will be treated as an ' +
'error in a future release. Call the done callback without ' +
"arguments if you don't want to trigger a spec failure."
);
}
function runNext() {
if (self.completeOnFirstError && errored) {
self.skipToCleanup(iterativeIndex);
function runNext() {
if (self.completeOnFirstError && errored) {
self.skipToCleanup(iterativeIndex);
} else {
self.run(iterativeIndex + 1);
}
}
if (completedSynchronously) {
self.setTimeout(runNext);
} else {
self.run(iterativeIndex + 1);
runNext();
}
},
function() {
try {
if (!timedOut) {
self.onMultipleDone();
}
} catch (error) {
// Any error we catch here is probably due to a bug in Jasmine,
// and it's not likely to end up anywhere useful if we let it
// propagate. Log it so it can at least show up when debugging.
console.error(error);
}
}
if (completedSynchronously) {
self.setTimeout(runNext);
} else {
runNext();
}
}),
),
errored = false,
timedOut = false,
queueableFn = self.queueableFns[iterativeIndex],
timeoutId,
maybeThenable;
@@ -143,6 +175,7 @@ getJasmineRequireObj().QueueRunner = function(j$) {
if (queueableFn.timeout !== undefined) {
var timeoutInterval = queueableFn.timeout || j$.DEFAULT_TIMEOUT_INTERVAL;
timeoutId = self.setTimeout(function() {
timedOut = true;
var error = new Error(
'Timeout - Async function did not complete within ' +
timeoutInterval +
@@ -151,6 +184,9 @@ getJasmineRequireObj().QueueRunner = function(j$) {
? '(custom timeout)'
: '(set by jasmine.DEFAULT_TIMEOUT_INTERVAL)')
);
// TODO Need to decide what to do about a successful completion after a
// timeout. That should probably not be a deprecation, and maybe not
// an error in 4.0. (But a diagnostic of some sort might be helpful.)
onException(error);
next();
}, timeoutInterval);