Skip to content

Commit

Permalink
fix: correct all spec inconsistencies
Browse files Browse the repository at this point in the history
  • Loading branch information
keithamus committed Mar 13, 2016
1 parent 5ec4759 commit cf65048
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 15 deletions.
179 changes: 166 additions & 13 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
'use strict';
/* globals Promise: false */
/* !
* type-detect
* Copyright(c) 2013 jake luer <jake@alogicalparadox.com>
* MIT Licensed
*/
var isPrototypeOfExists = typeof Object.getPrototypeOf === 'function';
var promiseExists = typeof Promise === 'function';
var getPrototypeOfExists = typeof Object.getPrototypeOf === 'function';
var globalObject = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : self; // eslint-disable-line
var isDom = 'location' in globalObject && 'document' in globalObject;
var htmlElementExists = typeof HTMLElement !== 'undefined';
var symbolExists = typeof Symbol !== 'undefined';
var mapExists = typeof Map !== 'undefined';
var setExists = typeof Set !== 'undefined';
var dataViewExists = typeof DataView !== 'undefined';
var symbolIteratorExists = symbolExists && Symbol.iterator;
var setEntriesExists = setExists && typeof Set.prototype.entries === 'function';
var mapEntriesExists = mapExists && typeof Map.prototype.entries === 'function';
var setIteratorPrototype = getPrototypeOfExists && setEntriesExists && Object.getPrototypeOf(new Set().entries());
var mapIteratorPrototype = getPrototypeOfExists && mapEntriesExists && Object.getPrototypeOf(new Map().entries());
var arrayIteratorExists = symbolIteratorExists && typeof Array.prototype[Symbol.iterator] === 'function';
var arrayIteratorPrototype = arrayIteratorExists && Object.getPrototypeOf([][Symbol.iterator]());
var stringIteratorExists = symbolIteratorExists && typeof Array.prototype[Symbol.iterator] === 'function';
var stringIteratorPrototype = stringIteratorExists && Object.getPrototypeOf(''[Symbol.iterator]());
var toStringLeftSliceLength = 8;
var toStringRightSliceLength = -1;
/**
Expand Down Expand Up @@ -40,16 +54,155 @@ module.exports = function typeDetect(obj) {
return 'undefined';
}

/* ! Spec Conformance
* ES6$25.4.5.4 - Promise.prototype[@@toStringTag] should be "Promise":
* Test: `Object.prototype.toString.call(Promise.resolve())``
* - Chrome <=47 === "[object Object]"
* - Edge <=20 === "[object Object]"
* - Firefox 29-Latest === "[object Promise]"
* - Safari 7.1-Latest === "[object Promise]"
*/
if (promiseExists && isPrototypeOfExists && Object.getPrototypeOf(obj) === Promise.prototype) {
return 'promise';
if (isDom) {
/* ! 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) {
return 'location';
}

/* ! Spec Conformance
* (https://html.spec.whatwg.org/#document)
* WhatWG HTML$3.1.1 - The `Document` object
* Note: Most browsers currently adher to the W3C DOM Level 2 spec
* (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-26809268)
* which suggests that browsers should use HTMLTableCellElement for
* both TD and TH elements. WhatWG separates these.
* WhatWG HTML states:
* > For historical reasons, Window objects must also have a
* > writable, configurable, non-enumerable property named
* > HTMLDocument whose value is the Document interface object.
* Test: `Object.prototype.toString.call(document)``
* - Chrome === "[object HTMLDocument]"
* - Firefox === "[object HTMLDocument]"
* - Safari === "[object HTMLDocument]"
* - IE <=10 === "[object Document]"
* - IE 11 === "[object HTMLDocument]"
* - IE Edge <=13 === "[object HTMLDocument]"
*/
if (obj === globalObject.document) {
return 'document';
}

/* ! Spec Conformance
* (https://html.spec.whatwg.org/multipage/webappapis.html#mimetypearray)
* WhatWG HTML$8.6.1.5 - Plugins - Interface MimeTypeArray
* Test: `Object.prototype.toString.call(navigator.mimeTypes)``
* - IE <=10 === "[object MSMimeTypesCollection]"
*/
if (obj === (globalObject.navigator || {}).mimeTypes) {
return 'mimetypearray';
}

/* ! Spec Conformance
* (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray)
* WhatWG HTML$8.6.1.5 - Plugins - Interface PluginArray
* Test: `Object.prototype.toString.call(navigator.plugins)``
* - IE <=10 === "[object MSPluginsCollection]"
*/
if (obj === (globalObject.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 (htmlElementExists && obj instanceof HTMLElement && 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 (htmlElementExists && obj instanceof HTMLElement && 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 (htmlElementExists && obj instanceof HTMLElement && obj.tagName === 'TH') {
return 'htmltableheadercellelement';
}
}

if (getPrototypeOfExists && (symbolExists === false || typeof obj[Symbol.toStringTag] === 'undefined')) {
var objPrototype = Object.getPrototypeOf(obj);
/* ! Spec Conformance
* (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-dataview.prototype-@@tostringtag)
* ES6$24.2.4.21 - DataView.prototype[@@toStringTag] should be "DataView":
* Test: `Object.prototype.toString.call(new DataView(new ArrayBuffer(1)))``
* - Edge <=13 === "[object Object]"
*/
if (dataViewExists && objPrototype === DataView.prototype) {
return 'dataview';
}

/* ! Spec Conformance
* (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%mapiteratorprototype%-@@tostringtag)
* ES6$23.1.5.2.2 - %MapIteratorPrototype%[@@toStringTag] should be "Map Iterator":
* Test: `Object.prototype.toString.call(new Map().entries())``
* - Edge <=13 === "[object Object]"
*/
if (mapExists && objPrototype === mapIteratorPrototype) {
return 'map iterator';
}

/* ! Spec Conformance
* (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%setiteratorprototype%-@@tostringtag)
* ES6$23.2.5.2.2 - %SetIteratorPrototype%[@@toStringTag] should be "Set Iterator":
* Test: `Object.prototype.toString.call(new Set().entries())``
* - Edge <=13 === "[object Object]"
*/
if (setExists && objPrototype === setIteratorPrototype) {
return 'set iterator';
}

/* ! Spec Conformance
* (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%arrayiteratorprototype%-@@tostringtag)
* ES6$22.1.5.2.2 - %ArrayIteratorPrototype%[@@toStringTag] should be "Array Iterator":
* Test: `Object.prototype.toString.call([][Symbol.iterator]())``
* - Edge <=13 === "[object Object]"
*/
if (arrayIteratorExists && objPrototype === arrayIteratorPrototype) {
return 'array iterator';
}

/* ! Spec Conformance
* (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%stringiteratorprototype%-@@tostringtag)
* ES6$21.1.5.2.2 - %StringIteratorPrototype%[@@toStringTag] should be "String Iterator":
* Test: `Object.prototype.toString.call(''[Symbol.iterator]())``
* - Edge <=13 === "[object Object]"
*/
if (stringIteratorExists && objPrototype === stringIteratorPrototype) {
return 'string iterator';
}
}

return Object
Expand Down
9 changes: 8 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,15 @@
"extends": [
"strict/es5"
],
"env": {
"es6": true
},
"globals": {
"HTMLElement": false
},
"rules": {
"complexity": 0
"complexity": 0,
"max-statements": 0
}
},
"dependencies": {},
Expand Down
2 changes: 1 addition & 1 deletion test/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describeIf(typeof window !== 'undefined' && typeof window.document !== 'undefine
});

it('document', function () {
assert(type(document) === 'htmldocument');
assert(type(document) === 'document');
});

it('domparser', function () {
Expand Down

0 comments on commit cf65048

Please sign in to comment.