package goja

import (
	
	
	
	
	

	

	
	
	
	
)

func ( *Runtime) () *collate.Collator {
	 := ._collator
	if  == nil {
		 = collate.New(language.Und)
		._collator = 
	}
	return 
}

func toString( Value) String {
	if ,  := .(String);  {
		return 
	}
	if ,  := .(*Symbol);  {
		return .descriptiveString()
	}
	return .toString()
}

func ( *Runtime) ( FunctionCall) Value {
	if len(.Arguments) > 0 {
		return toString(.Arguments[0])
	} else {
		return stringEmpty
	}
}

func ( *Runtime) ( String,  *Object) *Object {
	 := &Object{runtime: }

	 := &stringObject{}
	.class = classString
	.val = 
	.extensible = true
	.self = 
	.prototype = 
	if  != nil {
		.value = 
	}
	.init()
	return 
}

func ( *Runtime) ( []Value,  *Object) *Object {
	var  String
	if len() > 0 {
		 = [0].toString()
	} else {
		 = stringEmpty
	}
	return ._newString(, )
}

func ( *Runtime) ( Value,  string) Value {
	if ,  := .(String);  {
		return 
	}
	if ,  := .(*Object);  {
		if ,  := .self.(*stringObject);  {
			return .value
		}
		if ,  := .self.(*objectGoReflect);  && .class == classString {
			if  := .toString;  != nil {
				return ()
			}
			if  := .valueOf;  != nil {
				return ()
			}
		}
		if  == .global.StringPrototype {
			return stringEmpty
		}
	}
	.typeErrorResult(true, "String.prototype.%s is called on incompatible receiver", )
	return nil
}

func ( *Runtime) ( FunctionCall) Value {
	return .stringproto_toStringValueOf(.This, "toString")
}

func ( *Runtime) ( FunctionCall) Value {
	return .stringproto_toStringValueOf(.This, "valueOf")
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	return .createStringIterator(.This.toString())
}

func ( *Runtime) ( FunctionCall) Value {
	 := make([]byte, len(.Arguments))
	for ,  := range .Arguments {
		 := toUint16()
		if  >= utf8.RuneSelf {
			 := make([]uint16, len(.Arguments)+1)
			[0] = unistring.BOM
			 := [1:]
			for  := 0;  < ; ++ {
				[] = uint16([])
			}
			[] = 
			++
			for ,  := range .Arguments[:] {
				[+] = toUint16()
			}
			return unicodeString()
		}
		[] = byte()
	}

	return asciiString()
}

func ( *Runtime) ( FunctionCall) Value {
	var  StringBuilder
	for ,  := range .Arguments {
		 := .ToNumber()
		var  rune
		if ,  := .(valueInt);  {
			if  < 0 ||  > utf8.MaxRune {
				panic(.newError(.getRangeError(), "Invalid code point %d", ))
			}
			 = rune()
		} else {
			panic(.newError(.getRangeError(), "Invalid code point %s", ))
		}
		.WriteRune()
	}
	return .String()
}

