Repository: robertkrimen/otto (go)

Issue:
array sort function bug with custom compare function
Array sorting is wrong if compare function returns abs(value) < 1 or abs(value) > 2147483647.
```
package main

import "github.com/robertkrimen/otto"

func main() {
vm := otto.New()
vm.Run(`
	console.log([0.5, 0.8, 0.2].sort(function (a,b) { return a-b; }));
	console.log([2147483647, -1, 1].sort(function (a,b) { return a-b; }));
	console.log([2e10, -2e10, 0].sort(function (a,b) { return a-b; }));
`)
}
```
produces
```
0.5,0.2,0.8
2147483647,-1,1
0,-200000000000,200000000000
```

Pull request:
Fixing error of array sort with compare function (resolves #266) 
* Test for issue #266 
* New func toIntSign(..) to get value sign
* Updated sortCompare result from int(toInt32(..)) call to toIntSign(...)

Patch:
diff --git a/builtin_array.go b/builtin_array.go
index c31a070..cf75f77 100644
--- a/builtin_array.go
+++ b/builtin_array.go
@@ -385,7 +385,7 @@ func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int
 		return 1
 	}
 
-	return int(toInt32(compare.call(Value{}, []Value{x, y}, false, nativeFrame)))
+	return toIntSign(compare.call(Value{}, []Value{x, y}, false, nativeFrame))
 }
 
 func arraySortSwap(thisObject *_object, index0, index1 uint) {
diff --git a/value_number.go b/value_number.go
index 649fc68..8a7da02 100644
--- a/value_number.go
+++ b/value_number.go
@@ -300,3 +300,69 @@ func toUint16(value Value) uint16 {
 	}
 	return uint16(remainder)
 }
+
+// toIntSign returns sign of a number converted to -1, 0 ,1
+func toIntSign(value Value) int {
+	switch value := value.value.(type) {
+	case int8:
+		if int8(value) > 0 {
+			return 1
+		} else if int8(value) < 0 {
+			return -1
+		}
+	
+		return 0
+	case int16:
+		if int16(value) > 0 {
+			return 1
+		} else if int16(value) < 0 {
+			return -1
+		} 
+			
+		return 0
+	case int32:
+		if int32(value) > 0 {
+			return 1
+		} else if int32(value) < 0 {
+			return -1
+		} 
+			
+		return 0
+	case uint8:
+		if uint8(value) > 0 {
+			return 1
+		} else if uint8(value) < 0 {
+			return -1
+		} 
+			
+		return 0
+	case uint16:
+		if uint16(value) > 0 {
+			return 1
+		} else if uint16(value) < 0 {
+			return -1
+		} 
+			
+		return 0
+	case uint32:
+		if uint32(value) > 0 {
+			return 1
+		} else if uint32(value) < 0 {
+			return -1
+		} 
+			
+		return 0
+	}
+	floatValue := value.float64()
+	switch {
+	case math.IsNaN(floatValue), math.IsInf(floatValue, 0):
+		return 0
+	case floatValue == 0:
+		return 0
+	case floatValue > 0:
+		return 1
+	default:
+		return -1
+	}
+}
+


Test patch:
diff --git a/bug_test.go b/bug_test.go
index 8dd1788..604beda 100644
--- a/bug_test.go
+++ b/bug_test.go
@@ -748,3 +748,28 @@ func Test_issue186(t *testing.T) {
 		})
 	}
 }
+
+func Test_issue266(t *testing.T) {
+	tt(t, func() {
+		test, _ := test()
+
+		test(`
+			[0.5, 0.8, 0.2].sort(function(a, b) {
+				return a - b;
+			});
+        `, "0.2,0.5,0.8")
+
+		test(`
+			[2147483647, -1, 1].sort(function(a, b) {
+				return a - b;
+			});
+        `, "-1,1,2147483647")
+
+		test(`
+			[2e11, -2e11, 0].sort(function(a, b) {
+				return a - b;
+			});
+        `, "-200000000000,0,200000000000")
+
+	})
+}