Have QueueRunner run specs iteratively if possible, fallback to recursion for async specs

This prevents the stack from growing as large for the normal cases and is giving a significant speedup for the performance suite
This commit is contained in:
Davis W. Frank and Sheel Choksi
2013-07-02 16:05:26 -07:00
parent 264b1fea50
commit 09fe7b0540
4 changed files with 44 additions and 31 deletions

View File

@@ -1299,19 +1299,26 @@ getJasmineRequireObj().QueueRunner = function() {
this.run(this.fns, 0);
};
QueueRunner.prototype.run = function(fns, index) {
if (index >= fns.length) {
this.clearStack(this.onComplete);
return;
QueueRunner.prototype.run = function(fns, recursiveIndex) {
var length = fns.length,
self = this,
iterativeIndex;
for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) {
var fn = fns[iterativeIndex];
if (fn.length > 0) {
attempt(function() { fn.call(self, function() {
self.clearStack(function() { self.run(fns, iterativeIndex + 1); });
});
});
return;
} else {
attempt(function() { fn.call(self); });
}
}
var fn = fns[index];
var self = this;
if (fn.length > 0) {
attempt(function() { fn.call(self, function() { self.run(fns, index + 1); }); });
} else {
attempt(function() { fn.call(self); });
self.run(fns, index + 1);
if (iterativeIndex >= length) {
this.onComplete();
}
function attempt(fn) {
@@ -1549,9 +1556,7 @@ getJasmineRequireObj().Suite = function() {
}
function wrapChild(child) {
return function(done) {
child.execute(done);
};
return function() { child.execute(); };
}
};

View File

@@ -115,8 +115,8 @@ describe("QueueRunner", function() {
expect(completeCallback).toHaveBeenCalled();
});
it("calls a provided garbage collection function with the complete callback when done", function() {
var fn = jasmine.createSpy('fn'),
it("calls a provided stack clearing function when done with async specs", function() {
var fn = function(done) { done() },
completeCallback = jasmine.createSpy('completeCallback'),
clearStack = jasmine.createSpy('clearStack'),
queueRunner = new j$.QueueRunner({
@@ -125,8 +125,11 @@ describe("QueueRunner", function() {
onComplete: completeCallback
});
clearStack.andCallFake(function(fn) { fn(); });
queueRunner.execute();
expect(clearStack).toHaveBeenCalledWith(completeCallback);
expect(clearStack).toHaveBeenCalled();
expect(completeCallback).toHaveBeenCalled();
});
});

View File

@@ -12,19 +12,26 @@ getJasmineRequireObj().QueueRunner = function() {
this.run(this.fns, 0);
};
QueueRunner.prototype.run = function(fns, index) {
if (index >= fns.length) {
this.clearStack(this.onComplete);
return;
QueueRunner.prototype.run = function(fns, recursiveIndex) {
var length = fns.length,
self = this,
iterativeIndex;
for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) {
var fn = fns[iterativeIndex];
if (fn.length > 0) {
attempt(function() { fn.call(self, function() {
self.clearStack(function() { self.run(fns, iterativeIndex + 1); });
});
});
return;
} else {
attempt(function() { fn.call(self); });
}
}
var fn = fns[index];
var self = this;
if (fn.length > 0) {
attempt(function() { fn.call(self, function() { self.run(fns, index + 1); }); });
} else {
attempt(function() { fn.call(self); });
self.run(fns, index + 1);
if (iterativeIndex >= length) {
this.onComplete();
}
function attempt(fn) {

View File

@@ -93,9 +93,7 @@ getJasmineRequireObj().Suite = function() {
}
function wrapChild(child) {
return function(done) {
child.execute(done);
};
return function() { child.execute(); };
}
};