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  }