From 04e60ac6c5a34fdce0b68a2878f618a037546f17 Mon Sep 17 00:00:00 2001 From: Timo Tijhof Date: Mon, 15 Jul 2024 22:28:58 +0100 Subject: [PATCH] Core: Refactor internal core.js to declare QUnit as a single literal Remove any remaining dynamic or indirection in declaring the exports. Ref https://github.com/qunitjs/qunit/issues/1551. Ref https://github.com/qunitjs/qunit/issues/1724. --- src/callbacks.js | 38 +++++++++++++++++++++++++++ src/core.js | 37 ++++++++++++++------------ src/core/logging.js | 50 ------------------------------------ src/core/processing-queue.js | 2 +- src/test.js | 2 +- 5 files changed, 61 insertions(+), 68 deletions(-) create mode 100644 src/callbacks.js delete mode 100644 src/core/logging.js diff --git a/src/callbacks.js b/src/callbacks.js new file mode 100644 index 000000000..880b28d49 --- /dev/null +++ b/src/callbacks.js @@ -0,0 +1,38 @@ +import config from './core/config.js'; +import Promise from './promise.js'; + +export function createRegisterCallbackFunction (key) { + // Initialize key collection of callback + if (typeof config.callbacks[key] === 'undefined') { + config.callbacks[key] = []; + } + + return function registerCallback (callback) { + if (typeof callback !== 'function') { + throw new TypeError('Callback parameter must be a function'); + } + config.callbacks[key].push(callback); + }; +} + +export function runLoggingCallbacks (key, arg) { + const callbacks = config.callbacks[key]; + + // Handling 'log' callbacks separately. Unlike the other callbacks, + // the log callback is not controlled by the processing queue, + // but rather used by asserts. Hence to promisfy the 'log' callback + // would mean promisfying each step of a test + if (key === 'log') { + callbacks.map(callback => callback(arg)); + return; + } + + // ensure that each callback is executed serially + let promiseChain = Promise.resolve(); + callbacks.forEach(callback => { + promiseChain = promiseChain.then(() => { + return Promise.resolve(callback(arg)); + }); + }); + return promiseChain; +} diff --git a/src/core.js b/src/core.js index 0cfd14523..467b4c6bd 100644 --- a/src/core.js +++ b/src/core.js @@ -10,7 +10,7 @@ import reporters from './reporters.js'; import config from './core/config.js'; import hooks from './core/hooks.js'; import { extend, objectType, is, performance } from './core/utilities.js'; -import { registerLoggingCallbacks, runLoggingCallbacks } from './core/logging.js'; +import { createRegisterCallbackFunction, runLoggingCallbacks } from './callbacks.js'; import { sourceFromStacktrace } from './core/stacktrace.js'; import ProcessingQueue from './core/processing-queue.js'; @@ -20,8 +20,6 @@ import onUncaughtException from './core/on-uncaught-exception.js'; import diff from './diff.js'; import version from './version.js'; -const QUnit = {}; - // The "currentModule" object would ideally be defined using the createModule() // function. Since it isn't, add the missing suiteReport property to it now that // we have loaded all source code required to do so. @@ -32,13 +30,14 @@ config.currentModule.suiteReport = runSuite; config._pq = new ProcessingQueue(test); -// Figure out if we're running the tests from a server or not -QUnit.isLocal = (window && window.location && window.location.protocol === 'file:'); +const QUnit = { + + // Figure out if we're running the tests from a server or not + isLocal: (window && window.location && window.location.protocol === 'file:'), -// Expose the current QUnit version -QUnit.version = version; + // Expose the current QUnit version + version, -extend(QUnit, { config, urlParams, @@ -48,11 +47,19 @@ extend(QUnit, { reporters, hooks, is, - objectType, on, + objectType, onUncaughtException, pushFailure, + begin: createRegisterCallbackFunction('begin'), + done: createRegisterCallbackFunction('done'), + log: createRegisterCallbackFunction('log'), + moduleDone: createRegisterCallbackFunction('moduleDone'), + moduleStart: createRegisterCallbackFunction('moduleStart'), + testDone: createRegisterCallbackFunction('testDone'), + testStart: createRegisterCallbackFunction('testStart'), + assert: Assert.prototype, module, test, @@ -81,15 +88,15 @@ extend(QUnit, { // still wait for DOM ready to ensure reliable integration of reporters. window.addEventListener('load', function () { setTimeout(function () { - begin(); + doBegin(); }); }); } else if (setTimeout) { setTimeout(function () { - begin(); + doBegin(); }); } else { - begin(); + doBegin(); } }, @@ -101,16 +108,14 @@ extend(QUnit, { const source = sourceFromStacktrace(offset); return source; } -}); - -registerLoggingCallbacks(QUnit); +} function unblockAndAdvanceQueue () { config.blocking = false; config._pq.advance(); } -function begin () { +function doBegin () { if (config.started) { unblockAndAdvanceQueue(); return; diff --git a/src/core/logging.js b/src/core/logging.js deleted file mode 100644 index 763dd3420..000000000 --- a/src/core/logging.js +++ /dev/null @@ -1,50 +0,0 @@ -import config from './config.js'; -import Promise from '../promise.js'; - -// Register logging callbacks -export function registerLoggingCallbacks (obj) { - const callbackNames = ['begin', 'done', 'log', 'testStart', 'testDone', - 'moduleStart', 'moduleDone']; - - function registerLoggingCallback (key) { - return function loggingCallback (callback) { - if (typeof callback !== 'function') { - throw new TypeError('Callback parameter must be a function'); - } - config.callbacks[key].push(callback); - }; - } - - for (let i = 0; i < callbackNames.length; i++) { - const key = callbackNames[i]; - - // Initialize key collection of logging callback - if (typeof config.callbacks[key] === 'undefined') { - config.callbacks[key] = []; - } - - obj[key] = registerLoggingCallback(key); - } -} - -export function runLoggingCallbacks (key, arg) { - const callbacks = config.callbacks[key]; - - // Handling 'log' callbacks separately. Unlike the other callbacks, - // the log callback is not controlled by the processing queue, - // but rather used by asserts. Hence to promisfy the 'log' callback - // would mean promisfying each step of a test - if (key === 'log') { - callbacks.map(callback => callback(arg)); - return; - } - - // ensure that each callback is executed serially - let promiseChain = Promise.resolve(); - callbacks.forEach(callback => { - promiseChain = promiseChain.then(() => { - return Promise.resolve(callback(arg)); - }); - }); - return promiseChain; -} diff --git a/src/core/processing-queue.js b/src/core/processing-queue.js index b8c4201a2..397dbf5d3 100644 --- a/src/core/processing-queue.js +++ b/src/core/processing-queue.js @@ -1,6 +1,6 @@ import config from './config.js'; import { extend, generateHash, performance } from './utilities.js'; -import { runLoggingCallbacks } from './logging.js'; +import { runLoggingCallbacks } from '../callbacks.js'; import Promise from '../promise.js'; import { runSuite } from '../module.js'; diff --git a/src/test.js b/src/test.js index 465af0ddd..25b250585 100644 --- a/src/test.js +++ b/src/test.js @@ -14,7 +14,7 @@ import { inArray, performance } from './core/utilities.js'; -import { runLoggingCallbacks } from './core/logging.js'; +import { runLoggingCallbacks } from './callbacks.js'; import { extractStacktrace, sourceFromStacktrace } from './core/stacktrace.js'; import dump from './dump.js';