heyujie
2021-05-20 6ebdefb4a5b2be82a8c452c0bb4624f3d85a17b7
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
// 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])
);