github.com/goplusjs/gopherjs@v1.2.6-0.20211206034512-f187917453b8/compiler/natives/src/reflect/go113_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 hasGCProg bool 18 ) 19 for i, field := range fields { 20 if field.Name == "" { 21 panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no name") 22 } 23 if !isValidFieldName(field.Name) { 24 panic("reflect.StructOf: field " + strconv.Itoa(i) + " has invalid name") 25 } 26 if field.Type == nil { 27 panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no type") 28 } 29 f := runtimeStructField(field) 30 ft := f.typ 31 if ft.kind&kindGCProg != 0 { 32 hasGCProg = true 33 } 34 35 name := field.Name 36 if f.embedded() { 37 // Embedded field 38 if f.typ.Kind() == Ptr { 39 // Embedded ** and *interface{} are illegal 40 elem := ft.Elem() 41 if k := elem.Kind(); k == Ptr || k == Interface { 42 panic("reflect.StructOf: illegal embedded field type " + ft.String()) 43 } 44 } 45 46 switch f.typ.Kind() { 47 case Interface: 48 ift := (*interfaceType)(unsafe.Pointer(ft)) 49 for _, m := range ift.methods { 50 if ift.nameOff(m.name).pkgPath() != "" { 51 // TODO(sbinet). Issue 15924. 52 panic("reflect: embedded interface with unexported method(s) not implemented") 53 } 54 } 55 case Ptr: 56 ptr := (*ptrType)(unsafe.Pointer(ft)) 57 if unt := ptr.uncommon(); unt != nil { 58 if i > 0 && unt.mcount > 0 { 59 // Issue 15924. 60 panic("reflect: embedded type with methods not implemented if type is not first field") 61 } 62 if len(fields) > 1 { 63 panic("reflect: embedded type with methods not implemented if there is more than one field") 64 } 65 for _, m := range unt.methods() { 66 mname := ptr.nameOff(m.name) 67 if mname.pkgPath() != "" { 68 // TODO(sbinet). 69 // Issue 15924. 70 panic("reflect: embedded interface with unexported method(s) not implemented") 71 } 72 } 73 } 74 if unt := ptr.elem.uncommon(); unt != nil { 75 for _, m := range unt.methods() { 76 mname := ptr.nameOff(m.name) 77 if mname.pkgPath() != "" { 78 // TODO(sbinet) 79 // Issue 15924. 80 panic("reflect: embedded interface with unexported method(s) not implemented") 81 } 82 } 83 } 84 default: 85 if unt := ft.uncommon(); unt != nil { 86 if i > 0 && unt.mcount > 0 { 87 // Issue 15924. 88 panic("reflect: embedded type with methods not implemented if type is not first field") 89 } 90 if len(fields) > 1 && ft.kind&kindDirectIface != 0 { 91 panic("reflect: embedded type with methods not implemented for non-pointer type") 92 } 93 for _, m := range unt.methods() { 94 mname := ft.nameOff(m.name) 95 if mname.pkgPath() != "" { 96 // TODO(sbinet) 97 // Issue 15924. 98 panic("reflect: embedded interface with unexported method(s) not implemented") 99 } 100 } 101 } 102 } 103 } 104 if _, dup := fset[name]; dup { 105 panic("reflect.StructOf: duplicate field " + name) 106 } 107 fset[name] = struct{}{} 108 jsf := js.Global.Get("Object").New() 109 jsf.Set("prop", name) 110 jsf.Set("name", name) 111 jsf.Set("exported", f.name.isExported()) 112 jsf.Set("typ", jsType(field.Type)) 113 jsf.Set("tag", field.Tag) 114 jsf.Set("embedded", field.Anonymous) 115 jsFields[i] = jsf 116 } 117 _ = hasGCProg 118 typ := js.Global.Call("$structType", "", jsFields) 119 return _reflectType(typ, objstr) 120 } 121 122 func objstr(obj *js.Object) string { 123 return obj.String() 124 }