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  }