func ( *Runtime) ( FunctionCall) Value {
	 := .Argument(0).ToObject()
	 := nilSafe(.self.getStr("raw", nil)).ToObject()
	 := toLength(.self.getStr("length", nil))
	if  <= 0 {
		return stringEmpty
	}
	var  StringBuilder
	 := int64(0)
	 := int64(len(.Arguments) - 1)
	for {
		 := nilSafe(.self.getIdx(valueInt(), nil)).toString()
		.WriteString()
		if +1 ==  {
			return .String()
		}
		if  <  {
			.WriteString(nilSafe(.Arguments[+1]).toString())
		}
		++
	}
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := .This.toString()
	 := .Argument(0).ToInteger()
	 := int64(.Length())
	if  < 0 {
		 =  + 
	}
	if  >=  ||  < 0 {
		return _undefined
	}
	return .Substring(int(), int(+1))
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := .This.toString()
	 := .Argument(0).ToInteger()
	if  < 0 ||  >= int64(.Length()) {
		return stringEmpty
	}
	return .Substring(int(), int(+1))
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := .This.toString()
	 := .Argument(0).ToInteger()
	if  < 0 ||  >= int64(.Length()) {
		return _NaN
	}
	return intToValue(int64(.CharAt(toIntStrict()) & 0xFFFF))
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := .This.toString()
	 := .Argument(0).ToInteger()
	 := .Length()
	if  < 0 ||  >= int64() {
		return _undefined
	}
	 := toIntStrict()
	 := .CharAt()
	if isUTF16FirstSurrogate() {
		++
		if  <  {
			 := .CharAt()
			if isUTF16SecondSurrogate() {
				return intToValue(int64(utf16.DecodeRune(rune(), rune())))
			}
		}
	}
	return intToValue(int64( & 0xFFFF))
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := make([]String, len(.Arguments)+1)
	,  := devirtualizeString(.This.toString())
	 := true
	 := 0
	if  == nil {
		[0] = 
		 = len()
	} else {
		[0] = 
		 = .Length()
		 = false
	}
	for ,  := range .Arguments {
		,  := devirtualizeString(.toString())
		if  != nil {
			 = false
			 += .Length()
			[+1] = 
		} else {
			 += .Length()
			[+1] = 
		}
	}

	if  {
		var  strings.Builder
		.Grow()
		for ,  := range  {
			.WriteString(.String())
		}
		return asciiString(.String())
	} else {
		 := make([]uint16, +1)
		[0] = unistring.BOM
		 := 1
		for ,  := range  {
			switch s := .(type) {
			case asciiString:
				for  := 0;  < len(); ++ {
					[] = uint16([])
					++
				}
			case unicodeString:
				copy([:], [1:])
				 += .Length()
			}
		}
		return unicodeString()
	}
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := .This.toString()
	 := .Argument(0)
	if isRegexp() {
		panic(.NewTypeError("First argument to String.prototype.endsWith must not be a regular expression"))
	}
	 := .toString()
	 := int64(.Length())
	var  int64
	if  := .Argument(1);  != _undefined {
		 = .ToInteger()
	} else {
		 = 
	}
	 := toIntStrict(min(max(, 0), ))
	 := .Length()
	 :=  - 
	if  < 0 {
		return valueFalse
	}
	for  := 0;  < ; ++ {
		if .CharAt(+) != .CharAt() {
			return valueFalse
		}
	}
	return valueTrue
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := .This.toString()
	 := .Argument(0)
	if isRegexp() {
		panic(.NewTypeError("First argument to String.prototype.includes must not be a regular expression"))
	}
	 := .toString()
	var  int64
	if  := .Argument(1);  != _undefined {
		 = .ToInteger()
	} else {
		 = 0
	}
	 := toIntStrict(min(max(, 0), int64(.Length())))
	if .index(, ) != -1 {
		return valueTrue
	}
	return valueFalse
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := .This.toString()
	 := .Argument(0).toString()
	 := .Argument(1).ToNumber().ToInteger()

	if  < 0 {
		 = 0
	} else {
		 := int64(.Length())
		if  >  {
			 = 
		}
	}

	return intToValue(int64(.index(, toIntStrict())))
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := .This.toString()
	 := .Argument(0).toString()
	 := .Argument(1).ToNumber()

	var  int64
	if ,  := .(valueFloat);  && math.IsNaN(float64()) {
		 = int64(.Length())
	} else {
		 = .ToInteger()
		if  < 0 {
			 = 0
		} else {
			 := int64(.Length())
			if  >  {
				 = 
			}
		}
	}

	return intToValue(int64(.lastIndex(, toIntStrict())))
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := norm.NFD.String(.This.toString().String())
	 := norm.NFD.String(.Argument(0).toString().String())
	return intToValue(int64(.collator().CompareString(, )))
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := .Argument(0)
	if  != _undefined &&  != _null {
		if  := toMethod(.getV(, SymMatch));  != nil {
			return (FunctionCall{
				This:      ,
				Arguments: []Value{.This},
			})
		}
	}

	var  *regexpObject
	if ,  := .(*Object);  {
		, _ = .self.(*regexpObject)
	}

	if  == nil {
		 = .newRegExp(, nil, .getRegExpPrototype())
	}

	if ,  := .toObject(.getSym(SymMatch, nil)).self.assertCallable();  {
		return (FunctionCall{
			This:      .val,
			Arguments: []Value{.This.toString()},
		})
	}

	panic(.NewTypeError("RegExp matcher is not a function"))
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := .Argument(0)
	if  != _undefined &&  != _null {
		if isRegexp() {
			if ,  := .(*Object);  {
				 := nilSafe(.self.getStr("flags", nil))
				.checkObjectCoercible()
				if !strings.Contains(.toString().String(), "g") {
					panic(.NewTypeError("RegExp doesn't have global flag set"))
				}
			}
		}
		if  := toMethod(.getV(, SymMatchAll));  != nil {
			return (FunctionCall{
				This:      ,
				Arguments: []Value{.This},
			})
		}
	}

	 := .newRegExp(, asciiString("g"), .getRegExpPrototype())

	if ,  := .toObject(.getSym(SymMatchAll, nil)).self.assertCallable();  {
		return (FunctionCall{
			This:      .val,
			Arguments: []Value{.This.toString()},
		})
	}

	panic(.NewTypeError("RegExp matcher is not a function"))
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := .This.toString()
	var  string
	if  := .Argument(0);  != _undefined {
		 = .toString().toString().String()
	} else {
		 = "NFC"
	}
	var  norm.Form
	switch  {
	case "NFC":
		 = norm.NFC
	case "NFD":
		 = norm.NFD
	case "NFKC":
		 = norm.NFKC
	case "NFKD":
		 = norm.NFKD
	default:
		panic(.newError(.getRangeError(), "The normalization form should be one of NFC, NFD, NFKC, NFKD"))
	}

	switch s := .(type) {
	case asciiString:
		return 
	case unicodeString:
		 := .String()
		return newStringValue(.String())
	case *importedString:
		if .scanned && .u == nil {
			return asciiString(.s)
		}
		return newStringValue(.String(.s))
	default:
		panic(unknownStringTypeErr())
	}
}

