Skip to content

Commit 88e9e54

Browse files
committed
Refactor to support globalThis and add browser implementation to avoid issues with bundlers and global
1 parent 9180e22 commit 88e9e54

6 files changed

Lines changed: 323 additions & 7 deletions

File tree

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2022 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
// MODULES //
22+
23+
var isBoolean = require( '@stdlib/assert/is-boolean' ).isPrimitive;
24+
var format = require( '@stdlib/string/format' );
25+
var getThis = require( './codegen.js' );
26+
var Self = require( './self.js' );
27+
var Win = require( './window.js' );
28+
var GlobalThis = require( './global_this.js' );
29+
30+
31+
// MAIN //
32+
33+
/**
34+
* Returns the global object.
35+
*
36+
* ## Notes
37+
*
38+
* - Using code generation is the **most** reliable way to resolve the global object; however, doing so is likely to violate content security policies (CSPs) in, e.g., Chrome Apps and elsewhere.
39+
*
40+
* @private
41+
* @param {boolean} [codegen=false] - boolean indicating whether to use code generation to resolve the global object
42+
* @throws {TypeError} must provide a boolean
43+
* @throws {Error} unable to resolve global object
44+
* @returns {Object} global object
45+
*
46+
* @example
47+
* var g = getGlobal();
48+
* // returns {...}
49+
*/
50+
function getGlobal( codegen ) {
51+
if ( arguments.length ) {
52+
if ( !isBoolean( codegen ) ) {
53+
throw new TypeError( format( 'invalid argument. Must provide a boolean. Value: `%s`.', codegen ) );
54+
}
55+
if ( codegen ) {
56+
return getThis();
57+
}
58+
// Fall through...
59+
}
60+
// Case: 2020 revision of ECMAScript standard
61+
if ( GlobalThis ) {
62+
return GlobalThis;
63+
}
64+
// Case: browsers and web workers
65+
if ( Self ) {
66+
return Self;
67+
}
68+
// Case: browsers
69+
if ( Win ) {
70+
return Win;
71+
}
72+
// Case: unknown
73+
throw new Error( 'unexpected error. Unable to resolve global object.' );
74+
}
75+
76+
77+
// EXPORTS //
78+
79+
module.exports = getGlobal;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2022 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
// MAIN //
22+
23+
var obj = ( typeof globalThis === 'object' ) ? globalThis : null; // eslint-disable-line no-undef
24+
25+
26+
// EXPORTS //
27+
28+
module.exports = obj;

lib/node_modules/@stdlib/utils/global/lib/main.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ var getThis = require( './codegen.js' );
2626
var Self = require( './self.js' );
2727
var Win = require( './window.js' );
2828
var Global = require( './global.js' );
29+
var GlobalThis = require( './global_this.js' );
2930

3031

