Update pkg to same Node addon Header #8
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| *.node | ||||
							
								
								
									
										1
									
								
								LICENSE
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								LICENSE
									
									
									
									
									
								
							| @@ -1,6 +1,7 @@ | ||||
| MIT License | ||||
|  | ||||
| Copyright (c) 2022 Akshay Ganeshen | ||||
| Copyright (c) 2024 Matheus Sampaio Queiroga | ||||
|  | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
|   | ||||
							
								
								
									
										79
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										79
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,82 +1,3 @@ | ||||
| # napi-go | ||||
|  | ||||
| A Go library for building Node.js Native Addons using Node-API. | ||||
|  | ||||
| ## Usage | ||||
|  | ||||
| Use `go get` to install the library: | ||||
|  | ||||
| ```sh | ||||
| go get -u github.com/akshayganeshen/napi-go | ||||
| ``` | ||||
|  | ||||
| Then use the library to define handlers: | ||||
|  | ||||
| ```go | ||||
| package handlers | ||||
|  | ||||
| import "github.com/akshayganeshen/napi-go" | ||||
|  | ||||
| func MyHandler(env napi.Env, info napi.CallbackInfo) napi.Value { | ||||
|   return nil | ||||
| } | ||||
| ``` | ||||
|  | ||||
| Next, create a `main.go` that registers all module exports: | ||||
|  | ||||
| ```go | ||||
| package main | ||||
|  | ||||
| import "github.com/akshayganeshen/napi-go/entry" | ||||
|  | ||||
| func init() { | ||||
|   entry.Export("myHandler", MyHandler) | ||||
| } | ||||
|  | ||||
| func main() {} | ||||
| ``` | ||||
|  | ||||
| Finally, build the Node.js addon using `go build`: | ||||
|  | ||||
| ```sh | ||||
| go build -buildmode=c-shared -o "example.node" . | ||||
| ``` | ||||
|  | ||||
| The output `.node` file can now be imported via `require`: | ||||
|  | ||||
| ```js | ||||
| const example = require("./example.node"); | ||||
|  | ||||
| example.myHandler(); | ||||
| ``` | ||||
|  | ||||
| ### JS Helpers | ||||
|  | ||||
| In addition to the Node-API exposed via package `napi`, the `napi-go/js` | ||||
| package provides functions similar to the `syscall/js` standard library. | ||||
|  | ||||
| ```go | ||||
| package main | ||||
|  | ||||
| import ( | ||||
|   "github.com/akshayganeshen/napi-go/entry" | ||||
|   "github.com/akshayganeshen/napi-go/js" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
|   entry.Export("myCallback", js.AsCallback(MyCallback)) | ||||
| } | ||||
|  | ||||
| func MyCallback(env js.Env, this js.Value, args []js.Value) any { | ||||
|   return map[string]any{ | ||||
|     "message": "hello world", | ||||
|     "args":    args, | ||||
|   } | ||||
| } | ||||
|  | ||||
| func main() {} | ||||
| ``` | ||||
|  | ||||
| ## Examples | ||||
|  | ||||
| Check out the example addons in [`docs/examples`](docs/examples). | ||||
|   | ||||
							
								
								
									
										85
									
								
								array.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								array.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | ||||
