package goja import ( "io" "strconv" "unicode/utf16" "unicode/utf8" ) const ( __proto__ = "__proto__" ) var ( stringTrue valueString = asciiString("true") stringFalse valueString = asciiString("false") stringNull valueString = asciiString("null") stringUndefined valueString = asciiString("undefined") stringObjectC valueString = asciiString("object") stringFunction valueString = asciiString("function") stringBoolean valueString = asciiString("boolean") stringString valueString = asciiString("string") stringSymbol valueString = asciiString("symbol") stringNumber valueString = asciiString("number") stringNaN valueString = asciiString("NaN") stringInfinity = asciiString("Infinity") stringPlusInfinity = asciiString("+Infinity") stringNegInfinity = asciiString("-Infinity") stringEmpty valueString = asciiString("") stringError valueString = asciiString("Error") stringTypeError valueString = asciiString("TypeError") stringReferenceError valueString = asciiString("ReferenceError") stringSyntaxError valueString = asciiString("SyntaxError") stringRangeError valueString = asciiString("RangeError") stringEvalError valueString = asciiString("EvalError") stringURIError valueString = asciiString("URIError") stringGoError valueString = asciiString("GoError") stringObjectNull valueString = asciiString("[object Null]") stringObjectObject valueString = asciiString("[object Object]") stringObjectUndefined valueString = asciiString("[object Undefined]") stringGlobalObject valueString = asciiString("Global Object") stringInvalidDate valueString = asciiString("Invalid Date") ) type valueString interface { Value charAt(int64) rune length() int64 concat(valueString) valueString substring(start, end int64) valueString compareTo(valueString) int reader(start int) io.RuneReader index(valueString, int64) int64 lastIndex(valueString, int64) int64 toLower() valueString toUpper() valueString toTrimmedUTF8() string } type stringObject struct { baseObject value valueString length int64 lengthProp valueProperty } func newUnicodeString(s string) valueString { return unicodeString(utf16.Encode([]rune(s))) } func newStringValue(s string) valueString { for _, chr := range s { if chr >= utf8.RuneSelf { return newUnicodeString(s) } } return asciiString(s) } func (s *stringObject) init() { s.baseObject.init() s.setLength() } func (s *stringObject) setLength() { if s.value != nil { s.length = s.value.length() } s.lengthProp.value = intToValue(s.length) s._put("length", &s.lengthProp) } func (s *stringObject) getStr(name string, receiver Value) Value { if i := strToIdx64(name); i >= 0 && i < s.length { return s._getIdx(i) } return s.baseObject.getStr(name, receiver) } func (s *stringObject) getIdx(idx valueInt, receiver Value) Value { i := int64(idx) if i >= 0 { if i < s.length { return s._getIdx(i) } return nil } return s.baseObject.getStr(idx.String(), receiver) } func (s *stringObject) getOwnPropStr(name string) Value { if i := strToIdx64(name); i >= 0 && i < s.length { val := s._getIdx(i) return &valueProperty{ value: val, enumerable: true, } } return s.baseObject.getOwnPropStr(name) } func (s *stringObject) getOwnPropIdx(idx valueInt) Value { i := int64(idx) if i >= 0 { if i < s.length { val := s._getIdx(i) return &valueProperty{ value: val, enumerable: true, } } return nil } return s.baseObject.getOwnPropStr(idx.String()) } func (s *stringObject) _getIdx(idx int64) Value { return s.value.substring(idx, idx+1) } func (s *stringObject) setOwnStr(name string, val Value, throw bool) bool { if i := strToIdx64(name); i >= 0 && i < s.length { s.val.runtime.typeErrorResult(throw, "Cannot assign to read only property '%d' of a String", i) return false } return s.baseObject.setOwnStr(name, val, throw) } func (s *stringObject) setOwnIdx(idx valueInt, val Value, throw bool) bool { i := int64(idx) if i >= 0 && i < s.length { s.val.runtime.typeErrorResult(throw, "Cannot assign to read only property '%d' of a String", i) return false } return s.baseObject.setOwnStr(idx.String(), val, throw) } func (s *stringObject) setForeignStr(name string, val, receiver Value, throw bool) (bool, bool) { return s._setForeignStr(name, s.getOwnPropStr(name), val, receiver, throw) } func (s *stringObject) setForeignIdx(idx valueInt, val, receiver Value, throw bool) (bool, bool) { return s._setForeignIdx(idx, s.getOwnPropIdx(idx), val, receiver, throw) } func (s *stringObject) defineOwnPropertyStr(name string, descr PropertyDescriptor, throw bool) bool { if i := strToIdx64(name); i >= 0 && i < s.length { s.val.runtime.typeErrorResult(throw, "Cannot redefine property: %d", i) return false } return s.baseObject.defineOwnPropertyStr(name, descr, throw) } func (s *stringObject) defineOwnPropertyIdx(idx valueInt, descr PropertyDescriptor, throw bool) bool { i := int64(idx) if i >= 0 && i < s.length { s.val.runtime.typeErrorResult(throw, "Cannot redefine property: %d", i) return false } return s.baseObject.defineOwnPropertyStr(idx.String(), descr, throw) } type stringPropIter struct { str valueString // separate, because obj can be the singleton obj *stringObject idx, length int64 } func (i *stringPropIter) next() (propIterItem, iterNextFunc) { if i.idx < i.length { name := strconv.FormatInt(i.idx, 10) i.idx++ return propIterItem{name: name, enumerable: _ENUM_TRUE}, i.next } return i.obj.baseObject.enumerateUnfiltered()() } func (s *stringObject) enumerateUnfiltered() iterNextFunc { return (&stringPropIter{ str: s.value, obj: s, length: s.length, }).next } func (s *stringObject) ownKeys(all bool, accum []Value) []Value { for i := int64(0); i < s.length; i++ { accum = append(accum, asciiString(strconv.FormatInt(i, 10))) } return s.baseObject.ownKeys(all, accum) } func (s *stringObject) deleteStr(name string, throw bool) bool { if i := strToIdx64(name); i >= 0 && i < s.length { s.val.runtime.typeErrorResult(throw, "Cannot delete property '%d' of a String", i) return false } return s.baseObject.deleteStr(name, throw) } func (s *stringObject) deleteIdx(idx valueInt, throw bool) bool { i := int64(idx) if i >= 0 && i < s.length { s.val.runtime.typeErrorResult(throw, "Cannot delete property '%d' of a String", i) return false } return s.baseObject.deleteStr(idx.String(), throw) } func (s *stringObject) hasOwnPropertyStr(name string) bool { if i := strToIdx64(name); i >= 0 && i < s.length { return true } return s.baseObject.hasOwnPropertyStr(name) } func (s *stringObject) hasOwnPropertyIdx(idx valueInt) bool { i := int64(idx) if i >= 0 && i < s.length { return true } return s.baseObject.hasOwnPropertyStr(idx.String()) }