Skip to content

Commit

Permalink
feat: promise/is
Browse files Browse the repository at this point in the history
  • Loading branch information
medikoo committed Apr 4, 2019
1 parent 6762c0d commit a00de02
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 0 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,24 @@ ensureRegExp("foo"); // Thrown TypeError: null is not a regular expression objec

---

### Promise

The JavaScript _Promise_ instance

#### `promise/is`

Confirms if given object is a native _promise_

```javascript
const isPromise = require("type/promise/is");

isPromise(Promise.resolve()); // true
isPromise({ then: () => {} }); // false
isPromise({}); // false
```

---

#### Thenable

The JavaScript _thenable_ object (an object with `then` method)
Expand Down
1 change: 1 addition & 0 deletions error/is.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ module.exports = function (value) {

// Ensure its native Error object (has [[ErrorData]] slot)
// Note: it's not 100% precise as string tag may be overriden
// and other objects can be hacked to expose it
if (objectToString.call(value) !== objectTaggedString) return false;

return !isPrototype(value);
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"root": true,
"globals": {
"Map": true,
"Promise": true,
"Set": true,
"Symbol": true
},
Expand Down
27 changes: 27 additions & 0 deletions promise/is.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"use strict";

var isPrototype = require("../prototype/is");

// In theory we could rely on Symbol.toStringTag directly,
// still early native implementation (e.g. in FF) predated symbols
var objectToString = Object.prototype.toString
, objectTaggedString = objectToString.call(Promise.resolve());

module.exports = function (value) {
if (!value) return false;

// Sanity check (reject objects which do not expose common Error interface)
try {
if (typeof value.then !== "function") return false;
if (typeof value["catch"] !== "function") return false;
} catch (error) {
return false;
}

// Ensure its native Promise object (has [[PromiseState]] slot)
// Note: it's not 100% precise as string tag may be overriden
// and other objects could be hacked to expose it
if (objectToString.call(value) !== objectTaggedString) return false;

return !isPrototype(value);
};
39 changes: 39 additions & 0 deletions test/promise/is.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"use strict";

var assert = require("chai").assert
, isPromise = require("../../promise/is");

describe("promise/is", function () {
if (typeof Promise === "function") {
it("Should return true on promise", function () {
assert.equal(isPromise(Promise.resolve()), true);
});
}
it("Should return false on non-promise thenable", function () {
assert.equal(isPromise({ then: function () { return true; } }), false);
});

it("Should return false on plain object", function () { assert.equal(isPromise({}), false); });
it("Should return false on function", function () {
assert.equal(isPromise(function () { return true; }), false);
});
it("Should return false on array", function () { assert.equal(isPromise([]), false); });
if (typeof Object.create === "function") {
it("Should return false on object with no prototype", function () {
assert.equal(isPromise(Object.create(null)), false);
});
}
it("Should return false on string", function () { assert.equal(isPromise("foo"), false); });
it("Should return false on empty string", function () { assert.equal(isPromise(""), false); });
it("Should return false on number", function () { assert.equal(isPromise(123), false); });
it("Should return false on NaN", function () { assert.equal(isPromise(NaN), false); });
it("Should return false on boolean", function () { assert.equal(isPromise(true), false); });
if (typeof Symbol === "function") {
it("Should return false on symbol", function () {
assert.equal(isPromise(Symbol("foo")), false);
});
}

it("Should return false on null", function () { assert.equal(isPromise(null), false); });
it("Should return false on undefined", function () { assert.equal(isPromise(void 0), false); });
});
5 changes: 5 additions & 0 deletions test/thenable/is.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ describe("thenable/is", function () {
it("Should return true on object with `then` method", function () {
assert.equal(isThenable({ then: function () { return true; } }), true);
});
if (typeof Promise === "function") {
it("Should return true on promise", function () {
assert.equal(isThenable(Promise.resolve()), true);
});
}
it("Should return false on object with `then` non callable property", function () {
assert.equal(isThenable({ then: {} }), false);
});
Expand Down

0 comments on commit a00de02

Please sign in to comment.