Skip to content

Commit

Permalink
Build: Restore strict mode compatibility
Browse files Browse the repository at this point in the history
When bundling qunit as a library in another build, the use of `this`
would cause an error strict mode due to being undefined there.

Adopt [ES2020 globalThis](https://github.com/tc39/proposal-global),
and polyfill it for environments that don't implement it yet.

Fixes #1557.
Closes #1558.
  • Loading branch information
ef4 authored Mar 4, 2021
1 parent d80a986 commit eeaa482
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 22 deletions.
49 changes: 49 additions & 0 deletions lib/global-this-polyfill.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
https://github.com/ungap/global-this/blob/v0.4.4/esm/index.js
Copyright (c) 2020, Andrea Giammarchi, @WebReflection
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
-------
Patches for use in QUnit:
- 2021-02-25: 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).
*/

let foundGlobalThis;

(function (Object) {
if (typeof globalThis === "object") {
foundGlobalThis = globalThis;
} else {
this
? get()
: (Object.defineProperty(Object.prototype, "_T_", {
configurable: true,
get: get,
}),
_T_);

function get() {
foundGlobalThis = this || self;
delete Object.prototype._T_;
}
}
})(Object);

export default foundGlobalThis;
7 changes: 0 additions & 7 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ module.exports = {
__dirname + "/src/html-reporter/es6-map.js",
"utf8"
).toString().trim();
},

globals: {
global: "(function() { return this; }())"
}
},
plugins: [
Expand All @@ -57,8 +53,5 @@ module.exports = {
babelHelpers: "bundled",
babelrc: true
} )
],
external: [
"global"
]
};
4 changes: 2 additions & 2 deletions src/export.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* global module, exports, define */
import { window, document, self } from "./globals";
import global from "global";
import globalThis from "../lib/global-this-polyfill";

export default function exportQUnit( QUnit ) {
let exportedModule = false;
Expand Down Expand Up @@ -54,6 +54,6 @@ export default function exportQUnit( QUnit ) {
// For other environments, such as SpiderMonkey (mozjs) and other
// embedded JavaScript engines
if ( !exportedModule ) {
global.QUnit = QUnit;
globalThis.QUnit = QUnit;
}
}
18 changes: 9 additions & 9 deletions src/globals.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import global from "global";
import globalThis from "../lib/global-this-polyfill";

export const window = global.window;
export const self = global.self;
export const console = global.console;
export const setTimeout = global.setTimeout;
export const clearTimeout = global.clearTimeout;
export const window = globalThis.window;
export const self = globalThis.self;
export const console = globalThis.console;
export const setTimeout = globalThis.setTimeout;
export const clearTimeout = globalThis.clearTimeout;

export const document = window && window.document;
export const navigator = window && window.navigator;

export const localSessionStorage = ( function() {
const x = "qunit-test-string";
try {
global.sessionStorage.setItem( x, x );
global.sessionStorage.removeItem( x );
return global.sessionStorage;
globalThis.sessionStorage.setItem( x, x );
globalThis.sessionStorage.removeItem( x );
return globalThis.sessionStorage;
} catch ( e ) {
return undefined;
}
Expand Down
7 changes: 3 additions & 4 deletions src/test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import global from "global";

import globalThis from "../lib/global-this-polyfill";
import { begin } from "./core";
import { setTimeout, clearTimeout } from "./globals";
import { emit } from "./events";
Expand Down Expand Up @@ -648,8 +647,8 @@ function saveGlobal() {
config.pollution = [];

if ( config.noglobals ) {
for ( const key in global ) {
if ( hasOwn.call( global, key ) ) {
for ( const key in globalThis ) {
if ( hasOwn.call( globalThis, key ) ) {

// In Opera sometimes DOM element ids show up here, ignore them
if ( /^qunit-test-output/.test( key ) ) {
Expand Down

0 comments on commit eeaa482

Please sign in to comment.