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).
|
||||
|
72
array.go
Normal file
72
array.go
Normal file
@ -0,0 +1,72 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
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
@ -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() {}
|
53
entry/entry.go
Normal file
53
entry/entry.go
Normal file
@ -0,0 +1,53 @@
|
||||
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 (
|
||||
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)
|
||||
|
||||
for _, registerCall := range modFuncInit {
|
||||
registerCall(env, exports)
|
||||
}
|
||||
|
||||
return cExports
|
||||
}
|
||||
|
||||
func Register(fn func(gonapi.EnvType, *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"
|
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
|
||||
|
1264
internal/napi/js_native_api.go
Normal file
1264
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
|
||||
}
|
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)
|
||||
}
|
106
object.go
Normal file
106
object.go
Normal file
@ -0,0 +1,106 @@
|
||||
package napi
|
||||
|
||||
import "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()))
|
||||
}
|
17
string.go
Normal file
17
string.go
Normal file
@ -0,0 +1,17 @@
|
||||
package napi
|
||||
|
||||
import "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
|
||||
}
|
@ -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