From ec1d76e51e10d527d9a7ce7c3a47ddd4ef71743a Mon Sep 17 00:00:00 2001 From: Matheus Sampaio Queiroga Date: Mon, 28 Apr 2025 16:10:53 -0300 Subject: [PATCH] Start class implementation --- class.go | 79 +++++++++++++++++++++++++++++++++ internal/examples/class/main.go | 29 ++++++++++++ internal/napi/class.go | 27 +++++++++++ 3 files changed, 135 insertions(+) create mode 100644 class.go create mode 100644 internal/examples/class/main.go create mode 100644 internal/napi/class.go diff --git a/class.go b/class.go new file mode 100644 index 0000000..66f8bf2 --- /dev/null +++ b/class.go @@ -0,0 +1,79 @@ +package napi + +import ( + "fmt" + "reflect" + "unsafe" + + "sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi" +) + +type ( + PropertyDescriptor = napi.PropertyDescriptor + + ClassType interface { + Contructor(env EnvType, this ValueType, args []ValueType) (*Object, error) + } + + Class[T ClassType] struct { + value + Class T + classReflect reflect.Type + } +) + +const ( + PropertyAttributesDefault = napi.Default + PropertyAttributesWritable = napi.Writable + PropertyAttributesEnumerable = napi.Enumerable + PropertyAttributesConfigurable = napi.Configurable + PropertyAttributesStatic = napi.Static + PropertyAttributesDefaultMethod = napi.DefaultMethod + PropertyAttributesDefaultJSProperty = napi.DefaultJSProperty +) + +func CreateClass[T ClassType](env EnvType, propertys []PropertyDescriptor) (*Class[T], error) { + ptrType := reflect.TypeFor[T]() + switch ptrType.Kind() { + case reflect.Struct: + case reflect.Pointer: + if ptrType = ptrType.Elem(); ptrType.Kind() != reflect.Struct { + return nil, fmt.Errorf("type %s is not a struct", ptrType.Name()) + } + default: + return nil, fmt.Errorf("type %s is not a struct", ptrType.Name()) + } + + startStruct := &Class[T]{classReflect: ptrType} + value, status := napi.DefineClass(env.NapiValue(), ptrType.Name(), + func(env napi.Env, info napi.CallbackInfo) napi.Value { + startStruct.Class = reflect.New(ptrType).Interface().(T) + cbInfo, status := napi.GetCbInfo(env, info) + if err := status.ToError(); err != nil { + ThrowError(N_APIEnv(env), "", err.Error()) + return nil + } + + gonapiEnv := N_APIEnv(env) + this := N_APIValue(gonapiEnv, cbInfo.This) + args := make([]ValueType, len(cbInfo.Args)) + for i, cbArg := range cbInfo.Args { + args[i] = N_APIValue(gonapiEnv, cbArg) + } + + res, err := startStruct.Class.Contructor(gonapiEnv, this, args) + if err != nil { + ThrowError(gonapiEnv, "", err.Error()) + } else if res == nil { + und, _ := gonapiEnv.Undefined() + return und.NapiValue() + } + napi.Wrap(env, res.NapiValue(), unsafe.Pointer(startStruct), nil, nil) + return res.NapiValue() + }, propertys) + if err := status.ToError(); err != nil { + return nil, err + } + startStruct.value = N_APIValue(env, value) + return startStruct, nil +} diff --git a/internal/examples/class/main.go b/internal/examples/class/main.go new file mode 100644 index 0000000..46f1acf --- /dev/null +++ b/internal/examples/class/main.go @@ -0,0 +1,29 @@ +package main + +import ( + _ "unsafe" + + _ "sirherobrine23.com.br/Sirherobrine23/napi-go/entry" + + "sirherobrine23.com.br/Sirherobrine23/napi-go" +) + +func main() {} + +//go:linkname Register sirherobrine23.com.br/Sirherobrine23/napi-go/entry.Register +func Register(env napi.EnvType, export *napi.Object) { + class, err := napi.CreateClass[*ClassTest](env, []napi.PropertyDescriptor{}) + if err != nil { + panic(err) + } + + export.Set("class", class) +} + +type ClassTest struct{} + +func (class *ClassTest) Contructor(env napi.EnvType, this napi.ValueType, args []napi.ValueType) (*napi.Object, error) { + obj, _ := napi.CreateObject(env) + + return obj, nil +} diff --git a/internal/napi/class.go b/internal/napi/class.go new file mode 100644 index 0000000..4879edd --- /dev/null +++ b/internal/napi/class.go @@ -0,0 +1,27 @@ +package napi + +// #include +import "C" + +import "unsafe" + +func DefineClass(env Env, name string, constructor Callback, Property []PropertyDescriptor) (Value, Status) { + var pro *C.napi_property_descriptor + if len(Property) > 0 { + pro = (*C.napi_property_descriptor)(unsafe.Pointer(&Property[0])) + } + + var result Value + call := &constructor + status := Status(C.napi_define_class( + C.napi_env(env), + C.CString(name), + C.size_t(len(name)), + C.napi_callback(unsafe.Pointer(call)), + nil, + C.size_t(len(Property)), + pro, + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} -- 2.49.0