github.com/nuvolaris/goja@v0.0.0-20230825100449-967811910c6d/builtin_symbol.go (about) 1 package goja 2 3 import "github.com/nuvolaris/goja/unistring" 4 5 var ( 6 SymHasInstance = newSymbol(asciiString("Symbol.hasInstance")) 7 SymIsConcatSpreadable = newSymbol(asciiString("Symbol.isConcatSpreadable")) 8 SymIterator = newSymbol(asciiString("Symbol.iterator")) 9 SymMatch = newSymbol(asciiString("Symbol.match")) 10 SymMatchAll = newSymbol(asciiString("Symbol.matchAll")) 11 SymReplace = newSymbol(asciiString("Symbol.replace")) 12 SymSearch = newSymbol(asciiString("Symbol.search")) 13 SymSpecies = newSymbol(asciiString("Symbol.species")) 14 SymSplit = newSymbol(asciiString("Symbol.split")) 15 SymToPrimitive = newSymbol(asciiString("Symbol.toPrimitive")) 16 SymToStringTag = newSymbol(asciiString("Symbol.toStringTag")) 17 SymUnscopables = newSymbol(asciiString("Symbol.unscopables")) 18 ) 19 20 func (r *Runtime) builtin_symbol(call FunctionCall) Value { 21 var desc String 22 if arg := call.Argument(0); !IsUndefined(arg) { 23 desc = arg.toString() 24 } 25 return newSymbol(desc) 26 } 27 28 func (r *Runtime) symbolproto_tostring(call FunctionCall) Value { 29 sym, ok := call.This.(*Symbol) 30 if !ok { 31 if obj, ok := call.This.(*Object); ok { 32 if v, ok := obj.self.(*primitiveValueObject); ok { 33 if sym1, ok := v.pValue.(*Symbol); ok { 34 sym = sym1 35 } 36 } 37 } 38 } 39 if sym == nil { 40 panic(r.NewTypeError("Method Symbol.prototype.toString is called on incompatible receiver")) 41 } 42 return sym.descriptiveString() 43 } 44 45 func (r *Runtime) symbolproto_valueOf(call FunctionCall) Value { 46 _, ok := call.This.(*Symbol) 47 if ok { 48 return call.This 49 } 50 51 if obj, ok := call.This.(*Object); ok { 52 if v, ok := obj.self.(*primitiveValueObject); ok { 53 if sym, ok := v.pValue.(*Symbol); ok { 54 return sym 55 } 56 } 57 } 58 59 panic(r.NewTypeError("Symbol.prototype.valueOf requires that 'this' be a Symbol")) 60 } 61 62 func (r *Runtime) symbol_for(call FunctionCall) Value { 63 key := call.Argument(0).toString() 64 keyStr := key.string() 65 if v := r.symbolRegistry[keyStr]; v != nil { 66 return v 67 } 68 if r.symbolRegistry == nil { 69 r.symbolRegistry = make(map[unistring.String]*Symbol) 70 } 71 v := newSymbol(key) 72 r.symbolRegistry[keyStr] = v 73 return v 74 } 75 76 func (r *Runtime) symbol_keyfor(call FunctionCall) Value { 77 arg := call.Argument(0) 78 sym, ok := arg.(*Symbol) 79 if !ok { 80 panic(r.NewTypeError("%s is not a symbol", arg.String())) 81 } 82 for key, s := range r.symbolRegistry { 83 if s == sym { 84 return stringValueFromRaw(key) 85 } 86 } 87 return _undefined 88 } 89 90 func (r *Runtime) thisSymbolValue(v Value) *Symbol { 91 if sym, ok := v.(*Symbol); ok { 92 return sym 93 } 94 if obj, ok := v.(*Object); ok { 95 if pVal, ok := obj.self.(*primitiveValueObject); ok { 96 if sym, ok := pVal.pValue.(*Symbol); ok { 97 return sym 98 } 99 } 100 } 101 panic(r.NewTypeError("Value is not a Symbol")) 102 } 103 104 func (r *Runtime) createSymbolProto(val *Object) objectImpl { 105 o := &baseObject{ 106 class: classObject, 107 val: val, 108 extensible: true, 109 prototype: r.global.ObjectPrototype, 110 } 111 o.init() 112 113 o._putProp("constructor", r.global.Symbol, true, false, true) 114 o.setOwnStr("description", &valueProperty{ 115 configurable: true, 116 getterFunc: r.newNativeFunc(func(call FunctionCall) Value { 117 return r.thisSymbolValue(call.This).desc 118 }, nil, "get description", nil, 0), 119 accessor: true, 120 }, false) 121 o._putProp("toString", r.newNativeFunc(r.symbolproto_tostring, nil, "toString", nil, 0), true, false, true) 122 o._putProp("valueOf", r.newNativeFunc(r.symbolproto_valueOf, nil, "valueOf", nil, 0), true, false, true) 123 o._putSym(SymToPrimitive, valueProp(r.newNativeFunc(r.symbolproto_valueOf, nil, "[Symbol.toPrimitive]", nil, 1), false, false, true)) 124 o._putSym(SymToStringTag, valueProp(newStringValue("Symbol"), false, false, true)) 125 126 return o 127 } 128 129 func (r *Runtime) createSymbol(val *Object) objectImpl { 130 o := r.newNativeFuncObj(val, r.builtin_symbol, func(args []Value, proto *Object) *Object { 131 panic(r.NewTypeError("Symbol is not a constructor")) 132 }, "Symbol", r.global.SymbolPrototype, _positiveZero) 133 134 o._putProp("for", r.newNativeFunc(r.symbol_for, nil, "for", nil, 1), true, false, true) 135 o._putProp("keyFor", r.newNativeFunc(r.symbol_keyfor, nil, "keyFor", nil, 1), true, false, true) 136 137 for _, s := range []*Symbol{ 138 SymHasInstance, 139 SymIsConcatSpreadable, 140 SymIterator, 141 SymMatch, 142 SymMatchAll, 143 SymReplace, 144 SymSearch, 145 SymSpecies, 146 SymSplit, 147 SymToPrimitive, 148 SymToStringTag, 149 SymUnscopables, 150 } { 151 n := s.desc.(asciiString) 152 n = n[len("Symbol."):] 153 o._putProp(unistring.String(n), s, false, false, false) 154 } 155 156 return o 157 } 158 159 func (r *Runtime) initSymbol() { 160 r.global.SymbolPrototype = r.newLazyObject(r.createSymbolProto) 161 162 r.global.Symbol = r.newLazyObject(r.createSymbol) 163 r.addToGlobal("Symbol", r.global.Symbol) 164 165 }