Skip to content

Commit c11e8ff

Browse files
committed
fix: detection logic in quasi-browser environments
- Always use `window` object for detecting DOM-related types; a quasi-browser environment can be loaded on top of a server environment. - Always verify that each property of `window` exists before using it for type detection; nothing is guaranteed in a quasi-browser environment. - Refactor to remove redundant `instanceof window.HTMLElement`.
1 parent f79e0e4 commit c11e8ff

File tree

1 file changed

+53
-53
lines changed

1 file changed

+53
-53
lines changed

index.js

Lines changed: 53 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,6 @@ const promiseExists = typeof Promise === 'function';
88
/* eslint-disable no-undef */
99
const globalObject = typeof self === 'object' ? self : global; // eslint-disable-line id-blacklist
1010

11-
/*
12-
* All of these attributes must be available on the global object for the current environment
13-
* to be considered a DOM environment (browser)
14-
*/
15-
const isDom = typeof window === 'object' &&
16-
'document' in window &&
17-
'navigator' in window &&
18-
'HTMLElement' in window;
19-
/* eslint-enable */
20-
2111
const symbolExists = typeof Symbol !== 'undefined';
2212
const mapExists = typeof Map !== 'undefined';
2313
const setExists = typeof Set !== 'undefined';
@@ -36,6 +26,14 @@ const stringIteratorExists = symbolIteratorExists && typeof String.prototype[Sym
3626
const stringIteratorPrototype = stringIteratorExists && Object.getPrototypeOf(''[Symbol.iterator]());
3727
const toStringLeftSliceLength = 8;
3828
const toStringRightSliceLength = -1;
29+
const windowExists = typeof window === 'object';
30+
const windowLocationExists = windowExists && typeof window.location === 'object';
31+
const windowDocumentExists = windowExists && typeof window.document === 'object';
32+
const windowNavigatorExists = windowExists && typeof window.navigator === 'object';
33+
const windowNavigatorMimeTypesExists = windowNavigatorExists && typeof window.navigator.mimeTypes === 'object';
34+
const windowNavigatorPluginsExists = windowNavigatorExists && typeof window.navigator.plugins === 'object';
35+
const windowHTMLElementExists = windowExists &&
36+
(typeof window.HTMLElement === 'function' || typeof window.HTMLElement === 'object');
3937
/**
4038
* ### typeOf (obj)
4139
*
@@ -109,15 +107,15 @@ export default function typeDetect(obj) {
109107
return 'Array';
110108
}
111109

112-
if (isDom) {
110+
if (windowExists) {
113111
/* ! Spec Conformance
114112
* (https://html.spec.whatwg.org/multipage/browsers.html#location)
115113
* WhatWG HTML$7.7.3 - The `Location` interface
116114
* Test: `Object.prototype.toString.call(window.location)``
117115
* - IE <=11 === "[object Object]"
118116
* - IE Edge <=13 === "[object Object]"
119117
*/
120-
if (obj === globalObject.location) {
118+
if (windowLocationExists && obj === window.location) {
121119
return 'Location';
122120
}
123121

@@ -140,7 +138,7 @@ export default function typeDetect(obj) {
140138
* - IE 11 === "[object HTMLDocument]"
141139
* - IE Edge <=13 === "[object HTMLDocument]"
142140
*/
143-
if (obj === globalObject.document) {
141+
if (windowDocumentExists && obj === window.document) {
144142
return 'Document';
145143
}
146144

@@ -150,7 +148,7 @@ export default function typeDetect(obj) {
150148
* Test: `Object.prototype.toString.call(navigator.mimeTypes)``
151149
* - IE <=10 === "[object MSMimeTypesCollection]"
152150
*/
153-
if (obj === (globalObject.navigator || {}).mimeTypes) {
151+
if (windowNavigatorMimeTypesExists && obj === window.navigator.mimeTypes) {
154152
return 'MimeTypeArray';
155153
}
156154

@@ -160,50 +158,52 @@ export default function typeDetect(obj) {
160158
* Test: `Object.prototype.toString.call(navigator.plugins)``
161159
* - IE <=10 === "[object MSPluginsCollection]"
162160
*/
163-
if (obj === (globalObject.navigator || {}).plugins) {
161+
if (windowNavigatorPluginsExists && obj === window.navigator.plugins) {
164162
return 'PluginArray';
165163
}
166164

167-
/* ! Spec Conformance
168-
* (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray)
169-
* WhatWG HTML$4.4.4 - The `blockquote` element - Interface `HTMLQuoteElement`
170-
* Test: `Object.prototype.toString.call(document.createElement('blockquote'))``
171-
* - IE <=10 === "[object HTMLBlockElement]"
172-
*/
173-
if (obj instanceof globalObject.HTMLElement && obj.tagName === 'BLOCKQUOTE') {
174-
return 'HTMLQuoteElement';
175-
}
165+
if (windowHTMLElementExists && obj instanceof window.HTMLElement) {
166+
/* ! Spec Conformance
167+
* (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray)
168+
* WhatWG HTML$4.4.4 - The `blockquote` element - Interface `HTMLQuoteElement`
169+
* Test: `Object.prototype.toString.call(document.createElement('blockquote'))``
170+
* - IE <=10 === "[object HTMLBlockElement]"
171+
*/
172+
if (obj.tagName === 'BLOCKQUOTE') {
173+
return 'HTMLQuoteElement';
174+
}
176175

177-
/* ! Spec Conformance
178-
* (https://html.spec.whatwg.org/#htmltabledatacellelement)
179-
* WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableDataCellElement`
180-
* Note: Most browsers currently adher to the W3C DOM Level 2 spec
181-
* (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075)
182-
* which suggests that browsers should use HTMLTableCellElement for
183-
* both TD and TH elements. WhatWG separates these.
184-
* Test: Object.prototype.toString.call(document.createElement('td'))
185-
* - Chrome === "[object HTMLTableCellElement]"
186-
* - Firefox === "[object HTMLTableCellElement]"
187-
* - Safari === "[object HTMLTableCellElement]"
188-
*/
189-
if (obj instanceof globalObject.HTMLElement && obj.tagName === 'TD') {
190-
return 'HTMLTableDataCellElement';
191-
}
176+
/* ! Spec Conformance
177+
* (https://html.spec.whatwg.org/#htmltabledatacellelement)
178+
* WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableDataCellElement`
179+
* Note: Most browsers currently adher to the W3C DOM Level 2 spec
180+
* (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075)
181+
* which suggests that browsers should use HTMLTableCellElement for
182+
* both TD and TH elements. WhatWG separates these.
183+
* Test: Object.prototype.toString.call(document.createElement('td'))
184+
* - Chrome === "[object HTMLTableCellElement]"
185+
* - Firefox === "[object HTMLTableCellElement]"
186+
* - Safari === "[object HTMLTableCellElement]"
187+
*/
188+
if (obj.tagName === 'TD') {
189+
return 'HTMLTableDataCellElement';
190+
}
192191

193-
/* ! Spec Conformance
194-
* (https://html.spec.whatwg.org/#htmltableheadercellelement)
195-
* WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableHeaderCellElement`
196-
* Note: Most browsers currently adher to the W3C DOM Level 2 spec
197-
* (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075)
198-
* which suggests that browsers should use HTMLTableCellElement for
199-
* both TD and TH elements. WhatWG separates these.
200-
* Test: Object.prototype.toString.call(document.createElement('th'))
201-
* - Chrome === "[object HTMLTableCellElement]"
202-
* - Firefox === "[object HTMLTableCellElement]"
203-
* - Safari === "[object HTMLTableCellElement]"
204-
*/
205-
if (obj instanceof globalObject.HTMLElement && obj.tagName === 'TH') {
206-
return 'HTMLTableHeaderCellElement';
192+
/* ! Spec Conformance
193+
* (https://html.spec.whatwg.org/#htmltableheadercellelement)
194+
* WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableHeaderCellElement`
195+
* Note: Most browsers currently adher to the W3C DOM Level 2 spec
196+
* (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075)
197+
* which suggests that browsers should use HTMLTableCellElement for
198+
* both TD and TH elements. WhatWG separates these.
199+
* Test: Object.prototype.toString.call(document.createElement('th'))
200+
* - Chrome === "[object HTMLTableCellElement]"
201+
* - Firefox === "[object HTMLTableCellElement]"
202+
* - Safari === "[object HTMLTableCellElement]"
203+
*/
204+
if (obj.tagName === 'TH') {
205+
return 'HTMLTableHeaderCellElement';
206+
}
207207
}
208208
}
209209

0 commit comments

Comments
 (0)