func ( *Runtime) ( FunctionCall,  bool) Value {
	.checkObjectCoercible(.This)
	 := .This.toString()
	 := toLength(.Argument(0))
	 := int64(.Length())
	if  <=  {
		return 
	}
	,  := devirtualizeString()
	var  String
	var  asciiString
	var  unicodeString
	if  := .Argument(1);  != _undefined {
		 = .toString()
		if .Length() == 0 {
			return 
		}
		,  = devirtualizeString()
	} else {
		 = " "
		 = 
	}
	 := toIntStrict( - )
	if  == nil &&  == nil {
		 := .Length()
		var  strings.Builder
		.Grow(toIntStrict())
		if ! {
			.WriteString(string())
		}
		for  >=  {
			.WriteString(string())
			 -= 
		}
		if  > 0 {
			.WriteString(string([:]))
		}
		if  {
			.WriteString(string())
		}
		return asciiString(.String())
	}
	var  unicodeStringBuilder
	.ensureStarted(toIntStrict())
	if ! {
		.writeString()
	}
	 := .Length()
	for  >=  {
		.writeString()
		 -= 
	}
	if  > 0 {
		.writeString(.Substring(0, ))
	}
	if  {
		.writeString()
	}

	return .String()
}

func ( *Runtime) ( FunctionCall) Value {
	return ._stringPad(, false)
}

