Skip to content

Commit dd70f31

Browse files
committed
fix reflect.Select (fixes #420)
1 parent e271629 commit dd70f31

File tree

2 files changed

+39
-13
lines changed

2 files changed

+39
-13
lines changed

compiler/natives/reflect/reflect.go

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,9 +1152,9 @@ func (v Value) Close() {
11521152
var selectHelper = js.Global.Get("$select").Interface().(func(...interface{}) *js.Object)
11531153

11541154
func chanrecv(t *rtype, ch unsafe.Pointer, nb bool, val unsafe.Pointer) (selected, received bool) {
1155-
comms := [][]interface{}{{js.InternalObject(ch)}}
1155+
comms := [][]*js.Object{{js.InternalObject(ch)}}
11561156
if nb {
1157-
comms = append(comms, []interface{}{})
1157+
comms = append(comms, []*js.Object{})
11581158
}
11591159
selectRes := selectHelper(comms)
11601160
if nb && selectRes.Index(0).Int() == 1 {
@@ -1166,9 +1166,9 @@ func chanrecv(t *rtype, ch unsafe.Pointer, nb bool, val unsafe.Pointer) (selecte
11661166
}
11671167

11681168
func chansend(t *rtype, ch unsafe.Pointer, val unsafe.Pointer, nb bool) bool {
1169-
comms := [][]interface{}{{js.InternalObject(ch), js.InternalObject(val).Call("$get")}}
1169+
comms := [][]*js.Object{{js.InternalObject(ch), js.InternalObject(val).Call("$get")}}
11701170
if nb {
1171-
comms = append(comms, []interface{}{})
1171+
comms = append(comms, []*js.Object{})
11721172
}
11731173
selectRes := selectHelper(comms)
11741174
if nb && selectRes.Index(0).Int() == 1 {
@@ -1178,20 +1178,30 @@ func chansend(t *rtype, ch unsafe.Pointer, val unsafe.Pointer, nb bool) bool {
11781178
}
11791179

11801180
func rselect(rselects []runtimeSelect) (chosen int, recvOK bool) {
1181-
comms := make([][]interface{}, len(rselects))
1181+
comms := make([][]*js.Object, len(rselects))
11821182
for i, s := range rselects {
1183-
switch ChanDir(s.dir) {
1184-
case 0:
1185-
comms[i] = []interface{}{}
1186-
case RecvDir:
1187-
comms[i] = []interface{}{js.InternalObject(s.ch)}
1188-
case SendDir:
1189-
comms[i] = []interface{}{js.InternalObject(s.ch), js.InternalObject(s.val).Call("$get")}
1183+
switch SelectDir(s.dir) {
1184+
case SelectDefault:
1185+
comms[i] = []*js.Object{}
1186+
case SelectRecv:
1187+
ch := js.Global.Get("$chanNil")
1188+
if js.InternalObject(s.ch) != js.InternalObject(0) {
1189+
ch = js.InternalObject(s.ch)
1190+
}
1191+
comms[i] = []*js.Object{ch}
1192+
case SelectSend:
1193+
ch := js.Global.Get("$chanNil")
1194+
var val *js.Object
1195+
if js.InternalObject(s.ch) != js.InternalObject(0) {
1196+
ch = js.InternalObject(s.ch)
1197+
val = js.InternalObject(s.val).Call("$get")
1198+
}
1199+
comms[i] = []*js.Object{ch, val}
11901200
}
11911201
}
11921202
selectRes := selectHelper(comms)
11931203
c := selectRes.Index(0).Int()
1194-
if ChanDir(rselects[c].dir) == RecvDir {
1204+
if SelectDir(rselects[c].dir) == SelectRecv {
11951205
recvRes := selectRes.Index(1)
11961206
js.InternalObject(rselects[c].val).Call("$set", recvRes.Index(0))
11971207
return c, recvRes.Index(1).Bool()

compiler/natives/reflect/reflect_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
package reflect_test
44

55
import (
6+
"reflect"
67
"testing"
78
)
89

@@ -33,3 +34,18 @@ func TestGCBits(t *testing.T) {
3334
func TestChanAlloc(t *testing.T) {
3435
t.Skip()
3536
}
37+
38+
func TestSelectOnInvalid(t *testing.T) {
39+
reflect.Select([]reflect.SelectCase{
40+
{
41+
Dir: reflect.SelectRecv,
42+
Chan: reflect.Value{},
43+
}, {
44+
Dir: reflect.SelectSend,
45+
Chan: reflect.Value{},
46+
Send: reflect.ValueOf(1),
47+
}, {
48+
Dir: reflect.SelectDefault,
49+
},
50+
})
51+
}

0 commit comments

Comments
 (0)