Break into a setTimeout every once in a while
- Allows the CPU to run other things that used the real `setTimeout` - Fixes #1327 - See #1334 - Fixes jasmine/gulp-jasmine-browser#48
This commit is contained in:
@@ -21,6 +21,30 @@ describe("ClearStack", function() {
|
|||||||
expect(setImmediate).toHaveBeenCalled();
|
expect(setImmediate).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("uses setTimeout instead of setImmediate every 10 calls to make sure we release the CPU", function() {
|
||||||
|
var setImmediate = jasmine.createSpy('setImmediate'),
|
||||||
|
setTimeout = jasmine.createSpy('setTimeout'),
|
||||||
|
global = { setImmediate: setImmediate, setTimeout: setTimeout },
|
||||||
|
clearStack = jasmineUnderTest.getClearStack(global);
|
||||||
|
|
||||||
|
clearStack(function() { });
|
||||||
|
clearStack(function() { });
|
||||||
|
clearStack(function() { });
|
||||||
|
clearStack(function() { });
|
||||||
|
clearStack(function() { });
|
||||||
|
clearStack(function() { });
|
||||||
|
clearStack(function() { });
|
||||||
|
clearStack(function() { });
|
||||||
|
clearStack(function() { });
|
||||||
|
|
||||||
|
expect(setImmediate).toHaveBeenCalled();
|
||||||
|
expect(setTimeout).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
clearStack(function() { });
|
||||||
|
expect(setImmediate.calls.count()).toEqual(9);
|
||||||
|
expect(setTimeout).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
it("uses MessageChannels when available", function() {
|
it("uses MessageChannels when available", function() {
|
||||||
var fakeChannel = {
|
var fakeChannel = {
|
||||||
port1: {},
|
port1: {},
|
||||||
@@ -37,6 +61,37 @@ describe("ClearStack", function() {
|
|||||||
expect(called).toBe(true);
|
expect(called).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("uses setTimeout instead of MessageChannel every 10 calls to make sure we release the CPU", function() {
|
||||||
|
var fakeChannel = {
|
||||||
|
port1: {},
|
||||||
|
port2: {
|
||||||
|
postMessage: jasmine.createSpy('postMessage').and.callFake(function() {
|
||||||
|
fakeChannel.port1.onmessage();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setTimeout = jasmine.createSpy('setTimeout'),
|
||||||
|
global = { MessageChannel: function() { return fakeChannel; }, setTimeout: setTimeout },
|
||||||
|
clearStack = jasmineUnderTest.getClearStack(global);
|
||||||
|
|
||||||
|
clearStack(function() { });
|
||||||
|
clearStack(function() { });
|
||||||
|
clearStack(function() { });
|
||||||
|
clearStack(function() { });
|
||||||
|
clearStack(function() { });
|
||||||
|
clearStack(function() { });
|
||||||
|
clearStack(function() { });
|
||||||
|
clearStack(function() { });
|
||||||
|
clearStack(function() { });
|
||||||
|
|
||||||
|
expect(fakeChannel.port2.postMessage).toHaveBeenCalled();
|
||||||
|
expect(setTimeout).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
clearStack(function() { });
|
||||||
|
expect(fakeChannel.port2.postMessage.calls.count()).toEqual(9);
|
||||||
|
expect(setTimeout).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
it("calls setTimeout when onmessage is called recursively", function() {
|
it("calls setTimeout when onmessage is called recursively", function() {
|
||||||
var fakeChannel = {
|
var fakeChannel = {
|
||||||
port1: {},
|
port1: {},
|
||||||
|
|||||||
@@ -952,16 +952,15 @@ describe("Env integration", function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("with a mock clock", function() {
|
describe("with a mock clock", function() {
|
||||||
var originalTimeout;
|
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
originalTimeout = jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL;
|
this.originalTimeout = jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL;
|
||||||
|
this.realSetTimeout = window.setTimeout;
|
||||||
jasmine.clock().install();
|
jasmine.clock().install();
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
jasmine.clock().uninstall();
|
jasmine.clock().uninstall();
|
||||||
jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
|
jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL = this.originalTimeout;
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should wait a specified interval before failing specs haven't called done yet", function(done) {
|
it("should wait a specified interval before failing specs haven't called done yet", function(done) {
|
||||||
@@ -1079,7 +1078,8 @@ describe("Env integration", function() {
|
|||||||
|
|
||||||
it('should wait a custom interval before reporting async functions that fail to call done', function(done) {
|
it('should wait a custom interval before reporting async functions that fail to call done', function(done) {
|
||||||
var env = new jasmineUnderTest.Env(),
|
var env = new jasmineUnderTest.Env(),
|
||||||
reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone', 'suiteDone', 'specDone']);
|
reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone', 'suiteDone', 'specDone']),
|
||||||
|
realSetTimeout = this.realSetTimeout;
|
||||||
|
|
||||||
reporter.jasmineDone.and.callFake(function() {
|
reporter.jasmineDone.and.callFake(function() {
|
||||||
expect(reporter.specDone).toHaveFailedExpecationsForRunnable('suite beforeAll times out', [
|
expect(reporter.specDone).toHaveFailedExpecationsForRunnable('suite beforeAll times out', [
|
||||||
@@ -1109,6 +1109,11 @@ describe("Env integration", function() {
|
|||||||
jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL = 10000;
|
jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL = 10000;
|
||||||
|
|
||||||
env.describe('suite', function() {
|
env.describe('suite', function() {
|
||||||
|
env.afterAll(function() {
|
||||||
|
realSetTimeout(function() {
|
||||||
|
jasmine.clock().tick(10);
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
env.describe('beforeAll', function() {
|
env.describe('beforeAll', function() {
|
||||||
env.beforeAll(function(innerDone) {
|
env.beforeAll(function(innerDone) {
|
||||||
jasmine.clock().tick(5001);
|
jasmine.clock().tick(5001);
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
getJasmineRequireObj().clearStack = function(j$) {
|
getJasmineRequireObj().clearStack = function(j$) {
|
||||||
function messageChannelImpl(global) {
|
var maxInlineCallCount = 10;
|
||||||
|
|
||||||
|
function messageChannelImpl(global, setTimeout) {
|
||||||
var channel = new global.MessageChannel(),
|
var channel = new global.MessageChannel(),
|
||||||
head = {},
|
head = {},
|
||||||
tail = head;
|
tail = head;
|
||||||
@@ -22,25 +24,43 @@ getJasmineRequireObj().clearStack = function(j$) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var currentCallCount = 0;
|
||||||
return function clearStack(fn) {
|
return function clearStack(fn) {
|
||||||
tail = tail.next = { task: fn };
|
currentCallCount++;
|
||||||
channel.port2.postMessage(0);
|
|
||||||
|
if (currentCallCount < maxInlineCallCount) {
|
||||||
|
tail = tail.next = { task: fn };
|
||||||
|
channel.port2.postMessage(0);
|
||||||
|
} else {
|
||||||
|
setTimeout(fn);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getClearStack(global) {
|
function getClearStack(global) {
|
||||||
|
var currentCallCount = 0;
|
||||||
|
var realSetTimeout = global.setTimeout;
|
||||||
|
var setTimeoutImpl = function clearStack(fn) {
|
||||||
|
Function.prototype.apply.apply(realSetTimeout, [global, [fn, 0]]);
|
||||||
|
};
|
||||||
|
|
||||||
if (j$.isFunction_(global.setImmediate)) {
|
if (j$.isFunction_(global.setImmediate)) {
|
||||||
var realSetImmediate = global.setImmediate;
|
var realSetImmediate = global.setImmediate;
|
||||||
return function(fn) {
|
return function(fn) {
|
||||||
realSetImmediate(fn);
|
currentCallCount++;
|
||||||
|
|
||||||
|
if (currentCallCount < maxInlineCallCount) {
|
||||||
|
realSetImmediate(fn);
|
||||||
|
} else {
|
||||||
|
currentCallCount = 0;
|
||||||
|
|
||||||
|
setTimeoutImpl(fn);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} else if (!j$.util.isUndefined(global.MessageChannel)) {
|
} else if (!j$.util.isUndefined(global.MessageChannel)) {
|
||||||
return messageChannelImpl(global);
|
return messageChannelImpl(global, setTimeoutImpl);
|
||||||
} else {
|
} else {
|
||||||
var realSetTimeout = global.setTimeout;
|
return setTimeoutImpl;
|
||||||
return function clearStack(fn) {
|
|
||||||
Function.prototype.apply.apply(realSetTimeout, [global, [fn, 0]]);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user