mirror of
https://github.com/robertkrimen/otto.git
synced 2025-12-24 12:58:05 +08:00
Value.string(), .float64(), .bool(), etc.
This commit is contained in:
@@ -55,7 +55,7 @@ func Test_issue13(t *testing.T) {
|
||||
t.Error(err)
|
||||
t.FailNow()
|
||||
}
|
||||
is(result.toString(), "Xyzzy,42,def,ghi")
|
||||
is(result.string(), "Xyzzy,42,def,ghi")
|
||||
|
||||
anything := struct {
|
||||
Abc interface{}
|
||||
|
||||
20
builtin.go
20
builtin.go
@@ -18,7 +18,7 @@ func builtinGlobal_eval(call FunctionCall) Value {
|
||||
return src
|
||||
}
|
||||
runtime := call.runtime
|
||||
program := runtime.cmpl_parseOrThrow(toString(src))
|
||||
program := runtime.cmpl_parseOrThrow(src.string())
|
||||
if !call.eval {
|
||||
// Not a direct call to eval, so we enter the global ExecutionContext
|
||||
runtime.enterGlobalScope()
|
||||
@@ -32,12 +32,12 @@ func builtinGlobal_eval(call FunctionCall) Value {
|
||||
}
|
||||
|
||||
func builtinGlobal_isNaN(call FunctionCall) Value {
|
||||
value := toFloat(call.Argument(0))
|
||||
value := call.Argument(0).float64()
|
||||
return toValue_bool(math.IsNaN(value))
|
||||
}
|
||||
|
||||
func builtinGlobal_isFinite(call FunctionCall) Value {
|
||||
value := toFloat(call.Argument(0))
|
||||
value := call.Argument(0).float64()
|
||||
return toValue_bool(!math.IsNaN(value) && !math.IsInf(value, 0))
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ func digitValue(chr rune) int {
|
||||
}
|
||||
|
||||
func builtinGlobal_parseInt(call FunctionCall) Value {
|
||||
input := strings.TrimSpace(toString(call.Argument(0)))
|
||||
input := strings.TrimSpace(call.Argument(0).string())
|
||||
if len(input) == 0 {
|
||||
return NaNValue()
|
||||
}
|
||||
@@ -153,7 +153,7 @@ var parseFloat_matchValid = regexp.MustCompile(`[0-9eE\+\-\.]|Infinity`)
|
||||
|
||||
func builtinGlobal_parseFloat(call FunctionCall) Value {
|
||||
// Caveat emptor: This implementation does NOT match the specification
|
||||
input := strings.TrimSpace(toString(call.Argument(0)))
|
||||
input := strings.TrimSpace(call.Argument(0).string())
|
||||
if parseFloat_matchBadSpecial.MatchString(input) {
|
||||
return NaNValue()
|
||||
}
|
||||
@@ -185,7 +185,7 @@ func _builtinGlobal_encodeURI(call FunctionCall, escape *regexp.Regexp) Value {
|
||||
case []uint16:
|
||||
input = vl
|
||||
default:
|
||||
input = utf16.Encode([]rune(toString(value)))
|
||||
input = utf16.Encode([]rune(value.string()))
|
||||
}
|
||||
if len(input) == 0 {
|
||||
return toValue_string("")
|
||||
@@ -256,7 +256,7 @@ func _decodeURI(input string, reserve bool) (string, bool) {
|
||||
}
|
||||
|
||||
func builtinGlobal_decodeURI(call FunctionCall) Value {
|
||||
output, err := _decodeURI(toString(call.Argument(0)), true)
|
||||
output, err := _decodeURI(call.Argument(0).string(), true)
|
||||
if err {
|
||||
panic(newURIError("URI malformed"))
|
||||
}
|
||||
@@ -264,7 +264,7 @@ func builtinGlobal_decodeURI(call FunctionCall) Value {
|
||||
}
|
||||
|
||||
func builtinGlobal_decodeURIComponent(call FunctionCall) Value {
|
||||
output, err := _decodeURI(toString(call.Argument(0)), false)
|
||||
output, err := _decodeURI(call.Argument(0).string(), false)
|
||||
if err {
|
||||
panic(newURIError("URI malformed"))
|
||||
}
|
||||
@@ -345,9 +345,9 @@ func builtin_unescape(input string) string {
|
||||
}
|
||||
|
||||
func builtinGlobal_escape(call FunctionCall) Value {
|
||||
return toValue_string(builtin_escape(toString(call.Argument(0))))
|
||||
return toValue_string(builtin_escape(call.Argument(0).string()))
|
||||
}
|
||||
|
||||
func builtinGlobal_unescape(call FunctionCall) Value {
|
||||
return toValue_string(builtin_unescape(toString(call.Argument(0))))
|
||||
return toValue_string(builtin_unescape(call.Argument(0).string()))
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ func builtinArray_toLocaleString(call FunctionCall) Value {
|
||||
if !toLocaleString.isCallable() {
|
||||
panic(newTypeError())
|
||||
}
|
||||
stringValue = toLocaleString.call(toValue_object(object)).toString()
|
||||
stringValue = toLocaleString.call(toValue_object(object)).string()
|
||||
}
|
||||
stringList = append(stringList, stringValue)
|
||||
}
|
||||
@@ -70,7 +70,7 @@ func builtinArray_concat(call FunctionCall) Value {
|
||||
case valueObject:
|
||||
object := item._object()
|
||||
if isArray(object) {
|
||||
length := toInteger(object.get("length")).int64
|
||||
length := object.get("length").number().int64
|
||||
for index := int64(0); index < length; index += 1 {
|
||||
name := strconv.FormatInt(index, 10)
|
||||
if object.hasProperty(name) {
|
||||
@@ -143,7 +143,7 @@ func builtinArray_join(call FunctionCall) Value {
|
||||
{
|
||||
argument := call.Argument(0)
|
||||
if argument.IsDefined() {
|
||||
separator = toString(argument)
|
||||
separator = argument.string()
|
||||
}
|
||||
}
|
||||
thisObject := call.thisObject()
|
||||
@@ -158,7 +158,7 @@ func builtinArray_join(call FunctionCall) Value {
|
||||
switch value.kind {
|
||||
case valueEmpty, valueUndefined, valueNull:
|
||||
default:
|
||||
stringValue = toString(value)
|
||||
stringValue = value.string()
|
||||
}
|
||||
stringList = append(stringList, stringValue)
|
||||
}
|
||||
@@ -370,8 +370,8 @@ func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int
|
||||
}
|
||||
|
||||
if compare == nil {
|
||||
j.value = toString(x)
|
||||
k.value = toString(y)
|
||||
j.value = x.string()
|
||||
k.value = y.string()
|
||||
|
||||
if j.value == k.value {
|
||||
return 0
|
||||
@@ -464,7 +464,7 @@ func builtinArray_indexOf(call FunctionCall) Value {
|
||||
if length := int64(toUint32(thisObject.get("length"))); length > 0 {
|
||||
index := int64(0)
|
||||
if len(call.ArgumentList) > 1 {
|
||||
index = toInteger(call.Argument(1)).int64
|
||||
index = call.Argument(1).number().int64
|
||||
}
|
||||
if index < 0 {
|
||||
if index += length; index < 0 {
|
||||
@@ -492,7 +492,7 @@ func builtinArray_lastIndexOf(call FunctionCall) Value {
|
||||
length := int64(toUint32(thisObject.get("length")))
|
||||
index := length - 1
|
||||
if len(call.ArgumentList) > 1 {
|
||||
index = toInteger(call.Argument(1)).int64
|
||||
index = call.Argument(1).number().int64
|
||||
}
|
||||
if 0 > index {
|
||||
index += length
|
||||
@@ -523,7 +523,7 @@ func builtinArray_every(call FunctionCall) Value {
|
||||
callThis := call.Argument(1)
|
||||
for index := int64(0); index < length; index++ {
|
||||
if key := arrayIndexToString(index); thisObject.hasProperty(key) {
|
||||
if value := thisObject.get(key); iterator.call(callThis, value, toValue_int64(index), this).isTrue() {
|
||||
if value := thisObject.get(key); iterator.call(callThis, value, toValue_int64(index), this).bool() {
|
||||
continue
|
||||
}
|
||||
return falseValue
|
||||
@@ -542,7 +542,7 @@ func builtinArray_some(call FunctionCall) Value {
|
||||
callThis := call.Argument(1)
|
||||
for index := int64(0); index < length; index++ {
|
||||
if key := arrayIndexToString(index); thisObject.hasProperty(key) {
|
||||
if value := thisObject.get(key); iterator.call(callThis, value, toValue_int64(index), this).isTrue() {
|
||||
if value := thisObject.get(key); iterator.call(callThis, value, toValue_int64(index), this).bool() {
|
||||
return trueValue
|
||||
}
|
||||
}
|
||||
@@ -597,7 +597,7 @@ func builtinArray_filter(call FunctionCall) Value {
|
||||
for index := int64(0); index < length; index++ {
|
||||
if key := arrayIndexToString(index); thisObject.hasProperty(key) {
|
||||
value := thisObject.get(key)
|
||||
if iterator.call(callThis, value, index, this).isTrue() {
|
||||
if iterator.call(callThis, value, index, this).bool() {
|
||||
values = append(values, value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package otto
|
||||
// Boolean
|
||||
|
||||
func builtinBoolean(call FunctionCall) Value {
|
||||
return toValue_bool(toBoolean(call.Argument(0)))
|
||||
return toValue_bool(call.Argument(0).bool())
|
||||
}
|
||||
|
||||
func builtinNewBoolean(self *_object, argumentList []Value) Value {
|
||||
@@ -16,7 +16,7 @@ func builtinBoolean_toString(call FunctionCall) Value {
|
||||
// Will throw a TypeError if ThisObject is not a Boolean
|
||||
value = call.thisClassObject("Boolean").primitiveValue()
|
||||
}
|
||||
return toValue_string(toString(value))
|
||||
return toValue_string(value.string())
|
||||
}
|
||||
|
||||
func builtinBoolean_valueOf(call FunctionCall) Value {
|
||||
|
||||
@@ -69,7 +69,7 @@ func builtinDate_toJSON(call FunctionCall) Value {
|
||||
object := call.thisObject()
|
||||
value := object.DefaultValue(defaultValueHintNumber) // FIXME object.primitiveNumberValue
|
||||
{ // FIXME value.isFinite
|
||||
value := toFloat(value)
|
||||
value := value.float64()
|
||||
if math.IsNaN(value) || math.IsInf(value, 0) {
|
||||
return nullValue
|
||||
}
|
||||
@@ -102,7 +102,7 @@ func builtinDate_getTime(call FunctionCall) Value {
|
||||
func builtinDate_setTime(call FunctionCall) Value {
|
||||
object := call.thisObject()
|
||||
date := dateObjectOf(object)
|
||||
date.Set(toFloat(call.Argument(0)))
|
||||
date.Set(call.Argument(0).float64())
|
||||
object.value = date
|
||||
return date.Value()
|
||||
}
|
||||
@@ -126,16 +126,14 @@ func _builtinDate_beforeSet(call FunctionCall, argumentLimit int, timeLocal bool
|
||||
valueList := make([]int, argumentLimit)
|
||||
for index := 0; index < argumentLimit; index++ {
|
||||
value := call.ArgumentList[index]
|
||||
if value.IsNaN() {
|
||||
nm := value.number()
|
||||
switch nm.kind {
|
||||
case numberInteger, numberFloat:
|
||||
default:
|
||||
object.value = invalidDateObject
|
||||
return nil, nil, nil, nil
|
||||
}
|
||||
integer := toInteger(value)
|
||||
if !integer.valid() {
|
||||
object.value = invalidDateObject
|
||||
return nil, nil, nil, nil
|
||||
}
|
||||
valueList[index] = int(integer.int64)
|
||||
valueList[index] = int(nm.int64)
|
||||
}
|
||||
baseTime := date.Time()
|
||||
if timeLocal {
|
||||
@@ -146,7 +144,7 @@ func _builtinDate_beforeSet(call FunctionCall, argumentLimit int, timeLocal bool
|
||||
}
|
||||
|
||||
func builtinDate_parse(call FunctionCall) Value {
|
||||
date := toString(call.Argument(0))
|
||||
date := call.Argument(0).string()
|
||||
return toValue_float64(dateParse(date))
|
||||
}
|
||||
|
||||
|
||||
@@ -21,13 +21,13 @@ func builtinError_toString(call FunctionCall) Value {
|
||||
name := "Error"
|
||||
nameValue := thisObject.get("name")
|
||||
if nameValue.IsDefined() {
|
||||
name = toString(nameValue)
|
||||
name = nameValue.string()
|
||||
}
|
||||
|
||||
message := ""
|
||||
messageValue := thisObject.get("message")
|
||||
if messageValue.IsDefined() {
|
||||
message = toString(messageValue)
|
||||
message = messageValue.string()
|
||||
}
|
||||
|
||||
if len(name) == 0 {
|
||||
|
||||
@@ -22,7 +22,7 @@ func builtinNewFunction(self *_object, argumentList []Value) Value {
|
||||
func argumentList2parameterList(argumentList []Value) []string {
|
||||
parameterList := make([]string, 0, len(argumentList))
|
||||
for _, value := range argumentList {
|
||||
tmp := strings.FieldsFunc(toString(value), func(chr rune) bool {
|
||||
tmp := strings.FieldsFunc(value.string(), func(chr rune) bool {
|
||||
return chr == ',' || unicode.IsSpace(chr)
|
||||
})
|
||||
parameterList = append(parameterList, tmp...)
|
||||
@@ -38,10 +38,10 @@ func builtinNewFunctionNative(runtime *_runtime, argumentList []Value) *_object
|
||||
if count > 0 {
|
||||
tmp := make([]string, 0, count-1)
|
||||
for _, value := range argumentList[0 : count-1] {
|
||||
tmp = append(tmp, toString(value))
|
||||
tmp = append(tmp, value.string())
|
||||
}
|
||||
parameterList = strings.Join(tmp, ",")
|
||||
body = toString(argumentList[count-1])
|
||||
body = argumentList[count-1].string()
|
||||
}
|
||||
|
||||
function, err := parser.ParseFunction(parameterList, body)
|
||||
|
||||
@@ -23,7 +23,7 @@ func builtinJSON_parse(call FunctionCall) Value {
|
||||
}
|
||||
|
||||
var root interface{}
|
||||
err := json.Unmarshal([]byte(toString(call.Argument(0))), &root)
|
||||
err := json.Unmarshal([]byte(call.Argument(0).string()), &root)
|
||||
if err != nil {
|
||||
panic(newSyntaxError(err.Error()))
|
||||
}
|
||||
@@ -133,7 +133,7 @@ func builtinJSON_stringify(call FunctionCall) Value {
|
||||
default:
|
||||
continue
|
||||
}
|
||||
name := toString(value)
|
||||
name := value.string()
|
||||
if seen[name] {
|
||||
continue
|
||||
}
|
||||
@@ -151,21 +151,21 @@ func builtinJSON_stringify(call FunctionCall) Value {
|
||||
if spaceValue.kind == valueObject {
|
||||
switch spaceValue.value.(*_object).class {
|
||||
case "String":
|
||||
spaceValue = toValue_string(toString(spaceValue))
|
||||
spaceValue = toValue_string(spaceValue.string())
|
||||
case "Number":
|
||||
spaceValue = toNumber(spaceValue)
|
||||
spaceValue = spaceValue.numberValue()
|
||||
}
|
||||
}
|
||||
switch spaceValue.kind {
|
||||
case valueString:
|
||||
value := toString(spaceValue)
|
||||
value := spaceValue.string()
|
||||
if len(value) > 10 {
|
||||
ctx.gap = value[0:10]
|
||||
} else {
|
||||
ctx.gap = value
|
||||
}
|
||||
case valueNumber:
|
||||
value := toInteger(spaceValue).int64
|
||||
value := spaceValue.number().int64
|
||||
if value > 10 {
|
||||
value = 10
|
||||
} else if value < 0 {
|
||||
@@ -219,23 +219,23 @@ func builtinJSON_stringifyWalk(ctx _builtinJSON_stringifyContext, key string, ho
|
||||
case "Boolean":
|
||||
value = value._object().value.(Value)
|
||||
case "String":
|
||||
value = toValue_string(toString(value))
|
||||
value = toValue_string(value.string())
|
||||
case "Number":
|
||||
value = toNumber(value)
|
||||
value = value.numberValue()
|
||||
}
|
||||
}
|
||||
|
||||
switch value.kind {
|
||||
case valueBoolean:
|
||||
return toBoolean(value), true
|
||||
return value.bool(), true
|
||||
case valueString:
|
||||
return toString(value), true
|
||||
return value.string(), true
|
||||
case valueNumber:
|
||||
integer := toInteger(value)
|
||||
integer := value.number()
|
||||
switch integer.kind {
|
||||
case integerValid:
|
||||
case numberInteger:
|
||||
return integer.int64, true
|
||||
case integerFloat:
|
||||
case numberFloat:
|
||||
return integer.float64, true
|
||||
default:
|
||||
return nil, true
|
||||
|
||||
@@ -8,31 +8,31 @@ import (
|
||||
// Math
|
||||
|
||||
func builtinMath_abs(call FunctionCall) Value {
|
||||
number := toFloat(call.Argument(0))
|
||||
number := call.Argument(0).float64()
|
||||
return toValue_float64(math.Abs(number))
|
||||
}
|
||||
|
||||
func builtinMath_acos(call FunctionCall) Value {
|
||||
number := toFloat(call.Argument(0))
|
||||
number := call.Argument(0).float64()
|
||||
return toValue_float64(math.Acos(number))
|
||||
}
|
||||
|
||||
func builtinMath_asin(call FunctionCall) Value {
|
||||
number := toFloat(call.Argument(0))
|
||||
number := call.Argument(0).float64()
|
||||
return toValue_float64(math.Asin(number))
|
||||
}
|
||||
|
||||
func builtinMath_atan(call FunctionCall) Value {
|
||||
number := toFloat(call.Argument(0))
|
||||
number := call.Argument(0).float64()
|
||||
return toValue_float64(math.Atan(number))
|
||||
}
|
||||
|
||||
func builtinMath_atan2(call FunctionCall) Value {
|
||||
y := toFloat(call.Argument(0))
|
||||
y := call.Argument(0).float64()
|
||||
if math.IsNaN(y) {
|
||||
return NaNValue()
|
||||
}
|
||||
x := toFloat(call.Argument(1))
|
||||
x := call.Argument(1).float64()
|
||||
if math.IsNaN(x) {
|
||||
return NaNValue()
|
||||
}
|
||||
@@ -40,27 +40,27 @@ func builtinMath_atan2(call FunctionCall) Value {
|
||||
}
|
||||
|
||||
func builtinMath_cos(call FunctionCall) Value {
|
||||
number := toFloat(call.Argument(0))
|
||||
number := call.Argument(0).float64()
|
||||
return toValue_float64(math.Cos(number))
|
||||
}
|
||||
|
||||
func builtinMath_ceil(call FunctionCall) Value {
|
||||
number := toFloat(call.Argument(0))
|
||||
number := call.Argument(0).float64()
|
||||
return toValue_float64(math.Ceil(number))
|
||||
}
|
||||
|
||||
func builtinMath_exp(call FunctionCall) Value {
|
||||
number := toFloat(call.Argument(0))
|
||||
number := call.Argument(0).float64()
|
||||
return toValue_float64(math.Exp(number))
|
||||
}
|
||||
|
||||
func builtinMath_floor(call FunctionCall) Value {
|
||||
number := toFloat(call.Argument(0))
|
||||
number := call.Argument(0).float64()
|
||||
return toValue_float64(math.Floor(number))
|
||||
}
|
||||
|
||||
func builtinMath_log(call FunctionCall) Value {
|
||||
number := toFloat(call.Argument(0))
|
||||
number := call.Argument(0).float64()
|
||||
return toValue_float64(math.Log(number))
|
||||
}
|
||||
|
||||
@@ -69,14 +69,14 @@ func builtinMath_max(call FunctionCall) Value {
|
||||
case 0:
|
||||
return negativeInfinityValue()
|
||||
case 1:
|
||||
return toValue_float64(toFloat(call.ArgumentList[0]))
|
||||
return toValue_float64(call.ArgumentList[0].float64())
|
||||
}
|
||||
result := toFloat(call.ArgumentList[0])
|
||||
result := call.ArgumentList[0].float64()
|
||||
if math.IsNaN(result) {
|
||||
return NaNValue()
|
||||
}
|
||||
for _, value := range call.ArgumentList[1:] {
|
||||
value := toFloat(value)
|
||||
value := value.float64()
|
||||
if math.IsNaN(value) {
|
||||
return NaNValue()
|
||||
}
|
||||
@@ -90,14 +90,14 @@ func builtinMath_min(call FunctionCall) Value {
|
||||
case 0:
|
||||
return positiveInfinityValue()
|
||||
case 1:
|
||||
return toValue_float64(toFloat(call.ArgumentList[0]))
|
||||
return toValue_float64(call.ArgumentList[0].float64())
|
||||
}
|
||||
result := toFloat(call.ArgumentList[0])
|
||||
result := call.ArgumentList[0].float64()
|
||||
if math.IsNaN(result) {
|
||||
return NaNValue()
|
||||
}
|
||||
for _, value := range call.ArgumentList[1:] {
|
||||
value := toFloat(value)
|
||||
value := value.float64()
|
||||
if math.IsNaN(value) {
|
||||
return NaNValue()
|
||||
}
|
||||
@@ -108,8 +108,8 @@ func builtinMath_min(call FunctionCall) Value {
|
||||
|
||||
func builtinMath_pow(call FunctionCall) Value {
|
||||
// TODO Make sure this works according to the specification (15.8.2.13)
|
||||
x := toFloat(call.Argument(0))
|
||||
y := toFloat(call.Argument(1))
|
||||
x := call.Argument(0).float64()
|
||||
y := call.Argument(1).float64()
|
||||
if math.Abs(x) == 1 && math.IsInf(y, 0) {
|
||||
return NaNValue()
|
||||
}
|
||||
@@ -121,7 +121,7 @@ func builtinMath_random(call FunctionCall) Value {
|
||||
}
|
||||
|
||||
func builtinMath_round(call FunctionCall) Value {
|
||||
number := toFloat(call.Argument(0))
|
||||
number := call.Argument(0).float64()
|
||||
value := math.Floor(number + 0.5)
|
||||
if value == 0 {
|
||||
value = math.Copysign(0, number)
|
||||
@@ -130,16 +130,16 @@ func builtinMath_round(call FunctionCall) Value {
|
||||
}
|
||||
|
||||
func builtinMath_sin(call FunctionCall) Value {
|
||||
number := toFloat(call.Argument(0))
|
||||
number := call.Argument(0).float64()
|
||||
return toValue_float64(math.Sin(number))
|
||||
}
|
||||
|
||||
func builtinMath_sqrt(call FunctionCall) Value {
|
||||
number := toFloat(call.Argument(0))
|
||||
number := call.Argument(0).float64()
|
||||
return toValue_float64(math.Sqrt(number))
|
||||
}
|
||||
|
||||
func builtinMath_tan(call FunctionCall) Value {
|
||||
number := toFloat(call.Argument(0))
|
||||
number := call.Argument(0).float64()
|
||||
return toValue_float64(math.Tan(number))
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
|
||||
func numberValueFromNumberArgumentList(argumentList []Value) Value {
|
||||
if len(argumentList) > 0 {
|
||||
return toNumber(argumentList[0])
|
||||
return argumentList[0].numberValue()
|
||||
}
|
||||
return toValue_int(0)
|
||||
}
|
||||
@@ -35,7 +35,7 @@ func builtinNumber_toString(call FunctionCall) Value {
|
||||
radix = int(integer)
|
||||
}
|
||||
if radix == 10 {
|
||||
return toValue_string(toString(value))
|
||||
return toValue_string(value.string())
|
||||
}
|
||||
return toValue_string(numberToStringRadix(value, radix))
|
||||
}
|
||||
@@ -52,11 +52,11 @@ func builtinNumber_toFixed(call FunctionCall) Value {
|
||||
if call.This.IsNaN() {
|
||||
return toValue_string("NaN")
|
||||
}
|
||||
value := toFloat(call.This)
|
||||
value := call.This.float64()
|
||||
if math.Abs(value) >= 1e21 {
|
||||
return toValue_string(floatToString(value, 64))
|
||||
}
|
||||
return toValue_string(strconv.FormatFloat(toFloat(call.This), 'f', int(precision), 64))
|
||||
return toValue_string(strconv.FormatFloat(call.This.float64(), 'f', int(precision), 64))
|
||||
}
|
||||
|
||||
func builtinNumber_toExponential(call FunctionCall) Value {
|
||||
@@ -70,7 +70,7 @@ func builtinNumber_toExponential(call FunctionCall) Value {
|
||||
panic(newRangeError("RangeError: toExponential() precision must be greater than 0"))
|
||||
}
|
||||
}
|
||||
return toValue_string(strconv.FormatFloat(toFloat(call.This), 'e', int(precision), 64))
|
||||
return toValue_string(strconv.FormatFloat(call.This.float64(), 'e', int(precision), 64))
|
||||
}
|
||||
|
||||
func builtinNumber_toPrecision(call FunctionCall) Value {
|
||||
@@ -79,13 +79,13 @@ func builtinNumber_toPrecision(call FunctionCall) Value {
|
||||
}
|
||||
value := call.Argument(0)
|
||||
if value.IsUndefined() {
|
||||
return toValue_string(toString(call.This))
|
||||
return toValue_string(call.This.string())
|
||||
}
|
||||
precision := toIntegerFloat(value)
|
||||
if 1 > precision {
|
||||
panic(newRangeError("RangeError: toPrecision() precision must be greater than 1"))
|
||||
}
|
||||
return toValue_string(strconv.FormatFloat(toFloat(call.This), 'g', int(precision), 64))
|
||||
return toValue_string(strconv.FormatFloat(call.This.float64(), 'g', int(precision), 64))
|
||||
}
|
||||
|
||||
func builtinNumber_toLocaleString(call FunctionCall) Value {
|
||||
|
||||
@@ -34,7 +34,7 @@ func builtinObject_valueOf(call FunctionCall) Value {
|
||||
}
|
||||
|
||||
func builtinObject_hasOwnProperty(call FunctionCall) Value {
|
||||
propertyName := toString(call.Argument(0))
|
||||
propertyName := call.Argument(0).string()
|
||||
thisObject := call.thisObject()
|
||||
return toValue_bool(thisObject.hasOwnProperty(propertyName))
|
||||
}
|
||||
@@ -56,7 +56,7 @@ func builtinObject_isPrototypeOf(call FunctionCall) Value {
|
||||
}
|
||||
|
||||
func builtinObject_propertyIsEnumerable(call FunctionCall) Value {
|
||||
propertyName := toString(call.Argument(0))
|
||||
propertyName := call.Argument(0).string()
|
||||
thisObject := call.thisObject()
|
||||
property := thisObject.getOwnProperty(propertyName)
|
||||
if property != nil && property.enumerable() {
|
||||
@@ -106,7 +106,7 @@ func builtinObject_getOwnPropertyDescriptor(call FunctionCall) Value {
|
||||
panic(newTypeError())
|
||||
}
|
||||
|
||||
name := toString(call.Argument(1))
|
||||
name := call.Argument(1).string()
|
||||
descriptor := object.getOwnProperty(name)
|
||||
if descriptor == nil {
|
||||
return Value{}
|
||||
@@ -120,7 +120,7 @@ func builtinObject_defineProperty(call FunctionCall) Value {
|
||||
if object == nil {
|
||||
panic(newTypeError())
|
||||
}
|
||||
name := toString(call.Argument(1))
|
||||
name := call.Argument(1).string()
|
||||
descriptor := toPropertyDescriptor(call.Argument(2))
|
||||
object.defineOwnProperty(name, descriptor, true)
|
||||
return objectValue
|
||||
|
||||
@@ -26,15 +26,15 @@ func builtinNewRegExp(self *_object, argumentList []Value) Value {
|
||||
|
||||
func builtinRegExp_toString(call FunctionCall) Value {
|
||||
thisObject := call.thisObject()
|
||||
source := toString(thisObject.get("source"))
|
||||
source := thisObject.get("source").string()
|
||||
flags := []byte{}
|
||||
if toBoolean(thisObject.get("global")) {
|
||||
if thisObject.get("global").bool() {
|
||||
flags = append(flags, 'g')
|
||||
}
|
||||
if toBoolean(thisObject.get("ignoreCase")) {
|
||||
if thisObject.get("ignoreCase").bool() {
|
||||
flags = append(flags, 'i')
|
||||
}
|
||||
if toBoolean(thisObject.get("multiline")) {
|
||||
if thisObject.get("multiline").bool() {
|
||||
flags = append(flags, 'm')
|
||||
}
|
||||
return toValue_string(fmt.Sprintf("/%s/%s", source, flags))
|
||||
@@ -42,7 +42,7 @@ func builtinRegExp_toString(call FunctionCall) Value {
|
||||
|
||||
func builtinRegExp_exec(call FunctionCall) Value {
|
||||
thisObject := call.thisObject()
|
||||
target := toString(call.Argument(0))
|
||||
target := call.Argument(0).string()
|
||||
match, result := execRegExp(thisObject, target)
|
||||
if !match {
|
||||
return nullValue
|
||||
@@ -52,7 +52,7 @@ func builtinRegExp_exec(call FunctionCall) Value {
|
||||
|
||||
func builtinRegExp_test(call FunctionCall) Value {
|
||||
thisObject := call.thisObject()
|
||||
target := toString(call.Argument(0))
|
||||
target := call.Argument(0).string()
|
||||
match, _ := execRegExp(thisObject, target)
|
||||
return toValue_bool(match)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
func stringValueFromStringArgumentList(argumentList []Value) Value {
|
||||
if len(argumentList) > 0 {
|
||||
return toValue_string(toString(argumentList[0]))
|
||||
return toValue_string(argumentList[0].string())
|
||||
}
|
||||
return toValue_string("")
|
||||
}
|
||||
@@ -42,7 +42,7 @@ func builtinString_fromCharCode(call FunctionCall) Value {
|
||||
|
||||
func builtinString_charAt(call FunctionCall) Value {
|
||||
checkObjectCoercible(call.This)
|
||||
idx := int(toInteger(call.Argument(0)).int64)
|
||||
idx := int(call.Argument(0).number().int64)
|
||||
chr := stringAt(call.This._object().stringValue(), idx)
|
||||
if chr == utf8.RuneError {
|
||||
return toValue_string("")
|
||||
@@ -52,7 +52,7 @@ func builtinString_charAt(call FunctionCall) Value {
|
||||
|
||||
func builtinString_charCodeAt(call FunctionCall) Value {
|
||||
checkObjectCoercible(call.This)
|
||||
idx := int(toInteger(call.Argument(0)).int64)
|
||||
idx := int(call.Argument(0).number().int64)
|
||||
chr := stringAt(call.This._object().stringValue(), idx)
|
||||
if chr == utf8.RuneError {
|
||||
return NaNValue()
|
||||
@@ -63,17 +63,17 @@ func builtinString_charCodeAt(call FunctionCall) Value {
|
||||
func builtinString_concat(call FunctionCall) Value {
|
||||
checkObjectCoercible(call.This)
|
||||
var value bytes.Buffer
|
||||
value.WriteString(toString(call.This))
|
||||
value.WriteString(call.This.string())
|
||||
for _, item := range call.ArgumentList {
|
||||
value.WriteString(toString(item))
|
||||
value.WriteString(item.string())
|
||||
}
|
||||
return toValue_string(value.String())
|
||||
}
|
||||
|
||||
func builtinString_indexOf(call FunctionCall) Value {
|
||||
checkObjectCoercible(call.This)
|
||||
value := toString(call.This)
|
||||
target := toString(call.Argument(0))
|
||||
value := call.This.string()
|
||||
target := call.Argument(0).string()
|
||||
if 2 > len(call.ArgumentList) {
|
||||
return toValue_int(strings.Index(value, target))
|
||||
}
|
||||
@@ -95,8 +95,8 @@ func builtinString_indexOf(call FunctionCall) Value {
|
||||
|
||||
func builtinString_lastIndexOf(call FunctionCall) Value {
|
||||
checkObjectCoercible(call.This)
|
||||
value := toString(call.This)
|
||||
target := toString(call.Argument(0))
|
||||
value := call.This.string()
|
||||
target := call.Argument(0).string()
|
||||
if 2 > len(call.ArgumentList) || call.ArgumentList[1].IsUndefined() {
|
||||
return toValue_int(strings.LastIndex(value, target))
|
||||
}
|
||||
@@ -104,8 +104,8 @@ func builtinString_lastIndexOf(call FunctionCall) Value {
|
||||
if length == 0 {
|
||||
return toValue_int(strings.LastIndex(value, target))
|
||||
}
|
||||
start := toInteger(call.ArgumentList[1])
|
||||
if !start.valid() {
|
||||
start := call.ArgumentList[1].number()
|
||||
if start.kind == numberInfinity { // FIXME
|
||||
// startNumber is infinity, so start is the end of string (start = length)
|
||||
return toValue_int(strings.LastIndex(value, target))
|
||||
}
|
||||
@@ -121,13 +121,13 @@ func builtinString_lastIndexOf(call FunctionCall) Value {
|
||||
|
||||
func builtinString_match(call FunctionCall) Value {
|
||||
checkObjectCoercible(call.This)
|
||||
target := toString(call.This)
|
||||
target := call.This.string()
|
||||
matcherValue := call.Argument(0)
|
||||
matcher := matcherValue._object()
|
||||
if !matcherValue.IsObject() || matcher.class != "RegExp" {
|
||||
matcher = call.runtime.newRegExp(matcherValue, Value{})
|
||||
}
|
||||
global := toBoolean(matcher.get("global"))
|
||||
global := matcher.get("global").bool()
|
||||
if !global {
|
||||
match, result := execRegExp(matcher, target)
|
||||
if !match {
|
||||
@@ -190,7 +190,7 @@ func builtinString_findAndReplaceString(input []byte, lastIndex int, match []int
|
||||
|
||||
func builtinString_replace(call FunctionCall) Value {
|
||||
checkObjectCoercible(call.This)
|
||||
target := []byte(toString(call.This))
|
||||
target := []byte(call.This.string())
|
||||
searchValue := call.Argument(0)
|
||||
searchObject := searchValue._object()
|
||||
|
||||
@@ -205,7 +205,7 @@ func builtinString_replace(call FunctionCall) Value {
|
||||
find = -1
|
||||
}
|
||||
} else {
|
||||
search = regexp.MustCompile(regexp.QuoteMeta(toString(searchValue)))
|
||||
search = regexp.MustCompile(regexp.QuoteMeta(searchValue.string()))
|
||||
}
|
||||
|
||||
found := search.FindAllSubmatchIndex(target, find)
|
||||
@@ -237,13 +237,13 @@ func builtinString_replace(call FunctionCall) Value {
|
||||
}
|
||||
argumentList[matchCount+0] = toValue_int(match[0])
|
||||
argumentList[matchCount+1] = toValue_string(target)
|
||||
replacement := toString(replace.call(Value{}, argumentList, false))
|
||||
replacement := replace.call(Value{}, argumentList, false).string()
|
||||
result = append(result, []byte(replacement)...)
|
||||
lastIndex = match[1]
|
||||
}
|
||||
|
||||
} else {
|
||||
replace := []byte(toString(replaceValue))
|
||||
replace := []byte(replaceValue.string())
|
||||
for _, match := range found {
|
||||
result = builtinString_findAndReplaceString(result, lastIndex, match, target, replace)
|
||||
lastIndex = match[1]
|
||||
@@ -264,7 +264,7 @@ func builtinString_replace(call FunctionCall) Value {
|
||||
|
||||
func builtinString_search(call FunctionCall) Value {
|
||||
checkObjectCoercible(call.This)
|
||||
target := toString(call.This)
|
||||
target := call.This.string()
|
||||
searchValue := call.Argument(0)
|
||||
search := searchValue._object()
|
||||
if !searchValue.IsObject() || search.class != "RegExp" {
|
||||
@@ -290,7 +290,7 @@ func stringSplitMatch(target string, targetLength int64, index uint, search stri
|
||||
|
||||
func builtinString_split(call FunctionCall) Value {
|
||||
checkObjectCoercible(call.This)
|
||||
target := toString(call.This)
|
||||
target := call.This.string()
|
||||
|
||||
separatorValue := call.Argument(0)
|
||||
limitValue := call.Argument(1)
|
||||
@@ -365,7 +365,7 @@ func builtinString_split(call FunctionCall) Value {
|
||||
return toValue_object(call.runtime.newArrayOf(valueArray))
|
||||
|
||||
} else {
|
||||
separator := toString(separatorValue)
|
||||
separator := separatorValue.string()
|
||||
|
||||
splitLimit := limit
|
||||
excess := false
|
||||
@@ -391,7 +391,7 @@ func builtinString_split(call FunctionCall) Value {
|
||||
|
||||
func builtinString_slice(call FunctionCall) Value {
|
||||
checkObjectCoercible(call.This)
|
||||
target := toString(call.This)
|
||||
target := call.This.string()
|
||||
|
||||
length := int64(len(target))
|
||||
start, end := rangeStartEnd(call.ArgumentList, length, false)
|
||||
@@ -403,7 +403,7 @@ func builtinString_slice(call FunctionCall) Value {
|
||||
|
||||
func builtinString_substring(call FunctionCall) Value {
|
||||
checkObjectCoercible(call.This)
|
||||
target := toString(call.This)
|
||||
target := call.This.string()
|
||||
|
||||
length := int64(len(target))
|
||||
start, end := rangeStartEnd(call.ArgumentList, length, true)
|
||||
@@ -414,7 +414,7 @@ func builtinString_substring(call FunctionCall) Value {
|
||||
}
|
||||
|
||||
func builtinString_substr(call FunctionCall) Value {
|
||||
target := toString(call.This)
|
||||
target := call.This.string()
|
||||
|
||||
size := int64(len(target))
|
||||
start, length := rangeStartLength(call.ArgumentList, size)
|
||||
@@ -440,12 +440,12 @@ func builtinString_substr(call FunctionCall) Value {
|
||||
|
||||
func builtinString_toLowerCase(call FunctionCall) Value {
|
||||
checkObjectCoercible(call.This)
|
||||
return toValue_string(strings.ToLower(toString(call.This)))
|
||||
return toValue_string(strings.ToLower(call.This.string()))
|
||||
}
|
||||
|
||||
func builtinString_toUpperCase(call FunctionCall) Value {
|
||||
checkObjectCoercible(call.This)
|
||||
return toValue_string(strings.ToUpper(toString(call.This)))
|
||||
return toValue_string(strings.ToUpper(call.This.string()))
|
||||
}
|
||||
|
||||
// 7.2 Table 2 — Whitespace Characters & 7.3 Table 3 - Line Terminator Characters
|
||||
@@ -453,28 +453,28 @@ const builtinString_trim_whitespace = "\u0009\u000A\u000B\u000C\u000D\u0020\u00A
|
||||
|
||||
func builtinString_trim(call FunctionCall) Value {
|
||||
checkObjectCoercible(call.This)
|
||||
return toValue(strings.Trim(toString(call.This),
|
||||
return toValue(strings.Trim(call.This.string(),
|
||||
builtinString_trim_whitespace))
|
||||
}
|
||||
|
||||
// Mozilla extension, not ECMAScript 5
|
||||
func builtinString_trimLeft(call FunctionCall) Value {
|
||||
checkObjectCoercible(call.This)
|
||||
return toValue(strings.TrimLeft(toString(call.This),
|
||||
return toValue(strings.TrimLeft(call.This.string(),
|
||||
builtinString_trim_whitespace))
|
||||
}
|
||||
|
||||
// Mozilla extension, not ECMAScript 5
|
||||
func builtinString_trimRight(call FunctionCall) Value {
|
||||
checkObjectCoercible(call.This)
|
||||
return toValue(strings.TrimRight(toString(call.This),
|
||||
return toValue(strings.TrimRight(call.This.string(),
|
||||
builtinString_trim_whitespace))
|
||||
}
|
||||
|
||||
func builtinString_localeCompare(call FunctionCall) Value {
|
||||
checkObjectCoercible(call.This)
|
||||
this := toString(call.This)
|
||||
that := toString(call.Argument(0))
|
||||
this := call.This.string()
|
||||
that := call.Argument(0).string()
|
||||
if this < that {
|
||||
return toValue_int(-1)
|
||||
} else if this == that {
|
||||
@@ -487,7 +487,7 @@ func builtinString_localeCompare(call FunctionCall) Value {
|
||||
An alternate version of String.trim
|
||||
func builtinString_trim(call FunctionCall) Value {
|
||||
checkObjectCoercible(call.This)
|
||||
return toValue_string(strings.TrimFunc(toString(call.This), isWhiteSpaceOrLineTerminator))
|
||||
return toValue_string(strings.TrimFunc(call.string(.This), isWhiteSpaceOrLineTerminator))
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ func (self *_runtime) cmpl_call_nodeFunction(function *_object, stash *_fnStash,
|
||||
self.cmpl_variableDeclaration(node.varList)
|
||||
|
||||
result := self.cmpl_evaluate_nodeStatement(node.body)
|
||||
if result.isResult() {
|
||||
if result.kind == valueResult {
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
@@ -142,13 +142,13 @@ func (self *_runtime) cmpl_evaluate_nodeBinaryExpression(node *_nodeBinaryExpres
|
||||
switch node.operator {
|
||||
// Logical
|
||||
case token.LOGICAL_AND:
|
||||
if !toBoolean(leftValue) {
|
||||
if !leftValue.bool() {
|
||||
return leftValue
|
||||
}
|
||||
right := self.cmpl_evaluate_nodeExpression(node.right)
|
||||
return right.resolve()
|
||||
case token.LOGICAL_OR:
|
||||
if toBoolean(leftValue) {
|
||||
if leftValue.bool() {
|
||||
return leftValue
|
||||
}
|
||||
right := self.cmpl_evaluate_nodeExpression(node.right)
|
||||
@@ -173,7 +173,7 @@ func (self *_runtime) cmpl_evaluate_nodeBracketExpression(node *_nodeBracketExpr
|
||||
memberValue := member.resolve()
|
||||
|
||||
// TODO Pass in base value as-is, and defer toObject till later?
|
||||
return toValue(newPropertyReference(self.toObject(targetValue), toString(memberValue), false))
|
||||
return toValue(newPropertyReference(self.toObject(targetValue), memberValue.string(), false))
|
||||
}
|
||||
|
||||
func (self *_runtime) cmpl_evaluate_nodeCallExpression(node *_nodeCallExpression, withArgumentList []interface{}) Value {
|
||||
@@ -212,7 +212,7 @@ func (self *_runtime) cmpl_evaluate_nodeCallExpression(node *_nodeCallExpression
|
||||
func (self *_runtime) cmpl_evaluate_nodeConditionalExpression(node *_nodeConditionalExpression) Value {
|
||||
test := self.cmpl_evaluate_nodeExpression(node.test)
|
||||
testValue := test.resolve()
|
||||
if toBoolean(testValue) {
|
||||
if testValue.bool() {
|
||||
return self.cmpl_evaluate_nodeExpression(node.consequent)
|
||||
}
|
||||
return self.cmpl_evaluate_nodeExpression(node.alternate)
|
||||
@@ -295,7 +295,7 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi
|
||||
switch node.operator {
|
||||
case token.NOT:
|
||||
targetValue := target.resolve()
|
||||
if targetValue.toBoolean() {
|
||||
if targetValue.bool() {
|
||||
return falseValue
|
||||
}
|
||||
return trueValue
|
||||
@@ -305,10 +305,10 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi
|
||||
return toValue_int32(^integerValue)
|
||||
case token.PLUS:
|
||||
targetValue := target.resolve()
|
||||
return toValue_float64(targetValue.toFloat())
|
||||
return toValue_float64(targetValue.float64())
|
||||
case token.MINUS:
|
||||
targetValue := target.resolve()
|
||||
value := targetValue.toFloat()
|
||||
value := targetValue.float64()
|
||||
// TODO Test this
|
||||
sign := float64(-1)
|
||||
if math.Signbit(value) {
|
||||
@@ -319,13 +319,13 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi
|
||||
targetValue := target.resolve()
|
||||
if node.postfix {
|
||||
// Postfix++
|
||||
oldValue := targetValue.toFloat()
|
||||
oldValue := targetValue.float64()
|
||||
newValue := toValue_float64(+1 + oldValue)
|
||||
self.putValue(target.reference(), newValue)
|
||||
return toValue_float64(oldValue)
|
||||
} else {
|
||||
// ++Prefix
|
||||
newValue := toValue_float64(+1 + targetValue.toFloat())
|
||||
newValue := toValue_float64(+1 + targetValue.float64())
|
||||
self.putValue(target.reference(), newValue)
|
||||
return newValue
|
||||
}
|
||||
@@ -333,13 +333,13 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi
|
||||
targetValue := target.resolve()
|
||||
if node.postfix {
|
||||
// Postfix--
|
||||
oldValue := targetValue.toFloat()
|
||||
oldValue := targetValue.float64()
|
||||
newValue := toValue_float64(-1 + oldValue)
|
||||
self.putValue(target.reference(), newValue)
|
||||
return toValue_float64(oldValue)
|
||||
} else {
|
||||
// --Prefix
|
||||
newValue := toValue_float64(-1 + targetValue.toFloat())
|
||||
newValue := toValue_float64(-1 + targetValue.float64())
|
||||
self.putValue(target.reference(), newValue)
|
||||
return newValue
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ resultBreak:
|
||||
}
|
||||
}
|
||||
resultContinue:
|
||||
if !self.cmpl_evaluate_nodeExpression(test).resolve().isTrue() {
|
||||
if !self.cmpl_evaluate_nodeExpression(test).resolve().bool() {
|
||||
// Stahp: do ... while (false)
|
||||
break
|
||||
}
|
||||
@@ -184,7 +184,7 @@ func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement
|
||||
into := self.cmpl_evaluate_nodeExpression(into)
|
||||
// In the case of: for (var abc in def) ...
|
||||
if into.reference() == nil {
|
||||
identifier := toString(into)
|
||||
identifier := into.string()
|
||||
// TODO Should be true or false (strictness) depending on context
|
||||
into = toValue(getIdentifierReference(self.scope.lexical, identifier, false))
|
||||
}
|
||||
@@ -242,7 +242,7 @@ resultBreak:
|
||||
if test != nil {
|
||||
testResult := self.cmpl_evaluate_nodeExpression(test)
|
||||
testResultValue := testResult.resolve()
|
||||
if toBoolean(testResultValue) == false {
|
||||
if testResultValue.bool() == false {
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -275,7 +275,7 @@ resultBreak:
|
||||
func (self *_runtime) cmpl_evaluate_nodeIfStatement(node *_nodeIfStatement) Value {
|
||||
test := self.cmpl_evaluate_nodeExpression(node.test)
|
||||
testValue := test.resolve()
|
||||
if toBoolean(testValue) {
|
||||
if testValue.bool() {
|
||||
return self.cmpl_evaluate_nodeStatement(node.consequent)
|
||||
} else if node.alternate != nil {
|
||||
return self.cmpl_evaluate_nodeStatement(node.alternate)
|
||||
@@ -351,7 +351,7 @@ func (self *_runtime) cmpl_evaluate_nodeTryStatement(node *_nodeTryStatement) Va
|
||||
|
||||
if node.finally != nil {
|
||||
finallyValue := self.cmpl_evaluate_nodeStatement(node.finally)
|
||||
if finallyValue.isResult() {
|
||||
if finallyValue.kind == valueResult {
|
||||
return finallyValue
|
||||
}
|
||||
}
|
||||
@@ -373,7 +373,7 @@ func (self *_runtime) cmpl_evaluate_nodeWhileStatement(node *_nodeWhileStatement
|
||||
result := emptyValue
|
||||
resultBreakContinue:
|
||||
for {
|
||||
if !self.cmpl_evaluate_nodeExpression(test).resolve().isTrue() {
|
||||
if !self.cmpl_evaluate_nodeExpression(test).resolve().bool() {
|
||||
// Stahp: while (false) ...
|
||||
break
|
||||
}
|
||||
|
||||
2
error.go
2
error.go
@@ -136,7 +136,7 @@ func catchPanic(function func()) (err error) {
|
||||
}
|
||||
return
|
||||
case Value:
|
||||
err = errors.New(toString(caught))
|
||||
err = errors.New(caught.string())
|
||||
return
|
||||
//case string:
|
||||
// if strings.HasPrefix(caught, "SyntaxError:") {
|
||||
|
||||
48
evaluate.go
48
evaluate.go
@@ -65,38 +65,38 @@ func (self *_runtime) calculateBinaryExpression(operator token.Token, left Value
|
||||
rightValue = toPrimitive(rightValue)
|
||||
|
||||
if leftValue.IsString() || rightValue.IsString() {
|
||||
return toValue_string(strings.Join([]string{leftValue.toString(), rightValue.toString()}, ""))
|
||||
return toValue_string(strings.Join([]string{leftValue.string(), rightValue.string()}, ""))
|
||||
} else {
|
||||
return toValue_float64(leftValue.toFloat() + rightValue.toFloat())
|
||||
return toValue_float64(leftValue.float64() + rightValue.float64())
|
||||
}
|
||||
case token.MINUS:
|
||||
rightValue := right.resolve()
|
||||
return toValue_float64(leftValue.toFloat() - rightValue.toFloat())
|
||||
return toValue_float64(leftValue.float64() - rightValue.float64())
|
||||
|
||||
// Multiplicative
|
||||
case token.MULTIPLY:
|
||||
rightValue := right.resolve()
|
||||
return toValue_float64(leftValue.toFloat() * rightValue.toFloat())
|
||||
return toValue_float64(leftValue.float64() * rightValue.float64())
|
||||
case token.SLASH:
|
||||
rightValue := right.resolve()
|
||||
return self.evaluateDivide(leftValue.toFloat(), rightValue.toFloat())
|
||||
return self.evaluateDivide(leftValue.float64(), rightValue.float64())
|
||||
case token.REMAINDER:
|
||||
rightValue := right.resolve()
|
||||
return toValue_float64(math.Mod(leftValue.toFloat(), rightValue.toFloat()))
|
||||
return toValue_float64(math.Mod(leftValue.float64(), rightValue.float64()))
|
||||
|
||||
// Logical
|
||||
case token.LOGICAL_AND:
|
||||
left := toBoolean(leftValue)
|
||||
left := leftValue.bool()
|
||||
if !left {
|
||||
return falseValue
|
||||
}
|
||||
return toValue_bool(toBoolean(right.resolve()))
|
||||
return toValue_bool(right.resolve().bool())
|
||||
case token.LOGICAL_OR:
|
||||
left := toBoolean(leftValue)
|
||||
left := leftValue.bool()
|
||||
if left {
|
||||
return trueValue
|
||||
}
|
||||
return toValue_bool(toBoolean(right.resolve()))
|
||||
return toValue_bool(right.resolve().bool())
|
||||
|
||||
// Bitwise
|
||||
case token.AND:
|
||||
@@ -134,7 +134,7 @@ func (self *_runtime) calculateBinaryExpression(operator token.Token, left Value
|
||||
if !rightValue.IsObject() {
|
||||
panic(newTypeError())
|
||||
}
|
||||
return toValue_bool(rightValue._object().hasProperty(toString(leftValue)))
|
||||
return toValue_bool(rightValue._object().hasProperty(leftValue.string()))
|
||||
}
|
||||
|
||||
panic(hereBeDragons(operator))
|
||||
@@ -150,10 +150,10 @@ func makeEqualDispatch() map[int](func(Value, Value) bool) {
|
||||
key := valueKindDispatchKey
|
||||
return map[int](func(Value, Value) bool){
|
||||
|
||||
key(valueNumber, valueObject): func(x Value, y Value) bool { return x.toFloat() == y.toFloat() },
|
||||
key(valueString, valueObject): func(x Value, y Value) bool { return x.toFloat() == y.toFloat() },
|
||||
key(valueObject, valueNumber): func(x Value, y Value) bool { return x.toFloat() == y.toFloat() },
|
||||
key(valueObject, valueString): func(x Value, y Value) bool { return x.toFloat() == y.toFloat() },
|
||||
key(valueNumber, valueObject): func(x Value, y Value) bool { return x.float64() == y.float64() },
|
||||
key(valueString, valueObject): func(x Value, y Value) bool { return x.float64() == y.float64() },
|
||||
key(valueObject, valueNumber): func(x Value, y Value) bool { return x.float64() == y.float64() },
|
||||
key(valueObject, valueString): func(x Value, y Value) bool { return x.float64() == y.float64() },
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,13 +180,13 @@ func calculateLessThan(left Value, right Value, leftFirst bool) _lessThanResult
|
||||
|
||||
result := false
|
||||
if x.kind != valueString || y.kind != valueString {
|
||||
x, y := x.toFloat(), y.toFloat()
|
||||
x, y := x.float64(), y.float64()
|
||||
if math.IsNaN(x) || math.IsNaN(y) {
|
||||
return lessThanUndefined
|
||||
}
|
||||
result = x < y
|
||||
} else {
|
||||
x, y := x.toString(), y.toString()
|
||||
x, y := x.string(), y.string()
|
||||
result = x < y
|
||||
}
|
||||
|
||||
@@ -268,11 +268,11 @@ func (self *_runtime) calculateComparison(comparator token.Token, left Value, ri
|
||||
} else if x.kind <= valueNull || y.kind <= valueNull {
|
||||
result = false
|
||||
} else if x.kind <= valueString && y.kind <= valueString {
|
||||
result = x.toFloat() == y.toFloat()
|
||||
result = x.float64() == y.float64()
|
||||
} else if x.kind == valueBoolean {
|
||||
result = self.calculateComparison(token.EQUAL, toValue_float64(x.toFloat()), y)
|
||||
result = self.calculateComparison(token.EQUAL, toValue_float64(x.float64()), y)
|
||||
} else if y.kind == valueBoolean {
|
||||
result = self.calculateComparison(token.EQUAL, x, toValue_float64(y.toFloat()))
|
||||
result = self.calculateComparison(token.EQUAL, x, toValue_float64(y.float64()))
|
||||
} else if x.kind == valueObject {
|
||||
result = self.calculateComparison(token.EQUAL, toPrimitive(x), y)
|
||||
} else if y.kind == valueObject {
|
||||
@@ -289,17 +289,17 @@ func (self *_runtime) calculateComparison(comparator token.Token, left Value, ri
|
||||
case valueUndefined, valueNull:
|
||||
result = true
|
||||
case valueNumber:
|
||||
x := x.toFloat()
|
||||
y := y.toFloat()
|
||||
x := x.float64()
|
||||
y := y.float64()
|
||||
if math.IsNaN(x) || math.IsNaN(y) {
|
||||
result = false
|
||||
} else {
|
||||
result = x == y
|
||||
}
|
||||
case valueString:
|
||||
result = x.toString() == y.toString()
|
||||
result = x.string() == y.string()
|
||||
case valueBoolean:
|
||||
result = x.toBoolean() == y.toBoolean()
|
||||
result = x.bool() == y.bool()
|
||||
case valueObject:
|
||||
result = x._object() == y._object()
|
||||
default:
|
||||
|
||||
@@ -145,10 +145,10 @@ func (runtime *_runtime) newRegExp(patternValue Value, flagsValue Value) *_objec
|
||||
flags = regExp.flags
|
||||
} else {
|
||||
if patternValue.IsDefined() {
|
||||
pattern = toString(patternValue)
|
||||
pattern = patternValue.string()
|
||||
}
|
||||
if flagsValue.IsDefined() {
|
||||
flags = toString(flagsValue)
|
||||
flags = flagsValue.string()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -144,15 +144,13 @@ func TestNumber_toLocaleString(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func Test_toInteger(t *testing.T) {
|
||||
func TestValue_number(t *testing.T) {
|
||||
tt(t, func() {
|
||||
integer := toInteger(toValue(0.0))
|
||||
is(integer.valid(), true)
|
||||
is(integer.exact(), true)
|
||||
nm := toValue(0.0).number()
|
||||
is(nm.kind, numberInteger)
|
||||
|
||||
integer = toInteger(toValue(3.14159))
|
||||
is(integer.valid(), true)
|
||||
is(integer.exact(), false)
|
||||
nm = toValue(3.14159).number()
|
||||
is(nm.kind, numberFloat)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ func (self *_object) DefaultValue(hint _defaultValueHint) Value {
|
||||
}
|
||||
|
||||
func (self *_object) String() string {
|
||||
return toString(self.DefaultValue(defaultValueHintString))
|
||||
return self.DefaultValue(defaultValueHintString).string()
|
||||
}
|
||||
|
||||
func (self *_object) defineProperty(name string, value Value, mode _propertyMode, throw bool) bool {
|
||||
|
||||
4
otto_.go
4
otto_.go
@@ -73,7 +73,7 @@ func getValueOfArrayIndex(array []Value, index int) (Value, bool) {
|
||||
// A range index can be anything from 0 up to length. It is NOT safe to use as an index
|
||||
// to an array, but is useful for slicing and in some ECMA algorithms.
|
||||
func valueToRangeIndex(indexValue Value, length int64, negativeIsZero bool) int64 {
|
||||
index := toInteger(indexValue).int64
|
||||
index := indexValue.number().int64
|
||||
if negativeIsZero {
|
||||
if index < 0 {
|
||||
index = 0
|
||||
@@ -129,7 +129,7 @@ func rangeStartLength(source []Value, size int64) (start, length int64) {
|
||||
lengthValue := valueOfArrayIndex(source, 1)
|
||||
if !lengthValue.IsUndefined() {
|
||||
// Which it is not, so get the value as an array index
|
||||
length = toInteger(lengthValue).int64
|
||||
length = lengthValue.number().int64
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -649,7 +649,7 @@ func Test_PrimitiveValueObjectValue(t *testing.T) {
|
||||
test, _ := test()
|
||||
|
||||
Number11 := test(`new Number(11)`)
|
||||
is(toFloat(Number11), 11)
|
||||
is(Number11.float64(), 11)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -866,8 +866,8 @@ func TestDotMember(t *testing.T) {
|
||||
func Test_stringToFloat(t *testing.T) {
|
||||
tt(t, func() {
|
||||
|
||||
is(stringToFloat("10e10000"), _Infinity)
|
||||
is(stringToFloat("10e10_."), _NaN)
|
||||
is(parseNumber("10e10000"), _Infinity)
|
||||
is(parseNumber("10e10_."), _NaN)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ func toPropertyDescriptor(value Value) (descriptor _property) {
|
||||
{
|
||||
descriptor.mode = modeSetMask // Initially nothing is set
|
||||
if objectDescriptor.hasProperty("enumerable") {
|
||||
if objectDescriptor.get("enumerable").toBoolean() {
|
||||
if objectDescriptor.get("enumerable").bool() {
|
||||
descriptor.enumerateOn()
|
||||
} else {
|
||||
descriptor.enumerateOff()
|
||||
@@ -132,7 +132,7 @@ func toPropertyDescriptor(value Value) (descriptor _property) {
|
||||
}
|
||||
|
||||
if objectDescriptor.hasProperty("configurable") {
|
||||
if objectDescriptor.get("configurable").toBoolean() {
|
||||
if objectDescriptor.get("configurable").bool() {
|
||||
descriptor.configureOn()
|
||||
} else {
|
||||
descriptor.configureOff()
|
||||
@@ -140,7 +140,7 @@ func toPropertyDescriptor(value Value) (descriptor _property) {
|
||||
}
|
||||
|
||||
if objectDescriptor.hasProperty("writable") {
|
||||
if objectDescriptor.get("writable").toBoolean() {
|
||||
if objectDescriptor.get("writable").bool() {
|
||||
descriptor.writeOn()
|
||||
} else {
|
||||
descriptor.writeOff()
|
||||
|
||||
@@ -359,7 +359,7 @@ func TestComparison(t *testing.T) {
|
||||
|
||||
test("1 == 'Hello, World.'", false)
|
||||
|
||||
is(stringToFloat("-1"), -1)
|
||||
is(parseNumber("-1"), -1)
|
||||
|
||||
test("0+Object", "0function Object() { [native code] }")
|
||||
})
|
||||
|
||||
@@ -32,11 +32,11 @@ func objectLength(object *_object) uint32 {
|
||||
}
|
||||
|
||||
func arrayUint32(value Value) uint32 {
|
||||
tmp := toInteger(value)
|
||||
if !tmp.exact() || !isUint32(tmp.int64) {
|
||||
nm := value.number()
|
||||
if nm.kind != numberInteger || !isUint32(nm.int64) {
|
||||
panic(newRangeError())
|
||||
}
|
||||
return uint32(tmp.int64)
|
||||
return uint32(nm.int64)
|
||||
}
|
||||
|
||||
func arrayDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool {
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
)
|
||||
|
||||
func (runtime *_runtime) newBooleanObject(value Value) *_object {
|
||||
return runtime.newPrimitiveObject("Boolean", toValue_bool(toBoolean(value)))
|
||||
return runtime.newPrimitiveObject("Boolean", toValue_bool(value.bool()))
|
||||
}
|
||||
|
||||
func booleanToString(value bool) string {
|
||||
|
||||
@@ -180,7 +180,7 @@ func newDateTime(argumentList []Value, location *Time.Location) (epoch float64)
|
||||
if index >= len(argumentList) {
|
||||
return default_, false
|
||||
}
|
||||
value := toFloat(argumentList[index])
|
||||
value := argumentList[index].float64()
|
||||
if math.IsNaN(value) || math.IsInf(value, 0) {
|
||||
return 0, true
|
||||
}
|
||||
@@ -226,10 +226,10 @@ func newDateTime(argumentList []Value, location *Time.Location) (epoch float64)
|
||||
value := valueOfArrayIndex(argumentList, 0)
|
||||
value = toPrimitive(value)
|
||||
if value.IsString() {
|
||||
return dateParse(toString(value))
|
||||
return dateParse(value.string())
|
||||
}
|
||||
|
||||
return toFloat(value)
|
||||
return value.float64()
|
||||
}
|
||||
|
||||
INVALID:
|
||||
|
||||
@@ -3,7 +3,7 @@ package otto
|
||||
func (runtime *_runtime) newErrorObject(message Value) *_object {
|
||||
self := runtime.newClassObject("Error")
|
||||
if message.IsDefined() {
|
||||
self.defineProperty("message", toValue_string(toString(message)), 0111, false)
|
||||
self.defineProperty("message", toValue_string(message.string()), 0111, false)
|
||||
}
|
||||
return self
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
package otto
|
||||
|
||||
func (runtime *_runtime) newNumberObject(value Value) *_object {
|
||||
return runtime.newPrimitiveObject("Number", toNumber(value))
|
||||
return runtime.newPrimitiveObject("Number", value.numberValue())
|
||||
}
|
||||
|
||||
@@ -88,9 +88,9 @@ func execRegExp(this *_object, target string) (match bool, result []int) {
|
||||
if this.class != "RegExp" {
|
||||
panic(newTypeError("Calling RegExp.exec on a non-RegExp object"))
|
||||
}
|
||||
lastIndex := toInteger(this.get("lastIndex")).int64
|
||||
lastIndex := this.get("lastIndex").number().int64
|
||||
index := lastIndex
|
||||
global := toBoolean(this.get("global"))
|
||||
global := this.get("global").bool()
|
||||
if !global {
|
||||
index = 0
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ func stringAt(str _stringObject, index int) rune {
|
||||
}
|
||||
|
||||
func (runtime *_runtime) newStringObject(value Value) *_object {
|
||||
str := _newStringObject(toString(value))
|
||||
str := _newStringObject(value.string())
|
||||
|
||||
self := runtime.newClassObject("String")
|
||||
self.defineProperty("length", toValue_int(str.Length()), 0, false)
|
||||
|
||||
@@ -36,10 +36,10 @@ func (self *_tester) underscore() {
|
||||
}
|
||||
|
||||
vm.Set("assert", func(call FunctionCall) Value {
|
||||
if !toBoolean(call.Argument(0)) {
|
||||
if !call.Argument(0).bool() {
|
||||
message := "Assertion failed"
|
||||
if len(call.ArgumentList) > 1 {
|
||||
message = toString(call.ArgumentList[1])
|
||||
message = call.ArgumentList[1].string()
|
||||
}
|
||||
t := terst.Caller().T()
|
||||
is(message, nil)
|
||||
|
||||
79
value.go
79
value.go
@@ -94,14 +94,6 @@ func (value Value) isCallable() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (value Value) isResult() bool {
|
||||
return value.kind == valueResult
|
||||
}
|
||||
|
||||
func (value Value) isReference() bool {
|
||||
return value.kind == valueReference
|
||||
}
|
||||
|
||||
// Call the value as a function with the given this value and argument list and
|
||||
// return the result of invocation. It is essentially equivalent to:
|
||||
//
|
||||
@@ -176,7 +168,7 @@ func (value Value) IsNaN() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
return math.IsNaN(toFloat(value))
|
||||
return math.IsNaN(value.float64())
|
||||
}
|
||||
|
||||
// IsString will return true if value is a string (primitive).
|
||||
@@ -383,19 +375,11 @@ func toValue(value interface{}) Value {
|
||||
func (value Value) String() string {
|
||||
result := ""
|
||||
catchPanic(func() {
|
||||
result = value.toString()
|
||||
result = value.string()
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
func (value Value) toBoolean() bool {
|
||||
return toBoolean(value)
|
||||
}
|
||||
|
||||
func (value Value) isTrue() bool {
|
||||
return toBoolean(value)
|
||||
}
|
||||
|
||||
// ToBoolean will convert the value to a boolean (bool).
|
||||
//
|
||||
// ToValue(0).ToBoolean() => false
|
||||
@@ -408,17 +392,16 @@ func (value Value) isTrue() bool {
|
||||
func (value Value) ToBoolean() (bool, error) {
|
||||
result := false
|
||||
err := catchPanic(func() {
|
||||
result = toBoolean(value)
|
||||
result = value.bool()
|
||||
})
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (value Value) toNumber() Value {
|
||||
return toNumber(value)
|
||||
}
|
||||
|
||||
func (value Value) toFloat() float64 {
|
||||
return toFloat(value)
|
||||
func (value Value) numberValue() Value {
|
||||
if value.kind == valueNumber {
|
||||
return value
|
||||
}
|
||||
return Value{valueNumber, value.float64()}
|
||||
}
|
||||
|
||||
// ToFloat will convert the value to a number (float64).
|
||||
@@ -431,7 +414,7 @@ func (value Value) toFloat() float64 {
|
||||
func (value Value) ToFloat() (float64, error) {
|
||||
result := float64(0)
|
||||
err := catchPanic(func() {
|
||||
result = toFloat(value)
|
||||
result = value.float64()
|
||||
})
|
||||
return result, err
|
||||
}
|
||||
@@ -446,15 +429,11 @@ func (value Value) ToFloat() (float64, error) {
|
||||
func (value Value) ToInteger() (int64, error) {
|
||||
result := int64(0)
|
||||
err := catchPanic(func() {
|
||||
result = toInteger(value).int64
|
||||
result = value.number().int64
|
||||
})
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (value Value) toString() string {
|
||||
return toString(value)
|
||||
}
|
||||
|
||||
// ToString will convert the value to a string (string).
|
||||
//
|
||||
// ToValue(0).ToString() => "0"
|
||||
@@ -467,7 +446,7 @@ func (value Value) toString() string {
|
||||
func (value Value) ToString() (string, error) {
|
||||
result := ""
|
||||
err := catchPanic(func() {
|
||||
result = toString(value)
|
||||
result = value.string()
|
||||
})
|
||||
return result, err
|
||||
}
|
||||
@@ -586,8 +565,8 @@ func sameValue(x Value, y Value) bool {
|
||||
case valueUndefined, valueNull:
|
||||
result = true
|
||||
case valueNumber:
|
||||
x := x.toFloat()
|
||||
y := y.toFloat()
|
||||
x := x.float64()
|
||||
y := y.float64()
|
||||
if math.IsNaN(x) && math.IsNaN(y) {
|
||||
result = true
|
||||
} else {
|
||||
@@ -598,9 +577,9 @@ func sameValue(x Value, y Value) bool {
|
||||
}
|
||||
}
|
||||
case valueString:
|
||||
result = x.toString() == y.toString()
|
||||
result = x.string() == y.string()
|
||||
case valueBoolean:
|
||||
result = x.toBoolean() == y.toBoolean()
|
||||
result = x.bool() == y.bool()
|
||||
case valueObject:
|
||||
result = x._object() == y._object()
|
||||
default:
|
||||
@@ -619,17 +598,17 @@ func strictEqualityComparison(x Value, y Value) bool {
|
||||
case valueUndefined, valueNull:
|
||||
result = true
|
||||
case valueNumber:
|
||||
x := x.toFloat()
|
||||
y := y.toFloat()
|
||||
x := x.float64()
|
||||
y := y.float64()
|
||||
if math.IsNaN(x) && math.IsNaN(y) {
|
||||
result = false
|
||||
} else {
|
||||
result = x == y
|
||||
}
|
||||
case valueString:
|
||||
result = x.toString() == y.toString()
|
||||
result = x.string() == y.string()
|
||||
case valueBoolean:
|
||||
result = x.toBoolean() == y.toBoolean()
|
||||
result = x.bool() == y.bool()
|
||||
case valueObject:
|
||||
result = x._object() == y._object()
|
||||
default:
|
||||
@@ -784,7 +763,7 @@ func (self Value) exportNative() interface{} {
|
||||
func (value Value) toReflectValue(kind reflect.Kind) (reflect.Value, error) {
|
||||
switch kind {
|
||||
case reflect.Bool: // Bool
|
||||
return reflect.ValueOf(value.toBoolean()), nil
|
||||
return reflect.ValueOf(value.bool()), nil
|
||||
case reflect.Int: // Int
|
||||
// We convert to float64 here because converting to int64 will not tell us
|
||||
// if a value is outside the range of int64
|
||||
@@ -795,21 +774,21 @@ func (value Value) toReflectValue(kind reflect.Kind) (reflect.Value, error) {
|
||||
return reflect.ValueOf(int(tmp)), nil
|
||||
}
|
||||
case reflect.Int8: // Int8
|
||||
tmp := toInteger(value).int64
|
||||
tmp := value.number().int64
|
||||
if tmp < int64_minInt8 || tmp > int64_maxInt8 {
|
||||
return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int8", tmp, value)
|
||||
} else {
|
||||
return reflect.ValueOf(int8(tmp)), nil
|
||||
}
|
||||
case reflect.Int16: // Int16
|
||||
tmp := toInteger(value).int64
|
||||
tmp := value.number().int64
|
||||
if tmp < int64_minInt16 || tmp > int64_maxInt16 {
|
||||
return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int16", tmp, value)
|
||||
} else {
|
||||
return reflect.ValueOf(int16(tmp)), nil
|
||||
}
|
||||
case reflect.Int32: // Int32
|
||||
tmp := toInteger(value).int64
|
||||
tmp := value.number().int64
|
||||
if tmp < int64_minInt32 || tmp > int64_maxInt32 {
|
||||
return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int32", tmp, value)
|
||||
} else {
|
||||
@@ -834,21 +813,21 @@ func (value Value) toReflectValue(kind reflect.Kind) (reflect.Value, error) {
|
||||
return reflect.ValueOf(uint(tmp)), nil
|
||||
}
|
||||
case reflect.Uint8: // Uint8
|
||||
tmp := toInteger(value).int64
|
||||
tmp := value.number().int64
|
||||
if tmp < 0 || tmp > int64_maxUint8 {
|
||||
return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint8", tmp, value)
|
||||
} else {
|
||||
return reflect.ValueOf(uint8(tmp)), nil
|
||||
}
|
||||
case reflect.Uint16: // Uint16
|
||||
tmp := toInteger(value).int64
|
||||
tmp := value.number().int64
|
||||
if tmp < 0 || tmp > int64_maxUint16 {
|
||||
return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint16", tmp, value)
|
||||
} else {
|
||||
return reflect.ValueOf(uint16(tmp)), nil
|
||||
}
|
||||
case reflect.Uint32: // Uint32
|
||||
tmp := toInteger(value).int64
|
||||
tmp := value.number().int64
|
||||
if tmp < 0 || tmp > int64_maxUint32 {
|
||||
return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint32", tmp, value)
|
||||
} else {
|
||||
@@ -864,7 +843,7 @@ func (value Value) toReflectValue(kind reflect.Kind) (reflect.Value, error) {
|
||||
return reflect.ValueOf(uint64(tmp)), nil
|
||||
}
|
||||
case reflect.Float32: // Float32
|
||||
tmp := toFloat(value)
|
||||
tmp := value.float64()
|
||||
tmp1 := tmp
|
||||
if 0 > tmp1 {
|
||||
tmp1 = -tmp1
|
||||
@@ -875,10 +854,10 @@ func (value Value) toReflectValue(kind reflect.Kind) (reflect.Value, error) {
|
||||
return reflect.ValueOf(float32(tmp)), nil
|
||||
}
|
||||
case reflect.Float64: // Float64
|
||||
value := toFloat(value)
|
||||
value := value.float64()
|
||||
return reflect.ValueOf(float64(value)), nil
|
||||
case reflect.String: // String
|
||||
return reflect.ValueOf(value.toString()), nil
|
||||
return reflect.ValueOf(value.string()), nil
|
||||
case reflect.Invalid: // Invalid
|
||||
case reflect.Complex64: // FIXME? Complex64
|
||||
case reflect.Complex128: // FIXME? Complex128
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func toBoolean(value Value) bool {
|
||||
func (value Value) bool() bool {
|
||||
if value.kind == valueBoolean {
|
||||
return value.value.(bool)
|
||||
}
|
||||
@@ -38,12 +38,3 @@ func toBoolean(value Value) bool {
|
||||
}
|
||||
panic(fmt.Errorf("toBoolean(%T)", value.value))
|
||||
}
|
||||
|
||||
func stringToBoolean(value string) bool {
|
||||
if value == "true" {
|
||||
return true
|
||||
} else if value == "false" {
|
||||
return false
|
||||
}
|
||||
panic(fmt.Errorf("stringToBoolean(%s)", value))
|
||||
}
|
||||
|
||||
144
value_number.go
144
value_number.go
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
var stringToNumberParseInteger = regexp.MustCompile(`^(?:0[xX])`)
|
||||
|
||||
func stringToFloat(value string) float64 {
|
||||
func parseNumber(value string) float64 {
|
||||
value = strings.TrimSpace(value)
|
||||
|
||||
if value == "" {
|
||||
@@ -41,14 +41,7 @@ func stringToFloat(value string) float64 {
|
||||
return float64(number)
|
||||
}
|
||||
|
||||
func toNumber(value Value) Value {
|
||||
if value.kind == valueNumber {
|
||||
return value
|
||||
}
|
||||
return Value{valueNumber, toFloat(value)}
|
||||
}
|
||||
|
||||
func toFloat(value Value) float64 {
|
||||
func (value Value) float64() float64 {
|
||||
switch value.kind {
|
||||
case valueUndefined:
|
||||
return math.NaN()
|
||||
@@ -84,9 +77,9 @@ func toFloat(value Value) float64 {
|
||||
case float64:
|
||||
return value
|
||||
case string:
|
||||
return stringToFloat(value)
|
||||
return parseNumber(value)
|
||||
case *_object:
|
||||
return toFloat(value.DefaultValue(defaultValueHintNumber))
|
||||
return value.DefaultValue(defaultValueHintNumber).float64()
|
||||
}
|
||||
panic(fmt.Errorf("toFloat(%T)", value.value))
|
||||
}
|
||||
@@ -145,7 +138,7 @@ const (
|
||||
)
|
||||
|
||||
func toIntegerFloat(value Value) float64 {
|
||||
float := value.toFloat()
|
||||
float := value.float64()
|
||||
if math.IsInf(float, 0) {
|
||||
} else if math.IsNaN(float) {
|
||||
float = 0
|
||||
@@ -157,99 +150,88 @@ func toIntegerFloat(value Value) float64 {
|
||||
return float
|
||||
}
|
||||
|
||||
type _integerKind int
|
||||
type _numberKind int
|
||||
|
||||
const (
|
||||
integerValid _integerKind = iota // 3.0 => 3.0
|
||||
integerFloat // 3.14159 => 3.0, 1+2**63 > 2**63-1
|
||||
integerInfinite // Infinity => 2**63-1
|
||||
integerInvalid // NaN => 0
|
||||
numberInteger _numberKind = iota // 3.0 => 3.0
|
||||
numberFloat // 3.14159 => 3.0, 1+2**63 > 2**63-1
|
||||
numberInfinity // Infinity => 2**63-1
|
||||
numberNaN // NaN => 0
|
||||
)
|
||||
|
||||
type _integer struct {
|
||||
kind _integerKind
|
||||
type _number struct {
|
||||
kind _numberKind
|
||||
int64 int64
|
||||
float64 float64
|
||||
}
|
||||
|
||||
func (self _integer) valid() bool {
|
||||
return self.kind == integerValid || self.kind == integerFloat
|
||||
}
|
||||
|
||||
func (self _integer) exact() bool {
|
||||
return self.kind == integerValid
|
||||
}
|
||||
|
||||
func (self _integer) infinite() bool {
|
||||
return self.kind == integerInfinite
|
||||
}
|
||||
|
||||
// Could this use some improvement?
|
||||
// FIXME
|
||||
// http://www.goinggo.net/2013/08/gustavos-ieee-754-brain-teaser.html
|
||||
// http://bazaar.launchpad.net/~niemeyer/strepr/trunk/view/6/strepr.go#L160
|
||||
func toInteger(value Value) (integer _integer) {
|
||||
switch value := value.value.(type) {
|
||||
func (vl Value) number() (number _number) {
|
||||
switch vl := vl.value.(type) {
|
||||
case int8:
|
||||
integer.int64 = int64(value)
|
||||
number.int64 = int64(vl)
|
||||
return
|
||||
case int16:
|
||||
integer.int64 = int64(value)
|
||||
number.int64 = int64(vl)
|
||||
return
|
||||
case uint8:
|
||||
integer.int64 = int64(value)
|
||||
number.int64 = int64(vl)
|
||||
return
|
||||
case uint16:
|
||||
integer.int64 = int64(value)
|
||||
number.int64 = int64(vl)
|
||||
return
|
||||
case uint32:
|
||||
integer.int64 = int64(value)
|
||||
number.int64 = int64(vl)
|
||||
return
|
||||
case int:
|
||||
integer.int64 = int64(value)
|
||||
number.int64 = int64(vl)
|
||||
return
|
||||
case int64:
|
||||
integer.int64 = value
|
||||
number.int64 = vl
|
||||
return
|
||||
}
|
||||
{
|
||||
value := toFloat(value)
|
||||
integer.float64 = value
|
||||
if value == 0 {
|
||||
return
|
||||
}
|
||||
if math.IsNaN(value) {
|
||||
integer.kind = integerInvalid
|
||||
return
|
||||
}
|
||||
if math.IsInf(value, 0) {
|
||||
integer.kind = integerInfinite
|
||||
}
|
||||
if value >= float_maxInt64 {
|
||||
integer.int64 = math.MaxInt64
|
||||
integer.kind = integerFloat
|
||||
return
|
||||
}
|
||||
if value <= float_minInt64 {
|
||||
integer.int64 = math.MinInt64
|
||||
integer.kind = integerFloat
|
||||
return
|
||||
}
|
||||
{
|
||||
value0 := value
|
||||
value1 := float64(0)
|
||||
if value0 > 0 {
|
||||
value1 = math.Floor(value0)
|
||||
} else {
|
||||
value1 = math.Ceil(value0)
|
||||
}
|
||||
|
||||
if value0 != value1 {
|
||||
integer.kind = integerFloat
|
||||
}
|
||||
integer.int64 = int64(value1)
|
||||
return
|
||||
}
|
||||
float := vl.float64()
|
||||
if float == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
number.kind = numberFloat
|
||||
number.float64 = float
|
||||
|
||||
if math.IsNaN(float) {
|
||||
number.kind = numberNaN
|
||||
return
|
||||
}
|
||||
|
||||
if math.IsInf(float, 0) {
|
||||
number.kind = numberInfinity
|
||||
}
|
||||
|
||||
if float >= float_maxInt64 {
|
||||
number.int64 = math.MaxInt64
|
||||
return
|
||||
}
|
||||
|
||||
if float <= float_minInt64 {
|
||||
number.int64 = math.MinInt64
|
||||
return
|
||||
}
|
||||
|
||||
integer := float64(0)
|
||||
if float > 0 {
|
||||
integer = math.Floor(float)
|
||||
} else {
|
||||
integer = math.Ceil(float)
|
||||
}
|
||||
|
||||
if float == integer {
|
||||
number.kind = numberInteger
|
||||
}
|
||||
number.int64 = int64(float)
|
||||
return
|
||||
}
|
||||
|
||||
// ECMA 262: 9.5
|
||||
@@ -264,7 +246,7 @@ func toInt32(value Value) int32 {
|
||||
return value
|
||||
}
|
||||
}
|
||||
floatValue := value.toFloat()
|
||||
floatValue := value.float64()
|
||||
if math.IsNaN(floatValue) || math.IsInf(floatValue, 0) {
|
||||
return 0
|
||||
}
|
||||
@@ -298,7 +280,7 @@ func toUint32(value Value) uint32 {
|
||||
return value
|
||||
}
|
||||
}
|
||||
floatValue := value.toFloat()
|
||||
floatValue := value.float64()
|
||||
if math.IsNaN(floatValue) || math.IsInf(floatValue, 0) {
|
||||
return 0
|
||||
}
|
||||
@@ -325,7 +307,7 @@ func toUint16(value Value) uint16 {
|
||||
return value
|
||||
}
|
||||
}
|
||||
floatValue := value.toFloat()
|
||||
floatValue := value.float64()
|
||||
if math.IsNaN(floatValue) || math.IsInf(floatValue, 0) {
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
|
||||
var matchLeading0Exponent = regexp.MustCompile(`([eE][\+\-])0+([1-9])`) // 1e-07 => 1e-7
|
||||
|
||||
// FIXME
|
||||
// https://code.google.com/p/v8/source/browse/branches/bleeding_edge/src/conversions.cc?spec=svn18082&r=18082
|
||||
func floatToString(value float64, bitsize int) string {
|
||||
// TODO Fit to ECMA-262 9.8.1 specification
|
||||
if math.IsNaN(value) {
|
||||
@@ -28,7 +30,7 @@ func floatToString(value float64, bitsize int) string {
|
||||
}
|
||||
|
||||
func numberToStringRadix(value Value, radix int) string {
|
||||
float := toFloat(value)
|
||||
float := value.float64()
|
||||
if math.IsNaN(float) {
|
||||
return "NaN"
|
||||
} else if math.IsInf(float, 1) {
|
||||
@@ -42,7 +44,7 @@ func numberToStringRadix(value Value, radix int) string {
|
||||
return strconv.FormatInt(int64(float), radix)
|
||||
}
|
||||
|
||||
func toString(value Value) string {
|
||||
func (value Value) string() string {
|
||||
if value.kind == valueString {
|
||||
switch value := value.value.(type) {
|
||||
case string:
|
||||
@@ -95,7 +97,7 @@ func toString(value Value) string {
|
||||
case string:
|
||||
return value
|
||||
case *_object:
|
||||
return toString(value.DefaultValue(defaultValueHintString))
|
||||
return value.DefaultValue(defaultValueHintString).string()
|
||||
}
|
||||
panic(fmt.Errorf("toString(%v %T)", value.value, value.value))
|
||||
panic(fmt.Errorf("%v.string( %T)", value.value, value.value))
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ func TestValue(t *testing.T) {
|
||||
|
||||
is(toValue(false), false)
|
||||
is(toValue(1), 1)
|
||||
is(toValue(1).toFloat(), float64(1))
|
||||
is(toValue(1).float64(), float64(1))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ func TestToValue(t *testing.T) {
|
||||
func TestToBoolean(t *testing.T) {
|
||||
tt(t, func() {
|
||||
is := func(left interface{}, right bool) {
|
||||
is(toValue(left).toBoolean(), right)
|
||||
is(toValue(left).bool(), right)
|
||||
}
|
||||
|
||||
is("", false)
|
||||
@@ -104,7 +104,7 @@ func TestToFloat(t *testing.T) {
|
||||
tt(t, func() {
|
||||
{
|
||||
is := func(left interface{}, right float64) {
|
||||
is(toValue(left).toFloat(), right)
|
||||
is(toValue(left).float64(), right)
|
||||
}
|
||||
is("", 0)
|
||||
is("xyzzy", math.NaN())
|
||||
@@ -114,16 +114,16 @@ func TestToFloat(t *testing.T) {
|
||||
is(NullValue(), 0)
|
||||
//is(newObjectValue(), math.NaN())
|
||||
}
|
||||
is(math.IsNaN(UndefinedValue().toFloat()), true)
|
||||
is(math.IsNaN(UndefinedValue().float64()), true)
|
||||
})
|
||||
}
|
||||
|
||||
func TestToString(t *testing.T) {
|
||||
tt(t, func() {
|
||||
is("undefined", UndefinedValue().toString())
|
||||
is("null", NullValue().toString())
|
||||
is("true", toValue(true).toString())
|
||||
is("false", toValue(false).toString())
|
||||
is("undefined", UndefinedValue().string())
|
||||
is("null", NullValue().string())
|
||||
is("true", toValue(true).string())
|
||||
is("false", toValue(false).string())
|
||||
|
||||
is(UndefinedValue(), "undefined")
|
||||
is(NullValue(), "null")
|
||||
|
||||
Reference in New Issue
Block a user