Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4357975

Browse files
Updated reflect, reflectlite, and abi
1 parent c4be02f commit 4357975

File tree

13 files changed

+1296
-2084
lines changed

13 files changed

+1296
-2084
lines changed

compiler/expressions.go

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1104,22 +1104,54 @@ func (fc *funcContext) translateExprSlice(exprs []ast.Expr, desiredType types.Ty
11041104
return parts
11051105
}
11061106

1107+
// packageAllowsKindTypeConversion determines if the current package should
1108+
// be checked for a special type of casts, `kindType` or `kindTypeExt` conversions.
1109+
func (fc *funcContext) packageAllowsKindTypeConversion() bool {
1110+
switch fc.pkgCtx.Pkg.Path() {
1111+
case `internal/abi`, `internal/reflectlite`, `reflect`:
1112+
return true
1113+
}
1114+
return false
1115+
}
1116+
11071117
func (fc *funcContext) translateConversion(expr ast.Expr, desiredType types.Type) *expression {
11081118
exprType := fc.typeOf(expr)
11091119
if types.Identical(exprType, desiredType) {
11101120
return fc.translateExpr(expr)
11111121
}
11121122

1113-
if fc.pkgCtx.Pkg.Path() == "reflect" || fc.pkgCtx.Pkg.Path() == "internal/reflectlite" {
1123+
// For some specific packages, e.g. reflect, the Go code performs casts between different sized memory footprints
1124+
// and leverages the fact that the pointer to the first field is the same as the pointer to the full struct in Go.
1125+
// These conversions are normally not allowed by GopherJS. However, in those specific packages, the original code
1126+
// does this kind of cast so often, that to avoid them would cause massive amounts of native overrides.
1127+
// To simplify the native overrides we will allow casts between specific types for specific packages by looking up
1128+
// the `kindType` that is assigned when creating them.
1129+
//
1130+
// Given the structure `type K struct{T; additional fields}` the untyped pointer to `K` is also the untyped pointer
1131+
// to the first field, i.e. `T`. An example of this is `abi.MapType` with `abi.Type` as its first field.
1132+
// These packages will hold onto `t *T` then cast to the kind type with `k = (*K)unsafe.Pointer(t)`.
1133+
// Normally this isn't allowed in JS because `K` is larger with additional fields, but when we created `t` in the
1134+
// native overrides, we assign `k` as the `t.kindType` then we translate those specific casts to get that `kindType`,
1135+
// thus greatly reducing the amount of overrides we have to add to those packages.
1136+
if fc.packageAllowsKindTypeConversion() {
11141137
if call, isCall := expr.(*ast.CallExpr); isCall && types.Identical(fc.typeOf(call.Fun), types.Typ[types.UnsafePointer]) {
11151138
if ptr, isPtr := desiredType.(*types.Pointer); isPtr {
11161139
if named, isNamed := ptr.Elem().(*types.Named); isNamed {
1117-
switch named.Obj().Name() {
1118-
case "arrayType", "chanType", "funcType", "interfaceType", "mapType", "ptrType", "sliceType", "structType":
1119-
return fc.formatExpr("%e.kindType", call.Args[0]) // unsafe conversion
1120-
default:
1121-
return fc.translateExpr(expr)
1140+
switch named.Obj().Pkg().Path() {
1141+
case `internal/abi`:
1142+
switch named.Obj().Name() {
1143+
case `ArrayType`, `ChanType`, `FuncType`, `InterfaceType`, `MapType`, `PtrType`, `SliceType`, `StructType`:
1144+
return fc.formatExpr("%e.kindType", call.Args[0]) // unsafe conversion
1145+
}
1146+
case `reflect`:
1147+
switch named.Obj().Name() {
1148+
// The following are extensions of the ABI equivalent type to add more methods.
1149+
// e.g. `type structType struct { abi.StructType }`.
1150+
case `interfaceType`, `mapType`, `ptrType`, `sliceType`, `structType`:
1151+
return fc.formatExpr("toKindTypeExt(%e)", call.Args[0]) // unsafe conversion
1152+
}
11221153
}
1154+
return fc.translateExpr(expr)
11231155
}
11241156
}
11251157
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//go:build js
2+
3+
package abi_test
4+
5+
import "testing"
6+
7+
//gopherjs:replace
8+
func TestFuncPC(t *testing.T) {
9+
t.Skip(`test involes checking the PC (program counter)`)
10+
}
11+
12+
//gopherjs:replace
13+
func TestFuncPCCompileError(t *testing.T) {
14+
t.Skip(`test involes checking the PC (program counter)`)
15+
}

0 commit comments

Comments
 (0)