| package napi | ||||
|  | ||||
| import ( | ||||
| 	"iter" | ||||
|  | ||||
| 	"sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi" | ||||
| ) | ||||
|  | ||||
| type Array struct{ value } | ||||
|  | ||||
| // Convert [ValueType] to [*Array]. | ||||
| func ToArray(o ValueType) *Array { return &Array{o} } | ||||
|  | ||||
| // Create Array. | ||||
| func CreateArray(env EnvType, size ...int) (*Array, error) { | ||||
| 	sizeOf := 0 | ||||
| 	if len(size) > 0 { | ||||
| 		sizeOf = size[0] | ||||
| 	} | ||||
| 	napiValue, err := napi.Value(nil), error(nil) | ||||
| 	if sizeOf == 0 { | ||||
| 		napiValue, err = mustValueErr(napi.CreateArray(env.NapiValue())) | ||||
| 	} else { | ||||
| 		napiValue, err = mustValueErr(napi.CreateArrayWithLength(env.NapiValue(), sizeOf)) | ||||
| 	} | ||||
| 	// Check error exists | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return ToArray(N_APIValue(env, napiValue)), nil | ||||
| } | ||||
|  | ||||
| // Get array length. | ||||
| func (arr *Array) Length() (int, error) { | ||||
| 	return mustValueErr(napi.GetArrayLength(arr.NapiEnv(), arr.NapiValue())) | ||||
| } | ||||
|  | ||||
| // Delete index elemente from array. | ||||
| func (arr *Array) Delete(index int) (bool, error) { | ||||
| 	return mustValueErr(napi.DeleteElement(arr.NapiEnv(), arr.NapiValue(), index)) | ||||
| } | ||||
|  | ||||
| // Set value in index | ||||
| func (arr *Array) Set(index int, value ValueType) error { | ||||
| 	return singleMustValueErr(napi.SetElement(arr.NapiEnv(), arr.NapiValue(), index, value.NapiValue())) | ||||
| } | ||||
|  | ||||
| // Get Value from index | ||||
| func (arr *Array) Get(index int) (ValueType, error) { | ||||
| 	napiValue, err := mustValueErr(napi.GetElement(arr.NapiEnv(), arr.NapiValue(), index)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return N_APIValue(arr.Env(), napiValue), nil | ||||
| } | ||||
|  | ||||
| // Get values with [iter.Seq] | ||||
| func (arr *Array) Seq() iter.Seq[ValueType] { | ||||
| 	length, err := arr.Length() | ||||
| 	if err != nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return func(yield func(ValueType) bool) { | ||||
| 		for index := range length { | ||||
| 			if value, err := arr.Get(index); err == nil { | ||||
| 				if !yield(value) { | ||||
| 					return | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (arr *Array) Append(values ...ValueType) error { | ||||
| 	length, err := arr.Length() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	for valueIndex := range values { | ||||
| 		if err = arr.Set(length+valueIndex, values[valueIndex]); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										20
									
								
								boolean.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								boolean.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| package napi | ||||
|  | ||||
| import "sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi" | ||||
|  | ||||
| type Boolean struct{ value } | ||||
|  | ||||
| // Convert [ValueType] to [*Boolean] | ||||
| func ToBoolean(o ValueType) *Boolean { return &Boolean{o} } | ||||
|  | ||||
| func CreateBoolean(env EnvType, value bool) (*Boolean, error) { | ||||
| 	v, err := mustValueErr(napi.GetBoolean(env.NapiValue(), value)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return ToBoolean(N_APIValue(env, v)), nil | ||||
| } | ||||
|  | ||||
| func (bo *Boolean) Value() (bool, error) { | ||||
| 	return mustValueErr(napi.GetValueBool(bo.NapiEnv(), bo.NapiValue())) | ||||
| } | ||||
							
								
								
									
										36
									
								
								buffer.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								buffer.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| package napi | ||||
|  | ||||
| import "sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi" | ||||
|  | ||||
| type Buffer struct{ value } | ||||
|  | ||||
| // Convert [ValueType] to [*Buffer]. | ||||
| func ToBuffer(o ValueType) *Buffer { return &Buffer{o} } | ||||
|  | ||||
| // Create new Buffer with length | ||||
| func CreateBuffer(env EnvType, length int) (*Buffer, error) { | ||||
| 	napiValue, err := mustValueErr(napi.CreateBuffer(env.NapiValue(), length)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return ToBuffer(N_APIValue(env, napiValue)), nil | ||||
| } | ||||
|  | ||||
| // Copy []byte to Node::Buffer struct | ||||
| func CopyBuffer(env EnvType, buff []byte) (*Buffer, error) { | ||||
| 	napiValue, err := mustValueErr(napi.CreateBufferCopy(env.NapiValue(), buff)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return ToBuffer(N_APIValue(env, napiValue)), nil | ||||
| } | ||||
|  | ||||
| // Get size of buffer | ||||
| func (buff *Buffer) Length() (int, error) { | ||||
| 	return mustValueErr(napi.GetBufferInfoSize(buff.NapiEnv(), buff.NapiValue())) | ||||
| } | ||||
|  | ||||
| // return []byte from Buffer value | ||||
| func (buff *Buffer) Data() ([]byte, error) { | ||||
| 	return mustValueErr(napi.GetBufferInfoData(buff.NapiEnv(), buff.NapiValue())) | ||||
| } | ||||
							
								
								
									
										186
									
								
								c++/napi-inl.deprecated.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								c++/napi-inl.deprecated.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,186 @@ | ||||
| #ifndef SRC_NAPI_INL_DEPRECATED_H_ | ||||
| #define SRC_NAPI_INL_DEPRECATED_H_ | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| // PropertyDescriptor class | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| template <typename Getter> | ||||
| inline PropertyDescriptor PropertyDescriptor::Accessor( | ||||
|     const char* utf8name, | ||||
|     Getter getter, | ||||
|     napi_property_attributes attributes, | ||||
|     void* /*data*/) { | ||||
|   using CbData = details::CallbackData<Getter, Napi::Value>; | ||||
|   // TODO: Delete when the function is destroyed | ||||
|   auto callbackData = new CbData({getter, nullptr}); | ||||
|  | ||||
|   return PropertyDescriptor({utf8name, | ||||
|                              nullptr, | ||||
|                              nullptr, | ||||
|                              CbData::Wrapper, | ||||
|                              nullptr, | ||||
|                              nullptr, | ||||
|                              attributes, | ||||
|                              callbackData}); | ||||
| } | ||||
|  | ||||
| template <typename Getter> | ||||
| inline PropertyDescriptor PropertyDescriptor::Accessor( | ||||
|     const std::string& utf8name, | ||||
|     Getter getter, | ||||
|     napi_property_attributes attributes, | ||||
|     void* data) { | ||||
|   return Accessor(utf8name.c_str(), getter, attributes, data); | ||||
| } | ||||
|  | ||||
| template <typename Getter> | ||||
| inline PropertyDescriptor PropertyDescriptor::Accessor( | ||||
|     napi_value name, | ||||
|     Getter getter, | ||||
|     napi_property_attributes attributes, | ||||
|     void* /*data*/) { | ||||
|   using CbData = details::CallbackData<Getter, Napi::Value>; | ||||
|   // TODO: Delete when the function is destroyed | ||||
|   auto callbackData = new CbData({getter, nullptr}); | ||||
|  | ||||
|   return PropertyDescriptor({nullptr, | ||||
|                              name, | ||||
|                              nullptr, | ||||
|                              CbData::Wrapper, | ||||
|                              nullptr, | ||||
|                              nullptr, | ||||
|                              attributes, | ||||
|                              callbackData}); | ||||
| } | ||||
|  | ||||
| template <typename Getter> | ||||
| inline PropertyDescriptor PropertyDescriptor::Accessor( | ||||
|     Name name, Getter getter, napi_property_attributes attributes, void* data) { | ||||
|   napi_value nameValue = name; | ||||
|   return PropertyDescriptor::Accessor(nameValue, getter, attributes, data); | ||||
| } | ||||
|  | ||||
| template <typename Getter, typename Setter> | ||||
| inline PropertyDescriptor PropertyDescriptor::Accessor( | ||||
|     const char* utf8name, | ||||
|     Getter getter, | ||||
|     Setter setter, | ||||
|     napi_property_attributes attributes, | ||||
|     void* /*data*/) { | ||||
|   using CbData = details::AccessorCallbackData<Getter, Setter>; | ||||
|   // TODO: Delete when the function is destroyed | ||||
|   auto callbackData = new CbData({getter, setter, nullptr}); | ||||
|  | ||||
|   return PropertyDescriptor({utf8name, | ||||
|                              nullptr, | ||||
|                              nullptr, | ||||
|                              CbData::GetterWrapper, | ||||
|                              CbData::SetterWrapper, | ||||
|                              nullptr, | ||||
|                              attributes, | ||||
|                              callbackData}); | ||||
| } | ||||
|  | ||||
| template <typename Getter, typename Setter> | ||||
| inline PropertyDescriptor PropertyDescriptor::Accessor( | ||||
|     const std::string& utf8name, | ||||
|     Getter getter, | ||||
|     Setter setter, | ||||
|     napi_property_attributes attributes, | ||||
|     void* data) { | ||||
|   return Accessor(utf8name.c_str(), getter, setter, attributes, data); | ||||
| } | ||||
|  | ||||
| template <typename Getter, typename Setter> | ||||
| inline PropertyDescriptor PropertyDescriptor::Accessor( | ||||
|     napi_value name, | ||||
|     Getter getter, | ||||
|     Setter setter, | ||||
|     napi_property_attributes attributes, | ||||
|     void* /*data*/) { | ||||
|   using CbData = details::AccessorCallbackData<Getter, Setter>; | ||||
|   // TODO: Delete when the function is destroyed | ||||
|   auto callbackData = new CbData({getter, setter, nullptr}); | ||||
|  | ||||
|   return PropertyDescriptor({nullptr, | ||||
|                              name, | ||||
|                              nullptr, | ||||
|                              CbData::GetterWrapper, | ||||
|                              CbData::SetterWrapper, | ||||
|                              nullptr, | ||||
|                              attributes, | ||||
|                              callbackData}); | ||||
| } | ||||
|  | ||||
| template <typename Getter, typename Setter> | ||||
| inline PropertyDescriptor PropertyDescriptor::Accessor( | ||||
|     Name name, | ||||
|     Getter getter, | ||||
|     Setter setter, | ||||
|     napi_property_attributes attributes, | ||||
|     void* data) { | ||||
|   napi_value nameValue = name; | ||||
|   return PropertyDescriptor::Accessor( | ||||
|       nameValue, getter, setter, attributes, data); | ||||
| } | ||||
|  | ||||
| template <typename Callable> | ||||
| inline PropertyDescriptor PropertyDescriptor::Function( | ||||
|     const char* utf8name, | ||||
|     Callable cb, | ||||
|     napi_property_attributes attributes, | ||||
|     void* /*data*/) { | ||||
|   using ReturnType = decltype(cb(CallbackInfo(nullptr, nullptr))); | ||||
|   using CbData = details::CallbackData<Callable, ReturnType>; | ||||
|   // TODO: Delete when the function is destroyed | ||||
|   auto callbackData = new CbData({cb, nullptr}); | ||||
|  | ||||
|   return PropertyDescriptor({utf8name, | ||||
|                              nullptr, | ||||
|                              CbData::Wrapper, | ||||
|                              nullptr, | ||||
|                              nullptr, | ||||
|                              nullptr, | ||||
|                              attributes, | ||||
|                              callbackData}); | ||||
| } | ||||
|  | ||||
| template <typename Callable> | ||||
| inline PropertyDescriptor PropertyDescriptor::Function( | ||||
|     const std::string& utf8name, | ||||
|     Callable cb, | ||||
|     napi_property_attributes attributes, | ||||
|     void* data) { | ||||
|   return Function(utf8name.c_str(), cb, attributes, data); | ||||
| } | ||||
|  | ||||
| template <typename Callable> | ||||
| inline PropertyDescriptor PropertyDescriptor::Function( | ||||
|     napi_value name, | ||||
|     Callable cb, | ||||
|     napi_property_attributes attributes, | ||||
|     void* /*data*/) { | ||||
|   using ReturnType = decltype(cb(CallbackInfo(nullptr, nullptr))); | ||||
|   using CbData = details::CallbackData<Callable, ReturnType>; | ||||
|   // TODO: Delete when the function is destroyed | ||||
|   auto callbackData = new CbData({cb, nullptr}); | ||||
|  | ||||
|   return PropertyDescriptor({nullptr, | ||||
|                              name, | ||||
|                              CbData::Wrapper, | ||||
|                              nullptr, | ||||
|                              nullptr, | ||||
|                              nullptr, | ||||
|                              attributes, | ||||
|                              callbackData}); | ||||
| } | ||||
|  | ||||
| template <typename Callable> | ||||
| inline PropertyDescriptor PropertyDescriptor::Function( | ||||
|     Name name, Callable cb, napi_property_attributes attributes, void* data) { | ||||
|   napi_value nameValue = name; | ||||
|   return PropertyDescriptor::Function(nameValue, cb, attributes, data); | ||||
| } | ||||
|  | ||||
| #endif  // !SRC_NAPI_INL_DEPRECATED_H_ | ||||
							
								
								
									
										6936
									
								
								c++/napi-inl.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6936
									
								
								c++/napi-inl.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										3290
									
								
								c++/napi.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3290
									
								
								c++/napi.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										29
									
								
								date.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								date.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| package napi | ||||
|  | ||||
| import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi" | ||||
| ) | ||||
|  | ||||
| type Date struct{ value } | ||||
|  | ||||
| // Convert [ValueType] to [*Date] | ||||
| func ToDate(o ValueType) *Date { return &Date{o} } | ||||
|  | ||||
| func CreateDate(env EnvType, date time.Time) (*Date, error) { | ||||
| 	value, err := mustValueErr(napi.CreateDate(env.NapiValue(), float64(date.UnixMilli()))) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &Date{value: &Value{env: env, valueOf: value}}, nil | ||||
| } | ||||
|  | ||||
| // Get time from [*Date] object. | ||||
| func (d Date) Time() (time.Time, error) { | ||||
| 	timeFloat, err := mustValueErr(napi.GetDateValue(d.NapiEnv(), d.NapiValue())) | ||||
| 	if err != nil { | ||||
| 		return time.Time{}, err | ||||
| 	} | ||||
| 	return time.UnixMilli(int64(timeFloat)), nil | ||||
| } | ||||
| @@ -1,49 +0,0 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/akshayganeshen/napi-go" | ||||
| 	"github.com/akshayganeshen/napi-go/entry" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	entry.Export("getPromise", GetPromiseHandler) | ||||
| } | ||||
|  | ||||
| func GetPromiseHandler(env napi.Env, info napi.CallbackInfo) napi.Value { | ||||
| 	result, _ := napi.CreatePromise(env) | ||||
| 	asyncResourceName, _ := napi.CreateStringUtf8( | ||||
| 		env, | ||||
| 		"napi-go/async-promise-example", | ||||
| 	) | ||||
|  | ||||
| 	var asyncWork napi.AsyncWork | ||||
| 	asyncWork, _ = napi.CreateAsyncWork( | ||||
| 		env, | ||||
| 		nil, asyncResourceName, | ||||
| 		func(env napi.Env) { | ||||
| 			fmt.Printf("AsyncExecuteCallback(start)\n") | ||||
| 			defer fmt.Printf("AsyncExecuteCallback(stop)\n") | ||||
| 			time.Sleep(time.Second) | ||||
| 		}, | ||||
| 		func(env napi.Env, status napi.Status) { | ||||
| 			defer napi.DeleteAsyncWork(env, asyncWork) | ||||
|  | ||||
| 			if status == napi.StatusCancelled { | ||||
| 				fmt.Printf("AsyncCompleteCallback(cancelled)\n") | ||||
| 				return | ||||
| 			} | ||||
|  | ||||
| 			fmt.Printf("AsyncCompleteCallback\n") | ||||
| 			resolution, _ := napi.CreateStringUtf8(env, "resolved") | ||||
| 			napi.ResolveDeferred(env, result.Deferred, resolution) | ||||
| 		}, | ||||
| 	) | ||||
| 	napi.QueueAsyncWork(env, asyncWork) | ||||
|  | ||||
| 	return result.Value | ||||
| } | ||||
|  | ||||
| func main() {} | ||||
| @@ -1,25 +0,0 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"github.com/akshayganeshen/napi-go" | ||||
| 	"github.com/akshayganeshen/napi-go/entry" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	entry.Export("getCallback", GetCallbackHandler) | ||||
| } | ||||
|  | ||||
| func GetCallbackHandler(env napi.Env, info napi.CallbackInfo) napi.Value { | ||||
| 	result, _ := napi.CreateFunction( | ||||
| 		env, | ||||
| 		"callback", | ||||
| 		func(env napi.Env, info napi.CallbackInfo) napi.Value { | ||||
| 			result, _ := napi.CreateStringUtf8(env, "hello world") | ||||
| 			return result | ||||
| 		}, | ||||
| 	) | ||||
|  | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| func main() {} | ||||
| @@ -1,52 +0,0 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"github.com/akshayganeshen/napi-go" | ||||
| 	"github.com/akshayganeshen/napi-go/entry" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	entry.Export("describeArgs", DescribeArgsHandler) | ||||
| } | ||||
|  | ||||
| func DescribeArgsHandler(env napi.Env, info napi.CallbackInfo) napi.Value { | ||||
| 	extractedInfo, _ := napi.GetCbInfo(env, info) | ||||
| 	result, _ := napi.CreateArrayWithLength(env, len(extractedInfo.Args)) | ||||
| 	for i, arg := range extractedInfo.Args { | ||||
| 		vt, _ := napi.Typeof(env, arg) | ||||
| 		dv, _ := napi.CreateStringUtf8(env, DescribeValueType(vt)) | ||||
| 		napi.SetElement(env, result, i, dv) | ||||
| 	} | ||||
|  | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| func DescribeValueType(vt napi.ValueType) string { | ||||
| 	switch vt { | ||||
| 	case napi.ValueTypeUndefined: | ||||
| 		return "undefined" | ||||
| 	case napi.ValueTypeNull: | ||||
| 		return "null" | ||||
| 	case napi.ValueTypeBoolean: | ||||
| 		return "boolean" | ||||
| 	case napi.ValueTypeNumber: | ||||
| 		return "number" | ||||
| 	case napi.ValueTypeString: | ||||
| 		return "string" | ||||
| 	case napi.ValueTypeSymbol: | ||||
| 		return "symbol" | ||||
| 	case napi.ValueTypeObject: | ||||
| 		return "object" | ||||
| 	case napi.ValueTypeFunction: | ||||
| 		return "function" | ||||
| 	case napi.ValueTypeExternal: | ||||
| 		return "external" | ||||
| 	case napi.ValueTypeBigint: | ||||
| 		return "bigint" | ||||
|  | ||||
| 	default: | ||||
| 		return "other" | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func main() {} | ||||
| @@ -1,19 +0,0 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/akshayganeshen/napi-go" | ||||
| 	"github.com/akshayganeshen/napi-go/entry" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	entry.Export("hello", HelloHandler) | ||||
| } | ||||
|  | ||||
| func HelloHandler(env napi.Env, info napi.CallbackInfo) napi.Value { | ||||
| 	fmt.Println("hello world!") | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func main() {} | ||||
| @@ -1,81 +0,0 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/akshayganeshen/napi-go" | ||||
| 	"github.com/akshayganeshen/napi-go/entry" | ||||
| 	"github.com/akshayganeshen/napi-go/js" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	entry.Export("getMap", GetMapHandler) | ||||
| 	entry.Export("getCallback", js.AsCallback(GetCallback)) | ||||
| 	entry.Export("getArray", js.AsCallback(GetArray)) | ||||
| 	entry.Export("getPromiseResolve", js.AsCallback(GetPromiseResolve)) | ||||
| 	entry.Export("getPromiseReject", js.AsCallback(GetPromiseReject)) | ||||
| } | ||||
|  | ||||
| func GetMapHandler(env napi.Env, info napi.CallbackInfo) napi.Value { | ||||
| 	jsEnv := js.AsEnv(env) | ||||
|  | ||||
| 	return jsEnv.ValueOf( | ||||
| 		map[string]any{ | ||||
| 			"string":    "hello world", | ||||
| 			"number":    123, | ||||
| 			"bool":      false, | ||||
| 			"undefined": jsEnv.Undefined(), | ||||
| 			"null":      nil, | ||||
| 			"function": jsEnv.FuncOf( | ||||
| 				func(env js.Env, this js.Value, args []js.Value) any { | ||||
| 					return "hello world" | ||||
| 				}, | ||||
| 			), | ||||
| 		}, | ||||
| 	).Value | ||||
| } | ||||
|  | ||||
| func GetCallback(env js.Env, this js.Value, args []js.Value) any { | ||||
| 	return func(env js.Env, this js.Value, args []js.Value) any { | ||||
| 		return map[string]any{ | ||||
| 			"this": this, | ||||
| 			"args": args, | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func GetArray(env js.Env, this js.Value, args []js.Value) any { | ||||
| 	return []any{ | ||||
| 		"hello world", | ||||
| 		123, | ||||
| 		true, | ||||
| 		map[string]any{ | ||||
| 			"key": "value", | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func GetPromiseResolve(env js.Env, this js.Value, args []js.Value) any { | ||||
| 	promise := env.NewPromise() | ||||
|  | ||||
| 	go func() { | ||||
| 		time.Sleep(time.Second) | ||||
| 		promise.Resolve("resolved") | ||||
| 	}() | ||||
|  | ||||
| 	return promise | ||||
| } | ||||
|  | ||||
| func GetPromiseReject(env js.Env, this js.Value, args []js.Value) any { | ||||
| 	promise := env.NewPromise() | ||||
|  | ||||
| 	go func() { | ||||
| 		time.Sleep(time.Second) | ||||
| 		promise.Reject(fmt.Errorf("rejected")) | ||||
| 	}() | ||||
|  | ||||
| 	return promise | ||||
| } | ||||
|  | ||||
| func main() {} | ||||
							
								
								
									
										66
									
								
								entry/entry.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								entry/entry.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| package entry | ||||
|  | ||||
| /* | ||||
| #cgo CFLAGS: -DDEBUG | ||||
| #cgo CFLAGS: -D_DEBUG | ||||
| #cgo CFLAGS: -DV8_ENABLE_CHECKS | ||||
| #cgo CFLAGS: -DNAPI_EXPERIMENTAL | ||||
| #cgo CFLAGS: -I/usr/local/include/node | ||||
| #cgo CXXFLAGS: -std=c++11 | ||||
|  | ||||
| #cgo darwin LDFLAGS: -Wl,-undefined,dynamic_lookup | ||||
| #cgo darwin LDFLAGS: -Wl,-no_pie | ||||
| #cgo darwin LDFLAGS: -Wl,-search_paths_first | ||||
| #cgo (darwin && amd64) LDFLAGS: -arch x86_64 | ||||
| #cgo (darwin && arm64) LDFLAGS: -arch arm64 | ||||
|  | ||||
| #cgo linux LDFLAGS: -Wl,-unresolved-symbols=ignore-all | ||||
|  | ||||
| #cgo LDFLAGS: -L${SRCDIR} | ||||
|  | ||||
| #include <stdlib.h> | ||||
| #include "./entry.h" | ||||
| */ | ||||
| import "C" | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	gonapi "sirherobrine23.com.br/Sirherobrine23/napi-go" | ||||
| 	"sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi" | ||||
| ) | ||||
|  | ||||
| type registerCallback func(env napi.Env, object napi.Value) | ||||
|  | ||||
| var modFuncInit = []registerCallback{} | ||||
|  | ||||
| //export initializeModule | ||||
| func initializeModule(cEnv C.napi_env, cExports C.napi_value) C.napi_value { | ||||
| 	env, exports := napi.Env(cEnv), napi.Value(cExports) | ||||
| 	napi.InitializeInstanceData(env) | ||||
|  | ||||
| 	defer func() { | ||||
| 		if err := recover(); err != nil { | ||||
| 			switch v := err.(type) { | ||||
| 			case error: | ||||
| 				gonapi.ThrowError(gonapi.N_APIEnv(env), "", v.Error()) | ||||
| 			default: | ||||
| 				gonapi.ThrowError(gonapi.N_APIEnv(env), "", fmt.Sprintf("%s", v)) | ||||
| 			} | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| 	for _, registerCall := range modFuncInit { | ||||
| 		registerCall(env, exports) | ||||
| 	} | ||||
|  | ||||
| 	return cExports | ||||
| } | ||||
|  | ||||
| func Register(fn func(env gonapi.EnvType, export *gonapi.Object)) { | ||||
| 	modFuncInit = append(modFuncInit, func(env napi.Env, object napi.Value) { | ||||
| 		registerEnv := gonapi.N_APIEnv(env) | ||||
| 		registerObj := gonapi.ToObject(gonapi.N_APIValue(registerEnv, object)) | ||||
| 		fn(registerEnv, registerObj) | ||||
| 	}) | ||||
| } | ||||
| @@ -7,9 +7,9 @@ | ||||
| extern "C" { | ||||
| #endif /* __cplusplus */ | ||||
|  | ||||
| // InitializeModule is a N-API module initialization function. | ||||
| // InitializeModule is suitable for use as a napi_addon_register_func. | ||||
| extern napi_value InitializeModule( | ||||
| // initializeModule is a N-API module initialization function. | ||||
| // initializeModule is suitable for use as a napi_addon_register_func. | ||||
| extern napi_value initializeModule( | ||||
|   napi_env    env, | ||||
|   napi_value  exports | ||||
| ); | ||||
|   | ||||
| @@ -1,19 +0,0 @@ | ||||
| package entry | ||||
|  | ||||
| import ( | ||||
| 	"github.com/akshayganeshen/napi-go" | ||||
| ) | ||||
|  | ||||
| type napiGoExport struct { | ||||
| 	Name     string | ||||
| 	Callback napi.Callback | ||||
| } | ||||
|  | ||||
| var napiGoGlobalExports []napiGoExport | ||||
|  | ||||
| func Export(name string, callback napi.Callback) { | ||||
| 	napiGoGlobalExports = append(napiGoGlobalExports, napiGoExport{ | ||||
| 		Name:     name, | ||||
| 		Callback: callback, | ||||
| 	}) | ||||
| } | ||||
| @@ -2,4 +2,4 @@ | ||||
|  | ||||
| #include "./entry.h" | ||||
|  | ||||
| NAPI_MODULE(napiGo, InitializeModule) | ||||
| NAPI_MODULE(napiGo, initializeModule) | ||||
|   | ||||
| @@ -1,26 +0,0 @@ | ||||
| package entry | ||||
|  | ||||
| /* | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include "./entry.h" | ||||
| */ | ||||
| import "C" | ||||
|  | ||||
| import ( | ||||
| 	"github.com/akshayganeshen/napi-go" | ||||
| ) | ||||
|  | ||||
| //export InitializeModule | ||||
| func InitializeModule(cEnv C.napi_env, cExports C.napi_value) C.napi_value { | ||||
| 	env, exports := napi.Env(cEnv), napi.Value(cExports) | ||||
| 	napi.InitializeInstanceData(env) | ||||
|  | ||||
| 	for _, export := range napiGoGlobalExports { | ||||
| 		cb, _ := napi.CreateFunction(env, export.Name, export.Callback) | ||||
| 		name, _ := napi.CreateStringUtf8(env, export.Name) | ||||
| 		napi.SetProperty(env, exports, name, cb) | ||||
| 	} | ||||
|  | ||||
| 	return cExports | ||||
| } | ||||
| @@ -1,21 +0,0 @@ | ||||
| package entry | ||||
|  | ||||
| /* | ||||
| #cgo CFLAGS: -DDEBUG | ||||
| #cgo CFLAGS: -D_DEBUG | ||||
| #cgo CFLAGS: -DV8_ENABLE_CHECKS | ||||
| #cgo CFLAGS: -DNAPI_EXPERIMENTAL | ||||
| #cgo CFLAGS: -I/usr/local/include/node | ||||
| #cgo CXXFLAGS: -std=c++11 | ||||
|  | ||||
| #cgo darwin LDFLAGS: -Wl,-undefined,dynamic_lookup | ||||
| #cgo darwin LDFLAGS: -Wl,-no_pie | ||||
| #cgo darwin LDFLAGS: -Wl,-search_paths_first | ||||
| #cgo darwin LDFLAGS: -arch x86_64 | ||||
|  | ||||
| #cgo linux LDFLAGS: -Wl,-unresolved-symbols=ignore-all | ||||
|  | ||||
| #cgo LDFLAGS: -L${SRCDIR} | ||||
| #cgo LDFLAGS: -stdlib=libc++ | ||||
| */ | ||||
| import "C" | ||||
							
								
								
									
										37
									
								
								error.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								error.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| package napi | ||||
|  | ||||
| import ( | ||||
| 	"runtime" | ||||
|  | ||||
| 	"sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi" | ||||
| ) | ||||
|  | ||||
| type Error struct{ value } | ||||
|  | ||||
| func ToError(o ValueType) *Error { return &Error{o} } | ||||
|  | ||||
| func CreateError(env EnvType, msg string) (*Error, error) { | ||||
| 	napiMsg, err := CreateString(env, msg) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	napiValue, err := mustValueErr(napi.CreateError(env.NapiValue(), nil, napiMsg.NapiValue())) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return ToError(N_APIValue(env, napiValue)), nil | ||||
| } | ||||
|  | ||||
| func (er *Error) ThrowAsJavaScriptException() error { | ||||
| 	return singleMustValueErr(napi.Throw(er.NapiEnv(), er.NapiValue())) | ||||
| } | ||||
|  | ||||
| // This throws a JavaScript Error with the text provided. | ||||
| func ThrowError(env EnvType, code, err string) error { | ||||
| 	if code == "" { | ||||
| 		stackTraceBuf := make([]byte, 8192) | ||||
| 		stackTraceSz := runtime.Stack(stackTraceBuf, false) | ||||
| 		code = string(stackTraceBuf[:stackTraceSz]) | ||||
| 	} | ||||
| 	return singleMustValueErr(napi.ThrowError(env.NapiValue(), code, err)) | ||||
| } | ||||
							
								
								
									
										80
									
								
								example/test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								example/test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"net/netip" | ||||
|  | ||||
| 	"sirherobrine23.com.br/Sirherobrine23/napi-go" | ||||
| 	"sirherobrine23.com.br/Sirherobrine23/napi-go/entry" | ||||
| 	"sirherobrine23.com.br/Sirherobrine23/napi-go/js" | ||||
| ) | ||||
|  | ||||
| type Test struct { | ||||
| 	Int    int | ||||
| 	String string | ||||
| 	Sub    []any | ||||
| } | ||||
|  | ||||
| func init() { | ||||
| 	entry.Register(func(env napi.EnvType, export *napi.Object) { | ||||
| 		inNode, _ := napi.CreateString(env, "from golang napi string") | ||||
| 		inNode2, _ := napi.CopyBuffer(env, []byte{1, 0, 244, 21}) | ||||
| 		toGoReflect := &Test{ | ||||
| 			Int:    14, | ||||
| 			String: "From golang", | ||||
| 			Sub: []any{ | ||||
| 				1, | ||||
| 				[]string{"test", "gopher"}, | ||||
| 				[]bool{false, true}, | ||||
| 				[]int{23, 244, 10, 2024, 2025, 2000}, | ||||
| 				map[string]string{"exampleMap": "test"}, | ||||
| 				map[int]string{1: "one"}, | ||||
| 				map[bool]string{false: "false", true: "true"}, | ||||
| 				map[[2]string]string{[2]string{"go"}: "example"}, | ||||
| 				netip.IPv4Unspecified(), | ||||
| 				netip.IPv6Unspecified(), | ||||
| 				netip.AddrPortFrom(netip.IPv6Unspecified(), 19132), | ||||
| 				nil, | ||||
| 				true, | ||||
| 				false, | ||||
| 				inNode, | ||||
| 				inNode2, | ||||
| 				func() { | ||||
| 					println("called in go") | ||||
| 				}, | ||||
| 			}, | ||||
| 		} | ||||
|  | ||||
| 		napiStruct, err := js.ValueOf(env, toGoReflect) | ||||
| 		if err != nil { | ||||
| 			panic(err) | ||||
| 		} | ||||
| 		export.Set("goStruct", napiStruct) | ||||
|  | ||||
| 		fnCall, err := js.GoFuncOf(env, func(call ...any) (string, error) { | ||||
| 			d, err := json.MarshalIndent(call, "", "  ") | ||||
| 			if err == nil { | ||||
| 				println(string(d)) | ||||
| 			} | ||||
| 			return string(d), err | ||||
| 		}) | ||||
| 		if err != nil { | ||||
| 			panic(err) | ||||
| 		} | ||||
| 		export.Set("printAny", fnCall) | ||||
|  | ||||
| 		fnCallStruct, err := js.GoFuncOf(env, func(call ...Test) (string, error) { | ||||
| 			d, err := json.MarshalIndent(call, "", "  ") | ||||
| 			if err == nil { | ||||
| 				println(string(d)) | ||||
| 			} | ||||
| 			return string(d), err | ||||
| 		}) | ||||
| 		if err != nil { | ||||
| 			panic(err) | ||||
| 		} | ||||
| 		export.Set("printTestStruct", fnCallStruct) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func main() {} | ||||
							
								
								
									
										96
									
								
								function.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								function.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | ||||
| package napi | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi" | ||||
| ) | ||||
|  | ||||
| type Function struct{ value } | ||||
|  | ||||
| // Function to call on Javascript caller | ||||
| type Callback func(env EnvType, this ValueType, args []ValueType) (ValueType, error) | ||||
|  | ||||
| // Convert [ValueType] to [*Function] | ||||
| func ToFunction(o ValueType) *Function { return &Function{o} } | ||||
|  | ||||
| func CreateFunction(env EnvType, name string, callback Callback) (*Function, error) { | ||||
| 	return CreateFunctionNapi(env, name, func(napiEnv napi.Env, info napi.CallbackInfo) napi.Value { | ||||
| 		env := N_APIEnv(napiEnv) | ||||
| 		cbInfo, err := mustValueErr(napi.GetCbInfo(napiEnv, info)) | ||||
| 		if err != nil { | ||||
| 			ThrowError(env, "", err.Error()) | ||||
| 			return nil | ||||
| 		} | ||||
|  | ||||
| 		this := N_APIValue(env, cbInfo.This) | ||||
| 		args := make([]ValueType, len(cbInfo.Args)) | ||||
| 		for i, cbArg := range cbInfo.Args { | ||||
| 			args[i] = N_APIValue(env, cbArg) | ||||
| 		} | ||||
|  | ||||
| 		defer func() { | ||||
| 			if err := recover(); err != nil { | ||||
| 				switch v := err.(type) { | ||||
| 				case error: | ||||
| 					ThrowError(env, "", v.Error()) | ||||
| 				default: | ||||
| 					ThrowError(env, "", fmt.Sprintf("panic recover: %s", err)) | ||||
| 				} | ||||
| 			} | ||||
| 		}() | ||||
|  | ||||
| 		res, err := callback(env, this, args) | ||||
| 		switch { | ||||
| 		case err != nil: | ||||
| 			ThrowError(env, "", err.Error()) | ||||
| 			return nil | ||||
| 		case res == nil: | ||||
| 			und, _ := env.Undefined() | ||||
| 			return und.NapiValue() | ||||
| 		default: | ||||
| 			typeOf, _ := res.Type() | ||||
| 			if typeOf == TypeError { | ||||
| 				ToError(res).ThrowAsJavaScriptException() | ||||
| 				return nil | ||||
| 			} | ||||
| 			return res.NapiValue() | ||||
| 		} | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func CreateFunctionNapi(env EnvType, name string, callback napi.Callback) (*Function, error) { | ||||
| 	fnCall, err := mustValueErr(napi.CreateFunction(env.NapiValue(), name, callback)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return ToFunction(N_APIValue(env, fnCall)), nil | ||||
| } | ||||
|  | ||||
| func (fn *Function) internalCall(this napi.Value, argc int, argv []napi.Value) (ValueType, error) { | ||||
| 	// napi_call_function(env, global, add_two, argc, argv, &return_val); | ||||
| 	res, err := mustValueErr(napi.CallFunction(fn.NapiEnv(), this, fn.NapiValue(), argc, argv)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return N_APIValue(fn.Env(), res), nil | ||||
| } | ||||
|  | ||||
| // Call function with custom global/this value | ||||
| func (fn *Function) CallWithGlobal(this ValueType, args ...ValueType) (ValueType, error) { | ||||
| 	argc := len(args) | ||||
| 	argv := make([]napi.Value, argc) | ||||
| 	for index := range argc { | ||||
| 		argv[index] = args[index].NapiValue() | ||||
| 	} | ||||
| 	return fn.internalCall(this.NapiValue(), argc, argv) | ||||
| } | ||||
|  | ||||
| // Call function with args | ||||
| func (fn *Function) Call(args ...ValueType) (ValueType, error) { | ||||
| 	global, err := fn.Env().Global() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return fn.CallWithGlobal(global, args...) | ||||
| } | ||||
							
								
								
									
										4
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								go.mod
									
									
									
									
									
								
							| @@ -1,3 +1,3 @@ | ||||
| module github.com/akshayganeshen/napi-go | ||||
| module sirherobrine23.com.br/Sirherobrine23/napi-go | ||||
|  | ||||
| go 1.18 | ||||
| go 1.24 | ||||
|   | ||||
							
								
								
									
										1294
									
								
								internal/napi/js_native_api.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1294
									
								
								internal/napi/js_native_api.go
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										34
									
								
								internal/napi/key_type.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								internal/napi/key_type.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| package napi | ||||
|  | ||||
| /* | ||||
| #include <node/node_api.h> | ||||
| */ | ||||
| import "C" | ||||
|  | ||||
| // KeyCollectionMode type | ||||
| type KeyCollectionMode C.napi_key_collection_mode | ||||
|  | ||||
| const ( | ||||
| 	KeyIncludePrototypes KeyCollectionMode = C.napi_key_include_prototypes | ||||
| 	KeyOwnOnly           KeyCollectionMode = C.napi_key_own_only | ||||
| ) | ||||
|  | ||||
| // KeyFilter type | ||||
| type KeyFilter C.napi_key_filter | ||||
|  | ||||
| const ( | ||||
| 	KeyAllProperties KeyFilter = C.napi_key_all_properties | ||||
| 	KeyWritable      KeyFilter = C.napi_key_writable | ||||
| 	KeyEnumerable    KeyFilter = C.napi_key_enumerable | ||||
| 	KeyConfigurable  KeyFilter = C.napi_key_configurable | ||||
| 	KeySkipStrings   KeyFilter = C.napi_key_skip_strings | ||||
| 	KeySkipSymbols   KeyFilter = C.napi_key_skip_symbols | ||||
| ) | ||||
|  | ||||
| // KeyConversion type | ||||
| type KeyConversion C.napi_key_conversion | ||||
|  | ||||
| const ( | ||||
| 	KeyKeepNumbers      KeyConversion = C.napi_key_keep_numbers | ||||
| 	KeyNumbersToStrings KeyConversion = C.napi_key_numbers_to_strings | ||||
| ) | ||||
| @@ -11,11 +11,11 @@ package napi | ||||
| #cgo darwin LDFLAGS: -Wl,-undefined,dynamic_lookup | ||||
| #cgo darwin LDFLAGS: -Wl,-no_pie | ||||
| #cgo darwin LDFLAGS: -Wl,-search_paths_first | ||||
| #cgo darwin LDFLAGS: -arch x86_64 | ||||
| // #cgo darwin amd64 LDFLAGS: -arch x86_64 | ||||
| // #cgo darwin arm64 LDFLAGS: -arch arm64 | ||||
| 
 | ||||
| #cgo linux LDFLAGS: -Wl,-unresolved-symbols=ignore-all | ||||
| 
 | ||||
| #cgo LDFLAGS: -L${SRCDIR} | ||||
| #cgo LDFLAGS: -stdlib=libc++ | ||||
| */ | ||||
| import "C" | ||||
| import "C" | ||||
| @@ -1,6 +1,7 @@ | ||||
| package napi | ||||
| 
 | ||||
| /* | ||||
| #include <stdlib.h> | ||||
| #include <node/node_api.h> | ||||
| */ | ||||
| import "C" | ||||
| @@ -113,11 +114,12 @@ func CreateThreadsafeFunction( | ||||
| 
 | ||||
| func CallThreadsafeFunction( | ||||
| 	fn ThreadsafeFunction, | ||||
| 	mode ThreadsafeFunctionCallMode, | ||||
| ) Status { | ||||
| 	return Status(C.napi_call_threadsafe_function( | ||||
| 		C.napi_threadsafe_function(fn), | ||||
| 		nil, | ||||
| 		C.napi_tsfn_blocking, | ||||
| 		C.napi_threadsafe_function_call_mode(mode), | ||||
| 	)) | ||||
| } | ||||
| 
 | ||||
| @@ -129,9 +131,108 @@ func AcquireThreadsafeFunction(fn ThreadsafeFunction) Status { | ||||
| 
 | ||||
| func ReleaseThreadsafeFunction( | ||||
| 	fn ThreadsafeFunction, | ||||
| 	mode ThreadsafeFunctionReleaseMode, | ||||
| ) Status { | ||||
| 	return Status(C.napi_release_threadsafe_function( | ||||
| 		C.napi_threadsafe_function(fn), | ||||
| 		C.napi_tsfn_release, | ||||
| 		C.napi_threadsafe_function_release_mode(mode), | ||||
| 	)) | ||||
| } | ||||
| 
 | ||||
| func GetThreadsafeFunctionContext( | ||||
| 	fn ThreadsafeFunction, | ||||
| ) (unsafe.Pointer, Status) { | ||||
| 	var context unsafe.Pointer | ||||
| 	status := Status(C.napi_get_threadsafe_function_context( | ||||
| 		C.napi_threadsafe_function(fn), | ||||
| 		&context, | ||||
| 	)) | ||||
| 	return context, status | ||||
| } | ||||
| 
 | ||||
| func RefThreadsafeFunction(env Env, fn ThreadsafeFunction) Status { | ||||
| 	return Status(C.napi_ref_threadsafe_function( | ||||
| 		C.napi_env(env), | ||||
| 		C.napi_threadsafe_function(fn), | ||||
| 	)) | ||||
| } | ||||
| 
 | ||||
| func UnrefThreadsafeFunction(env Env, fn ThreadsafeFunction) Status { | ||||
| 	return Status(C.napi_unref_threadsafe_function( | ||||
| 		C.napi_env(env), | ||||
| 		C.napi_threadsafe_function(fn), | ||||
| 	)) | ||||
| } | ||||
| 
 | ||||
| func ThrowSyntaxError(env Env, code, msg string) Status { | ||||
| 	codeCStr, msgCStr := C.CString(code), C.CString(msg) | ||||
| 	defer C.free(unsafe.Pointer(codeCStr)) | ||||
| 	defer C.free(unsafe.Pointer(msgCStr)) | ||||
| 
 | ||||
| 	return Status(C.node_api_throw_syntax_error( | ||||
| 		C.napi_env(env), | ||||
| 		codeCStr, | ||||
| 		msgCStr, | ||||
| 	)) | ||||
| } | ||||
| 
 | ||||
| func CreateSyntaxError(env Env, code, msg Value) (Value, Status) { | ||||
| 	var result Value | ||||
| 	status := Status(C.node_api_create_syntax_error( | ||||
| 		C.napi_env(env), | ||||
| 		C.napi_value(code), | ||||
| 		C.napi_value(msg), | ||||
| 		(*C.napi_value)(unsafe.Pointer(&result)), | ||||
| 	)) | ||||
| 	return result, status | ||||
| } | ||||
| 
 | ||||
| func SymbolFor(env Env, description string) (Value, Status) { | ||||
| 	var result Value | ||||
| 	status := Status(C.node_api_symbol_for( | ||||
| 		C.napi_env(env), | ||||
| 		C.CString(description), | ||||
| 		C.size_t(len(description)), | ||||
| 		(*C.napi_value)(unsafe.Pointer(&result)), | ||||
| 	)) | ||||
| 	return result, status | ||||
| } | ||||
| 
 | ||||
| func CreatePropertyKeyLatin1(env Env, str string) (Value, Status) { | ||||
| 	cstr := C.CString(str) | ||||
| 	defer C.free(unsafe.Pointer(cstr)) | ||||
| 
 | ||||
| 	var result Value | ||||
| 	status := Status(C.node_api_create_property_key_latin1( | ||||
| 		C.napi_env(env), | ||||
| 		cstr, | ||||
| 		C.size_t(len([]byte(str))), | ||||
| 		(*C.napi_value)(unsafe.Pointer(&result)), | ||||
| 	)) | ||||
| 	return result, status | ||||
| } | ||||
| 
 | ||||
| func CreatePropertyKeyUtf16(env Env, str []uint16) (Value, Status) { | ||||
| 	var result Value | ||||
| 	status := Status(C.node_api_create_property_key_utf16( | ||||
| 		C.napi_env(env), | ||||
| 		(*C.char16_t)(unsafe.Pointer(&str[0])), | ||||
| 		C.size_t(len(str)), | ||||
| 		(*C.napi_value)(unsafe.Pointer(&result)), | ||||
| 	)) | ||||
| 	return result, status | ||||
| } | ||||
| 
 | ||||
| func CreatePropertyKeyUtf8(env Env, str string) (Value, Status) { | ||||
| 	cstr := C.CString(str) | ||||
| 	defer C.free(unsafe.Pointer(cstr)) | ||||
| 
 | ||||
| 	var result Value | ||||
| 	status := Status(C.node_api_create_property_key_utf8( | ||||
| 		C.napi_env(env), | ||||
| 		cstr, | ||||
| 		C.size_t(len([]byte(str))), | ||||
| 		(*C.napi_value)(unsafe.Pointer(&result)), | ||||
| 	)) | ||||
| 	return result, status | ||||
| } | ||||
							
								
								
									
										18
									
								
								internal/napi/property_attrib_type.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								internal/napi/property_attrib_type.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| package napi | ||||
|  | ||||
| /* | ||||
| #include <node/node_api.h> | ||||
| */ | ||||
| import "C" | ||||
|  | ||||
| type PropertyAttributes C.napi_property_attributes | ||||
|  | ||||
| const ( | ||||
| 	Default           PropertyAttributes = C.napi_default | ||||
| 	Writable          PropertyAttributes = C.napi_writable | ||||
| 	Enumerable        PropertyAttributes = C.napi_enumerable | ||||
| 	Configurable      PropertyAttributes = C.napi_configurable | ||||
| 	Static            PropertyAttributes = C.napi_static | ||||
| 	DefaultMethod     PropertyAttributes = C.napi_default_method | ||||
| 	DefaultJSProperty PropertyAttributes = C.napi_default_jsproperty | ||||
| ) | ||||
							
								
								
									
										20
									
								
								internal/napi/threadsafe_function_type.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								internal/napi/threadsafe_function_type.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| package napi | ||||
|  | ||||
| /* | ||||
| #include <node/node_api.h> | ||||
| */ | ||||
| import "C" | ||||
|  | ||||
| type ThreadsafeFunctionReleaseMode C.napi_threadsafe_function_release_mode | ||||
|  | ||||
| const ( | ||||
| 	Release ThreadsafeFunctionReleaseMode = C.napi_tsfn_release | ||||
| 	Abort   ThreadsafeFunctionReleaseMode = C.napi_tsfn_abort | ||||
| ) | ||||
|  | ||||
| type ThreadsafeFunctionCallMode C.napi_threadsafe_function_call_mode | ||||
|  | ||||
| const ( | ||||
| 	NonBlocking ThreadsafeFunctionCallMode = C.napi_tsfn_nonblocking | ||||
| 	Blocking    ThreadsafeFunctionCallMode = C.napi_tsfn_blocking | ||||
| ) | ||||
							
								
								
									
										22
									
								
								internal/napi/typed_array_type.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								internal/napi/typed_array_type.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| package napi | ||||
|  | ||||
| /* | ||||
| #include <node/node_api.h> | ||||
| */ | ||||
| import "C" | ||||
|  | ||||
| type TypedArrayType C.napi_typedarray_type | ||||
|  | ||||
| const ( | ||||
| 	TypedArrayInt8Array          TypedArrayType = C.napi_int8_array | ||||
| 	TypedArrayUint8Array         TypedArrayType = C.napi_uint8_array | ||||
| 	TypedArrayUint8ClampedArray  TypedArrayType = C.napi_uint8_clamped_array | ||||
| 	TypedArrayInt16Array         TypedArrayType = C.napi_int16_array | ||||
| 	TypedArrayUint16Array        TypedArrayType = C.napi_uint16_array | ||||
| 	TypedArrayInt32Array         TypedArrayType = C.napi_int32_array | ||||
| 	TypedArrayUint32Array        TypedArrayType = C.napi_uint32_array | ||||
| 	TypedArrayFloat32Array       TypedArrayType = C.napi_float32_array | ||||
| 	TypedArrayFloat64Array       TypedArrayType = C.napi_float64_array | ||||
| 	TypedArrayBigInt64Array      TypedArrayType = C.napi_bigint64_array | ||||
| 	TypedArrayBigUint64Array     TypedArrayType = C.napi_biguint64_array | ||||
| ) | ||||
							
								
								
									
										41
									
								
								internal/napi/types.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								internal/napi/types.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| package napi | ||||
|  | ||||
| /* | ||||
| #include <node/node_api.h> | ||||
| */ | ||||
| import "C" | ||||
| import "unsafe" | ||||
|  | ||||
| type PropertyDescriptor struct { | ||||
| 	Utf8name   string | ||||
| 	Name       Value | ||||
| 	Method     Callback | ||||
| 	Getter     Callback | ||||
| 	Setter     Callback | ||||
| 	Value      Value | ||||
| 	Attributes PropertyAttributes | ||||
| 	Data       unsafe.Pointer | ||||
| } | ||||
|  | ||||
| type Finalize func(env Env, finalizeData, finalizeHint unsafe.Pointer) | ||||
|  | ||||
| func FinalizeToFinalizer(fn Finalize) Finalizer { | ||||
| 	return func(env C.napi_env, finalizeData, finalizeHint unsafe.Pointer) { | ||||
| 		fn(Env(env), finalizeData, finalizeHint) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Finalizer as a C-compatible function pointer type | ||||
| type Finalizer func(env C.napi_env, finalizeData, finalizeHint unsafe.Pointer) | ||||
|  | ||||
| type Reference struct { | ||||
| 	Ref unsafe.Pointer | ||||
| } | ||||
|  | ||||
| type EscapableHandleScope struct { | ||||
| 	Scope unsafe.Pointer | ||||
| } | ||||
|  | ||||
| type HandleScope struct { | ||||
| 	Scope unsafe.Pointer | ||||
| } | ||||
							
								
								
									
										48
									
								
								internal/napi/value_type.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								internal/napi/value_type.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| package napi | ||||
|  | ||||
| /* | ||||
| #include <node/node_api.h> | ||||
| */ | ||||
| import "C" | ||||
|  | ||||
| type ValueType C.napi_valuetype | ||||
|  | ||||
| const ( | ||||
| 	ValueTypeUndefined ValueType = C.napi_undefined | ||||
| 	ValueTypeNull      ValueType = C.napi_null | ||||
| 	ValueTypeBoolean   ValueType = C.napi_boolean | ||||
| 	ValueTypeNumber    ValueType = C.napi_number | ||||
| 	ValueTypeString    ValueType = C.napi_string | ||||
| 	ValueTypeSymbol    ValueType = C.napi_symbol | ||||
| 	ValueTypeObject    ValueType = C.napi_object | ||||
| 	ValueTypeFunction  ValueType = C.napi_function | ||||
| 	ValueTypeExternal  ValueType = C.napi_external | ||||
| 	ValueTypeBigint    ValueType = C.napi_bigint | ||||
| ) | ||||
|  | ||||
| func (v ValueType) String() string { | ||||
| 	switch v { | ||||
| 	case ValueTypeUndefined: | ||||
| 		return "undefined" | ||||
| 	case ValueTypeNull: | ||||
| 		return "null" | ||||
| 	case ValueTypeBoolean: | ||||
| 		return "boolean" | ||||
| 	case ValueTypeNumber: | ||||
| 		return "number" | ||||
| 	case ValueTypeString: | ||||
| 		return "string" | ||||
| 	case ValueTypeSymbol: | ||||
| 		return "symbol" | ||||
| 	case ValueTypeObject: | ||||
| 		return "object" | ||||
| 	case ValueTypeFunction: | ||||
| 		return "function" | ||||
| 	case ValueTypeExternal: | ||||
| 		return "external" | ||||
| 	case ValueTypeBigint: | ||||
| 		return "bigint" | ||||
| 	default: | ||||
| 		return "undefined" | ||||
| 	} | ||||
| } | ||||
| @@ -1,32 +0,0 @@ | ||||
| package js | ||||
|  | ||||
| import ( | ||||
| 	"github.com/akshayganeshen/napi-go" | ||||
| ) | ||||
|  | ||||
| type Callback = func(env Env, this Value, args []Value) any | ||||
|  | ||||
| func AsCallback(fn Callback) napi.Callback { | ||||
| 	return func(env napi.Env, info napi.CallbackInfo) napi.Value { | ||||
| 		cbInfo, st := napi.GetCbInfo(env, info) | ||||
| 		if st != napi.StatusOK { | ||||
| 			panic(napi.StatusError(st)) | ||||
| 		} | ||||
|  | ||||
| 		jsEnv := AsEnv(env) | ||||
| 		this := Value{ | ||||
| 			Env:   jsEnv, | ||||
| 			Value: cbInfo.This, | ||||
| 		} | ||||
| 		args := make([]Value, len(cbInfo.Args)) | ||||
| 		for i, cbArg := range cbInfo.Args { | ||||
| 			args[i] = Value{ | ||||
| 				Env:   jsEnv, | ||||
| 				Value: cbArg, | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		result := fn(jsEnv, this, args) | ||||
| 		return jsEnv.ValueOf(result).Value | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										196
									
								
								js/env.go
									
									
									
									
									
								
							
							
						
						
									
										196
									
								
								js/env.go
									
									
									
									
									
								
							| @@ -1,196 +0,0 @@ | ||||
| package js | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"github.com/akshayganeshen/napi-go" | ||||
| ) | ||||
|  | ||||
| type Env struct { | ||||
| 	Env napi.Env | ||||
| } | ||||
|  | ||||
| type InvalidValueTypeError struct { | ||||
| 	Value any | ||||
| } | ||||
|  | ||||
| var _ error = InvalidValueTypeError{} | ||||
|  | ||||
| func AsEnv(env napi.Env) Env { | ||||
| 	return Env{ | ||||
| 		Env: env, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (e Env) Global() Value { | ||||
| 	v, st := napi.GetGlobal(e.Env) | ||||
| 	if st != napi.StatusOK { | ||||
| 		panic(napi.StatusError(st)) | ||||
| 	} | ||||
| 	return Value{ | ||||
| 		Env:   e, | ||||
| 		Value: v, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (e Env) Null() Value { | ||||
| 	v, st := napi.GetNull(e.Env) | ||||
| 	if st != napi.StatusOK { | ||||
| 		panic(napi.StatusError(st)) | ||||
| 	} | ||||
| 	return Value{ | ||||
| 		Env:   e, | ||||
| 		Value: v, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (e Env) Undefined() Value { | ||||
| 	v, st := napi.GetUndefined(e.Env) | ||||
| 	if st != napi.StatusOK { | ||||
| 		panic(napi.StatusError(st)) | ||||
| 	} | ||||
| 	return Value{ | ||||
| 		Env:   e, | ||||
| 		Value: v, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (e Env) ValueOf(x any) Value { | ||||
| 	var ( | ||||
| 		v  napi.Value | ||||
| 		st napi.Status | ||||
| 	) | ||||
|  | ||||
| 	switch xt := x.(type) { | ||||
| 	case Value: | ||||
| 		return xt | ||||
| 	case []Value: | ||||
| 		l := len(xt) | ||||
| 		v, st = napi.CreateArrayWithLength(e.Env, l) | ||||
| 		if st != napi.StatusOK { | ||||
| 			break | ||||
| 		} | ||||
|  | ||||
| 		for i, xti := range xt { | ||||
| 			// TODO: Use Value.SetIndex helper | ||||
| 			st = napi.SetElement(e.Env, v, i, xti.Value) | ||||
| 			if st != napi.StatusOK { | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 	case Func: | ||||
| 		return xt.Value | ||||
| 	case Callback: | ||||
| 		return e.FuncOf(xt).Value | ||||
| 	case *Promise: | ||||
| 		v, st = xt.Promise.Value, napi.StatusOK | ||||
| 	case napi.Value: | ||||
| 		v, st = xt, napi.StatusOK | ||||
|  | ||||
| 	case nil: | ||||
| 		v, st = napi.GetNull(e.Env) | ||||
| 	case bool: | ||||
| 		v, st = napi.GetBoolean(e.Env, xt) | ||||
| 	case int: | ||||
| 		v, st = napi.CreateDouble(e.Env, float64(xt)) | ||||
| 	case int8: | ||||
| 		v, st = napi.CreateDouble(e.Env, float64(xt)) | ||||
| 	case int16: | ||||
| 		v, st = napi.CreateDouble(e.Env, float64(xt)) | ||||
| 	case int64: | ||||
| 		v, st = napi.CreateDouble(e.Env, float64(xt)) | ||||
| 	case uint: | ||||
| 		v, st = napi.CreateDouble(e.Env, float64(xt)) | ||||
| 	case uint8: | ||||
| 		v, st = napi.CreateDouble(e.Env, float64(xt)) | ||||
| 	case uint16: | ||||
| 		v, st = napi.CreateDouble(e.Env, float64(xt)) | ||||
| 	case uint64: | ||||
| 		v, st = napi.CreateDouble(e.Env, float64(xt)) | ||||
| 	case uintptr: | ||||
| 		v, st = napi.CreateDouble(e.Env, float64(xt)) | ||||
| 	case unsafe.Pointer: | ||||
| 		v, st = napi.CreateDouble(e.Env, float64(uintptr(xt))) | ||||
| 	case float32: | ||||
| 		v, st = napi.CreateDouble(e.Env, float64(xt)) | ||||
| 	case float64: | ||||
| 		v, st = napi.CreateDouble(e.Env, xt) | ||||
| 	case string: | ||||
| 		v, st = napi.CreateStringUtf8(e.Env, xt) | ||||
| 	case error: | ||||
| 		msg := e.ValueOf(xt.Error()) | ||||
| 		v, st = napi.CreateError(e.Env, nil, msg.Value) | ||||
| 	case []any: | ||||
| 		l := len(xt) | ||||
| 		v, st = napi.CreateArrayWithLength(e.Env, l) | ||||
| 		if st != napi.StatusOK { | ||||
| 			break | ||||
| 		} | ||||
|  | ||||
| 		for i, xti := range xt { | ||||
| 			// TODO: Use Value.SetIndex helper | ||||
| 			vti := e.ValueOf(xti) | ||||
| 			st = napi.SetElement(e.Env, v, i, vti.Value) | ||||
| 			if st != napi.StatusOK { | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 	case map[string]any: | ||||
| 		v, st = napi.CreateObject(e.Env) | ||||
| 		if st != napi.StatusOK { | ||||
| 			break | ||||
| 		} | ||||
|  | ||||
| 		for xtk, xtv := range xt { | ||||
| 			// TODO: Use Value.Set helper | ||||
| 			vtk, vtv := e.ValueOf(xtk), e.ValueOf(xtv) | ||||
| 			st = napi.SetProperty(e.Env, v, vtk.Value, vtv.Value) | ||||
| 			if st != napi.StatusOK { | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 	default: | ||||
| 		panic(InvalidValueTypeError{x}) | ||||
| 	} | ||||
|  | ||||
| 	if st != napi.StatusOK { | ||||
| 		panic(napi.StatusError(st)) | ||||
| 	} | ||||
|  | ||||
| 	return Value{ | ||||
| 		Env:   e, | ||||
| 		Value: v, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (e Env) FuncOf(fn Callback) Func { | ||||
| 	// TODO: Add CreateReference to FuncOf to keep value alive | ||||
| 	v, st := napi.CreateFunction( | ||||
| 		e.Env, | ||||
| 		"", | ||||
| 		AsCallback(fn), | ||||
| 	) | ||||
|  | ||||
| 	if st != napi.StatusOK { | ||||
| 		panic(napi.StatusError(st)) | ||||
| 	} | ||||
|  | ||||
| 	return Func{ | ||||
| 		Value: Value{ | ||||
| 			Env:   e, | ||||
| 			Value: v, | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (e Env) NewPromise() *Promise { | ||||
| 	var result Promise | ||||
| 	result.reset(e) | ||||
| 	return &result | ||||
| } | ||||
|  | ||||
| func (err InvalidValueTypeError) Error() string { | ||||
| 	return fmt.Sprintf("Value cannot be represented in JS: %T", err.Value) | ||||
| } | ||||
| @@ -1,5 +0,0 @@ | ||||
| package js | ||||
|  | ||||
| type Func struct { | ||||
| 	Value | ||||
| } | ||||
							
								
								
									
										21
									
								
								js/funcof.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								js/funcof.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| # Go functions conversion to Javascript functions | ||||
|  | ||||
| ## Simples conversions | ||||
|  | ||||
| | Go                                | Node                                        | | ||||
| | --------------------------------- | ------------------------------------------- | | ||||
| | `func()`                          | `function(): void`                          | | ||||
| | `func() value`                    | `function(): value`                         | | ||||
| | `func(value1, value2)`            | `function(value1, value2): void`            | | ||||
| | `func() (value1, value2)`         | `function(): [value1, value2]`              | | ||||
| | `func(value1, value2, values...)` | `function(value1, value2, ...values): void` | | ||||
| | `func(values...)`                 | `function(...values): void`                 | | ||||
|  | ||||
| ## Error throw | ||||
|  | ||||
| | Go                                         | Node                                                | | ||||
| | ------------------------------------------ | --------------------------------------------------- | | ||||
| | `func() error`                             | `function(): throw Error`                           | | ||||
| | `func(value1, value2) error`               | `function(value1, value2): throw Error`             | | ||||
| | `func() (value, error)`                    | `function(): value \|\| throw Error`                | | ||||
| | `func(value1, value2) (...nValues, error)` | `function(value1, value2): (Array \|\|throw Error)` | | ||||
							
								
								
									
										575
									
								
								js/js.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										575
									
								
								js/js.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,575 @@ | ||||
| package js | ||||
|  | ||||
| import ( | ||||
| 	"encoding" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"reflect" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"sirherobrine23.com.br/Sirherobrine23/napi-go" | ||||
| ) | ||||
|  | ||||
| const propertiesTagName = "napi" | ||||
|  | ||||
| // Convert go types to valid NAPI, if not conpatible return Undefined. | ||||
| func ValueOf(env napi.EnvType, value any) (napiValue napi.ValueType, err error) { | ||||
| 	return valueOf(env, reflect.ValueOf(value)) | ||||
| } | ||||
|  | ||||
| // Convert NAPI value to Go values | ||||
| func ValueFrom(napiValue napi.ValueType, v any) error { | ||||
| 	ptr := reflect.ValueOf(v) | ||||
| 	if ptr.Kind() != reflect.Pointer { | ||||
| 		return fmt.Errorf("require point to convert napi value to go value") | ||||
| 	} | ||||
| 	return valueFrom(napiValue, ptr.Elem()) | ||||
| } | ||||
|  | ||||
| func valueOf(env napi.EnvType, ptr reflect.Value) (napiValue napi.ValueType, err error) { | ||||
| 	defer func(err *error) { | ||||
| 		if err2 := recover(); err2 != nil { | ||||
| 			switch v := err2.(type) { | ||||
| 			case error: | ||||
| 				*err = v | ||||
| 			default: | ||||
| 				*err = fmt.Errorf("panic recover: %s", err2) | ||||
| 			} | ||||
| 		} | ||||
| 	}(&err) | ||||
|  | ||||
| 	if !ptr.IsValid() || ptr.IsZero() { | ||||
| 		return env.Undefined() | ||||
| 	} | ||||
|  | ||||
| 	// Marshalers | ||||
| 	if ptr.CanInterface() { | ||||
| 		switch v := ptr.Interface().(type) { | ||||
| 		case napi.ValueType: | ||||
| 			return v, nil | ||||
| 		case time.Time: | ||||
| 			return napi.CreateDate(env, v) | ||||
| 		case encoding.TextMarshaler: | ||||
| 			data, err := v.MarshalText() | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 			return napi.CreateString(env, string(data)) | ||||
| 		case json.Marshaler: | ||||
| 			var pointData any | ||||
| 			data, err := v.MarshalJSON() | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} else if err = json.Unmarshal(data, &pointData); err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 			return ValueOf(env, pointData) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	ptrType := ptr.Type() | ||||
| 	switch ptrType.Kind() { | ||||
| 	case reflect.Pointer: | ||||
| 		return valueOf(env, ptr.Elem()) | ||||
| 	case reflect.String: | ||||
| 		return napi.CreateString(env, ptr.String()) | ||||
| 	case reflect.Bool: | ||||
| 		return napi.CreateBoolean(env, ptr.Bool()) | ||||
| 	case reflect.Int, reflect.Uint, reflect.Int32, reflect.Uint32, reflect.Float32, reflect.Int8, reflect.Uint8, reflect.Int16, reflect.Uint16: | ||||
| 		return napi.CreateNumber(env, ptr.Int()) | ||||
| 	case reflect.Float64: | ||||
| 		return napi.CreateNumber(env, ptr.Float()) | ||||
| 	case reflect.Int64, reflect.Uint64: | ||||
| 		return napi.CreateBigint(env, ptr.Int()) | ||||
| 	case reflect.Func: | ||||
| 		return funcOf(env, ptr) | ||||
| 	case reflect.Slice, reflect.Array: | ||||
| 		arr, err := napi.CreateArray(env, ptr.Len()) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		for index := range ptr.Len() { | ||||
| 			value, err := valueOf(env, ptr.Index(index)) | ||||
| 			if err != nil { | ||||
| 				return arr, err | ||||
| 			} else if err = arr.Set(index, value); err != nil { | ||||
| 				return arr, err | ||||
| 			} | ||||
| 		} | ||||
| 		return arr, nil | ||||
| 	case reflect.Struct: | ||||
| 		obj, err := napi.CreateObject(env) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		for keyIndex := range ptrType.NumField() { | ||||
| 			field, fieldType := ptr.Field(keyIndex), ptrType.Field(keyIndex) | ||||
| 			if !fieldType.IsExported() || fieldType.Tag.Get(propertiesTagName) == "-" { | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			value, err := valueOf(env, field) | ||||
| 			if err != nil { | ||||
| 				return obj, err | ||||
| 			} | ||||
|  | ||||
| 			typeof, err := value.Type() | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
|  | ||||
| 			keyNamed := fieldType.Name | ||||
| 			if strings.Count(fieldType.Tag.Get(propertiesTagName), ",") > 0 { | ||||
| 				fields := strings.SplitN(fieldType.Tag.Get(propertiesTagName), ",", 2) | ||||
| 				keyNamed = fields[0] | ||||
| 				switch fields[1] { | ||||
| 				case "omitempty": | ||||
| 					switch typeof { | ||||
| 					case napi.TypeUndefined, napi.TypeNull, napi.TypeUnkown: | ||||
| 						continue | ||||
| 					case napi.TypeString: | ||||
| 						str, err := napi.ToString(value).Utf8Value() | ||||
| 						if err != nil { | ||||
| 							return nil, err | ||||
| 						} else if str == "" { | ||||
| 							continue | ||||
| 						} | ||||
| 					} | ||||
| 				case "omitzero": | ||||
| 					switch typeof { | ||||
| 					case napi.TypeUndefined, napi.TypeNull, napi.TypeUnkown: | ||||
| 						continue | ||||
| 					case napi.TypeDate: | ||||
| 						value, err := napi.ToDate(value).Time() | ||||
| 						if err != nil { | ||||
| 							return nil, err | ||||
| 						} else if value.Unix() == 0 { | ||||
| 							continue | ||||
| 						} | ||||
| 					case napi.TypeBigInt: | ||||
| 						value, err := napi.ToBigint(value).Int64() | ||||
| 						if err != nil { | ||||
| 							return nil, err | ||||
| 						} else if value == 0 { | ||||
| 							continue | ||||
| 						} | ||||
| 					case napi.TypeNumber: | ||||
| 						value, err := napi.ToNumber(value).Int() | ||||
| 						if err != nil { | ||||
| 							return nil, err | ||||
| 						} else if value == 0 { | ||||
| 							continue | ||||
| 						} | ||||
| 					case napi.TypeArray: | ||||
| 						value, err := napi.ToArray(value).Length() | ||||
| 						if err != nil { | ||||
| 							return nil, err | ||||
| 						} else if value == 0 { | ||||
| 							continue | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			if err = obj.Set(keyNamed, value); err != nil { | ||||
| 				return obj, err | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return obj, nil | ||||
| 	case reflect.Map: | ||||
| 		obj, err := napi.CreateObject(env) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		for ptrKey, ptrValue := range ptr.Seq2() { | ||||
| 			key, err := valueOf(env, ptrKey) | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 			value, err := valueOf(env, ptrValue) | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} else if err = obj.SetWithValue(key, value); err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 		} | ||||
| 		return obj, nil | ||||
| 	case reflect.Interface: | ||||
| 		if ptr.IsValid() { | ||||
| 			if ptr.IsNil() { | ||||
| 				return env.Null() | ||||
| 			} else if ptr.CanInterface() { | ||||
| 				return valueOf(env, reflect.ValueOf(ptr.Interface())) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return env.Undefined() | ||||
| } | ||||
|  | ||||
| func valueFrom(napiValue napi.ValueType, ptr reflect.Value) error { | ||||
| 	typeOf, err := napiValue.Type() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	ptrType := ptr.Type() | ||||
| 	switch ptrType.Kind() { | ||||
| 	case reflect.Pointer: | ||||
| 		return valueFrom(napiValue, ptr.Elem()) | ||||
| 	case reflect.Interface: | ||||
| 		// Check if is any and can set | ||||
| 		if ptr.CanSet() && ptrType == reflect.TypeFor[any]() { | ||||
| 			switch typeOf { | ||||
| 			case napi.TypeNull, napi.TypeUndefined, napi.TypeUnkown: | ||||
| 				ptr.Set(reflect.Zero(ptrType)) | ||||
| 				return nil | ||||
| 			case napi.TypeBoolean: | ||||
| 				valueOf, err := napi.ToBoolean(napiValue).Value() | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				ptr.Set(reflect.ValueOf(valueOf)) | ||||
| 			case napi.TypeNumber: | ||||
| 				numberValue, err := napi.ToNumber(napiValue).Float() | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				ptr.Set(reflect.ValueOf(numberValue)) | ||||
| 			case napi.TypeBigInt: | ||||
| 				numberValue, err := napi.ToBigint(napiValue).Int64() | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				ptr.Set(reflect.ValueOf(numberValue)) | ||||
| 			case napi.TypeString: | ||||
| 				str, err := napi.ToString(napiValue).Utf8Value() | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				ptr.Set(reflect.ValueOf(str)) | ||||
| 			case napi.TypeDate: | ||||
| 				timeDate, err := napi.ToDate(napiValue).Time() | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				ptr.Set(reflect.ValueOf(timeDate)) | ||||
| 			case napi.TypeArray: | ||||
| 				napiArray := napi.ToArray(napiValue) | ||||
| 				size, err := napiArray.Length() | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				value := reflect.MakeSlice(reflect.SliceOf(ptrType), size, size) | ||||
| 				for index := range size { | ||||
| 					napiValue, err := napiArray.Get(index) | ||||
| 					if err != nil { | ||||
| 						return err | ||||
| 					} else if err = valueFrom(napiValue, value.Index(index)); err != nil { | ||||
| 						return err | ||||
| 					} | ||||
| 				} | ||||
| 				ptr.Set(value) | ||||
| 			case napi.TypeBuffer: | ||||
| 				buff, err := napi.ToBuffer(napiValue).Data() | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				ptr.Set(reflect.ValueOf(buff)) | ||||
| 			case napi.TypeObject: | ||||
| 				obj := napi.ToObject(napiValue) | ||||
| 				goMap := reflect.MakeMap(reflect.MapOf(reflect.TypeFor[string](), reflect.TypeFor[any]())) | ||||
| 				for keyName, value := range obj.Seq() { | ||||
| 					valueOf := reflect.New(reflect.TypeFor[any]()) | ||||
| 					if err := valueFrom(value, valueOf); err != nil { | ||||
| 						return err | ||||
| 					} | ||||
| 					goMap.SetMapIndex(reflect.ValueOf(keyName), valueOf) | ||||
| 				} | ||||
| 				ptr.Set(goMap) | ||||
| 			case napi.TypeFunction: | ||||
| 				ptr.Set(reflect.ValueOf(napi.ToFunction(napiValue))) | ||||
| 			} | ||||
| 			return nil | ||||
| 		} | ||||
| 		return fmt.Errorf("cannot set value, returned %s", typeOf) | ||||
| 	} | ||||
|  | ||||
| 	switch typeOf { | ||||
| 	case napi.TypeNull, napi.TypeUndefined, napi.TypeUnkown: | ||||
| 		switch ptrType.Kind() { | ||||
| 		case reflect.Interface, reflect.Pointer: | ||||
| 			ptr.Set(reflect.Zero(ptrType)) | ||||
| 			return nil | ||||
| 		default: | ||||
| 			return fmt.Errorf("cannot set value, returned %s", typeOf) | ||||
| 		} | ||||
| 	case napi.TypeBoolean: | ||||
| 		switch ptr.Kind() { | ||||
| 		case reflect.Bool: | ||||
| 			valueOf, err := napi.ToBoolean(napiValue).Value() | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			ptr.SetBool(valueOf) | ||||
| 		default: | ||||
| 			return fmt.Errorf("cannot set boolean value to %s", ptr.Kind()) | ||||
| 		} | ||||
| 	case napi.TypeNumber: | ||||
| 		switch ptrType.Kind() { | ||||
| 		case reflect.Float32, reflect.Float64: | ||||
| 			floatValue, err := napi.ToNumber(napiValue).Float() | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			ptr.SetFloat(floatValue) | ||||
| 			return nil | ||||
| 		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||||
| 			numberValue, err := napi.ToNumber(napiValue).Int() | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			ptr.SetInt(numberValue) | ||||
| 			return nil | ||||
| 		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | ||||
| 			numberValue, err := napi.ToNumber(napiValue).Int() | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			ptr.SetUint(uint64(numberValue)) | ||||
| 			return nil | ||||
| 		default: | ||||
| 			return fmt.Errorf("cannot set number value to %s", ptr.Kind()) | ||||
| 		} | ||||
| 	case napi.TypeBigInt: | ||||
| 		switch ptrType.Kind() { | ||||
| 		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||||
| 			numberValue, err := napi.ToNumber(napiValue).Int() | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			ptr.SetInt(numberValue) | ||||
| 			return nil | ||||
| 		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | ||||
| 			numberValue, err := napi.ToNumber(napiValue).Int() | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			ptr.SetUint(uint64(numberValue)) | ||||
| 			return nil | ||||
| 		default: | ||||
| 			return fmt.Errorf("cannot set number value to %s", ptr.Kind()) | ||||
| 		} | ||||
| 	case napi.TypeString: | ||||
| 		switch ptr.Kind() { | ||||
| 		case reflect.String: | ||||
| 		default: | ||||
| 			return fmt.Errorf("cannot set string to %s", ptr.Kind()) | ||||
| 		} | ||||
| 		str, err := napi.ToString(napiValue).Utf8Value() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		ptr.Set(reflect.ValueOf(str)) | ||||
| 		return nil | ||||
| 	case napi.TypeDate: | ||||
| 		switch ptrType.Kind() { | ||||
| 		case reflect.Struct: | ||||
| 			if ptrType == reflect.TypeFor[time.Time]() { | ||||
| 				break | ||||
| 			} | ||||
| 			fallthrough | ||||
| 		default: | ||||
| 			return fmt.Errorf("cannot set Date to %s", ptr.Kind()) | ||||
| 		} | ||||
| 		timeDate, err := napi.ToDate(napiValue).Time() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		ptr.Set(reflect.ValueOf(timeDate)) | ||||
| 		return nil | ||||
| 	case napi.TypeArray: | ||||
| 		napiArray := napi.ToArray(napiValue) | ||||
| 		size, err := napiArray.Length() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		switch ptr.Kind() { | ||||
| 		case reflect.Slice: | ||||
| 			value := reflect.MakeSlice(ptrType, size, size) | ||||
| 			for index := range size { | ||||
| 				napiValue, err := napiArray.Get(index) | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} else if err = valueFrom(napiValue, value.Index(index)); err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 			} | ||||
| 			ptr.Set(value) | ||||
| 			return nil | ||||
| 		case reflect.Array: | ||||
| 			value := reflect.New(ptrType) | ||||
| 			for index := range min(size, value.Len()) { | ||||
| 				napiValue, err := napiArray.Get(index) | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} else if err = valueFrom(napiValue, value.Index(index)); err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 			} | ||||
| 			ptr.Set(value) | ||||
| 			return nil | ||||
| 		default: | ||||
| 			return fmt.Errorf("cannot set Array to %s", ptr.Kind()) | ||||
| 		} | ||||
| 	case napi.TypeBuffer: | ||||
| 		switch ptr.Kind() { | ||||
| 		case reflect.Slice: | ||||
| 			if ptrType == reflect.TypeFor[[]byte]() { | ||||
| 				break | ||||
| 			} | ||||
| 			fallthrough | ||||
| 		default: | ||||
| 			return fmt.Errorf("cannot set Buffer to %s", ptr.Kind()) | ||||
| 		} | ||||
| 		buff, err := napi.ToBuffer(napiValue).Data() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		ptr.SetBytes(buff) | ||||
| 		return nil | ||||
| 	case napi.TypeObject: | ||||
| 		obj := napi.ToObject(napiValue) | ||||
| 		switch ptr.Kind() { | ||||
| 		case reflect.Struct: | ||||
| 			ptr.Set(reflect.New(ptrType).Elem()) | ||||
| 			for keyIndex := range ptrType.NumField() { | ||||
| 				field, fieldType := ptr.Field(keyIndex), ptrType.Field(keyIndex) | ||||
| 				if !fieldType.IsExported() || fieldType.Tag.Get(propertiesTagName) == "-" { | ||||
| 					continue | ||||
| 				} | ||||
|  | ||||
| 				keyName, omitEmpty, omitZero := fieldType.Name, false, false | ||||
| 				if strings.Count(fieldType.Tag.Get(propertiesTagName), ",") > 0 { | ||||
| 					fields := strings.SplitN(fieldType.Tag.Get(propertiesTagName), ",", 2) | ||||
| 					keyName = fields[0] | ||||
| 					switch fields[1] { | ||||
| 					case "omitempty": | ||||
| 						omitEmpty = true | ||||
| 					case "omitzero": | ||||
| 						omitZero = true | ||||
| 					} | ||||
| 				} else { | ||||
| 					omitEmpty, omitZero = true, true | ||||
| 				} | ||||
|  | ||||
| 				if ok, err := obj.Has(keyName); err != nil { | ||||
| 					return err | ||||
| 				} else if !ok && !(omitEmpty || omitZero) { | ||||
| 					return fmt.Errorf("cannot set %s to %s", keyName, ptr.Kind()) | ||||
| 				} | ||||
|  | ||||
| 				value, err := obj.Get(keyName) | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
|  | ||||
| 				valueTypeof, _ := value.Type() | ||||
| 				if omitEmpty || omitZero { | ||||
| 					switch valueTypeof { | ||||
| 					case napi.TypeUndefined, napi.TypeNull, napi.TypeUnkown: | ||||
| 						continue | ||||
| 					case napi.TypeString: | ||||
| 						if str, _ := napi.ToString(value).Utf8Value(); str == "" { | ||||
| 							continue | ||||
| 						} | ||||
| 					case napi.TypeDate: | ||||
| 						if timeDate, _ := napi.ToDate(value).Time(); timeDate.Unix() == 0 { | ||||
| 							continue | ||||
| 						} | ||||
| 					case napi.TypeBigInt: | ||||
| 						if numberValue, _ := napi.ToBigint(value).Int64(); numberValue == 0 { | ||||
| 							continue | ||||
| 						} | ||||
| 					case napi.TypeNumber: | ||||
| 						if numberValue, _ := napi.ToNumber(value).Int(); numberValue == 0 { | ||||
| 							continue | ||||
| 						} | ||||
| 					case napi.TypeArray: | ||||
| 						if size, _ := napi.ToArray(value).Length(); size == 0 { | ||||
| 							continue | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
|  | ||||
| 				valueOf := reflect.New(fieldType.Type).Elem() | ||||
| 				if err := valueFrom(value, valueOf); err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				field.Set(valueOf) | ||||
| 			} | ||||
| 			return nil | ||||
| 		case reflect.Map: | ||||
| 			// Check if key is string, bool, int*, uint*, float*, else return error | ||||
| 			switch ptrType.Key().Kind() { | ||||
| 			case reflect.String: | ||||
| 			case reflect.Bool: | ||||
| 			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||||
| 			case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | ||||
| 			case reflect.Float32, reflect.Float64: | ||||
| 			default: | ||||
| 				return fmt.Errorf("cannot set Object to %s", ptr.Kind()) | ||||
| 			} | ||||
|  | ||||
| 			goMap := reflect.MakeMap(ptrType) | ||||
| 			for keyName, value := range obj.Seq() { | ||||
| 				keySetValue := reflect.New(ptrType.Key()).Elem() | ||||
| 				switch ptrType.Key().Kind() { | ||||
| 				case reflect.String: | ||||
| 					keySetValue.SetString(keyName) | ||||
| 				case reflect.Bool: | ||||
| 					boolV, err := strconv.ParseBool(keyName) | ||||
| 					if err != nil { | ||||
| 						return err | ||||
| 					} | ||||
| 					keySetValue.SetBool(boolV) | ||||
| 				case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||||
| 					intV, err := strconv.ParseInt(keyName, 10, 64) | ||||
| 					if err != nil { | ||||
| 						return err | ||||
| 					} | ||||
| 					keySetValue.SetInt(intV) | ||||
| 				case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | ||||
| 					intV, err := strconv.ParseUint(keyName, 10, 64) | ||||
| 					if err != nil { | ||||
| 						return err | ||||
| 					} | ||||
| 					keySetValue.SetUint(intV) | ||||
| 				case reflect.Float32, reflect.Float64: | ||||
| 					floatV, err := strconv.ParseFloat(keyName, 64) | ||||
| 					if err != nil { | ||||
| 						return err | ||||
| 					} | ||||
| 					keySetValue.SetFloat(floatV) | ||||
| 				} | ||||
|  | ||||
| 				valueOf := reflect.New(ptrType.Elem()).Elem() | ||||
| 				if err := valueFrom(value, valueOf); err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				goMap.SetMapIndex(keySetValue, valueOf) | ||||
| 			} | ||||
| 			ptr.Set(goMap) | ||||
| 			return nil | ||||
| 		default: | ||||
| 			return fmt.Errorf("cannot set Object to %s", ptr.Kind()) | ||||
| 		} | ||||
| 	default: | ||||
| 		println(typeOf.String()) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										123
									
								
								js/js_func.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								js/js_func.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,123 @@ | ||||
| package js | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"reflect" | ||||
| 	"runtime" | ||||
|  | ||||
| 	"sirherobrine23.com.br/Sirherobrine23/napi-go" | ||||
| 	internalNapi "sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi" | ||||
| ) | ||||
|  | ||||
| // Create napi bind to golang functions | ||||
| func GoFuncOf(env napi.EnvType, function any) (napi.ValueType, error) { | ||||
| 	return funcOf(env, reflect.ValueOf(function)) | ||||
| } | ||||
|  | ||||
| func funcOf(env napi.EnvType, ptr reflect.Value) (napi.ValueType, error) { | ||||
| 	if ptr.Kind() != reflect.Func { | ||||
| 		return nil, fmt.Errorf("return function to return napi value") | ||||
| 	} | ||||
|  | ||||
| 	funcName := runtime.FuncForPC(ptr.Pointer()).Name() | ||||
| 	switch v := ptr.Interface().(type) { | ||||
| 	case nil: | ||||
| 		return nil, nil | ||||
| 	case napi.Callback: | ||||
| 		return napi.CreateFunction(env, funcName, v) | ||||
| 	case internalNapi.Callback: | ||||
| 		return napi.CreateFunctionNapi(env, funcName, v) | ||||
| 	default: | ||||
| 		return napi.CreateFunction(env, funcName, func(env napi.EnvType, this napi.ValueType, args []napi.ValueType) (napi.ValueType, error) { | ||||
| 			fnType := ptr.Type() | ||||
| 			returnValues := []reflect.Value{} | ||||
| 			switch { | ||||
| 			case fnType.NumIn() == 0 && fnType.NumOut() == 0: | ||||
| 				returnValues = ptr.Call([]reflect.Value{}) | ||||
| 			case !fnType.IsVariadic(): | ||||
| 				returnValues = ptr.Call(goValuesInFunc(ptr, args, false)) | ||||
| 			default: | ||||
| 				returnValues = ptr.CallSlice(goValuesInFunc(ptr, args, true)) | ||||
| 			} | ||||
|  | ||||
| 			switch len(returnValues) { | ||||
| 			case 0: | ||||
| 				return nil, nil | ||||
| 			case 1: | ||||
| 				return valueOf(env, returnValues[0]) | ||||
| 			default: | ||||
| 				lastValue := returnValues[len(returnValues)-1] | ||||
| 				if lastValue.CanConvert(reflect.TypeFor[error]()) { | ||||
| 					returnValues = returnValues[:len(returnValues)-1] | ||||
| 					if !lastValue.IsNil() { | ||||
| 						if err := lastValue.Interface().(error); err != nil { | ||||
| 							return nil, err | ||||
| 						} | ||||
| 					} | ||||
|  | ||||
| 				} | ||||
|  | ||||
| 				switch len(returnValues) { | ||||
| 				case 1: | ||||
| 					// Return value from return | ||||
| 					return valueOf(env, returnValues[0]) | ||||
| 				default: | ||||
| 					// Create array | ||||
| 					arr, err := napi.CreateArray(env, len(returnValues)) | ||||
| 					if err != nil { | ||||
| 						return nil, err | ||||
| 					} | ||||
|  | ||||
| 					// Append values to js array | ||||
| 					for index, value := range returnValues { | ||||
| 						napiValue, err := valueOf(env, value) | ||||
| 						if err != nil { | ||||
| 							return nil, err | ||||
| 						} else if err = arr.Set(index, napiValue); err != nil { | ||||
| 							return nil, err | ||||
| 						} | ||||
| 					} | ||||
|  | ||||
| 					return arr, nil | ||||
| 				} | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func goValuesInFunc(ptr reflect.Value, jsArgs []napi.ValueType, variadic bool) (values []reflect.Value) { | ||||
| 	if variadic && (ptr.Type().NumIn()-1 > 0) && ptr.Type().NumIn()-1 < len(jsArgs) { | ||||
| 		panic(fmt.Errorf("require minimun %d arguments, called with %d", ptr.Type().NumIn()-1, len(jsArgs))) | ||||
| 	} else if !variadic &&ptr.Type().NumIn() != len(jsArgs) { | ||||
| 		panic(fmt.Errorf("require %d arguments, called with %d", ptr.Type().NumIn(), len(jsArgs))) | ||||
| 	} | ||||
|  | ||||
| 	size := ptr.Type().NumIn() | ||||
| 	if variadic { | ||||
| 		size-- | ||||
| 	} | ||||
|  | ||||
| 	values = make([]reflect.Value, size) | ||||
| 	for index := range values { | ||||
| 		valueOf := reflect.New(ptr.Type().In(index)) | ||||
| 		if err := valueFrom(jsArgs[index], valueOf); err != nil { | ||||
| 			panic(err) | ||||
| 		} | ||||
| 		values[index] = valueOf | ||||
| 	} | ||||
|  | ||||
| 	if variadic { | ||||
| 		variadicType := ptr.Type().In(size).Elem() | ||||
| 		 | ||||
| 		valueAppend := jsArgs[size:] | ||||
| 		valueOf := reflect.MakeSlice(reflect.SliceOf(variadicType), len(valueAppend), len(valueAppend)) | ||||
| 		for index := range valueAppend { | ||||
| 			if err := valueFrom(valueAppend[index], valueOf.Index(index)); err != nil { | ||||
| 				panic(err) | ||||
| 			} | ||||
| 		} | ||||
| 		values = append(values, valueOf) | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										118
									
								
								js/promise.go
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								js/promise.go
									
									
									
									
									
								
							| @@ -1,118 +0,0 @@ | ||||
| package js | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
|  | ||||
| 	"github.com/akshayganeshen/napi-go" | ||||
| ) | ||||
|  | ||||
| type Promise struct { | ||||
| 	Promise            napi.Promise | ||||
| 	ThreadsafeFunction napi.ThreadsafeFunction | ||||
| 	Result             any | ||||
| 	ResultType         PromiseResultType | ||||
| } | ||||
|  | ||||
| type PromiseResultType string | ||||
|  | ||||
| type PromiseProvider interface { | ||||
| 	Resolve(resolution any) | ||||
| 	Reject(rejection any) | ||||
| } | ||||
|  | ||||
| var _ PromiseProvider = &Promise{} | ||||
|  | ||||
| const ( | ||||
| 	PromiseResultTypeResolved PromiseResultType = "resolved" | ||||
| 	PromiseResultTypeRejected PromiseResultType = "rejected" | ||||
| ) | ||||
|  | ||||
| var ErrPromiseSettled = errors.New( | ||||
| 	"Promise: Cannot resolve/reject a settled promise", | ||||
| ) | ||||
|  | ||||
| func (p *Promise) Resolve(resolution any) { | ||||
| 	p.ensurePending() | ||||
|  | ||||
| 	p.Result = resolution | ||||
| 	p.ResultType = PromiseResultTypeResolved | ||||
|  | ||||
| 	// function has already been acquired during reset | ||||
| 	defer p.release() | ||||
| 	p.settle() | ||||
| } | ||||
|  | ||||
| func (p *Promise) Reject(rejection any) { | ||||
| 	p.ensurePending() | ||||
|  | ||||
| 	p.Result = rejection | ||||
| 	p.ResultType = PromiseResultTypeRejected | ||||
|  | ||||
| 	// function has already been acquired during reset | ||||
| 	defer p.release() | ||||
| 	p.settle() | ||||
| } | ||||
|  | ||||
| func (p *Promise) reset(e Env) { | ||||
| 	np, st := napi.CreatePromise(e.Env) | ||||
| 	if st != napi.StatusOK { | ||||
| 		panic(napi.StatusError(st)) | ||||
| 	} | ||||
|  | ||||
| 	asyncResourceName := e.ValueOf("napi-go/js-promise") | ||||
| 	fn := e.FuncOf(func(env Env, this Value, args []Value) any { | ||||
| 		value := env.ValueOf(p.Result) | ||||
|  | ||||
| 		st := napi.StatusOK | ||||
| 		switch p.ResultType { | ||||
| 		case PromiseResultTypeResolved: | ||||
| 			st = napi.ResolveDeferred(env.Env, p.Promise.Deferred, value.Value) | ||||
| 		case PromiseResultTypeRejected: | ||||
| 			st = napi.RejectDeferred(env.Env, p.Promise.Deferred, value.Value) | ||||
| 		} | ||||
|  | ||||
| 		if st != napi.StatusOK { | ||||
| 			panic(napi.StatusError(st)) | ||||
| 		} | ||||
|  | ||||
| 		return nil | ||||
| 	}) | ||||
|  | ||||
| 	tsFn, st := napi.CreateThreadsafeFunction( | ||||
| 		e.Env, | ||||
| 		fn.Value.Value, | ||||
| 		nil, asyncResourceName.Value, | ||||
| 		0, | ||||
| 		1, // initialize with 1 acquisition | ||||
| 	) | ||||
| 	if st != napi.StatusOK { | ||||
| 		panic(napi.StatusError(st)) | ||||
| 	} | ||||
|  | ||||
| 	*p = Promise{ | ||||
| 		Promise:            np, | ||||
| 		ThreadsafeFunction: tsFn, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (p *Promise) ensurePending() { | ||||
| 	if p.ResultType != "" { | ||||
| 		panic(ErrPromiseSettled) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (p *Promise) settle() { | ||||
| 	st := napi.CallThreadsafeFunction(p.ThreadsafeFunction) | ||||
| 	if st != napi.StatusOK { | ||||
| 		panic(napi.StatusError(st)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (p *Promise) release() { | ||||
| 	st := napi.ReleaseThreadsafeFunction(p.ThreadsafeFunction) | ||||
| 	if st == napi.StatusClosing { | ||||
| 		p.ThreadsafeFunction = nil | ||||
| 	} else if st != napi.StatusOK { | ||||
| 		panic(napi.StatusError(st)) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										14
									
								
								js/value.go
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								js/value.go
									
									
									
									
									
								
							| @@ -1,14 +0,0 @@ | ||||
| package js | ||||
|  | ||||
| import ( | ||||
| 	"github.com/akshayganeshen/napi-go" | ||||
| ) | ||||
|  | ||||
| type Value struct { | ||||
| 	Env   Env | ||||
| 	Value napi.Value | ||||
| } | ||||
|  | ||||
| func (v Value) GetEnv() Env { | ||||
| 	return v.Env | ||||
| } | ||||
							
								
								
									
										341
									
								
								js_native_api.go
									
									
									
									
									
								
							
							
						
						
									
										341
									
								
								js_native_api.go
									
									
									
									
									
								
							| @@ -1,341 +0,0 @@ | ||||
| package napi | ||||
|  | ||||
| /* | ||||
| #include <stdlib.h> | ||||
| #include <node/node_api.h> | ||||
| */ | ||||
| import "C" | ||||
|  | ||||
| import ( | ||||
| 	"unsafe" | ||||
| ) | ||||
|  | ||||
| func GetUndefined(env Env) (Value, Status) { | ||||
| 	var result Value | ||||
| 	status := Status(C.napi_get_undefined( | ||||
| 		C.napi_env(env), | ||||
| 		(*C.napi_value)(unsafe.Pointer(&result)), | ||||
| 	)) | ||||
| 	return result, status | ||||
| } | ||||
|  | ||||
| func GetNull(env Env) (Value, Status) { | ||||
| 	var result Value | ||||
| 	status := Status(C.napi_get_null( | ||||
| 		C.napi_env(env), | ||||
| 		(*C.napi_value)(unsafe.Pointer(&result)), | ||||
| 	)) | ||||
| 	return result, status | ||||
| } | ||||
|  | ||||
| func GetGlobal(env Env) (Value, Status) { | ||||
| 	var result Value | ||||
| 	status := Status(C.napi_get_global( | ||||
| 		C.napi_env(env), | ||||
| 		(*C.napi_value)(unsafe.Pointer(&result)), | ||||
| 	)) | ||||
| 	return result, status | ||||
| } | ||||
|  | ||||
| func GetBoolean(env Env, value bool) (Value, Status) { | ||||
| 	var result Value | ||||
| 	status := Status(C.napi_get_boolean( | ||||
| 		C.napi_env(env), | ||||
| 		C.bool(value), | ||||
| 		(*C.napi_value)(unsafe.Pointer(&result)), | ||||
| 	)) | ||||
| 	return result, status | ||||
| } | ||||
|  | ||||
| func CreateObject(env Env) (Value, Status) { | ||||
| 	var result Value | ||||
| 	status := Status(C.napi_create_object( | ||||
| 		C.napi_env(env), | ||||
| 		(*C.napi_value)(unsafe.Pointer(&result)), | ||||
| 	)) | ||||
| 	return result, status | ||||
| } | ||||
|  | ||||
| func CreateArray(env Env) (Value, Status) { | ||||
| 	var result Value | ||||
| 	status := Status(C.napi_create_array( | ||||
| 		C.napi_env(env), | ||||
| 		(*C.napi_value)(unsafe.Pointer(&result)), | ||||
| 	)) | ||||
| 	return result, status | ||||
| } | ||||
|  | ||||
| func CreateArrayWithLength(env Env, length int) (Value, Status) { | ||||
| 	var result Value | ||||
| 	status := Status(C.napi_create_array_with_length( | ||||
| 		C.napi_env(env), | ||||
| 		C.size_t(length), | ||||
| 		(*C.napi_value)(unsafe.Pointer(&result)), | ||||
| 	)) | ||||
| 	return result, status | ||||
| } | ||||
|  | ||||
| func CreateDouble(env Env, value float64) (Value, Status) { | ||||
| 	var result Value | ||||
| 	status := Status(C.napi_create_double( | ||||
| 		C.napi_env(env), | ||||
| 		C.double(value), | ||||
| 		(*C.napi_value)(unsafe.Pointer(&result)), | ||||
| 	)) | ||||
| 	return result, status | ||||
| } | ||||
|  | ||||
| func CreateStringUtf8(env Env, str string) (Value, Status) { | ||||
| 	cstr := C.CString(str) | ||||
| 	defer C.free(unsafe.Pointer(cstr)) | ||||
|  | ||||
| 	var result Value | ||||
| 	status := Status(C.napi_create_string_utf8( | ||||
| 		C.napi_env(env), | ||||
| 		cstr, | ||||
| 		C.size_t(len([]byte(str))), // must pass number of bytes | ||||
| 		(*C.napi_value)(unsafe.Pointer(&result)), | ||||
| 	)) | ||||
| 	return result, status | ||||
| } | ||||
|  | ||||
| func CreateSymbol(env Env, description Value) (Value, Status) { | ||||
| 	var result Value | ||||
| 	status := Status(C.napi_create_symbol( | ||||
| 		C.napi_env(env), | ||||
| 		C.napi_value(description), | ||||
| 		(*C.napi_value)(unsafe.Pointer(&result)), | ||||
| 	)) | ||||
| 	return result, status | ||||
| } | ||||
|  | ||||
| func CreateFunction(env Env, name string, cb Callback) (Value, Status) { | ||||
| 	provider, status := getInstanceData(env) | ||||
| 	if status != StatusOK || provider == nil { | ||||
| 		return nil, status | ||||
| 	} | ||||
|  | ||||
| 	return provider.GetCallbackData().CreateCallback(env, name, cb) | ||||
| } | ||||
|  | ||||
| func CreateError(env Env, code, msg Value) (Value, Status) { | ||||
| 	var result Value | ||||
| 	status := Status(C.napi_create_error( | ||||
| 		C.napi_env(env), | ||||
| 		C.napi_value(code), | ||||
| 		C.napi_value(msg), | ||||
| 		(*C.napi_value)(unsafe.Pointer(&result)), | ||||
| 	)) | ||||
| 	return result, status | ||||
| } | ||||
|  | ||||
| func Typeof(env Env, value Value) (ValueType, Status) { | ||||
| 	var result ValueType | ||||
| 	status := Status(C.napi_typeof( | ||||
| 		C.napi_env(env), | ||||
| 		C.napi_value(value), | ||||
| 		(*C.napi_valuetype)(unsafe.Pointer(&result)), | ||||
| 	)) | ||||
| 	return result, status | ||||
| } | ||||
|  | ||||
| func GetValueDouble(env Env, value Value) (float64, Status) { | ||||
| 	var result float64 | ||||
| 	status := Status(C.napi_get_value_double( | ||||
| 		C.napi_env(env), | ||||
| 		C.napi_value(value), | ||||
| 		(*C.double)(unsafe.Pointer(&result)), | ||||
| 	)) | ||||
| 	return result, status | ||||
| } | ||||
|  | ||||
| func GetValueBool(env Env, value Value) (bool, Status) { | ||||
| 	var result bool | ||||
| 	status := Status(C.napi_get_value_bool( | ||||
| 		C.napi_env(env), | ||||
| 		C.napi_value(value), | ||||
| 		(*C.bool)(unsafe.Pointer(&result)), | ||||
| 	)) | ||||
| 	return result, status | ||||
| } | ||||
|  | ||||
| func GetValueStringUtf8(env Env, value Value) (string, Status) { | ||||
| 	// call napi_get_value_string_utf8 twice | ||||
| 	// first is to get number of bytes | ||||
| 	// second is to populate the actual string buffer | ||||
| 	bufsize := C.size_t(0) | ||||
| 	var strsize C.size_t | ||||
|  | ||||
| 	status := Status(C.napi_get_value_string_utf8( | ||||
| 		C.napi_env(env), | ||||
| 		C.napi_value(value), | ||||
| 		nil, | ||||
| 		bufsize, | ||||
| 		&strsize, | ||||
| 	)) | ||||
|  | ||||
| 	if status != StatusOK { | ||||
| 		return "", status | ||||
| 	} | ||||
|  | ||||
| 	// ensure there is room for the null terminator as well | ||||
| 	strsize++ | ||||
| 	cstr := (*C.char)(C.malloc(C.sizeof_char * strsize)) | ||||
| 	defer C.free(unsafe.Pointer(cstr)) | ||||
|  | ||||
| 	status = Status(C.napi_get_value_string_utf8( | ||||
| 		C.napi_env(env), | ||||
| 		C.napi_value(value), | ||||
| 		cstr, | ||||
| 		strsize, | ||||
| 		&strsize, | ||||
| 	)) | ||||
|  | ||||
| 	if status != StatusOK { | ||||
| 		return "", status | ||||
| 	} | ||||
|  | ||||
| 	return C.GoStringN( | ||||
| 		(*C.char)(cstr), | ||||
| 		(C.int)(strsize), | ||||
| 	), status | ||||
| } | ||||
|  | ||||
| func SetProperty(env Env, object, key, value Value) Status { | ||||
| 	return Status(C.napi_set_property( | ||||
| 		C.napi_env(env), | ||||
| 		C.napi_value(object), | ||||
| 		C.napi_value(key), | ||||
| 		C.napi_value(value), | ||||
| 	)) | ||||
| } | ||||
|  | ||||
| func SetElement(env Env, object Value, index int, value Value) Status { | ||||
| 	return Status(C.napi_set_element( | ||||
| 		C.napi_env(env), | ||||
| 		C.napi_value(object), | ||||
| 		C.uint32_t(index), | ||||
| 		C.napi_value(value), | ||||
| 	)) | ||||
| } | ||||
|  | ||||
| func StrictEquals(env Env, lhs, rhs Value) (bool, Status) { | ||||
| 	var result bool | ||||
| 	status := Status(C.napi_strict_equals( | ||||
| 		C.napi_env(env), | ||||
| 		C.napi_value(lhs), | ||||
| 		C.napi_value(rhs), | ||||
| 		(*C.bool)(&result), | ||||
| 	)) | ||||
| 	return result, status | ||||
| } | ||||
|  | ||||
| type GetCbInfoResult struct { | ||||
| 	Args []Value | ||||
| 	This Value | ||||
| } | ||||
|  | ||||
| func GetCbInfo(env Env, info CallbackInfo) (GetCbInfoResult, Status) { | ||||
| 	// call napi_get_cb_info twice | ||||
| 	// first is to get total number of arguments | ||||
| 	// second is to populate the actual arguments | ||||
| 	argc := C.size_t(0) | ||||
| 	status := Status(C.napi_get_cb_info( | ||||
| 		C.napi_env(env), | ||||
| 		C.napi_callback_info(info), | ||||
| 		&argc, | ||||
| 		nil, | ||||
| 		nil, | ||||
| 		nil, | ||||
| 	)) | ||||
|  | ||||
| 	if status != StatusOK { | ||||
| 		return GetCbInfoResult{}, status | ||||
| 	} | ||||
|  | ||||
| 	argv := make([]Value, int(argc)) | ||||
| 	var cArgv unsafe.Pointer | ||||
| 	if argc > 0 { | ||||
| 		cArgv = unsafe.Pointer(&argv[0]) // must pass element pointer | ||||
| 	} | ||||
|  | ||||
| 	var thisArg Value | ||||
|  | ||||
| 	status = Status(C.napi_get_cb_info( | ||||
| 		C.napi_env(env), | ||||
| 		C.napi_callback_info(info), | ||||
| 		&argc, | ||||
| 		(*C.napi_value)(cArgv), | ||||
| 		(*C.napi_value)(unsafe.Pointer(&thisArg)), | ||||
| 		nil, | ||||
| 	)) | ||||
|  | ||||
| 	return GetCbInfoResult{ | ||||
| 		Args: argv, | ||||
| 		This: thisArg, | ||||
| 	}, status | ||||
| } | ||||
|  | ||||
| func Throw(env Env, err Value) Status { | ||||
| 	return Status(C.napi_throw( | ||||
| 		C.napi_env(env), | ||||
| 		C.napi_value(err), | ||||
| 	)) | ||||
| } | ||||
|  | ||||
| func ThrowError(env Env, code, msg string) Status { | ||||
| 	codeCStr, msgCCstr := C.CString(code), C.CString(msg) | ||||
| 	defer C.free(unsafe.Pointer(codeCStr)) | ||||
| 	defer C.free(unsafe.Pointer(msgCCstr)) | ||||
|  | ||||
| 	return Status(C.napi_throw_error( | ||||
| 		C.napi_env(env), | ||||
| 		codeCStr, | ||||
| 		msgCCstr, | ||||
| 	)) | ||||
| } | ||||
|  | ||||
| func CreatePromise(env Env) (Promise, Status) { | ||||
| 	var result Promise | ||||
| 	status := Status(C.napi_create_promise( | ||||
| 		C.napi_env(env), | ||||
| 		(*C.napi_deferred)(unsafe.Pointer(&result.Deferred)), | ||||
| 		(*C.napi_value)(unsafe.Pointer(&result.Value)), | ||||
| 	)) | ||||
| 	return result, status | ||||
| } | ||||
|  | ||||
| func ResolveDeferred(env Env, deferred Deferred, resolution Value) Status { | ||||
| 	return Status(C.napi_resolve_deferred( | ||||
| 		C.napi_env(env), | ||||
| 		C.napi_deferred(deferred), | ||||
| 		C.napi_value(resolution), | ||||
| 	)) | ||||
| } | ||||
|  | ||||
| func RejectDeferred(env Env, deferred Deferred, rejection Value) Status { | ||||
| 	return Status(C.napi_reject_deferred( | ||||
| 		C.napi_env(env), | ||||
| 		C.napi_deferred(deferred), | ||||
| 		C.napi_value(rejection), | ||||
| 	)) | ||||
| } | ||||
|  | ||||
| func SetInstanceData(env Env, data any) Status { | ||||
| 	provider, status := getInstanceData(env) | ||||
| 	if status != StatusOK || provider == nil { | ||||
| 		return status | ||||
| 	} | ||||
|  | ||||
| 	provider.SetUserData(data) | ||||
| 	return status | ||||
| } | ||||
|  | ||||
| func GetInstanceData(env Env) (any, Status) { | ||||
| 	provider, status := getInstanceData(env) | ||||
| 	if status != StatusOK || provider == nil { | ||||
| 		return nil, status | ||||
| 	} | ||||
|  | ||||
| 	return provider.GetUserData(), status | ||||
| } | ||||
							
								
								
									
										40
									
								
								makefile
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								makefile
									
									
									
									
									
								
							| @@ -1,40 +0,0 @@ | ||||
| all: doc | ||||
| clean: clean-doc | ||||
|  | ||||
| EXAMPLE_DIR = docs/examples | ||||
| EXAMPLE_PACKAGES = \ | ||||
| 	async-promise \ | ||||
| 	callback \ | ||||
| 	describe-args \ | ||||
| 	hello-world \ | ||||
| 	js | ||||
|  | ||||
| NAPI_LIB_SUFFIX = .node | ||||
|  | ||||
| TARGET_BUILDDIR = build | ||||
|  | ||||
| EXAMPLE_BINDINGS = $(addsuffix $(NAPI_LIB_SUFFIX),$(EXAMPLE_PACKAGES)) | ||||
| TARGET_EXAMPLES = \ | ||||
|   $(addprefix $(TARGET_BUILDDIR)/, $(EXAMPLE_BINDINGS)) | ||||
|  | ||||
| # TODO: Configure CGO_LDFLAGS_ALLOW for non-darwin systems. | ||||
| CGO_LDFLAGS_ALLOW = (-Wl,(-undefined,dynamic_lookup|-no_pie|-search_paths_first)) | ||||
|  | ||||
| doc: $(TARGET_EXAMPLES) | ||||
|  | ||||
| $(TARGET_EXAMPLES): | $(TARGET_BUILDDIR) | ||||
| $(TARGET_EXAMPLES): $(TARGET_BUILDDIR)/%$(NAPI_LIB_SUFFIX): $(EXAMPLE_DIR)/% | ||||
| 	CGO_LDFLAGS_ALLOW='$(CGO_LDFLAGS_ALLOW)' \ | ||||
| 	  go build -buildmode=c-shared -o "$(@)" "./$(<)/" | ||||
|  | ||||
| $(TARGET_BUILDDIR): | ||||
| 	mkdir -p "$(TARGET_BUILDDIR)" | ||||
|  | ||||
| clean: | ||||
| 	rmdir "$(TARGET_BUILDDIR)" | ||||
|  | ||||
| clean-doc: | ||||
| 	rm -f $(patsubst %,"%",$(TARGET_EXAMPLES)) | ||||
|  | ||||
| .PHONY: all doc | ||||
| .PHONY: clean clean-doc | ||||
							
								
								
									
										50
									
								
								napi_env.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								napi_env.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| package napi | ||||
|  | ||||
| import "sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi" | ||||
|  | ||||
| type EnvType interface { | ||||
| 	NapiValue() napi.Env // Primitive value to NAPI call | ||||
| 	Global() (*Object, error) | ||||
| 	Undefined() (ValueType, error) | ||||
| 	Null() (ValueType, error) | ||||
| } | ||||
|  | ||||
| // Return N-API env reference | ||||
| func N_APIEnv(env napi.Env) EnvType { return &Env{env} } | ||||
|  | ||||
| // N-API Env | ||||
| type Env struct{ | ||||
| 	NapiEnv napi.Env | ||||
| } | ||||
|  | ||||
| // Return [napi.Env] to point from internal napi cgo | ||||
| func (e *Env) NapiValue() napi.Env { | ||||
| 	return e.NapiEnv | ||||
| } | ||||
|  | ||||
| // Return representantion to 'This' [*Object] | ||||
| func (e *Env) Global() (*Object, error) { | ||||
| 	napiValue, err := mustValueErr(napi.GetGlobal(e.NapiEnv)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return ToObject(N_APIValue(e, napiValue)), nil | ||||
| } | ||||
|  | ||||
| // Return Undefined value | ||||
| func (e *Env) Undefined() (ValueType, error) { | ||||
| 	napiValue, err := mustValueErr(napi.GetUndefined(e.NapiEnv)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return N_APIValue(e, napiValue), nil | ||||
| } | ||||
|  | ||||
| // Return Null value | ||||
| func (e *Env) Null() (ValueType, error) { | ||||
| 	napiValue, err := mustValueErr(napi.GetNull(e.NapiEnv)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return N_APIValue(e, napiValue), nil | ||||
| } | ||||
							
								
								
									
										35
									
								
								napi_status.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								napi_status.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| package napi | ||||
|  | ||||
| import "sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi" | ||||
|  | ||||
| // Process status to return error if StatusOK return nil on error | ||||
| func mustValueErr[T any](input T, status napi.Status) (T, error) { | ||||
| 	if status != napi.StatusOK { | ||||
| 		return input, napi.StatusError(status) | ||||
| 	} | ||||
| 	return input, nil | ||||
| } | ||||
|  | ||||
| // return error from status | ||||
| func singleMustValueErr(status napi.Status) error { | ||||
| 	if status != napi.StatusOK { | ||||
| 		return napi.StatusError(status) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Process status to return error if StatusOK return nil on error | ||||
| func mustValueErr2[T any](input T, _ bool, status napi.Status) (T, error) { | ||||
| 	if status != napi.StatusOK { | ||||
| 		return input, napi.StatusError(status) | ||||
| 	} | ||||
| 	return input, nil | ||||
| } | ||||
|  | ||||
| // Process status to return error if StatusOK return nil on error | ||||
| func mustValueErr3[T, C any](input T, i2 C, status napi.Status) (T, C, error) { | ||||
| 	if status != napi.StatusOK { | ||||
| 		return input, i2, napi.StatusError(status) | ||||
| 	} | ||||
| 	return input, i2, nil | ||||
| } | ||||
							
								
								
									
										167
									
								
								napi_value.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										167
									
								
								napi_value.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,167 @@ | ||||
| package napi | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi" | ||||
| ) | ||||
|  | ||||
| type ValueType interface { | ||||
| 	NapiValue() napi.Value // Primitive value to NAPI call | ||||
| 	NapiEnv() napi.Env     // NAPI Env to NAPI call | ||||
|  | ||||
| 	Env() EnvType            // NAPI Env to NAPI call | ||||
| 	Type() (NapiType, error) // NAPI Type of value | ||||
| } | ||||
|  | ||||
| type ( | ||||
| 	value = ValueType // to dont expose to external structs | ||||
|  | ||||
| 	// Generic type to NAPI value | ||||
| 	Value struct { | ||||
| 		env     EnvType | ||||
| 		valueOf napi.Value | ||||
| 	} | ||||
|  | ||||
| 	NapiType int // Return typeof of Value | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	TypeUnkown NapiType = iota | ||||
| 	TypeUndefined | ||||
| 	TypeNull | ||||
| 	TypeBoolean | ||||
| 	TypeNumber | ||||
| 	TypeBigInt | ||||
| 	TypeString | ||||
| 	TypeSymbol | ||||
| 	TypeObject | ||||
| 	TypeFunction | ||||
| 	TypeExternal | ||||
| 	TypeTypedArray | ||||
| 	TypePromise | ||||
| 	TypeDataView | ||||
| 	TypeBuffer | ||||
| 	TypeDate | ||||
| 	TypeArray | ||||
| 	TypeArrayBuffer | ||||
| 	TypeError | ||||
| ) | ||||
|  | ||||
| var napiTypeNames = map[NapiType]string{ | ||||
| 	TypeUnkown:      "Unknown", | ||||
| 	TypeUndefined:   "Undefined", | ||||
| 	TypeNull:        "Null", | ||||
| 	TypeBoolean:     "Boolean", | ||||
| 	TypeNumber:      "Number", | ||||
| 	TypeBigInt:      "BigInt", | ||||
| 	TypeString:      "String", | ||||
| 	TypeSymbol:      "Symbol", | ||||
| 	TypeObject:      "Object", | ||||
| 	TypeFunction:    "Function", | ||||
| 	TypeExternal:    "External", | ||||
| 	TypeTypedArray:  "TypedArray", | ||||
| 	TypePromise:     "Promise", | ||||
| 	TypeDataView:    "DaraView", | ||||
| 	TypeBuffer:      "Buffer", | ||||
| 	TypeDate:        "Date", | ||||
| 	TypeArray:       "Array", | ||||
| 	TypeArrayBuffer: "ArrayBuffer", | ||||
| 	TypeError:       "Error", | ||||
| } | ||||
|  | ||||
| // Return [ValueType] from [napi.Value] | ||||
| func N_APIValue(env EnvType, value napi.Value) ValueType { | ||||
| 	return &Value{env: env, valueOf: value} | ||||
| } | ||||
|  | ||||
| func (v *Value) NapiValue() napi.Value { return v.valueOf } | ||||
| func (v *Value) NapiEnv() napi.Env     { return v.env.NapiValue() } | ||||
| func (v *Value) Env() EnvType          { return v.env } | ||||
|  | ||||
| func (v *Value) Type() (NapiType, error) { | ||||
| 	isTypedArray, err := mustValueErr(napi.IsTypedArray(v.NapiEnv(), v.NapiValue())) | ||||
| 	if err != nil { | ||||
| 		return TypeUnkown, err | ||||
| 	} | ||||
| 	isPromise, err := mustValueErr(napi.IsPromise(v.NapiEnv(), v.NapiValue())) | ||||
| 	if err != nil { | ||||
| 		return TypeUnkown, err | ||||
| 	} | ||||
| 	isDataView, err := mustValueErr(napi.IsDataView(v.NapiEnv(), v.NapiValue())) | ||||
| 	if err != nil { | ||||
| 		return TypeUnkown, err | ||||
| 	} | ||||
| 	isBuffer, err := mustValueErr(napi.IsBuffer(v.NapiEnv(), v.NapiValue())) | ||||
| 	if err != nil { | ||||
| 		return TypeUnkown, err | ||||
| 	} | ||||
| 	isDate, err := mustValueErr(napi.IsDate(v.NapiEnv(), v.NapiValue())) | ||||
| 	if err != nil { | ||||
| 		return TypeUnkown, err | ||||
| 	} | ||||
| 	isArray, err := mustValueErr(napi.IsArray(v.NapiEnv(), v.NapiValue())) | ||||
| 	if err != nil { | ||||
| 		return TypeUnkown, err | ||||
| 	} | ||||
| 	isArrayBuffer, err := mustValueErr(napi.IsArrayBuffer(v.NapiEnv(), v.NapiValue())) | ||||
| 	if err != nil { | ||||
| 		return TypeUnkown, err | ||||
| 	} | ||||
| 	isError, err := mustValueErr(napi.IsError(v.NapiEnv(), v.NapiValue())) | ||||
| 	if err != nil { | ||||
| 		return TypeUnkown, err | ||||
| 	} | ||||
| 	isTypeof, err := mustValueErr(napi.Typeof(v.NapiEnv(), v.NapiValue())) | ||||
| 	if err != nil { | ||||
| 		return TypeUnkown, err | ||||
| 	} | ||||
|  | ||||
| 	switch { | ||||
| 	case isTypedArray: | ||||
| 		return TypeTypedArray, nil | ||||
| 	case isPromise: | ||||
| 		return TypePromise, nil | ||||
| 	case isDataView: | ||||
| 		return TypeDataView, nil | ||||
| 	case isBuffer: | ||||
| 		return TypeBuffer, nil | ||||
| 	case isDate: | ||||
| 		return TypeDate, nil | ||||
| 	case isArray: | ||||
| 		return TypeArray, nil | ||||
| 	case isArrayBuffer: | ||||
| 		return TypeArrayBuffer, nil | ||||
| 	case isError: | ||||
| 		return TypeError, nil | ||||
| 	case isTypeof == napi.ValueTypeUndefined: | ||||
| 		return TypeUndefined, nil | ||||
| 	case isTypeof == napi.ValueTypeNull: | ||||
| 		return TypeNull, nil | ||||
| 	case isTypeof == napi.ValueTypeBoolean: | ||||
| 		return TypeBoolean, nil | ||||
| 	case isTypeof == napi.ValueTypeNumber: | ||||
| 		return TypeNumber, nil | ||||
| 	case isTypeof == napi.ValueTypeString: | ||||
| 		return TypeString, nil | ||||
| 	case isTypeof == napi.ValueTypeSymbol: | ||||
| 		return TypeSymbol, nil | ||||
| 	case isTypeof == napi.ValueTypeObject: | ||||
| 		return TypeObject, nil | ||||
| 	case isTypeof == napi.ValueTypeFunction: | ||||
| 		return TypeFunction, nil | ||||
| 	case isTypeof == napi.ValueTypeExternal: | ||||
| 		return TypeExternal, nil | ||||
| 	case isTypeof == napi.ValueTypeBigint: | ||||
| 		return TypeBigInt, nil | ||||
| 	} | ||||
|  | ||||
| 	return TypeUnkown, nil | ||||
| } | ||||
|  | ||||
| func (t NapiType) String() string { | ||||
| 	if name, ok := napiTypeNames[t]; ok { | ||||
| 		return name | ||||
| 	} | ||||
| 	return fmt.Sprintf("Unknown NapiType %d", t) | ||||
| } | ||||
							
								
								
									
										114
									
								
								number.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								number.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,114 @@ | ||||
| package napi | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi" | ||||
| ) | ||||
|  | ||||
| type Number struct{ value } | ||||
| type Bigint struct{ value } | ||||
|  | ||||
| // Convert [ValueType] to [*Number] | ||||
| func ToNumber(o ValueType) *Number { return &Number{o} } | ||||
|  | ||||
| // Convert [ValueType] to [*Bigint] | ||||
| func ToBigint(o ValueType) *Bigint { return &Bigint{o} } | ||||
|  | ||||
| func (num *Number) Float() (float64, error) { | ||||
| 	return mustValueErr(napi.GetValueDouble(num.NapiEnv(), num.NapiValue())) | ||||
| } | ||||
|  | ||||
| func (num *Number) Int() (int64, error) { | ||||
| 	return mustValueErr(napi.GetValueInt64(num.NapiEnv(), num.NapiValue())) | ||||
| } | ||||
|  | ||||
| func (num *Number) Uint32() (uint32, error) { | ||||
| 	return mustValueErr(napi.GetValueUint32(num.NapiEnv(), num.NapiValue())) | ||||
| } | ||||
|  | ||||
| func (num *Number) Int32() (int32, error) { | ||||
| 	return mustValueErr(napi.GetValueInt32(num.NapiEnv(), num.NapiValue())) | ||||
| } | ||||
|  | ||||
| func (big *Bigint) Int64() (int64, error) { | ||||
| 	return mustValueErr2(napi.GetValueBigIntInt64(big.NapiEnv(), big.NapiValue())) | ||||
| } | ||||
| func (big *Bigint) Uint64() (uint64, error) { | ||||
| 	return mustValueErr2(napi.GetValueBigIntUint64(big.NapiEnv(), big.NapiValue())) | ||||
| } | ||||
|  | ||||
| func CreateBigint[T int64 | uint64](env EnvType, valueOf T) (*Bigint, error) { | ||||
| 	var value napi.Value | ||||
| 	var err error | ||||
| 	switch v := any(valueOf).(type) { | ||||
| 	case int64: | ||||
| 		if value, err = mustValueErr(napi.CreateBigIntInt64(env.NapiValue(), v)); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	case uint64: | ||||
| 		if value, err = mustValueErr(napi.CreateBigIntUint64(env.NapiValue(), v)); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return &Bigint{value: &Value{env: env, valueOf: value}}, nil | ||||
| } | ||||
|  | ||||
| func CreateNumber[T ~int | ~uint | ~int8 | ~uint8 | ~int16 | ~uint16 | ~int32 | ~uint32 | ~int64 | ~uint64 | ~float32 | ~float64](env EnvType, n T) (*Number, error) { | ||||
| 	var value napi.Value | ||||
| 	var err error | ||||
| 	switch v := any(n).(type) { | ||||
| 	case int: | ||||
| 		if value, err = mustValueErr(napi.CreateInt64(env.NapiValue(), int64(v))); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	case uint: | ||||
| 		if value, err = mustValueErr(napi.CreateInt64(env.NapiValue(), int64(v))); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	case int8: | ||||
| 		if value, err = mustValueErr(napi.CreateInt64(env.NapiValue(), int64(v))); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	case uint8: | ||||
| 		if value, err = mustValueErr(napi.CreateInt64(env.NapiValue(), int64(v))); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	case int16: | ||||
| 		if value, err = mustValueErr(napi.CreateInt64(env.NapiValue(), int64(v))); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	case uint16: | ||||
| 		if value, err = mustValueErr(napi.CreateInt64(env.NapiValue(), int64(v))); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	case int32: | ||||
| 		if value, err = mustValueErr(napi.CreateInt32(env.NapiValue(), v)); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	case uint32: | ||||
| 		if value, err = mustValueErr(napi.CreateUint32(env.NapiValue(), v)); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	case int64: | ||||
| 		if value, err = mustValueErr(napi.CreateInt64(env.NapiValue(), v)); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	case uint64: | ||||
| 		if value, err = mustValueErr(napi.CreateInt64(env.NapiValue(), int64(v))); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	case float32: | ||||
| 		if value, err = mustValueErr(napi.CreateDouble(env.NapiValue(), float64(v))); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	case float64: | ||||
| 		if value, err = mustValueErr(napi.CreateDouble(env.NapiValue(), v)); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	default: | ||||
| 		return nil, fmt.Errorf("invalid number type") | ||||
| 	} | ||||
| 	return ToNumber(N_APIValue(env, value)), err | ||||
| } | ||||
							
								
								
									
										134
									
								
								object.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								object.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,134 @@ | ||||
| package napi | ||||
|  | ||||
| import ( | ||||
| 	"iter" | ||||
|  | ||||
| 	"sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi" | ||||
| ) | ||||
|  | ||||
| type Object struct{ value } | ||||
|  | ||||
| // Convert ValueType to [*Object] | ||||
| func ToObject(o ValueType) *Object { return &Object{o} } | ||||
|  | ||||
| // Create [*Object] | ||||
| func CreateObject(env EnvType) (*Object, error) { | ||||
| 	napiValue, err := mustValueErr(napi.CreateObject(env.NapiValue())) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return ToObject(N_APIValue(env, napiValue)), nil | ||||
| } | ||||
|  | ||||
| // Check if exists named property. | ||||
| func (obj *Object) Has(name string) (bool, error) { | ||||
| 	return mustValueErr(napi.HasNamedProperty(obj.NapiEnv(), obj.NapiValue(), name)) | ||||
| } | ||||
|  | ||||
| // Checks whether a own property is present. | ||||
| func (obj *Object) HasOwnProperty(key ValueType) (bool, error) { | ||||
| 	return mustValueErr(napi.HasOwnProperty(obj.NapiEnv(), obj.NapiValue(), key.NapiValue())) | ||||
| } | ||||
|  | ||||
| // Checks whether a own property is present. | ||||
| func (obj *Object) HasOwnPropertyString(keyString string) (bool, error) { | ||||
| 	napiString, err := CreateString(obj.Env(), keyString) | ||||
| 	if err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
| 	return obj.HasOwnProperty(napiString) | ||||
| } | ||||
|  | ||||
| // Gets a property. | ||||
| func (obj *Object) Get(key string) (ValueType, error) { | ||||
| 	keyValue, err := CreateString(obj.Env(), key) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return obj.GetWithValue(keyValue) | ||||
| } | ||||
|  | ||||
| // Gets a property. | ||||
| func (obj *Object) GetWithValue(key ValueType) (ValueType, error) { | ||||
| 	napiValue, err := mustValueErr(napi.GetProperty(obj.Env().NapiValue(), obj.NapiValue(), key.NapiValue())) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return N_APIValue(obj.Env(), napiValue), nil | ||||
| } | ||||
|  | ||||
| // Sets a property. | ||||
| func (obj *Object) Set(key string, value ValueType) error { | ||||
| 	keyValue, err := CreateString(obj.Env(), key) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return obj.SetWithValue(keyValue, value) | ||||
| } | ||||
|  | ||||
| // Sets a property. | ||||
| func (obj *Object) SetWithValue(key, value ValueType) error { | ||||
| 	return singleMustValueErr(napi.SetProperty(obj.NapiEnv(), obj.NapiValue(), key.NapiValue(), value.NapiValue())) | ||||
| } | ||||
|  | ||||
| // Delete property. | ||||
| func (obj *Object) Delete(key string) (bool, error) { | ||||
| 	keyValue, err := CreateString(obj.Env(), key) | ||||
| 	if err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
| 	return obj.DeleteWithValue(keyValue) | ||||
| } | ||||
|  | ||||
| // Delete property. | ||||
| func (obj *Object) DeleteWithValue(key ValueType) (bool, error) { | ||||
| 	return mustValueErr(napi.DeleteProperty(obj.NapiEnv(), obj.NapiValue(), key.NapiValue())) | ||||
| } | ||||
|  | ||||
| // Get all property names. | ||||
| func (obj *Object) GetPropertyNames() (*Array, error) { | ||||
| 	arrValue, err := mustValueErr(napi.GetPropertyNames(obj.NapiEnv(), obj.NapiValue())) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return ToArray(N_APIValue(obj.Env(), arrValue)), nil | ||||
| } | ||||
|  | ||||
| // Checks if an object is an instance created by a constructor function, | ||||
| // this is equivalent to the JavaScript `instanceof` operator. | ||||
| func (obj *Object) InstanceOf(value ValueType) (bool, error) { | ||||
| 	return mustValueErr(napi.InstanceOf(obj.NapiEnv(), obj.NapiValue(), value.NapiValue())) | ||||
| } | ||||
|  | ||||
| // Freeze object. | ||||
| func (obj *Object) Freeze() error { | ||||
| 	return singleMustValueErr(napi.ObjectFreeze(obj.NapiEnv(), obj.NapiValue())) | ||||
| } | ||||
|  | ||||
| func (obj *Object) Seal() error { | ||||
| 	return singleMustValueErr(napi.ObjectSeal(obj.NapiEnv(), obj.NapiValue())) | ||||
| } | ||||
|  | ||||
| func (obj *Object) Seq() iter.Seq2[string, ValueType] { | ||||
| 	keys, err := obj.GetPropertyNames() | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	return func(yield func(string, ValueType) bool) { | ||||
| 		for key := range keys.Seq() { | ||||
| 			value, err := obj.GetWithValue(key) | ||||
| 			if err != nil { | ||||
| 				panic(err) | ||||
| 			} | ||||
|  | ||||
| 			keyName, err := ToString(key).Utf8Value() | ||||
| 			if err != nil { | ||||
| 				panic(err) | ||||
| 			} | ||||
|  | ||||
| 			if !yield(keyName, value) { | ||||
| 				return | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										44
									
								
								string.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								string.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
| package napi | ||||
|  | ||||
| import ( | ||||
| 	"unicode/utf16" | ||||
|  | ||||
| 	"sirherobrine23.com.br/Sirherobrine23/napi-go/internal/napi" | ||||
| ) | ||||
|  | ||||
| type String struct{ value } | ||||
|  | ||||
| // Convert [ValueType] to [*String] | ||||
| func ToString(o ValueType) *String { return &String{o} } | ||||
|  | ||||
| // Create [*String] from go string | ||||
| func CreateString(env EnvType, str string) (*String, error) { | ||||
| 	napiString, err := mustValueErr(napi.CreateStringUtf8(env.NapiValue(), str)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return ToString(N_APIValue(env, napiString)), nil | ||||
| } | ||||
|  | ||||
| // Create string to utf16 | ||||
| func CreateStringUtf16(env EnvType, str []rune) (*String, error) { | ||||
| 	napiString, err := mustValueErr(napi.CreateStringUtf16(env.NapiValue(), utf16.Encode(str))) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return ToString(N_APIValue(env, napiString)), nil | ||||
| } | ||||
|  | ||||
| // Get String value. | ||||
| func (str *String) Utf8Value() (string, error) { | ||||
| 	return mustValueErr(napi.GetValueStringUtf8(str.NapiEnv(), str.NapiValue())) | ||||
| } | ||||
|  | ||||
| // Converts a String value to a UTF-16 encoded in rune. | ||||
| func (str *String) Utf16Value() ([]rune, error) { | ||||
| 	valueOf, err := mustValueErr(napi.GetValueStringUtf16(str.NapiEnv(), str.NapiValue())) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return utf16.Decode(valueOf), nil | ||||
| } | ||||
| @@ -1,21 +0,0 @@ | ||||
| package napi | ||||
|  | ||||
| /* | ||||
| #include <node/node_api.h> | ||||
| */ | ||||
| import "C" | ||||
|  | ||||
| type ValueType int | ||||
|  | ||||
| const ( | ||||
| 	ValueTypeUndefined ValueType = C.napi_undefined | ||||
| 	ValueTypeNull      ValueType = C.napi_null | ||||
| 	ValueTypeBoolean   ValueType = C.napi_boolean | ||||
| 	ValueTypeNumber    ValueType = C.napi_number | ||||
| 	ValueTypeString    ValueType = C.napi_string | ||||
| 	ValueTypeSymbol    ValueType = C.napi_symbol | ||||
| 	ValueTypeObject    ValueType = C.napi_object | ||||
| 	ValueTypeFunction  ValueType = C.napi_function | ||||
| 	ValueTypeExternal  ValueType = C.napi_external | ||||
| 	ValueTypeBigint    ValueType = C.napi_bigint | ||||
| ) | ||||
		Reference in New Issue
	
	Block a user