package goja

import 

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 ( *Runtime) ( FunctionCall) Value {
	var  String
	if  := .Argument(0); !IsUndefined() {
		 = .toString()
	}
	return newSymbol()
}

func ( *Runtime) ( FunctionCall) Value {
	,  := .This.(*Symbol)
	if ! {
		if ,  := .This.(*Object);  {
			if ,  := .self.(*primitiveValueObject);  {
				if ,  := .pValue.(*Symbol);  {
					 = 
				}
			}
		}
	}
	if  == nil {
		panic(.NewTypeError("Method Symbol.prototype.toString is called on incompatible receiver"))
	}
	return .descriptiveString()
}

func ( *Runtime) ( FunctionCall) Value {
	,  := .This.(*Symbol)
	if  {
		return .This
	}

	if ,  := .This.(*Object);  {
		if ,  := .self.(*primitiveValueObject);  {
			if ,  := .pValue.(*Symbol);  {
				return 
			}
		}
	}

	panic(.NewTypeError("Symbol.prototype.valueOf requires that 'this' be a Symbol"))
}

func ( *Runtime) ( FunctionCall) Value {
	 := .Argument(0).toString()
	 := .string()
	if  := .symbolRegistry[];  != nil {
		return 
	}
	if .symbolRegistry == nil {
		.symbolRegistry = make(map[unistring.String]*Symbol)
	}
	 := newSymbol()
	.symbolRegistry[] = 
	return 
}

func ( *Runtime) ( FunctionCall) Value {
	 := .Argument(0)
	,  := .(*Symbol)
	if ! {
		panic(.NewTypeError("%s is not a symbol", .String()))
	}
	for ,  := range .symbolRegistry {
		if  ==  {
			return stringValueFromRaw()
		}
	}
	return _undefined
}

func ( *Runtime) ( Value) *Symbol {
	if ,  := .(*Symbol);  {
		return 
	}
	if ,  := .(*Object);  {
		if ,  := .self.(*primitiveValueObject);  {
			if ,  := .pValue.(*Symbol);  {
				return 
			}
		}
	}
	panic(.NewTypeError("Value is not a Symbol"))
}

func ( *Runtime) ( *Object) objectImpl {
	 := &baseObject{
		class:      classObject,
		val:        ,
		extensible: true,
		prototype:  .global.ObjectPrototype,
	}
	.init()

	._putProp("constructor", .getSymbol(), true, false, true)
	.setOwnStr("description", &valueProperty{
		configurable: true,
		getterFunc: .newNativeFunc(func( FunctionCall) Value {
			return .thisSymbolValue(.This).desc
		}, "get description", 0),
		accessor: true,
	}, false)
	._putProp("toString", .newNativeFunc(.symbolproto_tostring, "toString", 0), true, false, true)
	._putProp("valueOf", .newNativeFunc(.symbolproto_valueOf, "valueOf", 0), true, false, true)
	._putSym(SymToPrimitive, valueProp(.newNativeFunc(.symbolproto_valueOf, "[Symbol.toPrimitive]", 1), false, false, true))
	._putSym(SymToStringTag, valueProp(newStringValue("Symbol"), false, false, true))

	return 
}

func ( *Runtime) ( *Object) objectImpl {
	 := .newNativeFuncAndConstruct(, .builtin_symbol, func( []Value,  *Object) *Object {
		panic(.NewTypeError("Symbol is not a constructor"))
	}, .getSymbolPrototype(), "Symbol", _positiveZero)

	._putProp("for", .newNativeFunc(.symbol_for, "for", 1), true, false, true)
	._putProp("keyFor", .newNativeFunc(.symbol_keyfor, "keyFor", 1), true, false, true)

	for ,  := range []*Symbol{
		SymHasInstance,
		SymIsConcatSpreadable,
		SymIterator,
		SymMatch,
		SymMatchAll,
		SymReplace,
		SymSearch,
		SymSpecies,
		SymSplit,
		SymToPrimitive,
		SymToStringTag,
		SymUnscopables,
	} {
		 := .desc.(asciiString)
		 = [len("Symbol."):]
		._putProp(unistring.String(), , false, false, false)
	}

	return 
}

func ( *Runtime) () *Object {
	 := .global.SymbolPrototype
	if  == nil {
		 = &Object{runtime: }
		.global.SymbolPrototype = 
		.self = .createSymbolProto()
	}
	return 
}

func ( *Runtime) () *Object {
	 := .global.Symbol
	if  == nil {
		 = &Object{runtime: }
		.global.Symbol = 
		.self = .createSymbol()
	}
	return 
}