@@ -1179,6 +1179,11 @@ func (v Value) Cap() int {
1179
1179
return v .typ .Len ()
1180
1180
case Chan , Slice :
1181
1181
return v .object ().Get ("$capacity" ).Int ()
1182
+ case Ptr :
1183
+ if v .typ .Elem ().Kind () == Array {
1184
+ return v .typ .Elem ().Len ()
1185
+ }
1186
+ panic ("reflect: call of reflect.Value.Cap on ptr to non-array Value" )
1182
1187
}
1183
1188
panic (& ValueError {"reflect.Value.Cap" , k })
1184
1189
}
@@ -1405,6 +1410,11 @@ func (v Value) Len() int {
1405
1410
return v .object ().Get ("$buffer" ).Get ("length" ).Int ()
1406
1411
case Map :
1407
1412
return v .object ().Get ("size" ).Int ()
1413
+ case Ptr :
1414
+ if v .typ .Elem ().Kind () == Array {
1415
+ return v .typ .Elem ().Len ()
1416
+ }
1417
+ panic ("reflect: call of reflect.Value.Len on ptr to non-array Value" )
1408
1418
default :
1409
1419
panic (& ValueError {"reflect.Value.Len" , k })
1410
1420
}
@@ -1450,6 +1460,29 @@ func (v Value) Set(x Value) {
1450
1460
v .ptr = x .ptr
1451
1461
}
1452
1462
1463
+ func (v Value ) bytesSlow () []byte {
1464
+ switch v .kind () {
1465
+ case Slice :
1466
+ if v .typ .Elem ().Kind () != Uint8 {
1467
+ panic ("reflect.Value.Bytes of non-byte slice" )
1468
+ }
1469
+ return * (* []byte )(v .ptr )
1470
+ case Array :
1471
+ if v .typ .Elem ().Kind () != Uint8 {
1472
+ panic ("reflect.Value.Bytes of non-byte array" )
1473
+ }
1474
+ if ! v .CanAddr () {
1475
+ panic ("reflect.Value.Bytes of unaddressable byte array" )
1476
+ }
1477
+ // Replace the following with JS to avoid using unsafe pointers.
1478
+ // p := (*byte)(v.ptr)
1479
+ // n := int((*arrayType)(unsafe.Pointer(v.typ)).len)
1480
+ // return unsafe.Slice(p, n)
1481
+ return js .InternalObject (v .ptr ).Interface ().([]byte )
1482
+ }
1483
+ panic (& ValueError {"reflect.Value.Bytes" , v .kind ()})
1484
+ }
1485
+
1453
1486
func (v Value ) SetBytes (x []byte ) {
1454
1487
v .mustBeAssignable ()
1455
1488
v .mustBe (Slice )
@@ -1728,29 +1761,47 @@ func deepValueEqualJs(v1, v2 Value, visited [][2]unsafe.Pointer) bool {
1728
1761
return js .Global .Call ("$interfaceIsEqual" , js .InternalObject (valueInterface (v1 , false )), js .InternalObject (valueInterface (v2 , false ))).Bool ()
1729
1762
}
1730
1763
1731
- func methodNameSkip () string {
1732
- pc , _ , _ , _ := runtime .Caller (3 )
1733
- f := runtime .FuncForPC (pc )
1734
- if f == nil {
1735
- return "unknown method"
1736
- }
1737
- // Function name extracted from the call stack can be different from vanilla
1738
- // Go. Here we try to fix stuff like "Object.$packages.reflect.Q.ptr.SetIterKey"
1739
- // into "Value.SetIterKey".
1740
- // This workaround may become obsolete after https://github.com/gopherjs/gopherjs/issues/1085
1741
- // is resolved.
1742
- name := f .Name ()
1743
- idx := len (name ) - 1
1744
- for idx > 0 {
1745
- if name [idx ] == '.' {
1746
- break
1764
+ func stringsLastIndex (s string , c byte ) int {
1765
+ for i := len (s ) - 1 ; i >= 0 ; i -- {
1766
+ if s [i ] == c {
1767
+ return i
1747
1768
}
1748
- idx --
1749
1769
}
1750
- if idx < 0 {
1751
- return name
1770
+ return - 1
1771
+ }
1772
+
1773
+ func stringsHasPrefix (s , prefix string ) bool {
1774
+ return len (s ) >= len (prefix ) && s [:len (prefix )] == prefix
1775
+ }
1776
+
1777
+ func valueMethodName () string {
1778
+ var pc [5 ]uintptr
1779
+ n := runtime .Callers (1 , pc [:])
1780
+ frames := runtime .CallersFrames (pc [:n ])
1781
+ var frame runtime.Frame
1782
+ for more := true ; more ; {
1783
+ frame , more = frames .Next ()
1784
+ name := frame .Function
1785
+
1786
+ // Function name extracted from the call stack can be different from
1787
+ // vanilla Go, so is not prefixed by "reflect.Value." as needed by the original.
1788
+ // See https://cs.opensource.google/go/go/+/refs/tags/go1.19.13:src/reflect/value.go;l=173-191
1789
+ // Here we try to fix stuff like "Object.$packages.reflect.Q.ptr.SetIterKey"
1790
+ // into "reflect.Value.SetIterKey".
1791
+ // This workaround may become obsolete after
1792
+ // https://github.com/gopherjs/gopherjs/issues/1085 is resolved.
1793
+
1794
+ const prefix = `Object.$packages.reflect.`
1795
+ if stringsHasPrefix (name , prefix ) {
1796
+ if idx := stringsLastIndex (name , '.' ); idx >= 0 {
1797
+ methodName := name [idx + 1 :]
1798
+ if len (methodName ) > 0 && 'A' <= methodName [0 ] && methodName [0 ] <= 'Z' {
1799
+ return `reflect.Value.` + methodName
1800
+ }
1801
+ }
1802
+ }
1752
1803
}
1753
- return "Value" + name [ idx :]
1804
+ return "unknown method"
1754
1805
}
1755
1806
1756
1807
func verifyNotInHeapPtr (p uintptr ) bool {
0 commit comments