func ( *Runtime) ( FunctionCall) Value {
	return ._stringPad(, true)
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := .This.toString()
	 := .Argument(0).ToNumber()
	if  == _positiveInf {
		panic(.newError(.getRangeError(), "Invalid count value"))
	}
	 := .ToInteger()
	if  < 0 {
		panic(.newError(.getRangeError(), "Invalid count value"))
	}
	if  == 0 || .Length() == 0 {
		return stringEmpty
	}
	 := toIntStrict()
	,  := devirtualizeString()
	if  == nil {
		var  strings.Builder
		.Grow(len() * )
		for  := 0;  < ; ++ {
			.WriteString(string())
		}
		return asciiString(.String())
	}

	var  unicodeStringBuilder
	.Grow(.Length() * )
	for  := 0;  < ; ++ {
		.writeUnicodeString()
	}
	return .String()
}

func getReplaceValue( Value) ( String,  func(FunctionCall) Value) {
	if ,  := .(*Object);  {
		if ,  := .self.assertCallable();  {
			 = 
			return
		}
	}
	 = .toString()
	return
}

func stringReplace( String,  [][]int,  String,  func(FunctionCall) Value) Value {
	if len() == 0 {
		return 
	}

	,  := devirtualizeString()

	var  StringBuilder

	 := 0
	 := .Length()
	if  != nil {
		for ,  := range  {
			if [0] !=  {
				.WriteSubstring(, , [0])
			}
			 := len() / 2
			 := make([]Value, +2)
			for  := 0;  < ; ++ {
				 := 2 * 
				if [] != -1 {
					if  == nil {
						[] = [[]:[+1]]
					} else {
						[] = .Substring([], [+1])
					}
				} else {
					[] = _undefined
				}
			}
			[] = valueInt([0])
			[+1] = 
			 := (FunctionCall{
				This:      _undefined,
				Arguments: ,
			}).toString()
			.WriteString()
			 = [1]
		}
	} else {
		for ,  := range  {
			if [0] !=  {
				.WriteString(.Substring(, [0]))
			}
			 := len() / 2
			writeSubstitution(, [0], , func( int) String {
				if [*2] != -1 {
					if  == nil {
						return [[*2]:[*2+1]]
					}
					return .Substring([*2], [*2+1])
				}
				return stringEmpty
			}, , &)
			 = [1]
		}
	}

	if  !=  {
		.WriteString(.Substring(, ))
	}

	return .String()
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := .Argument(0)
	 := .Argument(1)
	if  != _undefined &&  != _null {
		if  := toMethod(.getV(, SymReplace));  != nil {
			return (FunctionCall{
				This:      ,
				Arguments: []Value{.This, },
			})
		}
	}

	 := .This.toString()
	var  [][]int
	 := .toString()
	 := .index(, 0)
	if  != -1 {
		 = append(, []int{,  + .Length()})
	}

	,  := getReplaceValue()
	return stringReplace(, , , )
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := .Argument(0)
	 := .Argument(1)
	if  != _undefined &&  != _null {
		if isRegexp() {
			if ,  := .(*Object);  {
				 := nilSafe(.self.getStr("flags", nil))
				.checkObjectCoercible()
				if !strings.Contains(.toString().String(), "g") {
					panic(.NewTypeError("String.prototype.replaceAll called with a non-global RegExp argument"))
				}
			}
		}
		if  := toMethod(.getV(, SymReplace));  != nil {
			return (FunctionCall{
				This:      ,
				Arguments: []Value{.This, },
			})
		}
	}

	 := .This.toString()
	var  [][]int
	 := .toString()
	 := .Length()
	 := toIntStrict(max(1, int64()))

	 := .index(, 0)
	for  != -1 {
		 = append(, []int{,  + })
		 = .index(, +)
	}

	,  := getReplaceValue()
	return stringReplace(, , , )
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := .Argument(0)
	if  != _undefined &&  != _null {
		if  := toMethod(.getV(, SymSearch));  != nil {
			return (FunctionCall{
				This:      ,
				Arguments: []Value{.This},
			})
		}
	}

	var  *regexpObject
	if ,  := .(*Object);  {
		, _ = .self.(*regexpObject)
	}

	if  == nil {
		 = .newRegExp(, nil, .getRegExpPrototype())
	}

	if ,  := .toObject(.getSym(SymSearch, nil)).self.assertCallable();  {
		return (FunctionCall{
			This:      .val,
			Arguments: []Value{.This.toString()},
		})
	}

	panic(.NewTypeError("RegExp searcher is not a function"))
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := .This.toString()

	 := int64(.Length())
	 := .Argument(0).ToInteger()
	var  int64
	if  := .Argument(1);  != _undefined {
		 = .ToInteger()
	} else {
		 = 
	}

	if  < 0 {
		 += 
		if  < 0 {
			 = 0
		}
	} else {
		if  >  {
			 = 
		}
	}

	if  < 0 {
		 += 
		if  < 0 {
			 = 0
		}
	} else {
		if  >  {
			 = 
		}
	}

	if  >  {
		return .Substring(int(), int())
	}
	return stringEmpty
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := .Argument(0)
	 := .Argument(1)
	if  != _undefined &&  != _null {
		if  := toMethod(.getV(, SymSplit));  != nil {
			return (FunctionCall{
				This:      ,
				Arguments: []Value{.This, },
			})
		}
	}
	 := .This.toString()

	 := -1
	if  != _undefined {
		 = int(toUint32())
	}

	 = .ToString()

	if  == 0 {
		return .newArrayValues(nil)
	}

	if  == _undefined {
		return .newArrayValues([]Value{})
	}

	 := .String()

	 := .String()
	 := 
	if  > 0 {
		 =  + 1
	}

	// TODO handle invalid UTF-16
	 := strings.SplitN(, , )

	if  > 0 && len() >  {
		 = [:]
	}

	 := make([]Value, len())
	for ,  := range  {
		[] = newStringValue()
	}

	return .newArrayValues()
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := .This.toString()
	 := .Argument(0)
	if isRegexp() {
		panic(.NewTypeError("First argument to String.prototype.startsWith must not be a regular expression"))
	}
	 := .toString()
	 := int64(.Length())
	var  int64
	if  := .Argument(1);  != _undefined {
		 = .ToInteger()
	}
	 := toIntStrict(min(max(, 0), ))
	 := .Length()
	if int64(+) >  {
		return valueFalse
	}
	for  := 0;  < ; ++ {
		if .CharAt(+) != .CharAt() {
			return valueFalse
		}
	}
	return valueTrue
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := .This.toString()

	 := int64(.Length())
	 := .Argument(0).ToInteger()
	var  int64
	if  := .Argument(1);  != _undefined {
		 = .ToInteger()
	} else {
		 = 
	}
	if  < 0 {
		 = 0
	} else if  >  {
		 = 
	}

	if  < 0 {
		 = 0
	} else if  >  {
		 = 
	}

	if  >  {
		,  = , 
	}

	return .Substring(int(), int())
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := .This.toString()

	return .toLower()
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := .This.toString()

	return .toUpper()
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := .This.toString()

	// TODO handle invalid UTF-16
	return newStringValue(strings.Trim(.String(), parser.WhitespaceChars))
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := .This.toString()

	// TODO handle invalid UTF-16
	return newStringValue(strings.TrimRight(.String(), parser.WhitespaceChars))
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := .This.toString()

	// TODO handle invalid UTF-16
	return newStringValue(strings.TrimLeft(.String(), parser.WhitespaceChars))
}

