Skip to content

Commit a1a5345

Browse files
Adding unsafe.SliceData
1 parent f657304 commit a1a5345

File tree

3 files changed

+47
-4
lines changed

3 files changed

+47
-4
lines changed

compiler/expressions.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,11 +1059,8 @@ func (fc *funcContext) translateBuiltin(name string, sig *types.Signature, args
10591059
sel, _ := fc.selectionOf(astutil.RemoveParens(args[0]).(*ast.SelectorExpr))
10601060
return fc.formatExpr("%d", typesutil.OffsetOf(sizes32, sel))
10611061
case "SliceData":
1062-
// SliceData returns nil if the slice is nil, otherwise returns a pointer to the first index of the array, &s[0].
1063-
// If the slice is empty (cap == 0), it returns an "unspecified memory address" or in our case, a pointer to the empty array.
10641062
t := fc.typeOf(args[0]).Underlying().(*types.Slice)
1065-
elemPtrType := types.NewPointer(t.Elem())
1066-
return fc.formatExpr("(%1e === %2s.nil) ? %3s.nil : $indexPtr(%1e.$array, %1e.$offset, %3s)", args[0], fc.typeName(t), fc.typeName(elemPtrType))
1063+
return fc.formatExpr(`$sliceData(%e, %s)`, args[0], fc.typeName(t))
10671064
default:
10681065
panic(fmt.Sprintf("Unhandled builtin: %s\n", name))
10691066
}

compiler/prelude/prelude.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,3 +569,10 @@ var $instanceOf = (x, y) => {
569569
var $typeOf = x => {
570570
return typeof (x);
571571
};
572+
573+
var $sliceData = (slice, typ) => {
574+
if (slice === typ.nil) {
575+
return $ptrType(typ.elem).nil;
576+
}
577+
return $indexPtr(slice.$array, slice.$offset, typ.elem);
578+
};

tests/js_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"strings"
1010
"testing"
1111
"time"
12+
"unsafe"
1213

1314
"github.com/google/go-cmp/cmp"
1415
"github.com/gopherjs/gopherjs/js"
@@ -936,3 +937,41 @@ func TestStructWithNonIdentifierJSTag(t *testing.T) {
936937
t.Errorf("value via js.Object.Get gave %q, want %q", got, want)
937938
}
938939
}
940+
941+
func TestSliceData(t *testing.T) {
942+
var (
943+
s0 = []int(nil)
944+
s1 = []int{}
945+
s2 = []int{1, 2, 3}
946+
s3 = s2[1:]
947+
s4 = []int{4, 5, 6}
948+
949+
sd0 = unsafe.SliceData(s0)
950+
sd1 = unsafe.SliceData(s1)
951+
sd2 = unsafe.SliceData(s2)
952+
sd3 = unsafe.SliceData(s3)
953+
sd4 = unsafe.SliceData(s4)
954+
)
955+
956+
if sd0 != nil {
957+
t.Errorf("slice data for nil slice was not nil")
958+
}
959+
if sd1 == nil {
960+
t.Errorf("slice data for empty slice was nil")
961+
}
962+
if sd2 == nil {
963+
t.Errorf("slice data for non-empty slice was nil")
964+
}
965+
if sd3 == nil {
966+
t.Errorf("slice data for sub-slice was nil")
967+
}
968+
if sd1 != sd2 {
969+
t.Errorf("slice data for empty and non-empty slices were the same")
970+
}
971+
if sd2 == sd3 {
972+
t.Errorf("slice data for slice and sub-slice were the same")
973+
}
974+
if sd2 == sd4 {
975+
t.Errorf("slice data for different slices were the same")
976+
}
977+
}

0 commit comments

Comments
 (0)