Skip to content

Commit 5b66707

Browse files
Fixing internalization of null slice and array fields
1 parent d25ca33 commit 5b66707

File tree

2 files changed

+90
-0
lines changed

2 files changed

+90
-0
lines changed

compiler/prelude/jsmapping.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,9 @@ var $internalize = (v, t, recv, seen, makeWrapper) => {
236236
case $kindFloat64:
237237
return parseFloat(v);
238238
case $kindArray:
239+
if (v == null) {
240+
return t.zero();
241+
}
239242
if (v.length !== t.len) {
240243
$throwRuntimeError("got array with wrong size from JavaScript native");
241244
}
@@ -331,6 +334,9 @@ var $internalize = (v, t, recv, seen, makeWrapper) => {
331334
return $internalize(v, t.elem, makeWrapper);
332335
}
333336
case $kindSlice:
337+
if (v == null) {
338+
return t.zero();
339+
}
334340
return new t($mapArray(v, e => { return $internalize(e, t.elem, makeWrapper); }));
335341
case $kindString:
336342
v = String(v);

tests/js_test.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,90 @@ func TestExternalize(t *testing.T) {
829829
}
830830
}
831831

832+
func TestInternalizeSlice(t *testing.T) {
833+
tests := []struct {
834+
name string
835+
init []int
836+
want string
837+
}{
838+
{
839+
name: `nil slice`,
840+
init: []int(nil),
841+
want: `[]int(nil)`,
842+
},
843+
{
844+
name: `empty slice`,
845+
init: []int{},
846+
want: `[]int{}`,
847+
},
848+
{
849+
name: `non-empty slice`,
850+
init: []int{42, 53, 64},
851+
want: `[]int{42, 53, 64}`,
852+
},
853+
}
854+
855+
for _, tt := range tests {
856+
t.Run(tt.name, func(t *testing.T) {
857+
b := struct {
858+
*js.Object
859+
V []int `js:"V"` // V is externalized
860+
}{Object: js.Global.Get("Object").New()}
861+
b.V = tt.init
862+
863+
result := fmt.Sprintf(`%#v`, b.V) // internalize b.V
864+
if result != tt.want {
865+
t.Errorf(`Unexpected result %q != %q`, result, tt.want)
866+
}
867+
})
868+
}
869+
}
870+
871+
func TestInternalizeArray(t *testing.T) {
872+
fn := js.Global.Call("eval", "(function(b, v) { b.V = v; })")
873+
874+
tests := []struct {
875+
name string
876+
init any
877+
want string
878+
}{
879+
{
880+
name: `null array`,
881+
init: nil,
882+
want: `[3]int{0, 0, 0}`,
883+
},
884+
{
885+
name: `zeros array`,
886+
init: [3]int{},
887+
want: `[3]int{0, 0, 0}`,
888+
},
889+
{
890+
name: `non-zero array`,
891+
init: [3]int{42, 53, 64},
892+
want: `[3]int{42, 53, 64}`,
893+
},
894+
}
895+
896+
for _, tt := range tests {
897+
t.Run(tt.name, func(t *testing.T) {
898+
b := struct {
899+
*js.Object
900+
V [3]int `js:"V"` // V is externalized
901+
}{Object: js.Global.Get("Object").New()}
902+
903+
// Assign the array to b.V using JS because of GopherJS
904+
// assignment of externalized array's issue,
905+
// see https://github.com/gopherjs/gopherjs/issues/1302
906+
fn.Invoke(b, tt.init)
907+
908+
result := fmt.Sprintf(`%#v`, b.V) // internalize b.V
909+
if result != tt.want {
910+
t.Errorf(`Unexpected result %q != %q`, result, tt.want)
911+
}
912+
})
913+
}
914+
}
915+
832916
func TestInternalizeExternalizeNull(t *testing.T) {
833917
type S struct {
834918
*js.Object

0 commit comments

Comments
 (0)