Skip to content

Commit 7321e75

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 7321e75

File tree

2 files changed

+20
-2
lines changed

2 files changed

+20
-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/lowlevel_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"testing"
1010

1111
"github.com/google/go-cmp/cmp"
12+
"github.com/gopherjs/gopherjs/js"
1213
)
1314

1415
// Test for internalization/externalization of time.Time/Date when time package is imported
@@ -49,3 +50,22 @@ func TestDeferBuiltin(t *testing.T) {
4950
t.Fatalf("%v:\n%s", err, got)
5051
}
5152
}
53+
54+
func TestIssue733(t *testing.T) {
55+
t.Run("sign", func(t *testing.T) {
56+
f := float64(-1)
57+
i := uint32(f)
58+
underlying := js.InternalObject(i).Float() // Get the raw JS number behind i.
59+
if want := float64(4294967295); underlying != want {
60+
t.Errorf("Got: uint32(float64(%v)) = %v. Want: %v.", f, underlying, want)
61+
}
62+
})
63+
t.Run("truncation", func(t *testing.T) {
64+
f := float64(300)
65+
i := uint8(f)
66+
underlying := js.InternalObject(i).Float() // Get the raw JS number behind i.
67+
if want := float64(44); underlying != want {
68+
t.Errorf("Got: uint32(float64(%v)) = %v. Want: %v.", f, underlying, want)
69+
}
70+
})
71+
}

0 commit comments

Comments
 (0)