|
1 | 1 | 'use strict';
|
2 |
| -/* globals Promise: false */ |
3 | 2 | /* !
|
4 | 3 | * type-detect
|
5 | 4 | * Copyright(c) 2013 jake luer <jake@alogicalparadox.com>
|
6 | 5 | * MIT Licensed
|
7 | 6 | */
|
8 |
| -var isPrototypeOfExists = typeof Object.getPrototypeOf === 'function'; |
9 |
| -var promiseExists = typeof Promise === 'function'; |
| 7 | +var getPrototypeOfExists = typeof Object.getPrototypeOf === 'function'; |
| 8 | +var globalObject = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : self; // eslint-disable-line |
| 9 | +var isDom = 'location' in globalObject && 'document' in globalObject; |
| 10 | +var htmlElementExists = typeof HTMLElement !== 'undefined'; |
| 11 | +var symbolExists = typeof Symbol !== 'undefined'; |
| 12 | +var mapExists = typeof Map !== 'undefined'; |
| 13 | +var setExists = typeof Set !== 'undefined'; |
| 14 | +var dataViewExists = typeof DataView !== 'undefined'; |
| 15 | +var symbolIteratorExists = symbolExists && Symbol.iterator; |
| 16 | +var setEntriesExists = setExists && typeof Set.prototype.entries === 'function'; |
| 17 | +var mapEntriesExists = mapExists && typeof Map.prototype.entries === 'function'; |
| 18 | +var setIteratorPrototype = getPrototypeOfExists && setEntriesExists && Object.getPrototypeOf(new Set().entries()); |
| 19 | +var mapIteratorPrototype = getPrototypeOfExists && mapEntriesExists && Object.getPrototypeOf(new Map().entries()); |
| 20 | +var arrayIteratorExists = symbolIteratorExists && typeof Array.prototype[Symbol.iterator] === 'function'; |
| 21 | +var arrayIteratorPrototype = arrayIteratorExists && Object.getPrototypeOf([][Symbol.iterator]()); |
| 22 | +var stringIteratorExists = symbolIteratorExists && typeof Array.prototype[Symbol.iterator] === 'function'; |
| 23 | +var stringIteratorPrototype = stringIteratorExists && Object.getPrototypeOf(''[Symbol.iterator]()); |
10 | 24 | var toStringLeftSliceLength = 8;
|
11 | 25 | var toStringRightSliceLength = -1;
|
12 | 26 | /**
|
@@ -40,16 +54,155 @@ module.exports = function typeDetect(obj) {
|
40 | 54 | return 'undefined';
|
41 | 55 | }
|
42 | 56 |
|
43 |
| - /* ! Spec Conformance |
44 |
| - * ES6$25.4.5.4 - Promise.prototype[@@toStringTag] should be "Promise": |
45 |
| - * Test: `Object.prototype.toString.call(Promise.resolve())`` |
46 |
| - * - Chrome <=47 === "[object Object]" |
47 |
| - * - Edge <=20 === "[object Object]" |
48 |
| - * - Firefox 29-Latest === "[object Promise]" |
49 |
| - * - Safari 7.1-Latest === "[object Promise]" |
50 |
| - */ |
51 |
| - if (promiseExists && isPrototypeOfExists && Object.getPrototypeOf(obj) === Promise.prototype) { |
52 |
| - return 'promise'; |
| 57 | + if (isDom) { |
| 58 | + /* ! Spec Conformance |
| 59 | + * (https://html.spec.whatwg.org/multipage/browsers.html#location) |
| 60 | + * WhatWG HTML$7.7.3 - The `Location` interface |
| 61 | + * Test: `Object.prototype.toString.call(window.location)`` |
| 62 | + * - IE <=11 === "[object Object]" |
| 63 | + * - IE Edge <=13 === "[object Object]" |
| 64 | + */ |
| 65 | + if (obj === globalObject.location) { |
| 66 | + return 'location'; |
| 67 | + } |
| 68 | + |
| 69 | + /* ! Spec Conformance |
| 70 | + * (https://html.spec.whatwg.org/#document) |
| 71 | + * WhatWG HTML$3.1.1 - The `Document` object |
| 72 | + * Note: Most browsers currently adher to the W3C DOM Level 2 spec |
| 73 | + * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-26809268) |
| 74 | + * which suggests that browsers should use HTMLTableCellElement for |
| 75 | + * both TD and TH elements. WhatWG separates these. |
| 76 | + * WhatWG HTML states: |
| 77 | + * > For historical reasons, Window objects must also have a |
| 78 | + * > writable, configurable, non-enumerable property named |
| 79 | + * > HTMLDocument whose value is the Document interface object. |
| 80 | + * Test: `Object.prototype.toString.call(document)`` |
| 81 | + * - Chrome === "[object HTMLDocument]" |
| 82 | + * - Firefox === "[object HTMLDocument]" |
| 83 | + * - Safari === "[object HTMLDocument]" |
| 84 | + * - IE <=10 === "[object Document]" |
| 85 | + * - IE 11 === "[object HTMLDocument]" |
| 86 | + * - IE Edge <=13 === "[object HTMLDocument]" |
| 87 | + */ |
| 88 | + if (obj === globalObject.document) { |
| 89 | + return 'document'; |
| 90 | + } |
| 91 | + |
| 92 | + /* ! Spec Conformance |
| 93 | + * (https://html.spec.whatwg.org/multipage/webappapis.html#mimetypearray) |
| 94 | + * WhatWG HTML$8.6.1.5 - Plugins - Interface MimeTypeArray |
| 95 | + * Test: `Object.prototype.toString.call(navigator.mimeTypes)`` |
| 96 | + * - IE <=10 === "[object MSMimeTypesCollection]" |
| 97 | + */ |
| 98 | + if (obj === (globalObject.navigator || {}).mimeTypes) { |
| 99 | + return 'mimetypearray'; |
| 100 | + } |
| 101 | + |
| 102 | + /* ! Spec Conformance |
| 103 | + * (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray) |
| 104 | + * WhatWG HTML$8.6.1.5 - Plugins - Interface PluginArray |
| 105 | + * Test: `Object.prototype.toString.call(navigator.plugins)`` |
| 106 | + * - IE <=10 === "[object MSPluginsCollection]" |
| 107 | + */ |
| 108 | + if (obj === (globalObject.navigator || {}).plugins) { |
| 109 | + return 'pluginarray'; |
| 110 | + } |
| 111 | + |
| 112 | + /* ! Spec Conformance |
| 113 | + * (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray) |
| 114 | + * WhatWG HTML$4.4.4 - The `blockquote` element - Interface `HTMLQuoteElement` |
| 115 | + * Test: `Object.prototype.toString.call(document.createElement('blockquote'))`` |
| 116 | + * - IE <=10 === "[object HTMLBlockElement]" |
| 117 | + */ |
| 118 | + if (htmlElementExists && obj instanceof HTMLElement && obj.tagName === 'BLOCKQUOTE') { |
| 119 | + return 'htmlquoteelement'; |
| 120 | + } |
| 121 | + |
| 122 | + /* ! Spec Conformance |
| 123 | + * (https://html.spec.whatwg.org/#htmltabledatacellelement) |
| 124 | + * WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableDataCellElement` |
| 125 | + * Note: Most browsers currently adher to the W3C DOM Level 2 spec |
| 126 | + * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075) |
| 127 | + * which suggests that browsers should use HTMLTableCellElement for |
| 128 | + * both TD and TH elements. WhatWG separates these. |
| 129 | + * Test: Object.prototype.toString.call(document.createElement('td')) |
| 130 | + * - Chrome === "[object HTMLTableCellElement]" |
| 131 | + * - Firefox === "[object HTMLTableCellElement]" |
| 132 | + * - Safari === "[object HTMLTableCellElement]" |
| 133 | + */ |
| 134 | + if (htmlElementExists && obj instanceof HTMLElement && obj.tagName === 'TD') { |
| 135 | + return 'htmltabledatacellelement'; |
| 136 | + } |
| 137 | + |
| 138 | + /* ! Spec Conformance |
| 139 | + * (https://html.spec.whatwg.org/#htmltableheadercellelement) |
| 140 | + * WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableHeaderCellElement` |
| 141 | + * Note: Most browsers currently adher to the W3C DOM Level 2 spec |
| 142 | + * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075) |
| 143 | + * which suggests that browsers should use HTMLTableCellElement for |
| 144 | + * both TD and TH elements. WhatWG separates these. |
| 145 | + * Test: Object.prototype.toString.call(document.createElement('th')) |
| 146 | + * - Chrome === "[object HTMLTableCellElement]" |
| 147 | + * - Firefox === "[object HTMLTableCellElement]" |
| 148 | + * - Safari === "[object HTMLTableCellElement]" |
| 149 | + */ |
| 150 | + if (htmlElementExists && obj instanceof HTMLElement && obj.tagName === 'TH') { |
| 151 | + return 'htmltableheadercellelement'; |
| 152 | + } |
| 153 | + } |
| 154 | + |
| 155 | + if (getPrototypeOfExists && (symbolExists === false || typeof obj[Symbol.toStringTag] === 'undefined')) { |
| 156 | + var objPrototype = Object.getPrototypeOf(obj); |
| 157 | + /* ! Spec Conformance |
| 158 | + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-dataview.prototype-@@tostringtag) |
| 159 | + * ES6$24.2.4.21 - DataView.prototype[@@toStringTag] should be "DataView": |
| 160 | + * Test: `Object.prototype.toString.call(new DataView(new ArrayBuffer(1)))`` |
| 161 | + * - Edge <=13 === "[object Object]" |
| 162 | + */ |
| 163 | + if (dataViewExists && objPrototype === DataView.prototype) { |
| 164 | + return 'dataview'; |
| 165 | + } |
| 166 | + |
| 167 | + /* ! Spec Conformance |
| 168 | + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%mapiteratorprototype%-@@tostringtag) |
| 169 | + * ES6$23.1.5.2.2 - %MapIteratorPrototype%[@@toStringTag] should be "Map Iterator": |
| 170 | + * Test: `Object.prototype.toString.call(new Map().entries())`` |
| 171 | + * - Edge <=13 === "[object Object]" |
| 172 | + */ |
| 173 | + if (mapExists && objPrototype === mapIteratorPrototype) { |
| 174 | + return 'map iterator'; |
| 175 | + } |
| 176 | + |
| 177 | + /* ! Spec Conformance |
| 178 | + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%setiteratorprototype%-@@tostringtag) |
| 179 | + * ES6$23.2.5.2.2 - %SetIteratorPrototype%[@@toStringTag] should be "Set Iterator": |
| 180 | + * Test: `Object.prototype.toString.call(new Set().entries())`` |
| 181 | + * - Edge <=13 === "[object Object]" |
| 182 | + */ |
| 183 | + if (setExists && objPrototype === setIteratorPrototype) { |
| 184 | + return 'set iterator'; |
| 185 | + } |
| 186 | + |
| 187 | + /* ! Spec Conformance |
| 188 | + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%arrayiteratorprototype%-@@tostringtag) |
| 189 | + * ES6$22.1.5.2.2 - %ArrayIteratorPrototype%[@@toStringTag] should be "Array Iterator": |
| 190 | + * Test: `Object.prototype.toString.call([][Symbol.iterator]())`` |
| 191 | + * - Edge <=13 === "[object Object]" |
| 192 | + */ |
| 193 | + if (arrayIteratorExists && objPrototype === arrayIteratorPrototype) { |
| 194 | + return 'array iterator'; |
| 195 | + } |
| 196 | + |
| 197 | + /* ! Spec Conformance |
| 198 | + * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%stringiteratorprototype%-@@tostringtag) |
| 199 | + * ES6$21.1.5.2.2 - %StringIteratorPrototype%[@@toStringTag] should be "String Iterator": |
| 200 | + * Test: `Object.prototype.toString.call(''[Symbol.iterator]())`` |
| 201 | + * - Edge <=13 === "[object Object]" |
| 202 | + */ |
| 203 | + if (stringIteratorExists && objPrototype === stringIteratorPrototype) { |
| 204 | + return 'string iterator'; |
| 205 | + } |
53 | 206 | }
|
54 | 207 |
|
55 | 208 | return Object
|
|
0 commit comments