package goja import ( "io" "strconv" "unicode/utf16" "unicode/utf8" ) 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") stringNumber valueString = asciiString("number") stringNaN valueString = asciiString("NaN") stringInfinity = asciiString("Infinity") stringPlusInfinity = asciiString("+Infinity") stringNegInfinity = asciiString("-Infinity") stringEmpty valueString = asciiString("") string__proto__ valueString = asciiString("__proto__") 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) get(n Value) Value { if idx := toIdx(n); idx >= 0 && idx < s.length { return s.getIdx(idx) } return s.baseObject.get(n) } func (s *stringObject) getStr(name string) Value { if i := strToIdx(name); i >= 0 && i < s.length { return s.getIdx(i) } return s.baseObject.getStr(name) } func (s *stringObject) getPropStr(name string) Value { if i := strToIdx(name); i >= 0 && i < s.length { return s.getIdx(i) } return s.baseObject.getPropStr(name) } func (s *stringObject) getProp(n Value) Value { if i := toIdx(n); i >= 0 && i < s.length { return s.getIdx(i) } return s.baseObject.getProp(n) } func (s *stringObject) getOwnProp(name string) Value { if i := strToIdx(name); i >= 0 && i < s.length { val := s.getIdx(i) return &valueProperty{ value: val, enumerable: true, } } return s.baseObject.getOwnProp(name) } func (s *stringObject) getIdx(idx int64) Value { return s.value.substring(idx, idx+1) } func (s *stringObject) put(n Value, val Value, throw bool) { if i := toIdx(n); i >= 0 && i < s.length { s.val.runtime.typeErrorResult(throw, "Cannot assign to read only property '%d' of a String", i) return } s.baseObject.put(n, val, throw) } func (s *stringObject) putStr(name string, val Value, throw bool) { if i := strToIdx(name); i >= 0 && i < s.length { s.val.runtime.typeErrorResult(throw, "Cannot assign to read only property '%d' of a String", i) return } s.baseObject.putStr(name, val, throw) } func (s *stringObject) defineOwnProperty(n Value, descr propertyDescr, throw bool) bool { if i := toIdx(n); i >= 0 && i < s.length { s.val.runtime.typeErrorResult(throw, "Cannot redefine property: %d", i) return false } return s.baseObject.defineOwnProperty(n, descr, throw) } type stringPropIter struct { str valueString // separate, because obj can be the singleton obj *stringObject idx, length int64 recursive bool } 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._enumerate(i.recursive)() } func (s *stringObject) _enumerate(recusrive bool) iterNextFunc { return (&stringPropIter{ str: s.value, obj: s, length: s.length, recursive: recusrive, }).next } func (s *stringObject) enumerate(all, recursive bool) iterNextFunc { return (&propFilterIter{ wrapped: s._enumerate(recursive), all: all, seen: make(map[string]bool), }).next } func (s *stringObject) deleteStr(name string, throw bool) bool { if i := strToIdx(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) delete(n Value, throw bool) bool { if i := toIdx(n); i >= 0 && i < s.length { s.val.runtime.typeErrorResult(throw, "Cannot delete property '%d' of a String", i) return false } return s.baseObject.delete(n, throw) } func (s *stringObject) hasOwnProperty(n Value) bool { if i := toIdx(n); i >= 0 && i < s.length { return true } return s.baseObject.hasOwnProperty(n) } func (s *stringObject) hasOwnPropertyStr(name string) bool { if i := strToIdx(name); i >= 0 && i < s.length { return true } return s.baseObject.hasOwnPropertyStr(name) }