polyfill-service
Version:
A polyfill combinator
228 lines (212 loc) • 6.3 kB
JavaScript
// A modification of https://github.com/WebReflection/get-own-property-symbols
// (C) Andrea Giammarchi - MIT Licensed
(function (Object, GOPS) {
var setDescriptor;
var G = typeof global === typeof G ? window : global;
var id = 0;
var random = '' + Math.random();
var prefix = '__\x01symbol:';
var prefixLength = prefix.length;
var internalSymbol = '__\x01symbol@@' + random;
var DP = 'defineProperty';
var DPies = 'defineProperties';
var GOPN = 'getOwnPropertyNames';
var GOPD = 'getOwnPropertyDescriptor';
var PIE = 'propertyIsEnumerable';
var gOPN = Object[GOPN];
var gOPD = Object[GOPD];
var create = Object.create;
var keys = Object.keys;
var freeze = Object.freeze || Object;
var defineProperty = Object[DP];
var $defineProperties = Object[DPies];
var descriptor = gOPD(Object, GOPN);
var ObjectProto = Object.prototype;
var hOP = ObjectProto.hasOwnProperty;
var pIE = ObjectProto[PIE];
var toString = ObjectProto.toString;
var indexOf = Array.prototype.indexOf || function (v) {
for (var i = this.length; i-- && this[i] !== v;) {}
return i;
};
var addInternalIfNeeded = function (o, uid, enumerable) {
if (!hOP.call(o, internalSymbol)) {
try {
defineProperty(o, internalSymbol, {
enumerable: false,
configurable: false,
writable: false,
value: {}
});
} catch (e) {
o.internalSymbol = value
}
}
o[internalSymbol]['@@' + uid] = enumerable;
};
var createWithSymbols = function (proto, descriptors) {
var self = create(proto);
gOPN(descriptors).forEach(function (key) {
if (propertyIsEnumerable.call(descriptors, key)) {
$defineProperty(self, key, descriptors[key]);
}
});
return self;
};
var copyAsNonEnumerable = function (descriptor) {
var newDescriptor = create(descriptor);
newDescriptor.enumerable = false;
return newDescriptor;
};
var get = function get(){};
var onlyNonSymbols = function (name) {
return name != internalSymbol &&
!hOP.call(source, name);
};
var onlySymbols = function (name) {
return name != internalSymbol &&
hOP.call(source, name);
};
var propertyIsEnumerable = function propertyIsEnumerable(key) {
var uid = '' + key;
return onlySymbols(uid) ? (
hOP.call(this, uid) &&
this[internalSymbol]['@@' + uid]
) : pIE.call(this, key);
}
var setAndGetSymbol = function (uid) {
var descriptor = {
enumerable: false,
configurable: true,
get: get,
set: function (value) {
setDescriptor(this, uid, {
enumerable: false,
configurable: true,
writable: true,
value: value
});
addInternalIfNeeded(this, uid, true);
}
};
try {
defineProperty(ObjectProto, uid, descriptor);
} catch (e) {
ObjectProto[uid] = descriptor.value;
}
return freeze(source[uid] = defineProperty(
Object(uid),
'constructor',
sourceConstructor
));
};
var Symbol = function Symbol(description) {
if (this instanceof Symbol) {
throw new TypeError('Symbol is not a constructor');
}
return setAndGetSymbol(
prefix.concat(description || '', random, ++id)
);
};
var source = create(null);
var sourceConstructor = {value: Symbol};
var sourceMap = function (uid) {
return source[uid];
};
var $defineProperty = function defineProp(o, key, descriptor) {
var uid = '' + key;
if (onlySymbols(uid)) {
setDescriptor(o, uid, descriptor.enumerable ?
copyAsNonEnumerable(descriptor) : descriptor);
addInternalIfNeeded(o, uid, !!descriptor.enumerable);
} else {
defineProperty(o, key, descriptor);
}
return o;
};
var $getOwnPropertySymbols = function getOwnPropertySymbols(o) {
return gOPN(o).filter(onlySymbols).map(sourceMap);
}
;
descriptor.value = $defineProperty;
defineProperty(Object, DP, descriptor);
descriptor.value = $getOwnPropertySymbols;
defineProperty(Object, GOPS, descriptor);
descriptor.value = function getOwnPropertyNames(o) {
return gOPN(o).filter(onlyNonSymbols);
};
defineProperty(Object, GOPN, descriptor);
descriptor.value = function defineProperties(o, descriptors) {
var symbols = $getOwnPropertySymbols(descriptors);
if (symbols.length) {
keys(descriptors).concat(symbols).forEach(function (uid) {
if (propertyIsEnumerable.call(descriptors, uid)) {
$defineProperty(o, uid, descriptors[uid]);
}
});
} else {
$defineProperties(o, descriptors);
}
return o;
};
defineProperty(Object, DPies, descriptor);
descriptor.value = propertyIsEnumerable;
defineProperty(ObjectProto, PIE, descriptor);
descriptor.value = Symbol;
defineProperty(G, 'Symbol', descriptor);
// defining `Symbol.for(key)`
descriptor.value = function (key) {
var uid = prefix.concat(prefix, key, random);
return uid in ObjectProto ? source[uid] : setAndGetSymbol(uid);
};
defineProperty(Symbol, 'for', descriptor);
// defining `Symbol.keyFor(symbol)`
descriptor.value = function (symbol) {
if (onlyNonSymbols(symbol))
throw new TypeError(symbol + ' is not a symbol');
return hOP.call(source, symbol) ?
symbol.slice(prefixLength * 2, -random.length) :
void 0
;
};
defineProperty(Symbol, 'keyFor', descriptor);
descriptor.value = function getOwnPropertyDescriptor(o, key) {
var descriptor = gOPD(o, key);
if (descriptor && onlySymbols(key)) {
descriptor.enumerable = propertyIsEnumerable.call(o, key);
}
return descriptor;
};
defineProperty(Object, GOPD, descriptor);
descriptor.value = function (proto, descriptors) {
return arguments.length === 1 ?
create(proto) :
createWithSymbols(proto, descriptors);
};
defineProperty(Object, 'create', descriptor);
descriptor.value = function () {
var str = toString.call(this);
return (str === '[object String]' && onlySymbols(this)) ? '[object Symbol]' : str;
};
defineProperty(ObjectProto, 'toString', descriptor);
try { // fails in few pre ES 5.1 engines
setDescriptor = create(
defineProperty(
{},
prefix,
{
get: function () {
return defineProperty(this, prefix, {value: false})[prefix];
}
}
)
)[prefix] || defineProperty;
} catch(o_O) {
setDescriptor = function (o, key, descriptor) {
var protoDescriptor = gOPD(ObjectProto, key);
delete ObjectProto[key];
defineProperty(o, key, descriptor);
defineProperty(ObjectProto, key, protoDescriptor);
};
}
}(Object, 'getOwnPropertySymbols'));