From 46ff44dd83a025acc7a75141a20533c250479eda Mon Sep 17 00:00:00 2001 From: Timmy Willison Date: Wed, 7 Feb 2024 10:37:51 -0500 Subject: [PATCH 1/4] Core: Fix compatibility with sinon.useFakeTimers in IE The Promise polyfill needed to save the unmodified setImmediate function in IE to use for Promise._immediateFn --- lib/promise-polyfill.js | 16 +++++++++------- test/main/promise.js | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/lib/promise-polyfill.js b/lib/promise-polyfill.js index 0513c4a0b..cbb1dd4cd 100644 --- a/lib/promise-polyfill.js +++ b/lib/promise-polyfill.js @@ -373,16 +373,18 @@ Promise.race = function(arr) { }; // Use polyfill for setImmediate for performance gains -Promise._immediateFn = +// @ts-ignore +if (typeof setImmediate === 'function') { // @ts-ignore - (typeof setImmediate === 'function' && - function(fn) { - // @ts-ignore - setImmediate(fn); - }) || - function(fn) { + var setImmediateFunc = setImmediate; + Promise._immediateFn = function(fn) { + setImmediateFunc(fn); + }; +} else { + Promise._immediateFn = function(fn) { setTimeoutFunc(fn, 0); }; +} Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) { if (typeof console !== 'undefined' && console) { diff --git a/test/main/promise.js b/test/main/promise.js index 8745e7da9..931203c07 100644 --- a/test/main/promise.js +++ b/test/main/promise.js @@ -8,6 +8,24 @@ var defer = typeof setTimeout !== 'undefined' Promise.resolve().then(fn); }; +// Get the global namespace the same way +// as the Promise polyfill. +var globalNS = (function() { + if (typeof globalThis !== 'undefined') { + return globalThis; + } + if (typeof self !== 'undefined') { + return self; + } + if (typeof window !== 'undefined') { + return window; + } + if (typeof global !== 'undefined') { + return global; + } + throw new Error('unable to locate global object'); +})(); + // NOTE: Adds 1 assertion function createMockPromise (assert, reject, value) { if (arguments.length < 3) { @@ -247,4 +265,25 @@ QUnit.module('Support for Promise', function () { return createMockPromise(assert, true, new Error('this is an error')); }); + + QUnit.module('compatible with fake timers', { + beforeEach: function (assert) { + this.setTimeout = globalNS.setTimeout; + globalNS.setTimeout = function () {}; + this.setImmediate = globalNS.setImmediate; + globalNS.setImmediate = function () {}; + // Adds 1 assertion + return createMockPromise(assert); + }, + afterEach: function (assert) { + globalNS.setTimeout = this.setTimeout; + globalNS.setImmediate = this.setImmediate; + // Adds 1 assertion + return createMockPromise(assert); + } + }); + + QUnit.test('test', function (assert) { + assert.expect(2); + }); }); From e7dbd7a9679fbb1ae5574a1bfe0d1837567d8964 Mon Sep 17 00:00:00 2001 From: Timmy Willison Date: Wed, 7 Feb 2024 20:06:13 -0500 Subject: [PATCH 2/4] fixup! address feedback --- lib/promise-polyfill.js | 2 ++ test/main/promise.js | 10 +++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/promise-polyfill.js b/lib/promise-polyfill.js index cbb1dd4cd..e56fc8618 100644 --- a/lib/promise-polyfill.js +++ b/lib/promise-polyfill.js @@ -26,6 +26,8 @@ THE SOFTWARE. Patches for use in QUnit: +- 2024-02-07: Save umodified setImmediate to avoid conflicts with fake timers. + - 2021-01-09: Export as module only, don't change global scope as QUnit must not affect the host context (e.g. people may test their application intentionally with different or no polyfills and we must not affect that). diff --git a/test/main/promise.js b/test/main/promise.js index 931203c07..5141ea5a8 100644 --- a/test/main/promise.js +++ b/test/main/promise.js @@ -270,14 +270,18 @@ QUnit.module('Support for Promise', function () { beforeEach: function (assert) { this.setTimeout = globalNS.setTimeout; globalNS.setTimeout = function () {}; - this.setImmediate = globalNS.setImmediate; - globalNS.setImmediate = function () {}; + if (globalNS.setImmediate) { + this.setImmediate = globalNS.setImmediate; + globalNS.setImmediate = function () {}; + } // Adds 1 assertion return createMockPromise(assert); }, afterEach: function (assert) { globalNS.setTimeout = this.setTimeout; - globalNS.setImmediate = this.setImmediate; + if (this.setImmediate) { + globalNS.setImmediate = this.setImmediate; + } // Adds 1 assertion return createMockPromise(assert); } From 4003c88cd58ac75f2a44e8bac252521e135b821b Mon Sep 17 00:00:00 2001 From: Timo Tijhof Date: Thu, 8 Feb 2024 12:35:52 +0000 Subject: [PATCH 3/4] Update promise-polyfill.js fix typo in "umodified". --- lib/promise-polyfill.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/promise-polyfill.js b/lib/promise-polyfill.js index e56fc8618..d144ac46d 100644 --- a/lib/promise-polyfill.js +++ b/lib/promise-polyfill.js @@ -26,8 +26,6 @@ THE SOFTWARE. Patches for use in QUnit: -- 2024-02-07: Save umodified setImmediate to avoid conflicts with fake timers. - - 2021-01-09: Export as module only, don't change global scope as QUnit must not affect the host context (e.g. people may test their application intentionally with different or no polyfills and we must not affect that). @@ -38,6 +36,8 @@ Patches for use in QUnit: - 2021-01-10: Add 'globalThis' to globalNS implementation to support SpiderMonkey. +- 2024-02-07: Save unmodified setImmediate to avoid conflicts with Sinon fake timers. + */ (function () { 'use strict'; From 3633a7216c1f295f4b1931a0d2ef9fa802bcfcda Mon Sep 17 00:00:00 2001 From: Timo Tijhof Date: Thu, 8 Feb 2024 12:38:24 +0000 Subject: [PATCH 4/4] Update promise.js: fix lint errors --- test/main/promise.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/main/promise.js b/test/main/promise.js index 5141ea5a8..a828bb331 100644 --- a/test/main/promise.js +++ b/test/main/promise.js @@ -8,19 +8,22 @@ var defer = typeof setTimeout !== 'undefined' Promise.resolve().then(fn); }; -// Get the global namespace the same way -// as the Promise polyfill. -var globalNS = (function() { +// Get the global namespace the same way as the Promise polyfill. +var globalNS = (function () { if (typeof globalThis !== 'undefined') { + // eslint-disable-next-line no-undef return globalThis; } if (typeof self !== 'undefined') { + // eslint-disable-next-line no-undef return self; } if (typeof window !== 'undefined') { + // eslint-disable-next-line no-undef return window; } if (typeof global !== 'undefined') { + // eslint-disable-next-line no-undef return global; } throw new Error('unable to locate global object');