github.com/goplusjs/gopherjs@v1.2.6-0.20211206034512-f187917453b8/compiler/natives/src/reflect/go114_structof.go (about)

     1  // +build js
     2  // +build go1.14
     3  
     4  package reflect
     5  
     6  import (
     7  	"strconv"
     8  	"unsafe"
     9  
    10  	"github.com/gopherjs/gopherjs/js"
    11  )
    12  
    13  func StructOf(fields []StructField) Type {
    14  	var (
    15  		jsFields  = make([]*js.Object, len(fields))
    16  		fset      = map[string]struct{}{}
    17  		pkgpath   string
    18  		hasGCProg bool
    19  	)
    20  	for i, field := range fields {
    21  		if field.Name == "" {
    22  			panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no name")
    23  		}
    24  		if !isValidFieldName(field.Name) {
    25  			panic("reflect.StructOf: field " + strconv.Itoa(i) + " has invalid name")
    26  		}
    27  		if field.Type == nil {
    28  			panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no type")
    29  		}
    30  		f, fpkgpath := runtimeStructField(field)
    31  		ft := f.typ
    32  		if ft.kind&kindGCProg != 0 {
    33  			hasGCProg = true
    34  		}
    35  		if fpkgpath != "" {
    36  			if pkgpath == "" {
    37  				pkgpath = fpkgpath
    38  			} else if pkgpath != fpkgpath {
    39  				panic("reflect.Struct: fields with different PkgPath " + pkgpath + " and " + fpkgpath)
    40  			}
    41  		}
    42  		name := field.Name
    43  		if f.embedded() {
    44  			// Embedded field
    45  			if field.Type.Kind() == Ptr {
    46  				// Embedded ** and *interface{} are illegal
    47  				elem := field.Type.Elem()
    48  				if k := elem.Kind(); k == Ptr || k == Interface {
    49  					panic("reflect.StructOf: illegal anonymous field type " + field.Type.String())
    50  				}
    51  			}
    52  			switch field.Type.Kind() {
    53  			case Interface:
    54  			case Ptr:
    55  				ptr := (*ptrType)(unsafe.Pointer(ft))
    56  				if unt := ptr.uncommon(); unt != nil {
    57  					if i > 0 && unt.mcount > 0 {
    58  						// Issue 15924.
    59  						panic("reflect: embedded type with methods not implemented if type is not first field")
    60  					}
    61  					if len(fields) > 1 {
    62  						panic("reflect: embedded type with methods not implemented if there is more than one field")
    63  					}
    64  				}
    65  			default:
    66  				if unt := ft.uncommon(); unt != nil {
    67  					if i > 0 && unt.mcount > 0 {
    68  						// Issue 15924.
    69  						panic("reflect: embedded type with methods not implemented if type is not first field")
    70  					}
    71  					if len(fields) > 1 && ft.kind&kindDirectIface != 0 {
    72  						panic("reflect: embedded type with methods not implemented for non-pointer type")
    73  					}
    74  				}
    75  			}
    76  		}
    77  
    78  		if _, dup := fset[name]; dup {
    79  			panic("reflect.StructOf: duplicate field " + name)
    80  		}
    81  		fset[name] = struct{}{}
    82  		jsf := js.Global.Get("Object").New()
    83  		jsf.Set("prop", name)
    84  		jsf.Set("name", name)
    85  		jsf.Set("exported", f.name.isExported())
    86  		jsf.Set("typ", jsType(field.Type))
    87  		jsf.Set("tag", field.Tag)
    88  		jsf.Set("embedded", field.Anonymous)
    89  		jsFields[i] = jsf
    90  	}
    91  	_ = hasGCProg
    92  	typ := js.Global.Call("$structType", "", jsFields)
    93  	if pkgpath != "" {
    94  		typ.Set("pkgPath", pkgpath)
    95  	}
    96  	return _reflectType(typ, objstr)
    97  }
    98  
    99  func objstr(obj *js.Object) string {
   100  	return obj.String()
   101  }