Skip to content

Commit

Permalink
Implementation.
Browse files Browse the repository at this point in the history
  • Loading branch information
ljharb committed Jan 24, 2015
1 parent 8af5663 commit cb51248
Showing 1 changed file with 27 additions and 0 deletions.
27 changes: 27 additions & 0 deletions index.js
@@ -0,0 +1,27 @@
'use strict';

var toStr = Object.prototype.toString;
var hasSymbols = typeof Symbol === 'function' && typeof Symbol() === 'symbol';

if (hasSymbols) {
var symToStr = Symbol.prototype.toString;
var symStringRegex = /^Symbol\(.*\)$/;
var isSymbolObject = function isSymbolObject(value) {
if (typeof value.valueOf() !== 'symbol') { return false; }

This comment has been minimized.

Copy link
@ljharb

ljharb Dec 24, 2015

Author Member

Symbol#valueOf is weird in node 0.11, and 0.12 possibly, and thus in some v8's. This certainly isn't robust against someone passing a Symbol object with a faked valueOf, but it's a fast negative bailout for someone who's mutated a Symbol object to have a non-symbol-producing valueOf. Essentially, in spec text, this is a "if Type(ToPrimitive(value)) is Symbol" check, but a "true" doesn't mean it's not a normal object with a Symbol-producing valueOf.

return symStringRegex.test(symToStr.call(value));

This comment has been minimized.

Copy link
@ljharb

ljharb Dec 24, 2015

Author Member

symToStr.call will throw if the value isn't a native Symbol with the proper internal slot. The symStringRegex test is just one of many ways I could have checked that it's a value wrapped with Symbol(…).

};
module.exports = function isSymbol(value) {
if (typeof value === 'symbol') { return true; }

This comment has been minimized.

Copy link
@ljharb

ljharb Dec 24, 2015

Author Member

this line is a fast positive bailout in an env with native symbols, since typeof can't be faked.

if (toStr.call(value) !== '[object Symbol]') { return false; }

This comment has been minimized.

Copy link
@ljharb

ljharb Dec 24, 2015

Author Member

this is a fast negative bailout in an env without Symbol.toStringTag, or, in an env with Symbol.toStringTag but someone has intentionally modified it to not report "Symbol".

try {
return isSymbolObject(value);

This comment has been minimized.

Copy link
@ljharb

ljharb Dec 24, 2015

Author Member

and this is the final, slow check. if it throws an exception, it's not a symbol object (the first line already checked if it's a primitive)

} catch (e) {
return false;
}
};

This comment has been minimized.

Copy link
@jdalton

jdalton Dec 24, 2015

Can you walk through the isSymbol method.
Like first this because of that, then this thing because of this other thing.

This comment has been minimized.

Copy link
@ljharb

ljharb Dec 24, 2015

Author Member

added a number of comments

This comment has been minimized.

Copy link
@ljharb

ljharb Dec 24, 2015

Author Member

https://github.com/ljharb/object.assign/blob/master/hasSymbols.js may also be useful, since it supports both core-js and get-own-property-symbols, unlike this module.

At some point, I will likely eventually add is-symbol/fake or something which would return true for a core-js symbol, and incorporate most of the logic from object.assign's hasSymbols check.

This comment has been minimized.

Copy link
@jdalton

jdalton Dec 24, 2015

Rock, thanks! 🎅

} else {
module.exports = function isSymbol(value) {
// this environment does not support Symbols.
return false;
};
}

0 comments on commit cb51248

Please sign in to comment.