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 }