Blame view

node_modules/es6-symbol/polyfill.js 4.97 KB
aaac7fed   liuqimichale   add
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
  // ES2015 Symbol polyfill for environments that do not (or partially) support it
  
  'use strict';
  
  var d              = require('d')
    , validateSymbol = require('./validate-symbol')
  
    , create = Object.create, defineProperties = Object.defineProperties
    , defineProperty = Object.defineProperty, objPrototype = Object.prototype
    , NativeSymbol, SymbolPolyfill, HiddenSymbol, globalSymbols = create(null)
    , isNativeSafe;
  
  if (typeof Symbol === 'function') {
  	NativeSymbol = Symbol;
  	try {
  		String(NativeSymbol());
  		isNativeSafe = true;
  	} catch (ignore) {}
  }
  
  var generateName = (function () {
  	var created = create(null);
  	return function (desc) {
  		var postfix = 0, name, ie11BugWorkaround;
  		while (created[desc + (postfix || '')]) ++postfix;
  		desc += (postfix || '');
  		created[desc] = true;
  		name = '@@' + desc;
  		defineProperty(objPrototype, name, d.gs(null, function (value) {
  			// For IE11 issue see:
  			// https://connect.microsoft.com/IE/feedbackdetail/view/1928508/
  			//    ie11-broken-getters-on-dom-objects
  			// https://github.com/medikoo/es6-symbol/issues/12
  			if (ie11BugWorkaround) return;
  			ie11BugWorkaround = true;
  			defineProperty(this, name, d(value));
  			ie11BugWorkaround = false;
  		}));
  		return name;
  	};
  }());
  
  // 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))
  	});
  };
  defineProperties(SymbolPolyfill, {
  	for: d(function (key) {
  		if (globalSymbols[key]) return globalSymbols[key];
  		return (globalSymbols[key] = SymbolPolyfill(String(key)));
  	}),
  	keyFor: d(function (s) {
  		var key;
  		validateSymbol(s);
  		for (key in globalSymbols) if (globalSymbols[key] === s) return key;
  	}),
  
  	// To ensure proper interoperability with other native functions (e.g. Array.from)
  	// fallback to eventual native implementation of given symbol
  	hasInstance: d('', (NativeSymbol && NativeSymbol.hasInstance) || SymbolPolyfill('hasInstance')),
  	isConcatSpreadable: d('', (NativeSymbol && NativeSymbol.isConcatSpreadable) ||
  		SymbolPolyfill('isConcatSpreadable')),
  	iterator: d('', (NativeSymbol && NativeSymbol.iterator) || SymbolPolyfill('iterator')),
  	match: d('', (NativeSymbol && NativeSymbol.match) || SymbolPolyfill('match')),
  	replace: d('', (NativeSymbol && NativeSymbol.replace) || SymbolPolyfill('replace')),
  	search: d('', (NativeSymbol && NativeSymbol.search) || SymbolPolyfill('search')),
  	species: d('', (NativeSymbol && NativeSymbol.species) || SymbolPolyfill('species')),
  	split: d('', (NativeSymbol && NativeSymbol.split) || SymbolPolyfill('split')),
  	toPrimitive: d('', (NativeSymbol && NativeSymbol.toPrimitive) || SymbolPolyfill('toPrimitive')),
  	toStringTag: d('', (NativeSymbol && NativeSymbol.toStringTag) || SymbolPolyfill('toStringTag')),
  	unscopables: d('', (NativeSymbol && NativeSymbol.unscopables) || SymbolPolyfill('unscopables'))
  });
  
  // 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]));