Skip to content

Commit 4f6746f

Browse files
committed
Fix float64 to uint{8,16,32} conversion.
Before this change, GopherJS compiler emitted `(f >> 0)` expression to convert a float64 `f` to any non-64-bit unsigned integer type. This is incorrect, because `>>` is a signed bitshift operator in JS, so the returned value remained signed. Moreover, it did not take into account to bit size of the target type. By removing the switch cause, we make the compiler fall through to the default clause where `fc.fixNumber()` actually does the right thing, taking the target into account. Fixes #733.
1 parent 3b5c01e commit 4f6746f

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

compiler/expressions.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,8 +1128,6 @@ func (fc *funcContext) translateConversion(expr ast.Expr, desiredType types.Type
11281128
return fc.fixNumber(fc.formatParenExpr("%1l + ((%1h >> 31) * 4294967296)", expr), t)
11291129
}
11301130
return fc.fixNumber(fc.formatExpr("%s.$low", fc.translateExpr(expr)), t)
1131-
case isFloat(basicExprType):
1132-
return fc.formatParenExpr("%e >> 0", expr)
11331131
case types.Identical(exprType, types.Typ[types.UnsafePointer]):
11341132
return fc.translateExpr(expr)
11351133
default:

tests/numeric_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"runtime"
66
"testing"
77
"testing/quick"
8+
9+
"github.com/gopherjs/gopherjs/js"
810
)
911

1012
// naiveMul64 performs 64-bit multiplication without using the multiplication
@@ -93,3 +95,26 @@ func BenchmarkMul64(b *testing.B) {
9395
}
9496
})
9597
}
98+
99+
func TestIssue733(t *testing.T) {
100+
if runtime.GOOS != "js" {
101+
t.Skip("test uses GopherJS-specific features")
102+
}
103+
104+
t.Run("sign", func(t *testing.T) {
105+
f := float64(-1)
106+
i := uint32(f)
107+
underlying := js.InternalObject(i).Float() // Get the raw JS number behind i.
108+
if want := float64(4294967295); underlying != want {
109+
t.Errorf("Got: uint32(float64(%v)) = %v. Want: %v.", f, underlying, want)
110+
}
111+
})
112+
t.Run("truncation", func(t *testing.T) {
113+
f := float64(300)
114+
i := uint8(f)
115+
underlying := js.InternalObject(i).Float() // Get the raw JS number behind i.
116+
if want := float64(44); underlying != want {
117+
t.Errorf("Got: uint32(float64(%v)) = %v. Want: %v.", f, underlying, want)
118+
}
119+
})
120+
}

0 commit comments

Comments
 (0)