Skip to content

Commit 0b776c1

Browse files
authored
Core: Fix IE 10 and IE 11 compatibility of internal Promise with sinon.useFakeTimers
The Promise polyfill needs to save the unmodified reference to the `setImmediate` function in IE, for use in `Promise._immediateFn`. This broke in QUnit 2.14.0, with the introduction of internal Promise usage as part of #1535. Closes #1738.
1 parent 5b86ff0 commit 0b776c1

File tree

2 files changed

+57
-7
lines changed

2 files changed

+57
-7
lines changed

lib/promise-polyfill.js

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ Patches for use in QUnit:
3636
3737
- 2021-01-10: Add 'globalThis' to globalNS implementation to support SpiderMonkey.
3838
39+
- 2024-02-07: Save unmodified setImmediate to avoid conflicts with Sinon fake timers.
40+
3941
*/
4042

4143
(function () { 'use strict';
@@ -373,16 +375,18 @@ Promise.race = function(arr) {
373375
};
374376

375377
// Use polyfill for setImmediate for performance gains
376-
Promise._immediateFn =
378+
// @ts-ignore
379+
if (typeof setImmediate === 'function') {
377380
// @ts-ignore
378-
(typeof setImmediate === 'function' &&
379-
function(fn) {
380-
// @ts-ignore
381-
setImmediate(fn);
382-
}) ||
383-
function(fn) {
381+
var setImmediateFunc = setImmediate;
382+
Promise._immediateFn = function(fn) {
383+
setImmediateFunc(fn);
384+
};
385+
} else {
386+
Promise._immediateFn = function(fn) {
384387
setTimeoutFunc(fn, 0);
385388
};
389+
}
386390

387391
Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) {
388392
if (typeof console !== 'undefined' && console) {

test/main/promise.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,27 @@ var defer = typeof setTimeout !== 'undefined'
88
Promise.resolve().then(fn);
99
};
1010

11+
// Get the global namespace the same way as the Promise polyfill.
12+
var globalNS = (function () {
13+
if (typeof globalThis !== 'undefined') {
14+
// eslint-disable-next-line no-undef
15+
return globalThis;
16+
}
17+
if (typeof self !== 'undefined') {
18+
// eslint-disable-next-line no-undef
19+
return self;
20+
}
21+
if (typeof window !== 'undefined') {
22+
// eslint-disable-next-line no-undef
23+
return window;
24+
}
25+
if (typeof global !== 'undefined') {
26+
// eslint-disable-next-line no-undef
27+
return global;
28+
}
29+
throw new Error('unable to locate global object');
30+
})();
31+
1132
// NOTE: Adds 1 assertion
1233
function createMockPromise (assert, reject, value) {
1334
if (arguments.length < 3) {
@@ -247,4 +268,29 @@ QUnit.module('Support for Promise', function () {
247268

248269
return createMockPromise(assert, true, new Error('this is an error'));
249270
});
271+
272+
QUnit.module('compatible with fake timers', {
273+
beforeEach: function (assert) {
274+
this.setTimeout = globalNS.setTimeout;
275+
globalNS.setTimeout = function () {};
276+
if (globalNS.setImmediate) {
277+
this.setImmediate = globalNS.setImmediate;
278+
globalNS.setImmediate = function () {};
279+
}
280+
// Adds 1 assertion
281+
return createMockPromise(assert);
282+
},
283+
afterEach: function (assert) {
284+
globalNS.setTimeout = this.setTimeout;
285+
if (this.setImmediate) {
286+
globalNS.setImmediate = this.setImmediate;
287+
}
288+
// Adds 1 assertion
289+
return createMockPromise(assert);
290+
}
291+
});
292+
293+
QUnit.test('test', function (assert) {
294+
assert.expect(2);
295+
});
250296
});

0 commit comments

Comments
 (0)