UNPKG

3.24 kBJavaScriptView Raw
1// ES2015 Symbol polyfill for environments that do not (or partially) support it
2
3"use strict";
4
5var d = require("d")
6 , validateSymbol = require("./validate-symbol")
7 , NativeSymbol = require("ext/global-this").Symbol
8 , generateName = require("./lib/private/generate-name")
9 , setupStandardSymbols = require("./lib/private/setup/standard-symbols")
10 , setupSymbolRegistry = require("./lib/private/setup/symbol-registry");
11
12var create = Object.create
13 , defineProperties = Object.defineProperties
14 , defineProperty = Object.defineProperty;
15
16var SymbolPolyfill, HiddenSymbol, isNativeSafe;
17
18if (typeof NativeSymbol === "function") {
19 try {
20 String(NativeSymbol());
21 isNativeSafe = true;
22 } catch (ignore) {}
23} else {
24 NativeSymbol = null;
25}
26
27// Internal constructor (not one exposed) for creating Symbol instances.
28// This one is used to ensure that `someSymbol instanceof Symbol` always return false
29HiddenSymbol = function Symbol(description) {
30 if (this instanceof HiddenSymbol) throw new TypeError("Symbol is not a constructor");
31 return SymbolPolyfill(description);
32};
33
34// Exposed `Symbol` constructor
35// (returns instances of HiddenSymbol)
36module.exports = SymbolPolyfill = function Symbol(description) {
37 var symbol;
38 if (this instanceof Symbol) throw new TypeError("Symbol is not a constructor");
39 if (isNativeSafe) return NativeSymbol(description);
40 symbol = create(HiddenSymbol.prototype);
41 description = description === undefined ? "" : String(description);
42 return defineProperties(symbol, {
43 __description__: d("", description),
44 __name__: d("", generateName(description))
45 });
46};
47
48setupStandardSymbols(SymbolPolyfill);
49setupSymbolRegistry(SymbolPolyfill);
50
51// Internal tweaks for real symbol producer
52defineProperties(HiddenSymbol.prototype, {
53 constructor: d(SymbolPolyfill),
54 toString: d("", function () { return this.__name__; })
55});
56
57// Proper implementation of methods exposed on Symbol.prototype
58// They won't be accessible on produced symbol instances as they derive from HiddenSymbol.prototype
59defineProperties(SymbolPolyfill.prototype, {
60 toString: d(function () { return "Symbol (" + validateSymbol(this).__description__ + ")"; }),
61 valueOf: d(function () { return validateSymbol(this); })
62});
63defineProperty(
64 SymbolPolyfill.prototype, SymbolPolyfill.toPrimitive,
65 d("", function () {
66 var symbol = validateSymbol(this);
67 if (typeof symbol === "symbol") return symbol;
68 return symbol.toString();
69 })
70);
71defineProperty(SymbolPolyfill.prototype, SymbolPolyfill.toStringTag, d("c", "Symbol"));
72
73// Proper implementaton of toPrimitive and toStringTag for returned symbol instances
74defineProperty(
75 HiddenSymbol.prototype, SymbolPolyfill.toStringTag,
76 d("c", SymbolPolyfill.prototype[SymbolPolyfill.toStringTag])
77);
78
79// Note: It's important to define `toPrimitive` as last one, as some implementations
80// implement `toPrimitive` natively without implementing `toStringTag` (or other specified symbols)
81// And that may invoke error in definition flow:
82// See: https://github.com/medikoo/es6-symbol/issues/13#issuecomment-164146149
83defineProperty(
84 HiddenSymbol.prototype, SymbolPolyfill.toPrimitive,
85 d("c", SymbolPolyfill.prototype[SymbolPolyfill.toPrimitive])
86);