Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26c48ab324 | ||
|
|
cfecab9f79 | ||
|
|
f934e6d816 | ||
|
|
79c6bbc189 |
31
.github/CONTRIBUTING.md
vendored
31
.github/CONTRIBUTING.md
vendored
@@ -1,19 +1,10 @@
|
|||||||
# Developing for Jasmine Core
|
# Contributing to Jasmine
|
||||||
|
|
||||||
We welcome your contributions! Thanks for helping make Jasmine a better project
|
We welcome your contributions! Thanks for helping make Jasmine a better project
|
||||||
for everyone. Please review the backlog and discussion lists before starting
|
for everyone. If you want to contribute but don't know what to work on,
|
||||||
work. What you're looking for may already have been done. If it hasn't, the
|
[issues tagged help needed](https://github.com/issues?q=is%3Aopen+is%3Aissue+org%3Ajasmine+label%3A%22help+needed%22+)
|
||||||
community can help make your contribution better. If you want to contribute but
|
|
||||||
don't know what to work on,
|
|
||||||
[issues tagged help needed](https://github.com/jasmine/jasmine/labels/help%20needed)
|
|
||||||
should have enough detail to get started.
|
should have enough detail to get started.
|
||||||
|
|
||||||
## Links
|
|
||||||
|
|
||||||
- [Jasmine Google Group](http://groups.google.com/group/jasmine-js)
|
|
||||||
- [Jasmine-dev Google Group](http://groups.google.com/group/jasmine-js-dev)
|
|
||||||
- [Jasmine backlog](https://www.pivotaltracker.com/n/projects/10606)
|
|
||||||
|
|
||||||
## Before Submitting a Pull Request
|
## Before Submitting a Pull Request
|
||||||
|
|
||||||
1. Ensure all specs are green in browsers *and* node.
|
1. Ensure all specs are green in browsers *and* node.
|
||||||
@@ -94,14 +85,7 @@ Or, How to make a successful pull request
|
|||||||
* _Write specs_ - Jasmine's a testing framework. Don't add functionality
|
* _Write specs_ - Jasmine's a testing framework. Don't add functionality
|
||||||
without test-driving it.
|
without test-driving it.
|
||||||
* _Write code in the style of the rest of the repo_ - Jasmine should look like
|
* _Write code in the style of the rest of the repo_ - Jasmine should look like
|
||||||
a cohesive whole.
|
a cohesive whole.
|
||||||
|
|
||||||
Key exceptions:
|
|
||||||
* Use `const` or `let` for new variable declarations, even if nearby code
|
|
||||||
uses `var`.
|
|
||||||
* New async specs should usually be async/await or promise-returning, not
|
|
||||||
callback based.
|
|
||||||
|
|
||||||
* _Ensure the *entire* test suite is green_ in all the big browsers, Node, and
|
* _Ensure the *entire* test suite is green_ in all the big browsers, Node, and
|
||||||
ESLint/Prettier. Your contribution shouldn't break Jasmine for other users.
|
ESLint/Prettier. Your contribution shouldn't break Jasmine for other users.
|
||||||
|
|
||||||
@@ -119,3 +103,10 @@ chromedriver), you can also use Jasmine's CI tooling:
|
|||||||
|
|
||||||
$ JASMINE_BROWSER=<name of browser> npm run ci
|
$ JASMINE_BROWSER=<name of browser> npm run ci
|
||||||
|
|
||||||
|
### Submitting a Pull Requeset
|
||||||
|
|
||||||
|
Once you've done the steps listed under "Before Submitting a Pull Request"
|
||||||
|
above, you can submit a pull request via the
|
||||||
|
[standard GitHub process](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request).
|
||||||
|
TL;DR: Fork the repository, push your work up to your fork, and create a PR from
|
||||||
|
there.
|
||||||
|
|||||||
@@ -2789,8 +2789,32 @@ getJasmineRequireObj().CallTracker = function(j$) {
|
|||||||
getJasmineRequireObj().clearStack = function(j$) {
|
getJasmineRequireObj().clearStack = function(j$) {
|
||||||
const maxInlineCallCount = 10;
|
const maxInlineCallCount = 10;
|
||||||
|
|
||||||
function messageChannelImpl(global, setTimeout) {
|
function browserQueueMicrotaskImpl(global) {
|
||||||
const channel = new global.MessageChannel();
|
const { setTimeout, queueMicrotask } = global;
|
||||||
|
let currentCallCount = 0;
|
||||||
|
return function clearStack(fn) {
|
||||||
|
currentCallCount++;
|
||||||
|
|
||||||
|
if (currentCallCount < maxInlineCallCount) {
|
||||||
|
queueMicrotask(fn);
|
||||||
|
} else {
|
||||||
|
currentCallCount = 0;
|
||||||
|
setTimeout(fn);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function nodeQueueMicrotaskImpl(global) {
|
||||||
|
const { queueMicrotask } = global;
|
||||||
|
|
||||||
|
return function(fn) {
|
||||||
|
queueMicrotask(fn);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function messageChannelImpl(global) {
|
||||||
|
const { MessageChannel, setTimeout } = global;
|
||||||
|
const channel = new MessageChannel();
|
||||||
let head = {};
|
let head = {};
|
||||||
let tail = head;
|
let tail = head;
|
||||||
|
|
||||||
@@ -2801,7 +2825,7 @@ getJasmineRequireObj().clearStack = function(j$) {
|
|||||||
delete head.task;
|
delete head.task;
|
||||||
|
|
||||||
if (taskRunning) {
|
if (taskRunning) {
|
||||||
global.setTimeout(task, 0);
|
setTimeout(task, 0);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
taskRunning = true;
|
taskRunning = true;
|
||||||
@@ -2827,29 +2851,31 @@ getJasmineRequireObj().clearStack = function(j$) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getClearStack(global) {
|
function getClearStack(global) {
|
||||||
let currentCallCount = 0;
|
const NODE_JS =
|
||||||
const realSetTimeout = global.setTimeout;
|
global.process &&
|
||||||
const setTimeoutImpl = function clearStack(fn) {
|
global.process.versions &&
|
||||||
Function.prototype.apply.apply(realSetTimeout, [global, [fn, 0]]);
|
typeof global.process.versions.node === 'string';
|
||||||
};
|
|
||||||
|
|
||||||
if (j$.isFunction_(global.setImmediate)) {
|
const SAFARI =
|
||||||
const realSetImmediate = global.setImmediate;
|
global.navigator &&
|
||||||
return function(fn) {
|
/^((?!chrome|android).)*safari/i.test(global.navigator.userAgent);
|
||||||
currentCallCount++;
|
|
||||||
|
|
||||||
if (currentCallCount < maxInlineCallCount) {
|
if (NODE_JS) {
|
||||||
realSetImmediate(fn);
|
// Unlike browsers, Node doesn't require us to do a periodic setTimeout
|
||||||
} else {
|
// so we avoid the overhead.
|
||||||
currentCallCount = 0;
|
return nodeQueueMicrotaskImpl(global);
|
||||||
|
} else if (
|
||||||
setTimeoutImpl(fn);
|
SAFARI ||
|
||||||
}
|
j$.util.isUndefined(global.MessageChannel) /* tests */
|
||||||
};
|
) {
|
||||||
} else if (!j$.util.isUndefined(global.MessageChannel)) {
|
// queueMicrotask is dramatically faster than MessageChannel in Safari.
|
||||||
return messageChannelImpl(global, setTimeoutImpl);
|
// Some of our own integration tests provide a mock queueMicrotask in all
|
||||||
|
// environments because it's simpler to mock than MessageChannel.
|
||||||
|
return browserQueueMicrotaskImpl(global);
|
||||||
} else {
|
} else {
|
||||||
return setTimeoutImpl;
|
// MessageChannel is faster than queueMicrotask in supported browsers
|
||||||
|
// other than Safari.
|
||||||
|
return messageChannelImpl(global);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4055,21 +4081,14 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (global.addEventListener) {
|
global.addEventListener('unhandledrejection', browserRejectionHandler);
|
||||||
global.addEventListener(
|
|
||||||
'unhandledrejection',
|
|
||||||
browserRejectionHandler
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.uninstall = function uninstall() {
|
this.uninstall = function uninstall() {
|
||||||
global.onerror = originalHandler;
|
global.onerror = originalHandler;
|
||||||
if (global.removeEventListener) {
|
global.removeEventListener(
|
||||||
global.removeEventListener(
|
'unhandledrejection',
|
||||||
'unhandledrejection',
|
browserRejectionHandler
|
||||||
browserRejectionHandler
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -10429,5 +10448,5 @@ getJasmineRequireObj().UserContext = function(j$) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
getJasmineRequireObj().version = function() {
|
getJasmineRequireObj().version = function() {
|
||||||
return '4.3.0';
|
return '4.4.0';
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "jasmine-core",
|
"name": "jasmine-core",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"version": "4.3.0",
|
"version": "4.4.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/jasmine/jasmine.git"
|
"url": "https://github.com/jasmine/jasmine.git"
|
||||||
|
|||||||
28
release_notes/4.4.0.md
Normal file
28
release_notes/4.4.0.md
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# Jasmine 4.4.0 Release Notes
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
* Optimized the process of transitioning between specs in Node, Safari, and
|
||||||
|
Edge. This change reduces the run time of jasmine-core's own test suite by
|
||||||
|
50-70% in Node, about 20% in Edge, and 75-90% in Safari. Your results may
|
||||||
|
vary. In general, suites with many fast specs will see the greatest
|
||||||
|
performance improvement.
|
||||||
|
|
||||||
|
* Removed old code to support browsers that don't provide
|
||||||
|
addEventListener/removeEventListener.
|
||||||
|
|
||||||
|
## Supported environments
|
||||||
|
|
||||||
|
jasmine-core 4.4.0 has been tested in the following environments.
|
||||||
|
|
||||||
|
| Environment | Supported versions |
|
||||||
|
|-------------------|--------------------|
|
||||||
|
| Node | 12.17+, 14, 16, 18 |
|
||||||
|
| Safari | 14-15 |
|
||||||
|
| Chrome | 105 |
|
||||||
|
| Firefox | 91, 102, 104 |
|
||||||
|
| Edge | 104 |
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||||
@@ -9,160 +9,216 @@ describe('ClearStack', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('uses setImmediate when available', function() {
|
describe('in Safari', function() {
|
||||||
const setImmediate = jasmine
|
usesQueueMicrotaskWithSetTimeout(function() {
|
||||||
.createSpy('setImmediate')
|
return {
|
||||||
.and.callFake(function(fn) {
|
navigator: {
|
||||||
fn();
|
userAgent:
|
||||||
}),
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.0.8 (KHTML, like Gecko) Version/15.1 Safari/605.0.8'
|
||||||
global = { setImmediate: setImmediate },
|
},
|
||||||
clearStack = jasmineUnderTest.getClearStack(global);
|
// queueMicrotask should be used even though MessageChannel is present
|
||||||
let called = false;
|
MessageChannel: fakeMessageChannel
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
clearStack(function() {
|
describe('in browsers other than Safari', function() {
|
||||||
called = true;
|
usesMessageChannel(function() {
|
||||||
|
return {
|
||||||
|
navigator: {
|
||||||
|
// Chrome's user agent string contains "Safari" so it's a good test case
|
||||||
|
userAgent:
|
||||||
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36'
|
||||||
|
}
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(called).toBe(true);
|
describe('when MessageChannel is unavailable', function() {
|
||||||
expect(setImmediate).toHaveBeenCalled();
|
usesQueueMicrotaskWithSetTimeout(function() {
|
||||||
|
return {
|
||||||
|
navigator: {
|
||||||
|
userAgent: 'CERN-LineMode/2.15 libwww/2.17b3',
|
||||||
|
MessageChannel: undefined
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('uses setTimeout instead of setImmediate every 10 calls to make sure we release the CPU', function() {
|
describe('in Node', function() {
|
||||||
const setImmediate = jasmine.createSpy('setImmediate'),
|
usesQueueMicrotaskWithoutSetTimeout(function() {
|
||||||
setTimeout = jasmine.createSpy('setTimeout'),
|
return {
|
||||||
global = { setImmediate: setImmediate, setTimeout: setTimeout },
|
process: {
|
||||||
clearStack = jasmineUnderTest.getClearStack(global);
|
versions: {
|
||||||
|
node: '3.1415927'
|
||||||
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.calls.count()).toEqual(1);
|
|
||||||
|
|
||||||
clearStack(function() {});
|
|
||||||
expect(setImmediate.calls.count()).toEqual(10);
|
|
||||||
expect(setTimeout.calls.count()).toEqual(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('uses MessageChannels when available', function() {
|
|
||||||
const fakeChannel = {
|
|
||||||
port1: {},
|
|
||||||
port2: {
|
|
||||||
postMessage: function() {
|
|
||||||
fakeChannel.port1.onmessage();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
global = {
|
});
|
||||||
MessageChannel: function() {
|
});
|
||||||
return fakeChannel;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
clearStack = jasmineUnderTest.getClearStack(global);
|
|
||||||
let called = false;
|
|
||||||
|
|
||||||
clearStack(function() {
|
function usesMessageChannel(makeGlobal) {
|
||||||
called = true;
|
it('uses MessageChannel', function() {
|
||||||
|
const global = {
|
||||||
|
...makeGlobal(),
|
||||||
|
MessageChannel: fakeMessageChannel
|
||||||
|
};
|
||||||
|
const clearStack = jasmineUnderTest.getClearStack(global);
|
||||||
|
let called = false;
|
||||||
|
|
||||||
|
clearStack(function() {
|
||||||
|
called = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
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() {
|
||||||
});
|
const fakeChannel = fakeMessageChannel();
|
||||||
|
spyOn(fakeChannel.port2, 'postMessage');
|
||||||
it('uses setTimeout instead of MessageChannel every 10 calls to make sure we release the CPU', function() {
|
const setTimeout = jasmine.createSpy('setTimeout');
|
||||||
const fakeChannel = {
|
const global = {
|
||||||
port1: {},
|
...makeGlobal(),
|
||||||
port2: {
|
setTimeout,
|
||||||
postMessage: jasmine
|
|
||||||
.createSpy('postMessage')
|
|
||||||
.and.callFake(function() {
|
|
||||||
fakeChannel.port1.onmessage();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setTimeout = jasmine.createSpy('setTimeout'),
|
|
||||||
global = {
|
|
||||||
MessageChannel: function() {
|
MessageChannel: function() {
|
||||||
return fakeChannel;
|
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.calls.count()).toEqual(1);
|
|
||||||
|
|
||||||
clearStack(function() {});
|
|
||||||
expect(fakeChannel.port2.postMessage.calls.count()).toEqual(10);
|
|
||||||
expect(setTimeout.calls.count()).toEqual(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('calls setTimeout when onmessage is called recursively', function() {
|
|
||||||
const fakeChannel = {
|
|
||||||
port1: {},
|
|
||||||
port2: {
|
|
||||||
postMessage: function() {
|
|
||||||
fakeChannel.port1.onmessage();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
setTimeout = jasmine.createSpy('setTimeout'),
|
const clearStack = jasmineUnderTest.getClearStack(global);
|
||||||
global = {
|
|
||||||
MessageChannel: function() {
|
|
||||||
return fakeChannel;
|
|
||||||
},
|
|
||||||
setTimeout: setTimeout
|
|
||||||
},
|
|
||||||
clearStack = jasmineUnderTest.getClearStack(global),
|
|
||||||
fn = jasmine.createSpy('second clearStack function');
|
|
||||||
|
|
||||||
clearStack(function() {
|
for (let i = 0; i < 9; i++) {
|
||||||
clearStack(fn);
|
clearStack(function() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(fakeChannel.port2.postMessage).toHaveBeenCalled();
|
||||||
|
expect(setTimeout).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
clearStack(function() {});
|
||||||
|
expect(fakeChannel.port2.postMessage).toHaveBeenCalledTimes(9);
|
||||||
|
expect(setTimeout).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
clearStack(function() {});
|
||||||
|
expect(fakeChannel.port2.postMessage).toHaveBeenCalledTimes(10);
|
||||||
|
expect(setTimeout).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(fn).not.toHaveBeenCalled();
|
it('calls setTimeout when onmessage is called recursively', function() {
|
||||||
expect(setTimeout).toHaveBeenCalledWith(fn, 0);
|
const setTimeout = jasmine.createSpy('setTimeout');
|
||||||
});
|
const global = {
|
||||||
|
...makeGlobal(),
|
||||||
|
setTimeout,
|
||||||
|
MessageChannel: fakeMessageChannel
|
||||||
|
};
|
||||||
|
const clearStack = jasmineUnderTest.getClearStack(global);
|
||||||
|
const fn = jasmine.createSpy('second clearStack function');
|
||||||
|
|
||||||
it('falls back to setTimeout', function() {
|
clearStack(function() {
|
||||||
const setTimeout = jasmine
|
clearStack(fn);
|
||||||
.createSpy('setTimeout')
|
});
|
||||||
.and.callFake(function(fn) {
|
|
||||||
|
expect(fn).not.toHaveBeenCalled();
|
||||||
|
expect(setTimeout).toHaveBeenCalledWith(fn, 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function usesQueueMicrotaskWithSetTimeout(makeGlobal) {
|
||||||
|
it('uses queueMicrotask', function() {
|
||||||
|
const global = {
|
||||||
|
...makeGlobal(),
|
||||||
|
queueMicrotask: function(fn) {
|
||||||
fn();
|
fn();
|
||||||
}),
|
}
|
||||||
global = { setTimeout: setTimeout },
|
};
|
||||||
clearStack = jasmineUnderTest.getClearStack(global);
|
const clearStack = jasmineUnderTest.getClearStack(global);
|
||||||
let called = false;
|
let called = false;
|
||||||
|
|
||||||
clearStack(function() {
|
clearStack(function() {
|
||||||
called = true;
|
called = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(called).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(called).toBe(true);
|
it('uses setTimeout instead of queueMicrotask every 10 calls to make sure we release the CPU', function() {
|
||||||
expect(setTimeout).toHaveBeenCalledWith(jasmine.any(Function), 0);
|
const queueMicrotask = jasmine.createSpy('queueMicrotask');
|
||||||
});
|
const setTimeout = jasmine.createSpy('setTimeout');
|
||||||
|
const global = {
|
||||||
|
...makeGlobal(),
|
||||||
|
queueMicrotask,
|
||||||
|
setTimeout
|
||||||
|
};
|
||||||
|
const clearStack = jasmineUnderTest.getClearStack(global);
|
||||||
|
|
||||||
|
for (let i = 0; i < 9; i++) {
|
||||||
|
clearStack(function() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(queueMicrotask).toHaveBeenCalled();
|
||||||
|
expect(setTimeout).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
clearStack(function() {});
|
||||||
|
expect(queueMicrotask).toHaveBeenCalledTimes(9);
|
||||||
|
expect(setTimeout).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
clearStack(function() {});
|
||||||
|
expect(queueMicrotask).toHaveBeenCalledTimes(10);
|
||||||
|
expect(setTimeout).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function usesQueueMicrotaskWithoutSetTimeout(makeGlobal) {
|
||||||
|
it('uses queueMicrotask', function() {
|
||||||
|
const global = {
|
||||||
|
...makeGlobal(),
|
||||||
|
queueMicrotask: function(fn) {
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const clearStack = jasmineUnderTest.getClearStack(global);
|
||||||
|
let called = false;
|
||||||
|
|
||||||
|
clearStack(function() {
|
||||||
|
called = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(called).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not use setTimeout', function() {
|
||||||
|
const queueMicrotask = jasmine.createSpy('queueMicrotask');
|
||||||
|
const setTimeout = jasmine.createSpy('setTimeout');
|
||||||
|
const global = {
|
||||||
|
...makeGlobal(),
|
||||||
|
queueMicrotask,
|
||||||
|
setTimeout
|
||||||
|
};
|
||||||
|
const clearStack = jasmineUnderTest.getClearStack(global);
|
||||||
|
|
||||||
|
clearStack(function() {});
|
||||||
|
clearStack(function() {});
|
||||||
|
clearStack(function() {});
|
||||||
|
clearStack(function() {});
|
||||||
|
clearStack(function() {});
|
||||||
|
clearStack(function() {});
|
||||||
|
clearStack(function() {});
|
||||||
|
clearStack(function() {});
|
||||||
|
clearStack(function() {});
|
||||||
|
clearStack(function() {});
|
||||||
|
|
||||||
|
expect(queueMicrotask).toHaveBeenCalledTimes(10);
|
||||||
|
expect(setTimeout).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function fakeMessageChannel() {
|
||||||
|
const channel = {
|
||||||
|
port1: {},
|
||||||
|
port2: {
|
||||||
|
postMessage: function() {
|
||||||
|
channel.port1.onmessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return channel;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
describe('GlobalErrors', function() {
|
describe('GlobalErrors', function() {
|
||||||
it('calls the added handler on error', function() {
|
it('calls the added handler on error', function() {
|
||||||
const fakeGlobal = { onerror: null },
|
const fakeGlobal = minimalBrowserGlobal();
|
||||||
handler = jasmine.createSpy('errorHandler'),
|
const handler = jasmine.createSpy('errorHandler');
|
||||||
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
const errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
||||||
|
|
||||||
errors.install();
|
errors.install();
|
||||||
errors.pushListener(handler);
|
errors.pushListener(handler);
|
||||||
@@ -13,10 +13,10 @@ describe('GlobalErrors', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('enables external interception of error by overriding global.onerror', function() {
|
it('enables external interception of error by overriding global.onerror', function() {
|
||||||
const fakeGlobal = { onerror: null },
|
const fakeGlobal = minimalBrowserGlobal();
|
||||||
handler = jasmine.createSpy('errorHandler'),
|
const handler = jasmine.createSpy('errorHandler');
|
||||||
hijackHandler = jasmine.createSpy('hijackErrorHandler'),
|
const hijackHandler = jasmine.createSpy('hijackErrorHandler');
|
||||||
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
const errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
||||||
|
|
||||||
errors.install();
|
errors.install();
|
||||||
errors.pushListener(handler);
|
errors.pushListener(handler);
|
||||||
@@ -30,10 +30,10 @@ describe('GlobalErrors', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('calls the global error handler with all parameters', function() {
|
it('calls the global error handler with all parameters', function() {
|
||||||
const fakeGlobal = { onerror: null },
|
const fakeGlobal = minimalBrowserGlobal();
|
||||||
handler = jasmine.createSpy('errorHandler'),
|
const handler = jasmine.createSpy('errorHandler');
|
||||||
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal),
|
const errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
||||||
fooError = new Error('foo');
|
const fooError = new Error('foo');
|
||||||
|
|
||||||
errors.install();
|
errors.install();
|
||||||
errors.pushListener(handler);
|
errors.pushListener(handler);
|
||||||
@@ -50,10 +50,10 @@ describe('GlobalErrors', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('only calls the most recent handler', function() {
|
it('only calls the most recent handler', function() {
|
||||||
const fakeGlobal = { onerror: null },
|
const fakeGlobal = minimalBrowserGlobal();
|
||||||
handler1 = jasmine.createSpy('errorHandler1'),
|
const handler1 = jasmine.createSpy('errorHandler1');
|
||||||
handler2 = jasmine.createSpy('errorHandler2'),
|
const handler2 = jasmine.createSpy('errorHandler2');
|
||||||
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
const errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
||||||
|
|
||||||
errors.install();
|
errors.install();
|
||||||
errors.pushListener(handler1);
|
errors.pushListener(handler1);
|
||||||
@@ -66,10 +66,10 @@ describe('GlobalErrors', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('calls previous handlers when one is removed', function() {
|
it('calls previous handlers when one is removed', function() {
|
||||||
const fakeGlobal = { onerror: null },
|
const fakeGlobal = minimalBrowserGlobal();
|
||||||
handler1 = jasmine.createSpy('errorHandler1'),
|
const handler1 = jasmine.createSpy('errorHandler1');
|
||||||
handler2 = jasmine.createSpy('errorHandler2'),
|
const handler2 = jasmine.createSpy('errorHandler2');
|
||||||
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
const errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
||||||
|
|
||||||
errors.install();
|
errors.install();
|
||||||
errors.pushListener(handler1);
|
errors.pushListener(handler1);
|
||||||
@@ -91,9 +91,12 @@ describe('GlobalErrors', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('uninstalls itself, putting back a previous callback', function() {
|
it('uninstalls itself, putting back a previous callback', function() {
|
||||||
const originalCallback = jasmine.createSpy('error'),
|
const originalCallback = jasmine.createSpy('error');
|
||||||
fakeGlobal = { onerror: originalCallback },
|
const fakeGlobal = {
|
||||||
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
...minimalBrowserGlobal(),
|
||||||
|
onerror: originalCallback
|
||||||
|
};
|
||||||
|
const errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
||||||
|
|
||||||
expect(fakeGlobal.onerror).toBe(originalCallback);
|
expect(fakeGlobal.onerror).toBe(originalCallback);
|
||||||
|
|
||||||
@@ -107,9 +110,9 @@ describe('GlobalErrors', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('rethrows the original error when there is no handler', function() {
|
it('rethrows the original error when there is no handler', function() {
|
||||||
const fakeGlobal = {},
|
const fakeGlobal = minimalBrowserGlobal();
|
||||||
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal),
|
const errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
||||||
originalError = new Error('nope');
|
const originalError = new Error('nope');
|
||||||
|
|
||||||
errors.install();
|
errors.install();
|
||||||
|
|
||||||
@@ -407,7 +410,7 @@ describe('GlobalErrors', function() {
|
|||||||
|
|
||||||
describe('#setOverrideListener', function() {
|
describe('#setOverrideListener', function() {
|
||||||
it('overrides the existing handlers in browsers until removed', function() {
|
it('overrides the existing handlers in browsers until removed', function() {
|
||||||
const fakeGlobal = { onerror: null };
|
const fakeGlobal = minimalBrowserGlobal();
|
||||||
const handler0 = jasmine.createSpy('handler0');
|
const handler0 = jasmine.createSpy('handler0');
|
||||||
const handler1 = jasmine.createSpy('handler1');
|
const handler1 = jasmine.createSpy('handler1');
|
||||||
const overrideHandler = jasmine.createSpy('overrideHandler');
|
const overrideHandler = jasmine.createSpy('overrideHandler');
|
||||||
@@ -529,8 +532,7 @@ describe('GlobalErrors', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('throws if there is already an override handler', function() {
|
it('throws if there is already an override handler', function() {
|
||||||
const fakeGlobal = { onerror: null };
|
const errors = new jasmineUnderTest.GlobalErrors(minimalBrowserGlobal());
|
||||||
const errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
|
||||||
|
|
||||||
errors.setOverrideListener(() => {}, () => {});
|
errors.setOverrideListener(() => {}, () => {});
|
||||||
expect(function() {
|
expect(function() {
|
||||||
@@ -541,9 +543,8 @@ describe('GlobalErrors', function() {
|
|||||||
|
|
||||||
describe('#removeOverrideListener', function() {
|
describe('#removeOverrideListener', function() {
|
||||||
it("calls the handler's onRemove callback", function() {
|
it("calls the handler's onRemove callback", function() {
|
||||||
const fakeGlobal = { onerror: null };
|
|
||||||
const onRemove = jasmine.createSpy('onRemove');
|
const onRemove = jasmine.createSpy('onRemove');
|
||||||
const errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
const errors = new jasmineUnderTest.GlobalErrors(minimalBrowserGlobal());
|
||||||
|
|
||||||
errors.setOverrideListener(() => {}, onRemove);
|
errors.setOverrideListener(() => {}, onRemove);
|
||||||
errors.removeOverrideListener();
|
errors.removeOverrideListener();
|
||||||
@@ -552,10 +553,17 @@ describe('GlobalErrors', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('does not throw if there is no handler', function() {
|
it('does not throw if there is no handler', function() {
|
||||||
const fakeGlobal = { onerror: null };
|
const errors = new jasmineUnderTest.GlobalErrors(minimalBrowserGlobal());
|
||||||
const errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
|
||||||
|
|
||||||
expect(() => errors.removeOverrideListener()).not.toThrow();
|
expect(() => errors.removeOverrideListener()).not.toThrow();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function minimalBrowserGlobal() {
|
||||||
|
return {
|
||||||
|
addEventListener() {},
|
||||||
|
removeEventListener() {},
|
||||||
|
onerror: null
|
||||||
|
};
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -431,11 +431,15 @@ describe('Env integration', function() {
|
|||||||
describe('Handling async errors', function() {
|
describe('Handling async errors', function() {
|
||||||
it('routes async errors to a running spec', async function() {
|
it('routes async errors to a running spec', async function() {
|
||||||
const global = {
|
const global = {
|
||||||
|
...browserEventMethods(),
|
||||||
setTimeout: function(fn, delay) {
|
setTimeout: function(fn, delay) {
|
||||||
return setTimeout(fn, delay);
|
return setTimeout(fn, delay);
|
||||||
},
|
},
|
||||||
clearTimeout: function(fn, delay) {
|
clearTimeout: function(fn, delay) {
|
||||||
clearTimeout(fn, delay);
|
clearTimeout(fn, delay);
|
||||||
|
},
|
||||||
|
queueMicrotask: function(fn) {
|
||||||
|
queueMicrotask(fn);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
||||||
@@ -468,11 +472,15 @@ describe('Env integration', function() {
|
|||||||
describe('When the running spec has reported specDone', function() {
|
describe('When the running spec has reported specDone', function() {
|
||||||
it('routes async errors to an ancestor suite', async function() {
|
it('routes async errors to an ancestor suite', async function() {
|
||||||
const global = {
|
const global = {
|
||||||
|
...browserEventMethods(),
|
||||||
setTimeout: function(fn, delay) {
|
setTimeout: function(fn, delay) {
|
||||||
return setTimeout(fn, delay);
|
return setTimeout(fn, delay);
|
||||||
},
|
},
|
||||||
clearTimeout: function(fn) {
|
clearTimeout: function(fn) {
|
||||||
clearTimeout(fn);
|
clearTimeout(fn);
|
||||||
|
},
|
||||||
|
queueMicrotask: function(fn) {
|
||||||
|
queueMicrotask(fn);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
||||||
@@ -524,11 +532,15 @@ describe('Env integration', function() {
|
|||||||
|
|
||||||
it('routes async errors to a running suite', async function() {
|
it('routes async errors to a running suite', async function() {
|
||||||
const global = {
|
const global = {
|
||||||
|
...browserEventMethods(),
|
||||||
setTimeout: function(fn, delay) {
|
setTimeout: function(fn, delay) {
|
||||||
return setTimeout(fn, delay);
|
return setTimeout(fn, delay);
|
||||||
},
|
},
|
||||||
clearTimeout: function(fn, delay) {
|
clearTimeout: function(fn, delay) {
|
||||||
clearTimeout(fn, delay);
|
clearTimeout(fn, delay);
|
||||||
|
},
|
||||||
|
queueMicrotask: function(fn) {
|
||||||
|
queueMicrotask(fn);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
||||||
@@ -545,8 +557,8 @@ describe('Env integration', function() {
|
|||||||
env.it('fails', function(specDone) {
|
env.it('fails', function(specDone) {
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
specDone();
|
specDone();
|
||||||
setTimeout(function() {
|
queueMicrotask(function() {
|
||||||
setTimeout(function() {
|
queueMicrotask(function() {
|
||||||
global.onerror('fail');
|
global.onerror('fail');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -573,11 +585,15 @@ describe('Env integration', function() {
|
|||||||
describe('When the running suite has reported suiteDone', function() {
|
describe('When the running suite has reported suiteDone', function() {
|
||||||
it('routes async errors to an ancestor suite', async function() {
|
it('routes async errors to an ancestor suite', async function() {
|
||||||
const global = {
|
const global = {
|
||||||
|
...browserEventMethods(),
|
||||||
setTimeout: function(fn, delay) {
|
setTimeout: function(fn, delay) {
|
||||||
return setTimeout(fn, delay);
|
return setTimeout(fn, delay);
|
||||||
},
|
},
|
||||||
clearTimeout: function(fn, delay) {
|
clearTimeout: function(fn, delay) {
|
||||||
clearTimeout(fn, delay);
|
clearTimeout(fn, delay);
|
||||||
|
},
|
||||||
|
queueMicrotask: function(fn) {
|
||||||
|
queueMicrotask(fn);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
||||||
@@ -633,11 +649,15 @@ describe('Env integration', function() {
|
|||||||
describe('When the env has started reporting jasmineDone', function() {
|
describe('When the env has started reporting jasmineDone', function() {
|
||||||
it('logs the error to the console', async function() {
|
it('logs the error to the console', async function() {
|
||||||
const global = {
|
const global = {
|
||||||
|
...browserEventMethods(),
|
||||||
setTimeout: function(fn, delay) {
|
setTimeout: function(fn, delay) {
|
||||||
return setTimeout(fn, delay);
|
return setTimeout(fn, delay);
|
||||||
},
|
},
|
||||||
clearTimeout: function(fn, delay) {
|
clearTimeout: function(fn, delay) {
|
||||||
clearTimeout(fn, delay);
|
clearTimeout(fn, delay);
|
||||||
|
},
|
||||||
|
queueMicrotask: function(fn) {
|
||||||
|
queueMicrotask(fn);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
||||||
@@ -672,11 +692,15 @@ describe('Env integration', function() {
|
|||||||
|
|
||||||
it('routes all errors that occur during stack clearing somewhere', async function() {
|
it('routes all errors that occur during stack clearing somewhere', async function() {
|
||||||
const global = {
|
const global = {
|
||||||
|
...browserEventMethods(),
|
||||||
setTimeout: function(fn, delay) {
|
setTimeout: function(fn, delay) {
|
||||||
return setTimeout(fn, delay);
|
return setTimeout(fn, delay);
|
||||||
},
|
},
|
||||||
clearTimeout: function(fn) {
|
clearTimeout: function(fn) {
|
||||||
clearTimeout(fn);
|
clearTimeout(fn);
|
||||||
|
},
|
||||||
|
queueMicrotask: function(fn) {
|
||||||
|
queueMicrotask(fn);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
||||||
@@ -1427,8 +1451,8 @@ describe('Env integration', function() {
|
|||||||
global: {
|
global: {
|
||||||
setTimeout: globalSetTimeout,
|
setTimeout: globalSetTimeout,
|
||||||
clearTimeout: clearTimeout,
|
clearTimeout: clearTimeout,
|
||||||
setImmediate: function(cb) {
|
queueMicrotask: function(fn) {
|
||||||
return setTimeout(cb, 0);
|
queueMicrotask(fn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1501,8 +1525,8 @@ describe('Env integration', function() {
|
|||||||
clearTimeout: clearTimeout,
|
clearTimeout: clearTimeout,
|
||||||
setInterval: setInterval,
|
setInterval: setInterval,
|
||||||
clearInterval: clearInterval,
|
clearInterval: clearInterval,
|
||||||
setImmediate: function(cb) {
|
queueMicrotask: function(fn) {
|
||||||
return realSetTimeout(cb, 0);
|
queueMicrotask(fn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -2619,12 +2643,16 @@ describe('Env integration', function() {
|
|||||||
|
|
||||||
it('reports errors that occur during loading', async function() {
|
it('reports errors that occur during loading', async function() {
|
||||||
const global = {
|
const global = {
|
||||||
|
...browserEventMethods(),
|
||||||
setTimeout: function(fn, delay) {
|
setTimeout: function(fn, delay) {
|
||||||
return setTimeout(fn, delay);
|
return setTimeout(fn, delay);
|
||||||
},
|
},
|
||||||
clearTimeout: function(fn, delay) {
|
clearTimeout: function(fn, delay) {
|
||||||
clearTimeout(fn, delay);
|
clearTimeout(fn, delay);
|
||||||
},
|
},
|
||||||
|
queueMicrotask: function(fn) {
|
||||||
|
queueMicrotask(fn);
|
||||||
|
},
|
||||||
onerror: function() {}
|
onerror: function() {}
|
||||||
};
|
};
|
||||||
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
||||||
@@ -2674,12 +2702,16 @@ describe('Env integration', function() {
|
|||||||
it('does not install a global error handler during loading', async function() {
|
it('does not install a global error handler during loading', async function() {
|
||||||
const originalOnerror = jasmine.createSpy('original onerror');
|
const originalOnerror = jasmine.createSpy('original onerror');
|
||||||
const global = {
|
const global = {
|
||||||
|
...browserEventMethods(),
|
||||||
setTimeout: function(fn, delay) {
|
setTimeout: function(fn, delay) {
|
||||||
return setTimeout(fn, delay);
|
return setTimeout(fn, delay);
|
||||||
},
|
},
|
||||||
clearTimeout: function(fn, delay) {
|
clearTimeout: function(fn, delay) {
|
||||||
clearTimeout(fn, delay);
|
clearTimeout(fn, delay);
|
||||||
},
|
},
|
||||||
|
queueMicrotask: function(fn) {
|
||||||
|
queueMicrotask(fn);
|
||||||
|
},
|
||||||
onerror: originalOnerror
|
onerror: originalOnerror
|
||||||
};
|
};
|
||||||
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
||||||
@@ -2864,11 +2896,15 @@ describe('Env integration', function() {
|
|||||||
describe('When there are load errors', function() {
|
describe('When there are load errors', function() {
|
||||||
it('is "failed"', async function() {
|
it('is "failed"', async function() {
|
||||||
const global = {
|
const global = {
|
||||||
|
...browserEventMethods(),
|
||||||
setTimeout: function(fn, delay) {
|
setTimeout: function(fn, delay) {
|
||||||
return setTimeout(fn, delay);
|
return setTimeout(fn, delay);
|
||||||
},
|
},
|
||||||
clearTimeout: function(fn, delay) {
|
clearTimeout: function(fn, delay) {
|
||||||
return clearTimeout(fn, delay);
|
return clearTimeout(fn, delay);
|
||||||
|
},
|
||||||
|
queueMicrotask: function(fn) {
|
||||||
|
queueMicrotask(fn);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
spyOn(jasmineUnderTest, 'getGlobal').and.returnValue(global);
|
||||||
@@ -3906,4 +3942,11 @@ describe('Env integration', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function browserEventMethods() {
|
||||||
|
return {
|
||||||
|
addEventListener() {},
|
||||||
|
removeEventListener() {}
|
||||||
|
};
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,8 +1,32 @@
|
|||||||
getJasmineRequireObj().clearStack = function(j$) {
|
getJasmineRequireObj().clearStack = function(j$) {
|
||||||
const maxInlineCallCount = 10;
|
const maxInlineCallCount = 10;
|
||||||
|
|
||||||
function messageChannelImpl(global, setTimeout) {
|
function browserQueueMicrotaskImpl(global) {
|
||||||
const channel = new global.MessageChannel();
|
const { setTimeout, queueMicrotask } = global;
|
||||||
|
let currentCallCount = 0;
|
||||||
|
return function clearStack(fn) {
|
||||||
|
currentCallCount++;
|
||||||
|
|
||||||
|
if (currentCallCount < maxInlineCallCount) {
|
||||||
|
queueMicrotask(fn);
|
||||||
|
} else {
|
||||||
|
currentCallCount = 0;
|
||||||
|
setTimeout(fn);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function nodeQueueMicrotaskImpl(global) {
|
||||||
|
const { queueMicrotask } = global;
|
||||||
|
|
||||||
|
return function(fn) {
|
||||||
|
queueMicrotask(fn);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function messageChannelImpl(global) {
|
||||||
|
const { MessageChannel, setTimeout } = global;
|
||||||
|
const channel = new MessageChannel();
|
||||||
let head = {};
|
let head = {};
|
||||||
let tail = head;
|
let tail = head;
|
||||||
|
|
||||||
@@ -13,7 +37,7 @@ getJasmineRequireObj().clearStack = function(j$) {
|
|||||||
delete head.task;
|
delete head.task;
|
||||||
|
|
||||||
if (taskRunning) {
|
if (taskRunning) {
|
||||||
global.setTimeout(task, 0);
|
setTimeout(task, 0);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
taskRunning = true;
|
taskRunning = true;
|
||||||
@@ -39,29 +63,31 @@ getJasmineRequireObj().clearStack = function(j$) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getClearStack(global) {
|
function getClearStack(global) {
|
||||||
let currentCallCount = 0;
|
const NODE_JS =
|
||||||
const realSetTimeout = global.setTimeout;
|
global.process &&
|
||||||
const setTimeoutImpl = function clearStack(fn) {
|
global.process.versions &&
|
||||||
Function.prototype.apply.apply(realSetTimeout, [global, [fn, 0]]);
|
typeof global.process.versions.node === 'string';
|
||||||
};
|
|
||||||
|
|
||||||
if (j$.isFunction_(global.setImmediate)) {
|
const SAFARI =
|
||||||
const realSetImmediate = global.setImmediate;
|
global.navigator &&
|
||||||
return function(fn) {
|
/^((?!chrome|android).)*safari/i.test(global.navigator.userAgent);
|
||||||
currentCallCount++;
|
|
||||||
|
|
||||||
if (currentCallCount < maxInlineCallCount) {
|
if (NODE_JS) {
|
||||||
realSetImmediate(fn);
|
// Unlike browsers, Node doesn't require us to do a periodic setTimeout
|
||||||
} else {
|
// so we avoid the overhead.
|
||||||
currentCallCount = 0;
|
return nodeQueueMicrotaskImpl(global);
|
||||||
|
} else if (
|
||||||
setTimeoutImpl(fn);
|
SAFARI ||
|
||||||
}
|
j$.util.isUndefined(global.MessageChannel) /* tests */
|
||||||
};
|
) {
|
||||||
} else if (!j$.util.isUndefined(global.MessageChannel)) {
|
// queueMicrotask is dramatically faster than MessageChannel in Safari.
|
||||||
return messageChannelImpl(global, setTimeoutImpl);
|
// Some of our own integration tests provide a mock queueMicrotask in all
|
||||||
|
// environments because it's simpler to mock than MessageChannel.
|
||||||
|
return browserQueueMicrotaskImpl(global);
|
||||||
} else {
|
} else {
|
||||||
return setTimeoutImpl;
|
// MessageChannel is faster than queueMicrotask in supported browsers
|
||||||
|
// other than Safari.
|
||||||
|
return messageChannelImpl(global);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -109,21 +109,14 @@ getJasmineRequireObj().GlobalErrors = function(j$) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (global.addEventListener) {
|
global.addEventListener('unhandledrejection', browserRejectionHandler);
|
||||||
global.addEventListener(
|
|
||||||
'unhandledrejection',
|
|
||||||
browserRejectionHandler
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.uninstall = function uninstall() {
|
this.uninstall = function uninstall() {
|
||||||
global.onerror = originalHandler;
|
global.onerror = originalHandler;
|
||||||
if (global.removeEventListener) {
|
global.removeEventListener(
|
||||||
global.removeEventListener(
|
'unhandledrejection',
|
||||||
'unhandledrejection',
|
browserRejectionHandler
|
||||||
browserRejectionHandler
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user