func ( *Runtime) ( FunctionCall) Value {
	.checkObjectCoercible(.This)
	 := .This.toString()
	 := .Argument(0).ToInteger()
	var  int64
	 := int64(.Length())
	if  := .Argument(1);  != _undefined {
		 = .ToInteger()
	} else {
		 = 
	}

	if  < 0 {
		 = max(+, 0)
	}

	 = min(max(, 0), -)
	if  <= 0 {
		return stringEmpty
	}

	return .Substring(int(), int(+))
}

func ( *Runtime) ( FunctionCall) Value {
	 := .toObject(.This)
	if ,  := .self.(*stringIterObject);  {
		return .next()
	}
	panic(.NewTypeError("Method String Iterator.prototype.next called on incompatible receiver %s", .objectproto_toString(FunctionCall{This: })))
}

func ( *Runtime) ( *Object) objectImpl {
	 := newBaseObjectObj(, .getIteratorPrototype(), classObject)

	._putProp("next", .newNativeFunc(.stringIterProto_next, "next", 0), true, false, true)
	._putSym(SymToStringTag, valueProp(asciiString(classStringIterator), false, false, true))

	return 
}

func ( *Runtime) () *Object {
	var  *Object
	if  = .global.StringIteratorPrototype;  == nil {
		 = &Object{runtime: }
		.global.StringIteratorPrototype = 
		.self = .createStringIterProto()
	}
	return 
}

