Skip to content

Commit

Permalink
fix: detection logic in quasi-browser environments
Browse files Browse the repository at this point in the history
- 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`.
  • Loading branch information
meeber committed Dec 4, 2017
1 parent f79e0e4 commit c11e8ff
Showing 1 changed file with 53 additions and 53 deletions.
106 changes: 53 additions & 53 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,6 @@ const promiseExists = typeof Promise === 'function';
/* eslint-disable no-undef */
const globalObject = typeof self === 'object' ? self : global; // eslint-disable-line id-blacklist

/*
* All of these attributes must be available on the global object for the current environment
* to be considered a DOM environment (browser)
*/
const isDom = typeof window === 'object' &&
'document' in window &&
'navigator' in window &&
'HTMLElement' in window;
/* eslint-enable */

const symbolExists = typeof Symbol !== 'undefined';
const mapExists = typeof Map !== 'undefined';
const setExists = typeof Set !== 'undefined';
Expand All @@ -36,6 +26,14 @@ const stringIteratorExists = symbolIteratorExists && typeof String.prototype[Sym
const stringIteratorPrototype = stringIteratorExists && Object.getPrototypeOf(''[Symbol.iterator]());
const toStringLeftSliceLength = 8;
const toStringRightSliceLength = -1;
const windowExists = typeof window === 'object';
const windowLocationExists = windowExists && typeof window.location === 'object';
const windowDocumentExists = windowExists && typeof window.document === 'object';
const windowNavigatorExists = windowExists && typeof window.navigator === 'object';
const windowNavigatorMimeTypesExists = windowNavigatorExists && typeof window.navigator.mimeTypes === 'object';
const windowNavigatorPluginsExists = windowNavigatorExists && typeof window.navigator.plugins === 'object';
const windowHTMLElementExists = windowExists &&
(typeof window.HTMLElement === 'function' || typeof window.HTMLElement === 'object');
/**
* ### typeOf (obj)
*
Expand Down Expand Up @@ -109,15 +107,15 @@ export default function typeDetect(obj) {
return 'Array';
}

if (isDom) {
if (windowExists) {
/* ! Spec Conformance
* (https://html.spec.whatwg.org/multipage/browsers.html#location)
* WhatWG HTML$7.7.3 - The `Location` interface
* Test: `Object.prototype.toString.call(window.location)``
* - IE <=11 === "[object Object]"
* - IE Edge <=13 === "[object Object]"
*/
if (obj === globalObject.location) {
if (windowLocationExists && obj === window.location) {
return 'Location';
}

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

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

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

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

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

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

Expand Down

0 comments on commit c11e8ff

Please sign in to comment.