78 lines
2.7 KiB
JavaScript
78 lines
2.7 KiB
JavaScript
'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]));
|