func createStringProtoTemplate() *objectTemplate {
	 := newObjectTemplate()
	.protoFactory = func( *Runtime) *Object {
		return .global.ObjectPrototype
	}

	.putStr("length", func( *Runtime) Value { return valueProp(intToValue(0), false, false, false) })

	.putStr("constructor", func( *Runtime) Value { return valueProp(.getString(), true, false, true) })

	.putStr("at", func( *Runtime) Value { return .methodProp(.stringproto_at, "at", 1) })
	.putStr("charAt", func( *Runtime) Value { return .methodProp(.stringproto_charAt, "charAt", 1) })
	.putStr("charCodeAt", func( *Runtime) Value { return .methodProp(.stringproto_charCodeAt, "charCodeAt", 1) })
	.putStr("codePointAt", func( *Runtime) Value { return .methodProp(.stringproto_codePointAt, "codePointAt", 1) })
	.putStr("concat", func( *Runtime) Value { return .methodProp(.stringproto_concat, "concat", 1) })
	.putStr("endsWith", func( *Runtime) Value { return .methodProp(.stringproto_endsWith, "endsWith", 1) })
	.putStr("includes", func( *Runtime) Value { return .methodProp(.stringproto_includes, "includes", 1) })
	.putStr("indexOf", func( *Runtime) Value { return .methodProp(.stringproto_indexOf, "indexOf", 1) })
	.putStr("lastIndexOf", func( *Runtime) Value { return .methodProp(.stringproto_lastIndexOf, "lastIndexOf", 1) })
	.putStr("localeCompare", func( *Runtime) Value { return .methodProp(.stringproto_localeCompare, "localeCompare", 1) })
	.putStr("match", func( *Runtime) Value { return .methodProp(.stringproto_match, "match", 1) })
	.putStr("matchAll", func( *Runtime) Value { return .methodProp(.stringproto_matchAll, "matchAll", 1) })
	.putStr("normalize", func( *Runtime) Value { return .methodProp(.stringproto_normalize, "normalize", 0) })
	.putStr("padEnd", func( *Runtime) Value { return .methodProp(.stringproto_padEnd, "padEnd", 1) })
	.putStr("padStart", func( *Runtime) Value { return .methodProp(.stringproto_padStart, "padStart", 1) })
	.putStr("repeat", func( *Runtime) Value { return .methodProp(.stringproto_repeat, "repeat", 1) })
	.putStr("replace", func( *Runtime) Value { return .methodProp(.stringproto_replace, "replace", 2) })
	.putStr("replaceAll", func( *Runtime) Value { return .methodProp(.stringproto_replaceAll, "replaceAll", 2) })
	.putStr("search", func( *Runtime) Value { return .methodProp(.stringproto_search, "search", 1) })
	.putStr("slice", func( *Runtime) Value { return .methodProp(.stringproto_slice, "slice", 2) })
	.putStr("split", func( *Runtime) Value { return .methodProp(.stringproto_split, "split", 2) })
	.putStr("startsWith", func( *Runtime) Value { return .methodProp(.stringproto_startsWith, "startsWith", 1) })
	.putStr("substring", func( *Runtime) Value { return .methodProp(.stringproto_substring, "substring", 2) })
	.putStr("toLocaleLowerCase", func( *Runtime) Value { return .methodProp(.stringproto_toLowerCase, "toLocaleLowerCase", 0) })
	.putStr("toLocaleUpperCase", func( *Runtime) Value { return .methodProp(.stringproto_toUpperCase, "toLocaleUpperCase", 0) })
	.putStr("toLowerCase", func( *Runtime) Value { return .methodProp(.stringproto_toLowerCase, "toLowerCase", 0) })
	.putStr("toString", func( *Runtime) Value { return .methodProp(.stringproto_toString, "toString", 0) })
	.putStr("toUpperCase", func( *Runtime) Value { return .methodProp(.stringproto_toUpperCase, "toUpperCase", 0) })
	.putStr("trim", func( *Runtime) Value { return .methodProp(.stringproto_trim, "trim", 0) })
	.putStr("trimEnd", func( *Runtime) Value { return valueProp(.getStringproto_trimEnd(), true, false, true) })
	.putStr("trimStart", func( *Runtime) Value { return valueProp(.getStringproto_trimStart(), true, false, true) })
	.putStr("trimRight", func( *Runtime) Value { return valueProp(.getStringproto_trimEnd(), true, false, true) })
	.putStr("trimLeft", func( *Runtime) Value { return valueProp(.getStringproto_trimStart(), true, false, true) })
	.putStr("valueOf", func( *Runtime) Value { return .methodProp(.stringproto_valueOf, "valueOf", 0) })

	// Annex B
	.putStr("substr", func( *Runtime) Value { return .methodProp(.stringproto_substr, "substr", 2) })

	.putSym(SymIterator, func( *Runtime) Value {
		return valueProp(.newNativeFunc(.stringproto_iterator, "[Symbol.iterator]", 0), true, false, true)
	})

	return 
}