3132
// MAIN //
@@ -56,6 +57,10 @@ function getGlobal( codegen ) {
5657
}
5758
// Fall through...
5859
}
60+
// Case: 2020 revision of ECMAScript standard
61+
if ( GlobalThis ) {
62+
return GlobalThis;
63+
}
5964
// Case: browsers and web workers
6065
if ( Self ) {
6166
return Self;

lib/node_modules/@stdlib/utils/global/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
}
1515
],
1616
"main": "./lib",
17+
"browser": "./lib/browser.js",
1718
"directories": {
1819
"benchmark": "./benchmark",
1920
"doc": "./docs",
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2018 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
// MODULES //
22+
23+
var tape = require( 'tape' );
24+
var proxyquire = require( 'proxyquire' );
25+
var getGlobal = require( './../lib/browser.js' );
26+
27+
28+
// TESTS //
29+
30+
tape( 'main export is a function', function test( t ) {
31+
t.ok( true, __filename );
32+
t.strictEqual( typeof getGlobal, 'function', 'main export is a function' );
33+
t.end();
34+
});
35+
36+
tape( 'the function throws a type error if provided an argument which is not a boolean primitive', function test( t ) {
37+
var values;
38+
var i;
39+
40+
values = [
41+
'5',
42+
5,
43+
NaN,
44+
void 0,
45+
null,
46+
[],
47+
{},
48+
function noop() {}
49+
];
50+
for ( i = 0; i < values.length; i++ ) {
51+
t.throws( badValue( values[ i ] ), TypeError, 'throws an error when provided '+values[ i ] );
52+
}
53+
t.end();
54+
55+
function badValue( value ) {
56+
return function badValue() {
57+
getGlobal( value );
58+
};
59+
}
60+
});
61+
62+
tape( 'if the `codegen` argument is `true`, the function returns an object', function test( t ) {
63+
t.strictEqual( typeof getGlobal( true ), 'object', 'returns an object' );
64+
t.end();
65+
});
66+
67+
tape( 'if the `globalThis` global variable is defined, the function returns the `globalThis` global object', function test( t ) {
68+
var GlobalThis;
69+
var getGlobal;
70+
71+
GlobalThis = {};
72+
getGlobal = proxyquire( './../lib/browser.js', {
73+
'./global_this.js': GlobalThis,
74+
'./window.js': false,
75+
'./self.js': false
76+
});
77+
78+
t.strictEqual( getGlobal(), GlobalThis, 'returns expected value' );
79+
t.end();
80+
});
81+
82+
tape( 'the `globalThis` global variable takes precedence over other potential global objects', function test( t ) {
83+
var GlobalThis;
84+
var getGlobal;
85+
86+
GlobalThis = {};
87+
getGlobal = proxyquire( './../lib/browser.js', {
88+
'./global_this.js': GlobalThis,
89+
'./window.js': {},
90+
'./self.js': {}
91+
});
92+
93+
t.strictEqual( getGlobal(), GlobalThis, 'returns expected value' );
94+
t.end();
95+
});
96+
97+
tape( 'if the `self` global variable is defined, the function returns the `self` global object', function test( t ) {
98+
var getGlobal;
99+
var Self;
100+
101+
Self = {};
102+
getGlobal = proxyquire( './../lib/browser.js', {
103+
'./self.js': Self,
104+
'./window.js': false,
105+
'./global_this.js': false
106+
});
107+
108+
t.strictEqual( getGlobal(), Self, 'returns expected value' );
109+
t.end();
110+
});
111+
112+
tape( 'the `self` global variable takes precedence over other potential global objects', function test( t ) {
113+
var getGlobal;
114+
var Self;
115+
116+
Self = {};
117+
getGlobal = proxyquire( './../lib/browser.js', {
118+
'./self.js': Self,
119+
'./window.js': {},
120+
'./global_this.js': false
121+
});
122+
123+
t.strictEqual( getGlobal(), Self, 'returns expected value' );
124+
t.end();
125+
});
126+
127+
tape( 'if the `window` global variable is defined, the function returns the `window` global object', function test( t ) {
128+
var getGlobal;
129+
var Window;
130+
131+
Window = {};
132+
getGlobal = proxyquire( './../lib/browser.js', {
133+
'./self.js': false,
134+
'./window.js': Window,
135+
'./global_this.js': false
136+
});
137+
138+
t.strictEqual( getGlobal(), Window, 'returns expected value' );
139+
t.end();
140+
});
141+
142+
tape( 'if unable to resolve a global object, the function throws an error (default)', function test( t ) {
143+
var getGlobal = proxyquire( './../lib/browser.js', {
144+
'./self.js': false,
145+
'./window.js': false,
146+
'./global_this.js': false
147+
});
148+
t.throws( getGlobal, Error, 'throws an error' );
149+
t.end();
150+
});
151+
152+
tape( 'if unable to resolve a global object, the function throws an error (codegen=false)', function test( t ) {
153+
var getGlobal = proxyquire( './../lib/browser.js', {
154+
'./self.js': false,
155+
'./window.js': false,
156+
'./global_this.js': false
157+
});
158+
t.throws( foo, Error, 'throws an error' );
159+
t.end();
160+
161+
function foo() {
162+
getGlobal( false );
163+
}
164+
});

0 commit comments

Comments
 (0)