diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index f72d9123..0d54f813 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -2942,20 +2942,25 @@ getJasmineRequireObj().clearStack = function(j$) { global.process.versions && typeof global.process.versions.node === 'string'; - const SAFARI = + // Windows builds of WebKit have a fairly generic user agent string when no application name is provided: + // e.g. "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/605.1.15 (KHTML, like Gecko)" + const SAFARI_OR_WIN_WEBKIT = global.navigator && - /^((?!chrome|android).)*safari/i.test(global.navigator.userAgent); + /(^((?!chrome|android).)*safari)|(Win64; x64\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\)$)/i.test( + global.navigator.userAgent + ); if (NODE_JS) { // Unlike browsers, Node doesn't require us to do a periodic setTimeout // so we avoid the overhead. return nodeQueueMicrotaskImpl(global); } else if ( - SAFARI || + SAFARI_OR_WIN_WEBKIT || j$.util.isUndefined(global.MessageChannel) /* tests */ ) { - // queueMicrotask is dramatically faster than MessageChannel in Safari, - // at least through version 16. + // queueMicrotask is dramatically faster than MessageChannel in Safari + // and other WebKit-based browsers, such as the one distributed by Playwright + // to test Safari-like behavior on Windows. // Some of our own integration tests provide a mock queueMicrotask in all // environments because it's simpler to mock than MessageChannel. return browserQueueMicrotaskImpl(global); diff --git a/spec/core/ClearStackSpec.js b/spec/core/ClearStackSpec.js index 626969f5..b60aee7e 100644 --- a/spec/core/ClearStackSpec.js +++ b/spec/core/ClearStackSpec.js @@ -22,6 +22,19 @@ describe('ClearStack', function() { }); }); + describe("in WebKit (Playwright's build for Windows)", function() { + usesQueueMicrotaskWithSetTimeout(function() { + return { + navigator: { + userAgent: + 'Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/605.1.15 (KHTML, like Gecko)' + }, + // queueMicrotask should be used even though MessageChannel is present + MessageChannel: fakeMessageChannel + }; + }); + }); + describe('in browsers other than Safari', function() { usesMessageChannel(function() { return { diff --git a/src/core/ClearStack.js b/src/core/ClearStack.js index 3be593c4..c8b2ed21 100644 --- a/src/core/ClearStack.js +++ b/src/core/ClearStack.js @@ -68,20 +68,25 @@ getJasmineRequireObj().clearStack = function(j$) { global.process.versions && typeof global.process.versions.node === 'string'; - const SAFARI = + // Windows builds of WebKit have a fairly generic user agent string when no application name is provided: + // e.g. "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/605.1.15 (KHTML, like Gecko)" + const SAFARI_OR_WIN_WEBKIT = global.navigator && - /^((?!chrome|android).)*safari/i.test(global.navigator.userAgent); + /(^((?!chrome|android).)*safari)|(Win64; x64\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\)$)/i.test( + global.navigator.userAgent + ); if (NODE_JS) { // Unlike browsers, Node doesn't require us to do a periodic setTimeout // so we avoid the overhead. return nodeQueueMicrotaskImpl(global); } else if ( - SAFARI || + SAFARI_OR_WIN_WEBKIT || j$.util.isUndefined(global.MessageChannel) /* tests */ ) { - // queueMicrotask is dramatically faster than MessageChannel in Safari, - // at least through version 16. + // queueMicrotask is dramatically faster than MessageChannel in Safari + // and other WebKit-based browsers, such as the one distributed by Playwright + // to test Safari-like behavior on Windows. // Some of our own integration tests provide a mock queueMicrotask in all // environments because it's simpler to mock than MessageChannel. return browserQueueMicrotaskImpl(global);