You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
87 lines
3.2 KiB
87 lines
3.2 KiB
// ES2015 Symbol polyfill for environments that do not (or partially) support it |
|
|
|
"use strict"; |
|
|
|
var d = require("d") |
|
, validateSymbol = require("./validate-symbol") |
|
, NativeSymbol = require("ext/global-this").Symbol |
|
, generateName = require("./lib/private/generate-name") |
|
, setupStandardSymbols = require("./lib/private/setup/standard-symbols") |
|
, setupSymbolRegistry = require("./lib/private/setup/symbol-registry"); |
|
|
|
var create = Object.create |
|
, defineProperties = Object.defineProperties |
|
, defineProperty = Object.defineProperty; |
|
|
|
var SymbolPolyfill, HiddenSymbol, isNativeSafe; |
|
|
|
if (typeof NativeSymbol === "function") { |
|
try { |
|
String(NativeSymbol()); |
|
isNativeSafe = true; |
|
} catch (ignore) {} |
|
} else { |
|
NativeSymbol = null; |
|
} |
|
|
|
// Internal constructor (not one exposed) for creating Symbol instances. |
|
// This one is used to ensure that `someSymbol instanceof Symbol` always return false |
|
HiddenSymbol = function Symbol(description) { |
|
if (this instanceof HiddenSymbol) throw new TypeError("Symbol is not a constructor"); |
|
return SymbolPolyfill(description); |
|
}; |
|
|
|
// Exposed `Symbol` constructor |
|
// (returns instances of HiddenSymbol) |
|
module.exports = SymbolPolyfill = function Symbol(description) { |
|
var symbol; |
|
if (this instanceof Symbol) throw new TypeError("Symbol is not a constructor"); |
|
if (isNativeSafe) return NativeSymbol(description); |
|
symbol = create(HiddenSymbol.prototype); |
|
description = description === undefined ? "" : String(description); |
|
return defineProperties(symbol, { |
|
__description__: d("", description), |
|
__name__: d("", generateName(description)) |
|
}); |
|
}; |
|
|
|
setupStandardSymbols(SymbolPolyfill); |
|
setupSymbolRegistry(SymbolPolyfill); |
|
|
|
// Internal tweaks for real symbol producer |
|
defineProperties(HiddenSymbol.prototype, { |
|
constructor: d(SymbolPolyfill), |
|
toString: d("", function () { return this.__name__; }) |
|
}); |
|
|
|
// Proper implementation of methods exposed on Symbol.prototype |
|
// They won't be accessible on produced symbol instances as they derive from HiddenSymbol.prototype |
|
defineProperties(SymbolPolyfill.prototype, { |
|
toString: d(function () { return "Symbol (" + validateSymbol(this).__description__ + ")"; }), |
|
valueOf: d(function () { return validateSymbol(this); }) |
|
}); |
|
defineProperty( |
|
SymbolPolyfill.prototype, |
|
SymbolPolyfill.toPrimitive, |
|
d("", function () { |
|
var symbol = validateSymbol(this); |
|
if (typeof symbol === "symbol") return symbol; |
|
return symbol.toString(); |
|
}) |
|
); |
|
defineProperty(SymbolPolyfill.prototype, SymbolPolyfill.toStringTag, d("c", "Symbol")); |
|
|
|
// Proper implementaton of toPrimitive and toStringTag for returned symbol instances |
|
defineProperty( |
|
HiddenSymbol.prototype, SymbolPolyfill.toStringTag, |
|
d("c", SymbolPolyfill.prototype[SymbolPolyfill.toStringTag]) |
|
); |
|
|
|
// Note: It's important to define `toPrimitive` as last one, as some implementations |
|
// implement `toPrimitive` natively without implementing `toStringTag` (or other specified symbols) |
|
// And that may invoke error in definition flow: |
|
// See: https://github.com/medikoo/es6-symbol/issues/13#issuecomment-164146149 |
|
defineProperty( |
|
HiddenSymbol.prototype, SymbolPolyfill.toPrimitive, |
|
d("c", SymbolPolyfill.prototype[SymbolPolyfill.toPrimitive]) |
|
);
|
|
|