Deprecate multiple calls to done callbacks
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user