[Pkg-javascript-commits] [node-type-detect] 01/08: Imported Upstream version 4.0.0

Sruthi Chandran srud-guest at moszumanska.debian.org
Wed Oct 12 17:52:25 UTC 2016


This is an automated email from the git hooks/post-receive script.

srud-guest pushed a commit to branch master
in repository node-type-detect.

commit c474dd5b69bedf0a02d04ac10eaa3209ed97a370
Author: Syam G Krishnan <sgk at riseup.net>
Date:   Tue Oct 11 17:33:40 2016 +0530

    Imported Upstream version 4.0.0
---
 .gitignore                   |  21 +++
 .travis.yml                  |  25 +++
 LICENSE                      |  19 +++
 MAINTAINERS                  |   4 +
 README.md                    | 219 ++++++++++++++++++++++++++
 bench/.eslintrc              |  17 ++
 bench/index.js               |  78 +++++++++
 index.js                     | 366 +++++++++++++++++++++++++++++++++++++++++++
 karma.conf.js                |  96 ++++++++++++
 package.json                 |  85 ++++++++++
 test/.eslintrc               |  19 +++
 test/dom.js                  | 332 +++++++++++++++++++++++++++++++++++++++
 test/index.js                | 272 ++++++++++++++++++++++++++++++++
 test/new-ecmascript-types.js | 136 ++++++++++++++++
 test/node.js                 |  18 +++
 15 files changed, 1707 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6b5659a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,21 @@
