package goja import "github.com/dop251/goja/unistring" var ( SymHasInstance = newSymbol(asciiString("Symbol.hasInstance")) SymIsConcatSpreadable = newSymbol(asciiString("Symbol.isConcatSpreadable")) SymIterator = newSymbol(asciiString("Symbol.iterator")) SymMatch = newSymbol(asciiString("Symbol.match")) SymMatchAll = newSymbol(asciiString("Symbol.matchAll")) SymReplace = newSymbol(asciiString("Symbol.replace")) SymSearch = newSymbol(asciiString("Symbol.search")) SymSpecies = newSymbol(asciiString("Symbol.species")) SymSplit = newSymbol(asciiString("Symbol.split")) SymToPrimitive = newSymbol(asciiString("Symbol.toPrimitive")) SymToStringTag = newSymbol(asciiString("Symbol.toStringTag")) SymUnscopables = newSymbol(asciiString("Symbol.unscopables")) ) func (r *Runtime) builtin_symbol(call FunctionCall) Value { var desc String if arg := call.Argument(0); !IsUndefined(arg) { desc = arg.toString() } return newSymbol(desc) } func (r *Runtime) symbolproto_tostring(call FunctionCall) Value { sym, ok := call.This.(*Symbol) if !ok { if obj, ok := call.This.(*Object); ok { if v, ok := obj.self.(*primitiveValueObject); ok { if sym1, ok := v.pValue.(*Symbol); ok { sym = sym1 } } } } if sym == nil { panic(r.NewTypeError("Method Symbol.prototype.toString is called on incompatible receiver")) } return sym.descriptiveString() } func (r *Runtime) symbolproto_valueOf(call FunctionCall) Value { _, ok := call.This.(*Symbol) if ok { return call.This } if obj, ok := call.This.(*Object); ok { if v, ok := obj.self.(*primitiveValueObject); ok { if sym, ok := v.pValue.(*Symbol); ok { return sym } } } panic(r.NewTypeError("Symbol.prototype.valueOf requires that 'this' be a Symbol")) } func (r *Runtime) symbol_for(call FunctionCall) Value { key := call.Argument(0).toString() keyStr := key.string() if v := r.symbolRegistry[keyStr]; v != nil { return v } if r.symbolRegistry == nil { r.symbolRegistry = make(map[unistring.String]*Symbol) } v := newSymbol(key) r.symbolRegistry[keyStr] = v return v } func (r *Runtime) symbol_keyfor(call FunctionCall) Value { arg := call.Argument(0) sym, ok := arg.(*Symbol) if !ok { panic(r.NewTypeError("%s is not a symbol", arg.String())) } for key, s := range r.symbolRegistry { if s == sym { return stringValueFromRaw(key) } } return _undefined } func (r *Runtime) thisSymbolValue(v Value) *Symbol { if sym, ok := v.(*Symbol); ok { return sym } if obj, ok := v.(*Object); ok { if pVal, ok := obj.self.(*primitiveValueObject); ok { if sym, ok := pVal.pValue.(*Symbol); ok { return sym } } } panic(r.NewTypeError("Value is not a Symbol")) } func (r *Runtime) createSymbolProto(val *Object) objectImpl { o := &baseObject{ class: classObject, val: val, extensible: true, prototype: r.global.ObjectPrototype, } o.init() o._putProp("constructor", r.getSymbol(), true, false, true) o.setOwnStr("description", &valueProperty{ configurable: true, getterFunc: r.newNativeFunc(func(call FunctionCall) Value { return r.thisSymbolValue(call.This).desc }, "get description", 0), accessor: true, }, false) o._putProp("toString", r.newNativeFunc(r.symbolproto_tostring, "toString", 0), true, false, true) o._putProp("valueOf", r.newNativeFunc(r.symbolproto_valueOf, "valueOf", 0), true, false, true) o._putSym(SymToPrimitive, valueProp(r.newNativeFunc(r.symbolproto_valueOf, "[Symbol.toPrimitive]", 1), false, false, true)) o._putSym(SymToStringTag, valueProp(newStringValue("Symbol"), false, false, true)) return o } func (r *Runtime) createSymbol(val *Object) objectImpl { o := r.newNativeFuncAndConstruct(val, r.builtin_symbol, func(args []Value, newTarget *Object) *Object { panic(r.NewTypeError("Symbol is not a constructor")) }, r.getSymbolPrototype(), "Symbol", _positiveZero) o._putProp("for", r.newNativeFunc(r.symbol_for, "for", 1), true, false, true) o._putProp("keyFor", r.newNativeFunc(r.symbol_keyfor, "keyFor", 1), true, false, true) for _, s := range []*Symbol{ SymHasInstance, SymIsConcatSpreadable, SymIterator, SymMatch, SymMatchAll, SymReplace, SymSearch, SymSpecies, SymSplit, SymToPrimitive, SymToStringTag, SymUnscopables, } { n := s.desc.(asciiString) n = n[len("Symbol."):] o._putProp(unistring.String(n), s, false, false, false) } return o } func (r *Runtime) getSymbolPrototype() *Object { ret := r.global.SymbolPrototype if ret == nil { ret = &Object{runtime: r} r.global.SymbolPrototype = ret ret.self = r.createSymbolProto(ret) } return ret } func (r *Runtime) getSymbol() *Object { ret := r.global.Symbol if ret == nil { ret = &Object{runtime: r} r.global.Symbol = ret ret.self = r.createSymbol(ret) } return ret }