diff --git a/spec/runner.html b/spec/runner.html
new file mode 100644
index 00000000..f963bb46
--- /dev/null
+++ b/spec/runner.html
@@ -0,0 +1,76 @@
+
+
+
+ Jasmine Test Runner
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spec/suites/QueueSpec.js b/spec/suites/QueueSpec.js
new file mode 100644
index 00000000..59a70f39
--- /dev/null
+++ b/spec/suites/QueueSpec.js
@@ -0,0 +1,23 @@
+describe("jasmine.Queue", function() {
+ it("should not call itself recursively, so we don't get stack overflow errors", function() {
+ var queue = new jasmine.Queue(new jasmine.Env());
+ queue.add(new jasmine.Block(null, function() {}));
+ queue.add(new jasmine.Block(null, function() {}));
+ queue.add(new jasmine.Block(null, function() {}));
+ queue.add(new jasmine.Block(null, function() {}));
+
+ var nestCount = 0;
+ var maxNestCount = 0;
+ var nextCallCount = 0;
+ queue.next_ = function() {
+ nestCount++;
+ if (nestCount > maxNestCount) maxNestCount = nestCount;
+
+ jasmine.Queue.prototype.next_.apply(queue, arguments);
+ nestCount--;
+ };
+
+ queue.start();
+ expect(maxNestCount).toEqual(1);
+ });
+});
\ No newline at end of file
diff --git a/src/Queue.js b/src/Queue.js
index 27d3737b..c3e064a9 100644
--- a/src/Queue.js
+++ b/src/Queue.js
@@ -6,7 +6,7 @@ jasmine.Queue = function(env) {
this.offset = 0;
};
-jasmine.Queue.prototype.addBefore = function (block) {
+jasmine.Queue.prototype.addBefore = function(block) {
this.blocks.unshift(block);
};
@@ -14,59 +14,74 @@ jasmine.Queue.prototype.add = function(block) {
this.blocks.push(block);
};
-jasmine.Queue.prototype.insertNext = function (block) {
+jasmine.Queue.prototype.insertNext = function(block) {
this.blocks.splice((this.index + this.offset + 1), 0, block);
this.offset++;
};
jasmine.Queue.prototype.start = function(onComplete) {
- var self = this;
- self.running = true;
- self.onComplete = onComplete;
- if (self.blocks[0]) {
- self.blocks[0].execute(function () {
- self._next();
- });
- } else {
- self.finish();
- }
+ this.running = true;
+ this.onComplete = onComplete;
+ this.next_();
};
-jasmine.Queue.prototype.isRunning = function () {
+jasmine.Queue.prototype.isRunning = function() {
return this.running;
};
-jasmine.Queue.prototype._next = function () {
+jasmine.Queue.LOOP_DONT_RECURSE = true;
+
+jasmine.Queue.prototype.next_ = function() {
var self = this;
- var doNext = function () {
- self.offset = 0;
- self.index++;
+ var goAgain = true;
+
+ while (goAgain) {
+ goAgain = false;
+
if (self.index < self.blocks.length) {
- self.blocks[self.index].execute(function () {
- self._next();
- });
+ var calledSynchronously = true;
+ var completedSynchronously = false;
+
+ var onComplete = function () {
+ if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) {
+ completedSynchronously = true;
+ return;
+ }
+
+ self.offset = 0;
+ self.index++;
+
+ var now = new Date().getTime();
+ if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) {
+ self.env.lastUpdate = now;
+ self.env.setTimeout(function() {
+ self.next_();
+ }, 0);
+ } else {
+ if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) {
+ goAgain = true;
+ } else {
+ self.next_();
+ }
+ }
+ };
+ self.blocks[self.index].execute(onComplete);
+
+ calledSynchronously = false;
+ if (completedSynchronously) {
+ onComplete();
+ }
+
} else {
- self.finish();
+ self.running = false;
+ if (self.onComplete) {
+ self.onComplete();
+ }
}
- };
- var now = new Date().getTime();
- if (this.env.updateInterval && now - this.env.lastUpdate > this.env.updateInterval) {
- this.env.lastUpdate = now;
- this.env.setTimeout(doNext, 0);
- } else {
- doNext();
- }
-
-};
-
-jasmine.Queue.prototype.finish = function () {
- this.running = false;
- if (this.onComplete) {
- this.onComplete();
}
};
-jasmine.Queue.prototype.results = function () {
+jasmine.Queue.prototype.results = function() {
var results = new jasmine.NestedResults();
for (var i = 0; i < this.blocks.length; i++) {
if (this.blocks[i].results) {