+lib-cov
+*.seed
+*.log
+*.csv
+*.dat
+*.out
+*.pid
+*.gz
+
+pids
+logs
+results
+build
+components
+
+node_modules
+npm-debug.log
+
+coverage/
+
+type-detect.js
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..0521b42
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,25 @@
+sudo: false
+language: node_js
+addons:
+  sauce_connect: true
+cache:
+  directories:
+    - node_modules
+node_js:
+  - 0.1
+  - 4.3
+  - stable
+before_install:
+  - npm i -g npm
+script:
+  - npm t
+after_success:
+  - 'travis-after-all && npm run semantic-release'
+env:
+  global:
+    - secure: AgiUWRCNP2z0oHCjdm3lk4YawBOQz8Q4DOrzOR3tDt2fSWo2t40cynfGJlQwpFmTvec5G04lO9bEC9/yoW7xAS0ysu5p7utngXaKtKDoq3Zr0aYLLLsCv/0PAv1YstMyo/mRbRetxob76wUFcrbB3r5alIF5YW1JCmj/O9bvdUQ=
+    - secure: TepAZmznoPWUX12snu2eb7Sni+31tiOO6ZeU3wovrhCpGzykBNr6xAvUklr88L+uKtvfsTq8sipX0jtZvL7lcIEzujirTpjaj4QV5mUFiV2N40o+C3LdNmfmU9dhUcXRu9vMSs9uc7YfPers4We8X99UxTHxljK7VyJe39ULpRk=
+    - SAUCE_CONNECT_READY_FILE=/tmp/sauce-connect-ready
+    - LOGS_DIR=/tmp/chai-build/logs
+    - secure: fakflt6DaPW9NYFdUpTfQGoKFt5F1EZeSiGqWeTCZ3+VDiEC/d9rPf7JfHkDklpr4swEW7ovbfV4PHp+MeT+jje8eQAezbhdT8hAmChykeTKKfgvifMwQp6TD3DQVrf6cJqqZfkJkkzuYJjGivZ8FA4KXTglyBrjozM8KH675UU=
+    - secure: bE+qM+B4dA+oQSfHo4BM9NVU5LCdgkEmfThfmIp3kmX19RO/1R1dlu18M1rVyDUNaqFUwCsq/W/9a+Dv1r+7knmfmJoUKuXCcIjn6WBs4Pd2kPwjCjvQ+5RWTw67v44de78AFb3IH7dT2H+fhgeHrfaI3NIV27BlKx6OqTnqDRY=
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..7ea799f
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2013 Jake Luer <jake at alogicalparadox.com> (http://alogicalparadox.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/MAINTAINERS b/MAINTAINERS
new file mode 100644
index 0000000..baebbae
--- /dev/null
+++ b/MAINTAINERS
@@ -0,0 +1,4 @@
+keithamus
+davelosert
+lucasfcosta
+meeber  
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..da892e5
--- /dev/null
+++ b/README.md
@@ -0,0 +1,219 @@
+<h1 align=center>
+  <a href="http://chaijs.com" title="Chai Documentation">
+    <img alt="ChaiJS" src="http://chaijs.com/img/chai-logo.png"/> type-detect
+  </a>
+</h1>
+
+<p align=center>
+  Improved typeof detection for <a href="http://nodejs.org">node</a> and the browser.
+</p>
+
+<p align=center>
+  <a href="./LICENSE">
+    <img
+      alt="license:mit"
+      src="https://img.shields.io/badge/license-mit-green.svg?style=flat-square"
+    />
+  </a>
+  <a href="https://github.com/chaijs/type-detect/releases">
+    <img
+      alt="tag:?"
+      src="https://img.shields.io/github/tag/chaijs/type-detect.svg?style=flat-square"
+    />
+  </a>
+  <a href="https://travis-ci.org/chaijs/type-detect">
+    <img
+      alt="build:?"
+      src="https://img.shields.io/travis/chaijs/type-detect/master.svg?style=flat-square"
+    />
+  </a>
+  <a href="https://coveralls.io/r/chaijs/type-detect">
+    <img
+      alt="coverage:?"
+      src="https://img.shields.io/coveralls/chaijs/type-detect/master.svg?style=flat-square"
+    />
+  </a>
+  <a href="https://www.npmjs.com/packages/type-detect">
+    <img
+      alt="npm:?"
+      src="https://img.shields.io/npm/v/type-detect.svg?style=flat-square"
+    />
+  </a>
+  <a href="https://www.npmjs.com/packages/type-detect">
+    <img
+      alt="dependencies:?"
+      src="https://img.shields.io/npm/dm/type-detect.svg?style=flat-square"
+    />
+  </a>
+  <a href="">
+    <img
+      alt="devDependencies:?"
+      src="https://img.shields.io/david/chaijs/type-detect.svg?style=flat-square"
+    />
+  </a>
+  <br/>
+  <a href="https://saucelabs.com/u/chaijs-type-detect">
+    <img
+      alt="Selenium Test Status"
+      src="https://saucelabs.com/browser-matrix/chaijs-type-detect.svg"
+    />
+  </a>
+  <br>
+  <a href="https://chai-slack.herokuapp.com/">
+    <img
+      alt="Join the Slack chat"
+      src="https://img.shields.io/badge/slack-join%20chat-E2206F.svg?style=flat-square"
+    />
+  </a>
+  <a href="https://gitter.im/chaijs/chai">
+    <img
+      alt="Join the Gitter chat"
+      src="https://img.shields.io/badge/gitter-join%20chat-D0104D.svg?style=flat-square"
+    />
+  </a>
+</p>
+
+## What is Type-Detect?
+
+Type Detect is a module which you can use to detect the type of a given object. It returns a string representation of the object's type, either using [`typeof`](http://www.ecma-international.org/ecma-262/6.0/index.html#sec-typeof-operator) or [`@@toStringTag`](http://www.ecma-international.org/ecma-262/6.0/index.html#sec-symbol.tostringtag). It also normalizes some object names for consistency among browsers.
+
+## Why?
+
+The `typeof` operator will only specify primitive values; everthing else is `"object"` (including `null`, arrays, regexps, etc). Many developers use `Object.prototype.toString()` - which is a fine alternative and returns many more types (null returns `[object Null]`, Arrays as `[object Array]`, regexps as `[object RegExp]` etc). 
+
+Sadly, `Object.prototype.toString` is slow, and buggy. By slow - we mean it is slower than `typeof`. By buggy - we mean that some values (like Promises, the global object, iterators, dataviews, a bunch of HTML elements) all report different things in different browsers.
+
+`type-detect` fixes all of the shortcomings with `Object.prototype.toString`. We have extra code to speed up checks of JS and DOM objects, as much as 20-30x faster for some values. `type-detect` also fixes any consistencies with these objects.
+
+## Installation
+
+### Node.js
+
+`type-detect` is available on [npm](http://npmjs.org). To install it, type:
+
+    $ npm install type-detect
+
+### Browsers
+
+You can also use it within the browser; install via npm and use the `type-detect.js` file found within the download. For example:
+
+```html
+<script src="./node_modules/type-detect/type-detect.js"></script>
+```
+
+## Usage
+
+The primary export of `type-detect` is function that can serve as a replacement for `typeof`. The results of this function will be more specific than that of native `typeof`.
+
+```js
+var type = require('type-detect');
+```
+
+#### array
+
+```js
+assert(type([]) === 'Array');
+assert(type(new Array()) === 'Array');
+```
+
+#### regexp
+
+```js
+assert(type(/a-z/gi) === 'RegExp');
+assert(type(new RegExp('a-z')) === 'RegExp');
+```
+
+#### function
+
+```js
+assert(type(function () {}) === 'function');
+```
+
+#### arguments
+
+```js
+(function () {
+  assert(type(arguments) === 'Arguments');
+})();
+```
+
+#### date
+
+```js
+assert(type(new Date) === 'Date');
+```
+
+#### number
+
+```js
+assert(type(1) === 'number');
+assert(type(1.234) === 'number');
+assert(type(-1) === 'number');
+assert(type(-1.234) === 'number');
+assert(type(Infinity) === 'number');
+assert(type(NaN) === 'number');
+assert(type(new Number(1)) === 'Number'); // note - the object version has a capital N
+```
+
+#### string
+
+```js
+assert(type('hello world') === 'string');
+assert(type(new String('hello')) === 'String'); // note - the object version has a capital S
+```
+
+#### null
+
+```js
+assert(type(null) === 'null');
+assert(type(undefined) !== 'null');
+```
+
+#### undefined
+
+```js
+assert(type(undefined) === 'undefined');
+assert(type(null) !== 'undefined');
+```
+
+#### object
+
+```js
+var Noop = function () {};
+assert(type({}) === 'Object');
+assert(type(Noop) !== 'Object');
+assert(type(new Noop) === 'Object');
+assert(type(new Object) === 'Object');
+```
+
+#### ECMA6 Types
+
+All new ECMAScript 2015 objects are also supported, such as Promises and Symbols:
+
+```js
+assert(type(new Map() === 'Map');
+assert(type(new WeakMap()) === 'WeakMap');
+assert(type(new Set()) === 'Set');
+assert(type(new WeakSet()) === 'WeakSet');
+assert(type(Symbol()) === 'Symbol');
+assert(type(new Promise(callback) === 'Promise');
+assert(type(new Int8Array()) === 'Int8Array');
+assert(type(new Uint8Array()) === 'Uint8Array');
+assert(type(new UInt8ClampedArray()) === 'Uint8ClampedArray');
+assert(type(new Int16Array()) === 'Int16Array');
+assert(type(new Uint16Array()) === 'Uint16Array');
+assert(type(new Int32Array()) === 'Int32Array');
+assert(type(new UInt32Array()) === 'Uint32Array');
+assert(type(new Float32Array()) === 'Float32Array');
+assert(type(new Float64Array()) === 'Float64Array');
+assert(type(new ArrayBuffer()) === 'ArrayBuffer');
+assert(type(new DataView(arrayBuffer)) === 'DataView');
+```
+
+Also, if you use `Symbol.toStringTag` to change an Objects return value of the `toString()` Method, `type()` will return this value, e.g:
+
+```js
+var myObject = {};
+myObject[Symbol.toStringTag] = 'myCustomType';
+assert(type(myObject) === 'myCustomType');
+```
diff --git a/bench/.eslintrc b/bench/.eslintrc
new file mode 100644
index 0000000..acc6682
--- /dev/null
+++ b/bench/.eslintrc
@@ -0,0 +1,17 @@
+{
+  "extends": [ "strict/test" ],
+  "env": {
+    "node": true,
+    "browser": true,
+    "es6": true
+  },
+  "rules": {
+    "no-new-wrappers": 0,
+    "no-array-constructor": 0,
+    "no-new-object": 0,
+    "no-empty-function": 0,
+    "no-undefined": 0,
+    "no-console": 0,
+    "id-length": 0
+  }
+}
diff --git a/bench/index.js b/bench/index.js
new file mode 100644
index 0000000..c5d5a01
--- /dev/null
+++ b/bench/index.js
@@ -0,0 +1,78 @@
+'use strict';
+var typeDetect = require('../');
+var Benchmark = require('benchmark');
+var benches = [];
+var fixtures = {
+  'string literal    ': '',
+  'array literal     ': [],
+  'boolean literal   ': true,
+  'object literal    ': {},
+  'object from null  ': Object.create(null),
+  'regex literal     ': /^$/,
+  'number literal    ': 1,
+  'promise           ': Promise.resolve(),
+  'null              ': null,
+  'undefined         ': undefined,
+  'function          ': function () {},
+
+  'buffer            ': new Buffer(1),
+  'date              ': new Date(),
+  'error             ': new Error(),
+  'map               ': new Map(),
+  'regex constructor ': new RegExp(),
+  'set               ': new Set(),
+  'string constructor': new String(),
+  'weakmap           ': new WeakMap(),
+  'weakset           ': new WeakSet(),
+  'arguments         ': (function () {
+    return arguments;
+  }()),
+};
+try {
+  fixtures['arrow function    '] = eval('() => {}'); // eslint-disable-line no-eval
+} catch (error) {
+  console.error('cannot benchmark arrow functions');
+}
+try {
+  fixtures['generator function'] = eval('function * generator() {}; generator'); // eslint-disable-line no-eval
+} catch (error) {
+  console.error('cannot benchmark generator functions');
+}
+[
+  'Float64Array', 'Float32Array',
+  'Uint32Array', 'Uint16Array', 'Uint8Array',
+  'Int32Array', 'Int16Array', 'Int8Array',
+  'Uint8ClampedArray',
+].forEach(function (value) {
+  if (typeof global[value] === 'function') {
+    fixtures[value + new Array(19 - value.length).join(' ')] = new (global[value])(1);
+  }
+});
+if (typeof DataView === 'function') {
+  fixtures['DataView          '] = new DataView(new ArrayBuffer(1));
+}
+
+var filter = process.argv[2] || '';
+Object.keys(fixtures).filter(function (key) {
+  return key.indexOf(filter) !== -1;
+}).forEach(function (test) {
+  benches.push(new Benchmark(test, {
+    fn: function () {
+      typeDetect(fixtures[test]);
+    },
+    onCycle: function (event) {
+      process.stdout.clearLine();
+      process.stdout.cursorTo(0);
+      process.stdout.write(event.target.toString());
+    },
+  }));
+});
+Benchmark.invoke(benches, {
+  name: 'run',
+  onCycle: function onCycle() {
+    console.log('');
+  },
+  onComplete: function onComplete() {
+    console.log('~Fin~');
+  },
+});
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..c6d7d5d
--- /dev/null
+++ b/index.js
@@ -0,0 +1,366 @@
+'use strict';
+/* !
+ * type-detect
+ * Copyright(c) 2013 jake luer <jake at alogicalparadox.com>
+ * MIT Licensed
+ */
+var promiseExists = typeof Promise === 'function';
+var globalObject = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : self; // eslint-disable-line
+var isDom = 'location' in globalObject && 'document' in globalObject;
+var symbolExists = typeof Symbol !== 'undefined';
+var mapExists = typeof Map !== 'undefined';
+var setExists = typeof Set !== 'undefined';
+var weakMapExists = typeof WeakMap !== 'undefined';
+var weakSetExists = typeof WeakSet !== 'undefined';
+var dataViewExists = typeof DataView !== 'undefined';
+var symbolIteratorExists = symbolExists && typeof Symbol.iterator !== 'undefined';
+var symbolToStringTagExists = symbolExists && typeof Symbol.toStringTag !== 'undefined';
+var setEntriesExists = setExists && typeof Set.prototype.entries === 'function';
+var mapEntriesExists = mapExists && typeof Map.prototype.entries === 'function';
+var setIteratorPrototype = setEntriesExists && Object.getPrototypeOf(new Set().entries());
+var mapIteratorPrototype = 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;
+/**
+ * ### typeOf (obj)
+ *
+ * Uses `Object.prototype.toString` to determine the type of an object,
+ * normalising behaviour across engine versions & well optimised.
+ *
+ * @param {Mixed} object
+ * @return {String} object type
+ * @api public
+ */
+module.exports = function typeDetect(obj) {
+  /* ! Speed optimisation
+   * Pre:
+   *   string literal     x 3,039,035 ops/sec ±1.62% (78 runs sampled)
+   *   boolean literal    x 1,424,138 ops/sec ±4.54% (75 runs sampled)
+   *   number literal     x 1,653,153 ops/sec ±1.91% (82 runs sampled)
+   *   undefined          x 9,978,660 ops/sec ±1.92% (75 runs sampled)
+   *   function           x 2,556,769 ops/sec ±1.73% (77 runs sampled)
+   * Post:
+   *   string literal     x 38,564,796 ops/sec ±1.15% (79 runs sampled)
+   *   boolean literal    x 31,148,940 ops/sec ±1.10% (79 runs sampled)
+   *   number literal     x 32,679,330 ops/sec ±1.90% (78 runs sampled)
+   *   undefined          x 32,363,368 ops/sec ±1.07% (82 runs sampled)
+   *   function           x 31,296,870 ops/sec ±0.96% (83 runs sampled)
+   */
+  var typeofObj = typeof obj;
+  if (typeofObj !== 'object') {
+    return typeofObj;
+  }
+
+  /* ! Speed optimisation
+   * Pre:
+   *   null               x 28,645,765 ops/sec ±1.17% (82 runs sampled)
+   * Post:
+   *   null               x 36,428,962 ops/sec ±1.37% (84 runs sampled)
+   */
+  if (obj === null) {
+    return 'null';
+  }
+
+  /* ! Spec Conformance
+   * Test: `Object.prototype.toString.call(window)``
+   *  - Node === "[object global]"
+   *  - Chrome === "[object global]"
+   *  - Firefox === "[object Window]"
+   *  - PhantomJS === "[object Window]"
+   *  - Safari === "[object Window]"
+   *  - IE 11 === "[object Window]"
+   *  - IE Edge === "[object Window]"
+   * Test: `Object.prototype.toString.call(this)``
+   *  - Chrome Worker === "[object global]"
+   *  - Firefox Worker === "[object DedicatedWorkerGlobalScope]"
+   *  - Safari Worker === "[object DedicatedWorkerGlobalScope]"
+   *  - IE 11 Worker === "[object WorkerGlobalScope]"
+   *  - IE Edge Worker === "[object WorkerGlobalScope]"
+   */
+  if (obj === globalObject) {
+    return 'global';
+  }
+
+  /* ! Speed optimisation
+   * Pre:
+   *   array literal      x 2,888,352 ops/sec ±0.67% (82 runs sampled)
+   * Post:
+   *   array literal      x 22,479,650 ops/sec ±0.96% (81 runs sampled)
+   */
+  if (Array.isArray(obj)) {
+    return 'Array';
+  }
+
+  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 (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 (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 (obj instanceof HTMLElement && obj.tagName === 'TH') {
+      return 'HTMLTableHeaderCellElement';
+    }
+  }
+
+  /* ! Speed optimisation
+  * Pre:
+  *   Float64Array       x 625,644 ops/sec ±1.58% (80 runs sampled)
+  *   Float32Array       x 1,279,852 ops/sec ±2.91% (77 runs sampled)
+  *   Uint32Array        x 1,178,185 ops/sec ±1.95% (83 runs sampled)
+  *   Uint16Array        x 1,008,380 ops/sec ±2.25% (80 runs sampled)
+  *   Uint8Array         x 1,128,040 ops/sec ±2.11% (81 runs sampled)
+  *   Int32Array         x 1,170,119 ops/sec ±2.88% (80 runs sampled)
+  *   Int16Array         x 1,176,348 ops/sec ±5.79% (86 runs sampled)
+  *   Int8Array          x 1,058,707 ops/sec ±4.94% (77 runs sampled)
+  *   Uint8ClampedArray  x 1,110,633 ops/sec ±4.20% (80 runs sampled)
+  * Post:
+  *   Float64Array       x 7,105,671 ops/sec ±13.47% (64 runs sampled)
+  *   Float32Array       x 5,887,912 ops/sec ±1.46% (82 runs sampled)
+  *   Uint32Array        x 6,491,661 ops/sec ±1.76% (79 runs sampled)
+  *   Uint16Array        x 6,559,795 ops/sec ±1.67% (82 runs sampled)
+  *   Uint8Array         x 6,463,966 ops/sec ±1.43% (85 runs sampled)
+  *   Int32Array         x 5,641,841 ops/sec ±3.49% (81 runs sampled)
+  *   Int16Array         x 6,583,511 ops/sec ±1.98% (80 runs sampled)
+  *   Int8Array          x 6,606,078 ops/sec ±1.74% (81 runs sampled)
+  *   Uint8ClampedArray  x 6,602,224 ops/sec ±1.77% (83 runs sampled)
+  */
+  var stringTag = (symbolToStringTagExists && obj[Symbol.toStringTag]);
+  if (typeof stringTag === 'string') {
+    return stringTag;
+  }
+
+  var objPrototype = Object.getPrototypeOf(obj);
+  /* ! Speed optimisation
+  * Pre:
+  *   regex literal      x 1,772,385 ops/sec ±1.85% (77 runs sampled)
+  *   regex constructor  x 2,143,634 ops/sec ±2.46% (78 runs sampled)
+  * Post:
+  *   regex literal      x 3,928,009 ops/sec ±0.65% (78 runs sampled)
+  *   regex constructor  x 3,931,108 ops/sec ±0.58% (84 runs sampled)
+  */
+  if (objPrototype === RegExp.prototype) {
+    return 'RegExp';
+  }
+
+  /* ! Speed optimisation
+  * Pre:
+  *   date               x 2,130,074 ops/sec ±4.42% (68 runs sampled)
+  * Post:
+  *   date               x 3,953,779 ops/sec ±1.35% (77 runs sampled)
+  */
+  if (objPrototype === Date.prototype) {
+    return 'Date';
+  }
+
+  /* ! Spec Conformance
+   * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-promise.prototype-@@tostringtag)
+   * 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 && objPrototype === Promise.prototype) {
+    return 'Promise';
+  }
+
+  /* ! Speed optimisation
+  * Pre:
+  *   set                x 2,222,186 ops/sec ±1.31% (82 runs sampled)
+  * Post:
+  *   set                x 4,545,879 ops/sec ±1.13% (83 runs sampled)
+  */
+  if (setExists && objPrototype === Set.prototype) {
+    return 'Set';
+  }
+
+  /* ! Speed optimisation
+  * Pre:
+  *   map                x 2,396,842 ops/sec ±1.59% (81 runs sampled)
+  * Post:
+  *   map                x 4,183,945 ops/sec ±6.59% (82 runs sampled)
+  */
+  if (mapExists && objPrototype === Map.prototype) {
+    return 'Map';
+  }
+
+  /* ! Speed optimisation
+  * Pre:
+  *   weakset            x 1,323,220 ops/sec ±2.17% (76 runs sampled)
+  * Post:
+  *   weakset            x 4,237,510 ops/sec ±2.01% (77 runs sampled)
+  */
+  if (weakSetExists && objPrototype === WeakSet.prototype) {
+    return 'WeakSet';
+  }
+
+  /* ! Speed optimisation
+  * Pre:
+  *   weakmap            x 1,500,260 ops/sec ±2.02% (78 runs sampled)
+  * Post:
+  *   weakmap            x 3,881,384 ops/sec ±1.45% (82 runs sampled)
+  */
+  if (weakMapExists && objPrototype === WeakMap.prototype) {
+    return 'WeakMap';
+  }
+
+  /* ! 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';
+  }
+
+  /* ! Speed optimisation
+  * Pre:
+  *   object from null   x 2,424,320 ops/sec ±1.67% (76 runs sampled)
+  * Post:
+  *   object from null   x 5,838,000 ops/sec ±0.99% (84 runs sampled)
+  */
+  if (objPrototype === null) {
+    return 'Object';
+  }
+
+  return Object
+    .prototype
+    .toString
+    .call(obj)
+    .slice(toStringLeftSliceLength, toStringRightSliceLength);
+};
+
+module.exports.typeDetect = module.exports;
diff --git a/karma.conf.js b/karma.conf.js
new file mode 100644
index 0000000..e7a9848
--- /dev/null
+++ b/karma.conf.js
@@ -0,0 +1,96 @@
+'use strict';
+var packageJson = require('./package.json');
+var defaultTimeout = 120000;
+var browserifyIstanbul = require('browserify-istanbul');
+module.exports = function configureKarma(config) {
+  var localBrowsers = [
+    'PhantomJS',
+  ];
+  var sauceLabsBrowsers = {
+    SauceChromeLatest: {
+      base: 'SauceLabs',
+      browserName: 'Chrome',
+    },
+    SauceFirefoxLatest: {
+      base: 'SauceLabs',
+      browserName: 'Firefox',
+    },
+    SauceSafariLatest: {
+      base: 'SauceLabs',
+      browserName: 'Safari',
+      platform: 'OS X 10.11',
+    },
+    SauceInternetExplorerLatest: {
+      base: 'SauceLabs',
+      browserName: 'Internet Explorer',
+    },
+    SauceInternetExplorerOldestSupported: {
+      base: 'SauceLabs',
+      browserName: 'Internet Explorer',
+      version: 9,
+    },
+    SauceEdgeLatest: {
+      base: 'SauceLabs',
+      browserName: 'MicrosoftEdge',
+    },
+    SauceAndroidLatest: {
+      base: 'SauceLabs',
+      browserName: 'Android',
+    },
+  };
+  config.set({
+    basePath: '',
+    browsers: localBrowsers,
+    logLevel: process.env.npm_config_debug ? config.LOG_DEBUG : config.LOG_INFO,
+    frameworks: [ 'browserify', 'mocha' ],
+    files: [ 'test/*.js' ],
+    exclude: [],
+    preprocessors: {
+      'test/*.js': [ 'browserify' ],
+    },
+    browserify: {
+      debug: true,
+      bare: true,
+      transform: [
+        browserifyIstanbul({ ignore: [ '**/node_modules/**', '**/test/**' ] }),
+      ],
+    },
+    reporters: [ 'progress', 'coverage' ],
+    coverageReporter: {
+      type: 'lcov',
+      dir: 'coverage',
+    },
+    port: 9876,
+    colors: true,
+    concurrency: 3,
+    autoWatch: false,
+    captureTimeout: defaultTimeout,
+    browserDisconnectTimeout: defaultTimeout,
+    browserNoActivityTimeout: defaultTimeout,
+    singleRun: true,
+  });
+
+  if (process.env.SAUCE_ACCESS_KEY && process.env.SAUCE_USERNAME) {
+    var branch = process.env.TRAVIS_BRANCH || 'local';
+    var build = 'localbuild';
+    if (process.env.TRAVIS_JOB_NUMBER) {
+      build = 'travis@' + process.env.TRAVIS_JOB_NUMBER;
+    }
+    config.reporters.push('saucelabs');
+    config.set({
+      customLaunchers: sauceLabsBrowsers,
+      browsers: localBrowsers.concat(Object.keys(sauceLabsBrowsers)),
+      sauceLabs: {
+        testName: packageJson.name,
+        tunnelIdentifier: process.env.TRAVIS_JOB_NUMBER || new Date().getTime(),
+        recordVideo: true,
+        startConnect: ('TRAVIS' in process.env) === false,
+        tags: [
+          'typeDetect_' + packageJson.version,
+          process.env.SAUCE_USERNAME + '@' + branch,
+          build,
+        ],
+      },
+    });
+  }
+};
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..c6ae189
--- /dev/null
+++ b/package.json
@@ -0,0 +1,85 @@
+{
+  "name": "type-detect",
+  "description": "Improved typeof detection for node.js and the browser.",
+  "keywords": [
+    "type",
+    "typeof",
+    "types"
+  ],
+  "license": "MIT",
+  "author": "Jake Luer <jake at alogicalparadox.com> (http://alogicalparadox.com)",
+  "contributors": [
+    "David Losert (https://github.com/davelosert)",
+    "Keith Cirkel (https://github.com/keithamus)",
+    "Miroslav Bajtoš (https://github.com/bajtos)"
+  ],
+  "files": [
+    "index.js",
+    "type-detect.js"
+  ],
+  "main": "./index.js",
+  "repository": {
+    "type": "git",
+    "url": "git+ssh://git@github.com/chaijs/type-detect.git"
+  },
+  "scripts": {
+    "bench": "node bench",
+    "build": "browserify --bare $npm_pakcage_main --standalone typeDetect -o type-detect.js",
+    "lint": "eslint --ignore-path .gitignore .",
+    "prepublish": "npm run build",
+    "semantic-release": "semantic-release pre && npm publish && semantic-release post",
+    "pretest": "npm run lint",
+    "test": "npm run test:node && npm run test:browser && npm run upload-coverage",
+    "test:browser": "karma start --singleRun=true",
+    "test:node": "istanbul cover _mocha",
+    "upload-coverage": "lcov-result-merger 'coverage/**/lcov.info' | coveralls; exit 0"
+  },
+  "config": {
+    "ghooks": {
+      "commit-msg": "validate-commit-msg"
+    }
+  },
+  "eslintConfig": {
+    "extends": [
+      "strict/es5"
+    ],
+    "env": {
+      "es6": true
+    },
+    "globals": {
+      "HTMLElement": false
+    },
+    "rules": {
+      "complexity": 0,
+      "max-statements": 0
+    }
+  },
+  "dependencies": {},
+  "devDependencies": {
+    "benchmark": "^2.1.0",
+    "browserify": "^13.0.0",
+    "browserify-istanbul": "^1.0.0",
+    "coveralls": "2.11.9",
+    "eslint": "^2.9.0",
+    "eslint-config-strict": "^8.5.0",
+    "eslint-plugin-filenames": "^0.2.0",
+    "ghooks": "^1.0.1",
+    "istanbul": "^0.4.2",
+    "karma": "^1.1.2",
+    "karma-browserify": "^5.0.2",
+    "karma-coverage": "^1.0.0",
+    "karma-mocha": "^1.0.1",
+    "karma-phantomjs-launcher": "^1.0.0",
+    "karma-sauce-launcher": "^1.0.0",
+    "lcov-result-merger": "^1.2.0",
+    "mocha": "^3.0.0",
+    "phantomjs-prebuilt": "^2.1.5",
+    "semantic-release": "^4.3.5",
+    "simple-assert": "^1.0.0",
+    "travis-after-all": "^1.4.4",
+    "validate-commit-msg": "^2.3.1"
+  },
+  "engines": {
+    "node": "*"
+  }
+}
diff --git a/test/.eslintrc b/test/.eslintrc
new file mode 100644
index 0000000..edffc56
--- /dev/null
+++ b/test/.eslintrc
@@ -0,0 +1,19 @@
+{
+  "extends": [ "strict/test" ],
+  "env": {
+    "node": true,
+    "browser": true,
+    "es6": true,
+    "mocha": true
+  },
+  "rules": {
+    "no-new-wrappers": 0,
+    "no-array-constructor": 0,
+    "no-new-object": 0,
+    "no-empty-function": 0,
+    "no-undefined": 0,
+    "complexity": 0,
+    "max-statements": 0,
+    "id-match": 0
+  }
+}
diff --git a/test/dom.js b/test/dom.js
new file mode 100644
index 0000000..f7380ba
--- /dev/null
+++ b/test/dom.js
@@ -0,0 +1,332 @@
+'use strict';
+var assert = require('simple-assert');
+var type = require('..');
+function describeIf(condition) {
+  return condition ? describe : describe.skip;
+}
+function itIf(condition) {
+  return condition ? it : it.skip;
+}
+describeIf(typeof window !== 'undefined' && typeof window.document !== 'undefined')('DOM Specific', function () {
+
+  it('window', function () {
+    assert(type(window) === 'global');
+  });
+
+  it('document', function () {
+    assert(type(document) === 'Document');
+  });
+
+  it('domparser', function () {
+    assert(type(new DOMParser()) === 'DOMParser');
+  });
+
+  it('history', function () {
+    assert(type(window.history) === 'History');
+  });
+
+  it('location', function () {
+    assert(type(window.location) === 'Location');
+  });
+
+  it('attr', function () {
+    var div = document.createElement('div');
+    div.setAttribute('id', 'foo');
+    assert(type(div.getAttributeNode('id')) === 'Attr');
+  });
+
+  describe('Events', function () {
+
+    it('event', function () {
+      assert(type(document.createEvent('Event')) === 'Event');
+    });
+
+    itIf(typeof HashChangeEvent !== 'undefined')('HashChangeEvent', function () {
+      assert(type(new HashChangeEvent('')) === 'HashChangeEvent');
+    });
+
+  });
+
+  describe('Navigator', function () {
+
+    it('navigator', function () {
+      assert(type(window.navigator) === 'Navigator');
+    });
+
+    itIf(typeof navigator !== 'undefined' && 'geolocation' in navigator)('geolocation', function () {
+      assert(type(navigator.geolocation) === 'Geolocation');
+    });
+
+    itIf(typeof navigator !== 'undefined' && 'connection' in navigator)('networkinformation', function () {
+      assert(type(navigator.connection) === 'NetworkInformation');
+    });
+
+    itIf(typeof navigator !== 'undefined' && 'mediaDevices' in navigator)('mediadevices', function () {
+      assert(type(navigator.mediaDevices) === 'MediaDevices');
+    });
+
+    itIf(typeof navigator !== 'undefined' && 'mimeTypes' in navigator)('mimetypearray', function () {
+      assert(type(navigator.mimeTypes) === 'MimeTypeArray');
+    });
+
+    itIf(typeof navigator !== 'undefined' && 'nfc' in navigator)('nfc', function () {
+      assert(type(navigator.nfc) === 'NFC');
+    });
+
+    itIf(typeof navigator !== 'undefined' && 'permissions' in navigator)('permissions', function () {
+      assert(type(navigator.permissions) === 'Permissions');
+    });
+
+    itIf(typeof navigator !== 'undefined' && 'plugins' in navigator)('pluginarray', function () {
+      assert(type(navigator.plugins) === 'PluginArray');
+    });
+
+    itIf(typeof navigator !== 'undefined' && 'plugins' in navigator && navigator.plugins.length)('plugin', function () {
+      assert(type(navigator.plugins[0]) === 'Plugin');
+    });
+
+    itIf(typeof navigator !== 'undefined' && 'presentation' in navigator)('presentation', function () {
+      assert(type(navigator.presentation) === 'Presentation');
+    });
+
+    itIf(typeof navigator !== 'undefined' && 'serviceworker' in navigator)('serviceworkercontainer', function () {
+      assert(type(navigator.serviceworker) === 'ServiceWorkerContainer');
+    });
+
+    itIf(typeof navigator !== 'undefined' && 'services' in navigator)('serviceportcollection', function () {
+      assert(type(navigator.services) === 'ServicePortCollection');
+    });
+
+    itIf(typeof navigator !== 'undefined' && 'storage' in navigator)('storagemanager', function () {
+      assert(type(navigator.storage) === 'StorageManager');
+    });
+
+    itIf(typeof navigator !== 'undefined' && 'storageQuota' in navigator)('storagequota', function () {
+      assert(type(navigator.storageQuota) === 'StorageQuota');
+    });
+
+    itIf(typeof navigator !== 'undefined' && 'usb' in navigator)('usb', function () {
+      assert(type(navigator.usb) === 'USB');
+    });
+
+  });
+
+  describe('(HTMLElements)', function () {
+
+    it('HTMLAreaElement', function () {
+      assert(type(document.createElement('Area')) === 'HTMLAreaElement');
+    });
+
+    it('HTMLBRElement', function () {
+      assert(type(document.createElement('BR')) === 'HTMLBRElement');
+    });
+
+    it('HTMLBaseElement', function () {
+      assert(type(document.createElement('Base')) === 'HTMLBaseElement');
+    });
+
+    it('HTMLBodyElement', function () {
+      assert(type(document.createElement('Body')) === 'HTMLBodyElement');
+    });
+
+    it('HTMLButtonElement', function () {
+      assert(type(document.createElement('Button')) === 'HTMLButtonElement');
+    });
+
+    it('HTMLCanvasElement', function () {
+      assert(type(document.createElement('Canvas')) === 'HTMLCanvasElement');
+    });
+
+    it('HTMLDListElement', function () {
+      assert(type(document.createElement('DL')) === 'HTMLDListElement');
+    });
+
+    // not yet supported in Safari
+    itIf(typeof HTMLDataListElement === 'function')('HTMLDataListElement', function () {
+      assert(type(document.createElement('DataList')) === 'HTMLDataListElement');
+    });
+
+    it('HTMLDivElement', function () {
+      assert(type(document.createElement('Div')) === 'HTMLDivElement');
+    });
+
+    it('HTMLFieldSetElement', function () {
+      assert(type(document.createElement('FieldSet')) === 'HTMLFieldSetElement');
+    });
+
+    it('HTMLFormElement', function () {
+      assert(type(document.createElement('Form')) === 'HTMLFormElement');
+    });
+
+    it('HTMLFrameSetElement', function () {
+      assert(type(document.createElement('FrameSet')) === 'HTMLFrameSetElement');
+    });
+
+    it('HTMLHRElement', function () {
+      assert(type(document.createElement('HR')) === 'HTMLHRElement');
+    });
+
+    it('HTMLHeadElement', function () {
+      assert(type(document.createElement('Head')) === 'HTMLHeadElement');
+    });
+
+    it('HTMLHeadingElement', function () {
+      assert(type(document.createElement('H1')) === 'HTMLHeadingElement');
+      assert(type(document.createElement('H2')) === 'HTMLHeadingElement');
+      assert(type(document.createElement('H3')) === 'HTMLHeadingElement');
+      assert(type(document.createElement('H4')) === 'HTMLHeadingElement');
+      assert(type(document.createElement('H5')) === 'HTMLHeadingElement');
+      assert(type(document.createElement('H6')) === 'HTMLHeadingElement');
+    });
+
+    it('HTMLHtmlElement', function () {
+      assert(type(document.createElement('Html')) === 'HTMLHtmlElement');
+    });
+
+    it('HTMLIFrameElement', function () {
+      assert(type(document.createElement('IFrame')) === 'HTMLIFrameElement');
+    });
+
+    it('HTMLImageElement', function () {
+      assert(type(document.createElement('Img')) === 'HTMLImageElement');
+    });
+
+    it('HTMLInputElement', function () {
+      assert(type(document.createElement('Input')) === 'HTMLInputElement');
+    });
+
+    it('HTMLLIElement', function () {
+      assert(type(document.createElement('LI')) === 'HTMLLIElement');
+    });
+
+    it('HTMLLabelElement', function () {
+      assert(type(document.createElement('Label')) === 'HTMLLabelElement');
+    });
+
+    it('HTMLLegendElement', function () {
+      assert(type(document.createElement('Legend')) === 'HTMLLegendElement');
+    });
+
+    it('HTMLLinkElement', function () {
+      assert(type(document.createElement('Link')) === 'HTMLLinkElement');
+    });
+
+    it('HTMLMapElement', function () {
+      assert(type(document.createElement('Map')) === 'HTMLMapElement');
+    });
+
+    it('HTMLMetaElement', function () {
+      assert(type(document.createElement('Meta')) === 'HTMLMetaElement');
+    });
+
+    itIf(typeof HTMLMeterElement !== 'undefined')('HTMLMeterElement', function () {
+      assert(type(document.createElement('Meter')) === 'HTMLMeterElement');
+    });
+
+    it('HTMLModElement', function () {
+      assert(type(document.createElement('Del')) === 'HTMLModElement');
+    });
+
+    it('HTMLOListElement', function () {
+      assert(type(document.createElement('OL')) === 'HTMLOListElement');
+    });
+
+    it('HTMLOptGroupElement', function () {
+      assert(type(document.createElement('OptGroup')) === 'HTMLOptGroupElement');
+    });
+
+    it('HTMLOptionElement', function () {
+      assert(type(document.createElement('Option')) === 'HTMLOptionElement');
+    });
+
+    itIf(typeof HTMLOutputElement !== 'undefined')('HTMLOutputElement', function () {
+      assert(type(document.createElement('Output')) === 'HTMLOutputElement');
+    });
+
+    it('HTMLParagraphElement', function () {
+      assert(type(document.createElement('P')) === 'HTMLParagraphElement');
+    });
+
+    it('HTMLParamElement', function () {
+      assert(type(document.createElement('Param')) === 'HTMLParamElement');
+    });
+
+    it('HTMLPreElement', function () {
+      assert(type(document.createElement('Pre')) === 'HTMLPreElement');
+    });
+
+    itIf(typeof HTMLProgressElement !== 'undefined')('HTMLProgressElement', function () {
+      assert(type(document.createElement('Progress')) === 'HTMLProgressElement');
+    });
+
+    it('HTMLQuoteElement', function () {
+      assert(type(document.createElement('BlockQuote')) === 'HTMLQuoteElement');
+      assert(type(document.createElement('Q')) === 'HTMLQuoteElement');
+    });
+
+    it('HTMLScriptElement', function () {
+      assert(type(document.createElement('Script')) === 'HTMLScriptElement');
+    });
+
+    it('HTMLSelectElement', function () {
+      assert(type(document.createElement('Select')) === 'HTMLSelectElement');
+    });
+
+    it('HTMLSpanElement', function () {
+      assert(type(document.createElement('Span')) === 'HTMLSpanElement');
+    });
+
+    it('HTMLStyleElement', function () {
+      assert(type(document.createElement('Style')) === 'HTMLStyleElement');
+    });
+
+    it('HTMLTableCaptionElement', function () {
+      assert(type(document.createElement('Caption')) === 'HTMLTableCaptionElement');
+    });
+
+    it('HTMLTableDataCellElement', function () {
+      assert(type(document.createElement('TD')) === 'HTMLTableDataCellElement');
+    });
+
+    it('HTMLTableHeaderCellElement', function () {
+      assert(type(document.createElement('TH')) === 'HTMLTableHeaderCellElement');
+    });
+
+    it('HTMLTableColElement', function () {
+      assert(type(document.createElement('Col')) === 'HTMLTableColElement');
+      assert(type(document.createElement('ColGroup')) === 'HTMLTableColElement');
+    });
+
+    it('HTMLTableElement', function () {
+      assert(type(document.createElement('Table')) === 'HTMLTableElement');
+    });
+
+    it('HTMLTableRowElement', function () {
+      assert(type(document.createElement('TR')) === 'HTMLTableRowElement');
+    });
+
+    it('HTMLTableSectionElement', function () {
+      assert(type(document.createElement('THead')) === 'HTMLTableSectionElement');
+      assert(type(document.createElement('TBody')) === 'HTMLTableSectionElement');
+      assert(type(document.createElement('TFoot')) === 'HTMLTableSectionElement');
+    });
+
+    it('HTMLTextAreaElement', function () {
+      assert(type(document.createElement('TextArea')) === 'HTMLTextAreaElement');
+    });
+
+    it('HTMLTitleElement', function () {
+      assert(type(document.createElement('Title')) === 'HTMLTitleElement');
+    });
+
+    it('HTMLUListElement', function () {
+      assert(type(document.createElement('UL')) === 'HTMLUListElement');
+    });
+
+    it('HTMLUnknownElement', function () {
+      assert(type(document.createElement('foobarbaz')) === 'HTMLUnknownElement');
+    });
+
+  });
+
+});
diff --git a/test/index.js b/test/index.js
new file mode 100644
index 0000000..1018a70
--- /dev/null
+++ b/test/index.js
@@ -0,0 +1,272 @@
+'use strict';
+var assert = require('simple-assert');
+var type = require('..');
+describe('Generic', function () {
+
+  it('array', function () {
+    assert(type([]) === 'Array');
+    assert(type(new Array()) === 'Array');
+  });
+
+  it('regexp', function () {
+    assert(type(/a-z/gi) === 'RegExp');
+    assert(type(new RegExp('a-z')) === 'RegExp');
+  });
+
+  it('function', function () {
+    assert(type(function () {}) === 'function');
+  });
+
+  it('arguments', function () {
+    assert(type(arguments) === 'Arguments');
+  });
+
+  it('date', function () {
+    assert(type(new Date()) === 'Date');
+  });
+
+  it('number', function () {
+    assert(type(1) === 'number');
+    assert(type(1.234) === 'number');
+    assert(type(-1) === 'number');
+    assert(type(-1.234) === 'number');
+    assert(type(Infinity) === 'number');
+    assert(type(NaN) === 'number');
+  });
+
+  it('number objects', function () {
+    assert(type(new Number(2)) === 'Number');
+  });
+
+  it('string', function () {
+    assert(type('hello world') === 'string');
+  });
+
+  it('string objects', function () {
+    assert(type(new String('hello')) === 'String');
+  });
+
+  it('null', function () {
+    assert(type(null) === 'null');
+    assert(type(undefined) !== 'null');
+  });
+
+  it('undefined', function () {
+    assert(type(undefined) === 'undefined');
+    assert(type(null) !== 'undefined');
+  });
+
+  it('object', function () {
+    function Noop() {}
+    assert(type({}) === 'Object');
+    assert(type(Noop) !== 'Object');
+    assert(type(new Noop()) === 'Object');
+    assert(type(new Object()) === 'Object');
+    assert(type(Object.create(null)) === 'Object');
+    assert(type(Object.create(Object.prototype)) === 'Object');
+  });
+
+  // See: https://github.com/chaijs/type-detect/pull/25
+  it('object with .undefined property getter', function () {
+    var foo = {};
+    Object.defineProperty(foo, 'undefined', {
+      get: function () {
+        throw Error('Should never happen');
+      },
+    });
+    assert(type(foo) === 'Object');
+  });
+
+  it('boolean', function () {
+    assert(type(true) === 'boolean');
+    assert(type(false) === 'boolean');
+    assert(type(!0) === 'boolean');
+  });
+
+  it('boolean object', function () {
+    assert(type(new Boolean()) === 'Boolean');
+  });
+
+  it('error', function () {
+    assert(type(new Error()) === 'Error');
+    assert(type(new TypeError()) === 'Error');
+    assert(type(new EvalError()) === 'Error');
+    assert(type(new RangeError()) === 'Error');
+    assert(type(new ReferenceError()) === 'Error');
+    assert(type(new SyntaxError()) === 'Error');
+    assert(type(new TypeError()) === 'Error');
+    assert(type(new URIError()) === 'Error');
+  });
+
+  it('Math', function () {
+    assert(type(Math) === 'Math');
+  });
+
+  it('JSON', function () {
+    assert(type(JSON) === 'JSON');
+  });
+
+  describe('Stubbed ES2015 Types', function () {
+    var originalObjectToString = Object.prototype.toString;
+    function stubObjectToStringOnce(staticValue) {
+      Object.prototype.toString = function () {  // eslint-disable-line no-extend-native
+        Object.prototype.toString = originalObjectToString;  // eslint-disable-line no-extend-native
+        return staticValue;
+      };
+    }
+    function Thing() {}
+
+    it('map', function () {
+      stubObjectToStringOnce('[object Map]');
+      assert(type(new Thing()) === 'Map');
+    });
+
+    it('weakmap', function () {
+      stubObjectToStringOnce('[object WeakMap]');
+      assert(type(new Thing()) === 'WeakMap');
+    });
+
+    it('set', function () {
+      stubObjectToStringOnce('[object Set]');
+      assert(type(new Thing()) === 'Set');
+    });
+
+    it('weakset', function () {
+      stubObjectToStringOnce('[object WeakSet]');
+      assert(type(new Thing()) === 'WeakSet');
+    });
+
+    it('symbol', function () {
+      stubObjectToStringOnce('[object Symbol]');
+      assert(type(new Thing()) === 'Symbol');
+    });
+
+    it('promise', function () {
+      stubObjectToStringOnce('[object Promise]');
+      assert(type(new Thing()) === 'Promise');
+    });
+
+    it('int8array', function () {
+      stubObjectToStringOnce('[object Int8Array]');
+      assert(type(new Thing()) === 'Int8Array');
+    });
+
+    it('uint8array', function () {
+      stubObjectToStringOnce('[object Uint8Array]');
+      assert(type(new Thing()) === 'Uint8Array');
+    });
+
+    it('uint8clampedarray', function () {
+      stubObjectToStringOnce('[object Uint8ClampedArray]');
+      assert(type(new Thing()) === 'Uint8ClampedArray');
+    });
+
+    it('int16array', function () {
+      stubObjectToStringOnce('[object Int16Array]');
+      assert(type(new Thing()) === 'Int16Array');
+    });
+
+    it('uint16array', function () {
+      stubObjectToStringOnce('[object Uint16Array]');
+      assert(type(new Thing()) === 'Uint16Array');
+    });
+
+    it('int32array', function () {
+      stubObjectToStringOnce('[object Int32Array]');
+      assert(type(new Thing()) === 'Int32Array');
+    });
+
+    it('uint32array', function () {
+      stubObjectToStringOnce('[object Uint32Array]');
+      assert(type(new Thing()) === 'Uint32Array');
+    });
+
+    it('float32array', function () {
+      stubObjectToStringOnce('[object Float32Array]');
+      assert(type(new Thing()) === 'Float32Array');
+    });
+
+    it('float64array', function () {
+      stubObjectToStringOnce('[object Float64Array]');
+      assert(type(new Thing()) === 'Float64Array');
+    });
+
+    it('dataview', function () {
+      stubObjectToStringOnce('[object DataView]');
+      assert(type(new Thing()) === 'DataView');
+    });
+
+    it('arraybuffer', function () {
+      stubObjectToStringOnce('[object ArrayBuffer]');
+      assert(type(new Thing()) === 'ArrayBuffer');
+    });
+
+    it('generatorfunction', function () {
+      stubObjectToStringOnce('[object GeneratorFunction]');
+      assert(type(new Thing()) === 'GeneratorFunction');
+    });
+
+    it('generator', function () {
+      stubObjectToStringOnce('[object Generator]');
+      assert(type(new Thing()) === 'Generator');
+    });
+
+    it('string iterator', function () {
+      stubObjectToStringOnce('[object String Iterator]');
+      assert(type(new Thing()) === 'String Iterator');
+    });
+
+    it('array iterator', function () {
+      stubObjectToStringOnce('[object Array Iterator]');
+      assert(type(new Thing()) === 'Array Iterator');
+    });
+
+    it('map iterator', function () {
+      stubObjectToStringOnce('[object Map Iterator]');
+      assert(type(new Thing()) === 'Map Iterator');
+    });
+
+    it('set iterator', function () {
+      stubObjectToStringOnce('[object Set Iterator]');
+      assert(type(new Thing()) === 'Set Iterator');
+    });
+
+  });
+
+  describe('@@toStringTag Sham', function () {
+    var originalObjectToString = Object.prototype.toString;
+    before(function () {
+      global.Symbol = global.Symbol || {};
+      if (!global.Symbol.toStringTag) {
+        global.Symbol.toStringTag = '__@@toStringTag__';
+      }
+      var test = {};
+      test[Symbol.toStringTag] = function () {
+        return 'foo';
+      };
+      if (Object.prototype.toString(test) !== '[object foo]') {
+        Object.prototype.toString = function () { // eslint-disable-line no-extend-native
+          if (typeof this === 'object' && typeof this[Symbol.toStringTag] === 'function') {
+            return '[object ' + this[Symbol.toStringTag]() + ']';
+          }
+          return originalObjectToString.call(this);
+        };
+      }
+    });
+
+    after(function () {
+      Object.prototype.toString = originalObjectToString; // eslint-disable-line no-extend-native
+    });
+
+
+    it('plain object', function () {
+      var obj = {};
+      obj[Symbol.toStringTag] = function () {
+        return 'Foo';
+      };
+      assert(type(obj) === 'Foo', 'type(obj) === "Foo"');
+    });
+
+  });
+
+});
diff --git a/test/new-ecmascript-types.js b/test/new-ecmascript-types.js
new file mode 100644
index 0000000..d0028af
--- /dev/null
+++ b/test/new-ecmascript-types.js
@@ -0,0 +1,136 @@
+'use strict';
+var assert = require('simple-assert');
+var type = require('..');
+var symbolExists = typeof Symbol === 'function';
+var setExists = typeof Set === 'function';
+var mapExists = typeof Map === 'function';
+var supportArrows = false;
+var supportGenerators = false;
+try {
+  eval('function * foo () {}; foo'); // eslint-disable-line no-eval
+  supportGenerators = true;
+} catch (error) {
+  supportGenerators = false;
+}
+try {
+  eval('() => {}'); // eslint-disable-line no-eval
+  supportArrows = true;
+} catch (error) {
+  supportArrows = false;
+}
+function itIf(condition) {
+  return condition ? it : it.skip;
+}
+
+describe('ES2015 Specific', function () {
+  itIf(symbolExists && typeof String.prototype[Symbol.iterator] === 'function')('string iterator', function () {
+    assert(type(''[Symbol.iterator]()) === 'String Iterator');
+  });
+
+  itIf(symbolExists && typeof Array.prototype[Symbol.iterator] === 'function')('array iterator', function () {
+    assert(type([][Symbol.iterator]()) === 'Array Iterator');
+  });
+
+  itIf(typeof Array.prototype.entries === 'function')('array iterator (entries)', function () {
+    assert(type([].entries()) === 'Array Iterator');
+  });
+
+  itIf(mapExists)('map', function () {
+    assert(type(new Map()) === 'Map');
+  });
+
+  itIf(symbolExists && mapExists && typeof Map.prototype[Symbol.iterator] === 'function')('map iterator', function () {
+    assert(type(new Map()[Symbol.iterator]()) === 'Map Iterator');
+  });
+
+  itIf(mapExists && typeof Map.prototype.entries === 'function')('map iterator (entries)', function () {
+    assert(type(new Map().entries()) === 'Map Iterator');
+  });
+
+  itIf(typeof WeakMap === 'function')('weakmap', function () {
+    assert(type(new WeakMap()) === 'WeakMap');
+  });
+
+  itIf(setExists)('set', function () {
+    assert(type(new Set()) === 'Set');
+  });
+
+  itIf(symbolExists && setExists && typeof Set.prototype[Symbol.iterator] === 'function')('set iterator', function () {
+    assert(type(new Set()[Symbol.iterator]()) === 'Set Iterator');
+  });
+
+  itIf(setExists && typeof Set.prototype.entries === 'function')('set iterator', function () {
+    assert(type(new Set().entries()) === 'Set Iterator');
+  });
+
+  itIf(typeof WeakSet === 'function')('weakset', function () {
+    assert(type(new WeakSet()) === 'WeakSet');
+  });
+
+  itIf(typeof Symbol === 'function')('symbol', function () {
+    assert(type(Symbol()) === 'symbol');
+  });
+
+  itIf(typeof Promise === 'function')('promise', function () {
+    function noop() {}
+    assert(type(new Promise(noop)) === 'Promise');
+  });
+
+  itIf(typeof Int8Array === 'function')('int8array', function () {
+    assert(type(new Int8Array()) === 'Int8Array');
+  });
+
+  itIf(typeof Uint8Array === 'function')('uint8array', function () {
+    assert(type(new Uint8Array()) === 'Uint8Array');
+  });
+
+  itIf(typeof Uint8ClampedArray === 'function')('uint8clampedarray', function () {
+    assert(type(new Uint8ClampedArray()) === 'Uint8ClampedArray');
+  });
+
+  itIf(typeof Int16Array === 'function')('int16array', function () {
+    assert(type(new Int16Array()) === 'Int16Array');
+  });
+
+  itIf(typeof Uint16Array === 'function')('uint16array', function () {
+    assert(type(new Uint16Array()) === 'Uint16Array');
+  });
+
+  itIf(typeof Int32Array === 'function')('int32array', function () {
+    assert(type(new Int32Array()) === 'Int32Array');
+  });
+
+  itIf(typeof Uint32Array === 'function')('uint32array', function () {
+    assert(type(new Uint32Array()) === 'Uint32Array');
+  });
+
+  itIf(typeof Float32Array === 'function')('float32array', function () {
+    assert(type(new Float32Array()) === 'Float32Array');
+  });
+
+  itIf(typeof Float64Array === 'function')('float64array', function () {
+    assert(type(new Float64Array()) === 'Float64Array');
+  });
+
+  itIf(typeof DataView === 'function')('dataview', function () {
+    var arrayBuffer = new ArrayBuffer(1);
+    assert(type(new DataView(arrayBuffer)) === 'DataView');
+  });
+
+  itIf(typeof ArrayBuffer === 'function')('arraybuffer', function () {
+    assert(type(new ArrayBuffer(1)) === 'ArrayBuffer');
+  });
+
+  itIf(supportArrows)('arrow function', function () {
+    assert(type(eval('() => {}')) === 'function'); // eslint-disable-line no-eval
+  });
+
+  itIf(supportGenerators)('generator function', function () {
+    assert(type(eval('function * foo () {}; foo')) === 'function'); // eslint-disable-line no-eval
+  });
+
+  itIf(supportGenerators)('generator', function () {
+    assert(type(eval('(function * foo () {}())')) === 'Generator'); // eslint-disable-line no-eval
+  });
+
+});
diff --git a/test/node.js b/test/node.js
new file mode 100644
index 0000000..eba98f2
--- /dev/null
+++ b/test/node.js
@@ -0,0 +1,18 @@
+'use strict';
+var assert = require('simple-assert');
+var type = require('..');
+var isNode = typeof process !== 'undefined' && typeof process.release === 'object' && process.release.name;
+function describeIf(condition) {
+  return condition ? describe : describe.skip;
+}
+describeIf(isNode)('Node Specific', function () {
+
+  it('global', function () {
+    assert(type(global) === 'global');
+  });
+
+  it('process', function () {
+    assert(type(process) === 'process');
+  });
+
+});

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-type-detect.git



More information about the Pkg-javascript-commits mailing list