diff --git a/src/export.js b/src/export.js index e0bd6da3b..9d5d0415f 100644 --- a/src/export.js +++ b/src/export.js @@ -1,18 +1,39 @@ /* global module, exports, define */ import { window, document, globalThis } from './globals'; +/** + * Available exports: + * + * globalThis: + * - browser (globalThis === window) + * - Web Worker (globalThis === self) + * - Node.js + * - SpiderMonkey (mozjs) + * - Rhino (since 7.14) + * - any other embedded JS engine + * + * CommonJS module.exports (commonjs2): + * - Node.js + * + * CommonJS exports (commonjs, https://wiki.commonjs.org/wiki/Modules): + * - Rhino + * + * AMD (RequireJS): + * - Browser + */ export default function exportQUnit (QUnit) { - let exportedModule = false; - - if (window && document) { - // QUnit may be defined when it is preconfigured but then only QUnit and QUnit.config may be defined. - if (window.QUnit && window.QUnit.version) { - throw new Error('QUnit has already been defined.'); - } - - window.QUnit = QUnit; - - exportedModule = true; + // If there is a placeholder QUnit global for preconfiguration, + // we must replace it with the real one. Such placeholder can be recognised + // by not having QUnit.version (it should only contain a QUnit.config property). + // + // If a real QUnit global is already defined, then replace our reference with that one. + // Since QUnit 3.0, we no longer throw an error if QUnit is loaded twice. + // This enables supporting mixed use of ESM import and CJS require() in a project, + // in a way that avoids split-brain problems for QUnit state. + if (globalThis.QUnit && globalThis.QUnit.version) { + QUnit = globalThis.QUnit; + } else { + globalThis.QUnit = QUnit; } // For Node.js @@ -21,15 +42,11 @@ export default function exportQUnit (QUnit) { // For consistency with CommonJS environments' exports module.exports.QUnit = QUnit; - - exportedModule = true; } // For CommonJS with exports, but without module.exports, like Rhino if (typeof exports !== 'undefined' && exports) { exports.QUnit = QUnit; - - exportedModule = true; } // For AMD @@ -38,13 +55,5 @@ export default function exportQUnit (QUnit) { return QUnit; }); QUnit.config.autostart = false; - - exportedModule = true; - } - - // For other environments, including Web Workers (globalThis === self), - // SpiderMonkey (mozjs), and other embedded JavaScript engines - if (!exportedModule) { - globalThis.QUnit = QUnit; } }