func ( *Runtime) () *Object {
	 := .global.stringproto_trimEnd
	if  == nil {
		 = .newNativeFunc(.stringproto_trimEnd, "trimEnd", 0)
		.global.stringproto_trimEnd = 
	}
	return 
}

func ( *Runtime) () *Object {
	 := .global.stringproto_trimStart
	if  == nil {
		 = .newNativeFunc(.stringproto_trimStart, "trimStart", 0)
		.global.stringproto_trimStart = 
	}
	return 
}

func ( *Runtime) () *stringObject {
	 := .stringSingleton
	if  == nil {
		 = .builtin_new(.getString(), nil).self.(*stringObject)
		.stringSingleton = 
	}
	return 
}

func ( *Runtime) () *Object {
	 := .global.String
	if  == nil {
		 = &Object{runtime: }
		.global.String = 
		 := .getStringPrototype()
		 := .newNativeFuncAndConstruct(, .builtin_String, .wrapNativeConstruct(.builtin_newString, , ), , "String", intToValue(1))
		.self = 
		._putProp("fromCharCode", .newNativeFunc(.string_fromcharcode, "fromCharCode", 1), true, false, true)
		._putProp("fromCodePoint", .newNativeFunc(.string_fromcodepoint, "fromCodePoint", 1), true, false, true)
		._putProp("raw", .newNativeFunc(.string_raw, "raw", 1), true, false, true)
	}
	return 
}

var stringProtoTemplate *objectTemplate
var stringProtoTemplateOnce sync.Once

func getStringProtoTemplate() *objectTemplate {
	stringProtoTemplateOnce.Do(func() {
		stringProtoTemplate = createStringProtoTemplate()
	})
	return stringProtoTemplate
}

func ( *Runtime) () *Object {
	 := .global.StringPrototype
	if  == nil {
		 = &Object{runtime: }
		.global.StringPrototype = 
		 := .newTemplatedObject(getStringProtoTemplate(), )
		.class = classString
	}
	return 
}