'use strict'; var d = require('d') , validateSymbol = require('./validate-symbol') , create = Object.create, defineProperties = Object.defineProperties , defineProperty = Object.defineProperty, objPrototype = Object.prototype , Symbol, HiddenSymbol, globalSymbols = create(null); var generateName = (function () { var created = create(null); return function (desc) { var postfix = 0, name; while (created[desc + (postfix || '')]) ++postfix; desc += (postfix || ''); created[desc] = true; name = '@@' + desc; defineProperty(objPrototype, name, d.gs(null, function (value) { defineProperty(this, name, d(value)); })); return name; }; }()); HiddenSymbol = function Symbol(description) { if (this instanceof HiddenSymbol) throw new TypeError('TypeError: Symbol is not a constructor'); return Symbol(description); }; module.exports = Symbol = function Symbol(description) { var symbol; if (this instanceof Symbol) throw new TypeError('TypeError: Symbol is not a constructor'); symbol = create(HiddenSymbol.prototype); description = (description === undefined ? '' : String(description)); return defineProperties(symbol, { __description__: d('', description), __name__: d('', generateName(description)) }); }; defineProperties(Symbol, { for: d(function (key) { if (globalSymbols[key]) return globalSymbols[key]; return (globalSymbols[key] = Symbol(String(key))); }), keyFor: d(function (s) { var key; validateSymbol(s); for (key in globalSymbols) if (globalSymbols[key] === s) return key; }), hasInstance: d('', Symbol('hasInstance')), isConcatSpreadable: d('', Symbol('isConcatSpreadable')), iterator: d('', Symbol('iterator')), match: d('', Symbol('match')), replace: d('', Symbol('replace')), search: d('', Symbol('search')), species: d('', Symbol('species')), split: d('', Symbol('split')), toPrimitive: d('', Symbol('toPrimitive')), toStringTag: d('', Symbol('toStringTag')), unscopables: d('', Symbol('unscopables')) }); defineProperties(HiddenSymbol.prototype, { constructor: d(Symbol), toString: d('', function () { return this.__name__; }) }); defineProperties(Symbol.prototype, { toString: d(function () { return 'Symbol (' + validateSymbol(this).__description__ + ')'; }), valueOf: d(function () { return validateSymbol(this); }) }); defineProperty(Symbol.prototype, Symbol.toPrimitive, d('', function () { return validateSymbol(this); })); defineProperty(Symbol.prototype, Symbol.toStringTag, d('c', 'Symbol')); defineProperty(HiddenSymbol.prototype, Symbol.toPrimitive, d('c', Symbol.prototype[Symbol.toPrimitive])); defineProperty(HiddenSymbol.prototype, Symbol.toStringTag, d('c', Symbol.prototype[Symbol.toStringTag]));