diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6dad59b --- /dev/null +++ b/.gitignore @@ -0,0 +1,182 @@ +### Node ### +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +### Node Patch ### +# Serverless Webpack directories +.webpack/ + +# Optional stylelint cache + +# SvelteKit build / generate output +.svelte-kit + +### Git template +# Created by git for backups. To disable backups in Git: +# $ git config --global mergetool.keepBackup false +*.orig + +# Created by git when using merge tools for conflicts +*.BACKUP.* +*.BASE.* +*.LOCAL.* +*.REMOTE.* +*_BACKUP_*.txt +*_BASE_*.txt +*_LOCAL_*.txt +*_REMOTE_*.txt + +### Go template +# If you prefer the allow list template instead of the deny list, see community template: +# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore +# +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +vendor/ + +# Go workspace file +go.work + +### CUSTOM IGNORES ### +temp/ +tmp/ +build/ \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..f48b48b --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,108 @@ +# Contributing + +## TODO + +### Unstable APIs + +```go +// filename: node_api.go + +package napi + +func BasicFinalize(env Env, finalizeData, finalizeHint unsafe.Pointer) Status { + return Status(C.node_api_basic_finalize( + C.napi_env(env), + finalizeData, + finalizeHint, + )) +} + + +func BasicEnv(env Env) Status { + return Status(C.node_api_basic_env(C.napi_env(env))) +} + + +func PostFinalizer(env Env, finalizeData, finalizeHint unsafe.Pointer) Status { + return Status(C.node_api_post_finalizer( + C.napi_env(env), + finalizeData, + finalizeHint, + )) +} + +``` + +### Fix the following functions + +```go +// filename: node_api.go + +package napi + +/* +#include +#include +*/ +import "C" +import "unsafe" + +// OpenCallbackScope Function to open a callback scope +func OpenCallbackScope(env Env, resourceObject, context Value) (CallbackScope, Status) { + var scope CallbackScope + status := Status(C.napi_open_callback_scope( + C.napi_env(env), + C.napi_value(resourceObject), + C.napi_value(context), + (*C.napi_callback_scope)(unsafe.Pointer(&scope.scope)), + )) + return scope, status +} + +func CreateExternalStringLatin1(env Env, str string, finalize Finalize, finalizeHint unsafe.Pointer) (Value, Status) { + cstr := C.CString(str) + defer C.free(unsafe.Pointer(cstr)) + + finalizer := FinalizeToFinalizer(finalize) + var result Value + status := Status(C.node_api_create_external_string_latin1( + C.napi_env(env), + cstr, + C.size_t(len([]byte(str))), + C.napi_finalize(unsafe.Pointer(&finalizer)), + finalizeHint, + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + + +func CreateExternalStringUtf16(env Env, str []uint16, finalize Finalize, finalizeHint unsafe.Pointer) (Value, Status) { + var result Value + finalizer := FinalizeToFinalizer(finalize) + status := Status(C.node_api_create_external_string_utf16( + C.napi_env(env), + (*C.char16_t)(unsafe.Pointer(&str[0])), + C.size_t(len(str)), + C.napi_finalize(unsafe.Pointer(&finalizer)), + finalizeHint, + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + + +func CreateBufferFromArrayBuffer(env Env, arrayBuffer Value, byteOffset, length int) (Value, *byte, Status) { + var result Value + var data *byte + status := Status(C.node_api_create_buffer_from_arraybuffer( + C.napi_env(env), + C.napi_value(arrayBuffer), + C.size_t(byteOffset), + C.size_t(length), + unsafe.Pointer(&data), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, data, status +} +``` \ No newline at end of file diff --git a/js/promise.go b/js/promise.go index 20bcb9f..da6530a 100644 --- a/js/promise.go +++ b/js/promise.go @@ -102,14 +102,14 @@ func (p *Promise) ensurePending() { } func (p *Promise) settle() { - st := napi.CallThreadsafeFunction(p.ThreadsafeFunction) + st := napi.CallThreadsafeFunction(p.ThreadsafeFunction, napi.Blocking) if st != napi.StatusOK { panic(napi.StatusError(st)) } } func (p *Promise) release() { - st := napi.ReleaseThreadsafeFunction(p.ThreadsafeFunction) + st := napi.ReleaseThreadsafeFunction(p.ThreadsafeFunction, napi.Release) if st == napi.StatusClosing { p.ThreadsafeFunction = nil } else if st != napi.StatusOK { diff --git a/js_native_api.go b/js_native_api.go index 3bcd6dc..688f941 100644 --- a/js_native_api.go +++ b/js_native_api.go @@ -339,3 +339,886 @@ func GetInstanceData(env Env) (any, Status) { return provider.GetUserData(), status } + +func CreateBuffer(env Env, length int) (Value, []byte, Status) { + var result Value + data := make([]byte, length) + dataPtr := unsafe.Pointer(&data[0]) + + status := Status(C.napi_create_buffer( + C.napi_env(env), + C.size_t(length), + &dataPtr, + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, data, status +} + +func CreateExternal(env Env, data unsafe.Pointer, finalize Finalize, finalizeHint unsafe.Pointer) (Value, Status) { + var result Value + finalizer := FinalizeToFinalizer(finalize) + status := Status(C.napi_create_external( + C.napi_env(env), + data, + C.napi_finalize(unsafe.Pointer(&finalizer)), + finalizeHint, + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func GetValueInt32(env Env, value Value) (int32, Status) { + var result C.int32_t + status := Status(C.napi_get_value_int32( + C.napi_env(env), + C.napi_value(value), + &result, + )) + return int32(result), status +} + +func GetValueUint32(env Env, value Value) (uint32, Status) { + var result uint32 + status := Status(C.napi_get_value_uint32( + C.napi_env(env), + C.napi_value(value), + (*C.uint32_t)(unsafe.Pointer(&result)), + )) + return result, status +} + +func GetValueInt64(env Env, value Value) (int64, Status) { + var result int64 + status := Status(C.napi_get_value_int64( + C.napi_env(env), + C.napi_value(value), + (*C.int64_t)(unsafe.Pointer(&result)), + )) + return result, status +} + +func GetValueBigIntInt64(env Env, value Value) (int64, bool, Status) { + var result int64 + var lossless bool + status := Status(C.napi_get_value_bigint_int64( + C.napi_env(env), + C.napi_value(value), + (*C.int64_t)(unsafe.Pointer(&result)), + (*C.bool)(unsafe.Pointer(&lossless)), + )) + return result, lossless, status +} + +func GetValueBigIntWords(env Env, value Value, signBit int, wordCount int, words *uint64) Status { + return Status(C.napi_get_value_bigint_words( + C.napi_env(env), + C.napi_value(value), + (*C.int)(unsafe.Pointer(&signBit)), + (*C.size_t)(unsafe.Pointer(&wordCount)), + (*C.uint64_t)(unsafe.Pointer(words)), + )) +} + +func GetValueExternal(env Env, value Value) (unsafe.Pointer, Status) { + var result unsafe.Pointer + status := Status(C.napi_get_value_external( + C.napi_env(env), + C.napi_value(value), + &result, + )) + return result, status +} + +func CoerceToBool(env Env, value Value) (Value, Status) { + var result Value + status := Status(C.napi_coerce_to_bool( + C.napi_env(env), + C.napi_value(value), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func CoerceToNumber(env Env, value Value) (Value, Status) { + var result Value + status := Status(C.napi_coerce_to_number( + C.napi_env(env), + C.napi_value(value), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func CoerceToObject(env Env, value Value) (Value, Status) { + var result Value + status := Status(C.napi_coerce_to_object( + C.napi_env(env), + C.napi_value(value), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func CoerceToString(env Env, value Value) (Value, Status) { + var result Value + status := Status(C.napi_coerce_to_string( + C.napi_env(env), + C.napi_value(value), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func CreateBufferCopy(env Env, data []byte) (Value, *byte, Status) { + var result Value + var copiedData *byte + copiedDataPtr := unsafe.Pointer(&copiedData) + status := Status(C.napi_create_buffer_copy( + C.napi_env(env), + C.size_t(len(data)), + unsafe.Pointer(&data[0]), + &copiedDataPtr, + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, copiedData, status +} + +func GetBufferInfo(env Env, value Value) (*byte, int, Status) { + var data *byte + var length C.size_t + + dataPtr := unsafe.Pointer(&data) + + status := Status(C.napi_get_buffer_info( + C.napi_env(env), + C.napi_value(value), + &dataPtr, + &length, + )) + return data, int(length), status +} + +func GetArrayLength(env Env, value Value) (int, Status) { + var length C.uint32_t + status := Status(C.napi_get_array_length( + C.napi_env(env), + C.napi_value(value), + &length, + )) + return int(length), status +} + +func GetPrototype(env Env, value Value) (Value, Status) { + var result Value + status := Status(C.napi_get_prototype( + C.napi_env(env), + C.napi_value(value), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func InstanceOf(env Env, object, constructor Value) (bool, Status) { + var result bool + status := Status(C.napi_instanceof( + C.napi_env(env), + C.napi_value(object), + C.napi_value(constructor), + (*C.bool)(unsafe.Pointer(&result)), + )) + return result, status +} + +func IsArray(env Env, value Value) (bool, Status) { + var result bool + status := Status(C.napi_is_array( + C.napi_env(env), + C.napi_value(value), + (*C.bool)(unsafe.Pointer(&result)), + )) + return result, status +} + +func IsBuffer(env Env, value Value) (bool, Status) { + var result bool + status := Status(C.napi_is_buffer( + C.napi_env(env), + C.napi_value(value), + (*C.bool)(unsafe.Pointer(&result)), + )) + return result, status +} + +func IsError(env Env, value Value) (bool, Status) { + var result bool + status := Status(C.napi_is_error( + C.napi_env(env), + C.napi_value(value), + (*C.bool)(unsafe.Pointer(&result)), + )) + return result, status +} + +func IsPromise(env Env, value Value) (bool, Status) { + var result bool + status := Status(C.napi_is_promise( + C.napi_env(env), + C.napi_value(value), + (*C.bool)(unsafe.Pointer(&result)), + )) + return result, status +} + +func IsTypedArray(env Env, value Value) (bool, Status) { + var result bool + status := Status(C.napi_is_typedarray( + C.napi_env(env), + C.napi_value(value), + (*C.bool)(unsafe.Pointer(&result)), + )) + return result, status +} + +func GetTypedArrayInfo(env Env, value Value) (TypedArrayType, int, *byte, Value, int, Status) { + var type_ TypedArrayType + var length C.size_t + var data *byte + var arrayBuffer Value + var byteOffset C.size_t + + dataPtr := unsafe.Pointer(&data) + status := Status(C.napi_get_typedarray_info( + C.napi_env(env), + C.napi_value(value), + (*C.napi_typedarray_type)(unsafe.Pointer(&type_)), + &length, + &dataPtr, + (*C.napi_value)(unsafe.Pointer(&arrayBuffer)), + &byteOffset, + )) + return type_, int(length), data, arrayBuffer, int(byteOffset), status +} + +func CreateTypedArray(env Env, type_ TypedArrayType, length int, arrayBuffer Value, byteOffset int) (Value, Status) { + var result Value + status := Status(C.napi_create_typedarray( + C.napi_env(env), + C.napi_typedarray_type(type_), + C.size_t(length), + C.napi_value(arrayBuffer), + C.size_t(byteOffset), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func AdjustExternalMemory(env Env, change int64) (int64, Status) { + var result int64 + status := Status(C.napi_adjust_external_memory( + C.napi_env(env), + C.int64_t(change), + (*C.int64_t)(unsafe.Pointer(&result)), + )) + return result, status +} + +func CreateDataView(env Env, length int, arrayBuffer Value, byteOffset int) (Value, Status) { + var result Value + status := Status(C.napi_create_dataview( + C.napi_env(env), + C.size_t(length), + C.napi_value(arrayBuffer), + C.size_t(byteOffset), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func GetDataViewInfo(env Env, value Value) (int, *byte, Value, int, Status) { + var length C.size_t + var data *byte + var arrayBuffer Value + var byteOffset C.size_t + + dataPtr := unsafe.Pointer(&data) + status := Status(C.napi_get_dataview_info( + C.napi_env(env), + C.napi_value(value), + &length, + &dataPtr, + (*C.napi_value)(unsafe.Pointer(&arrayBuffer)), + &byteOffset, + )) + return int(length), data, arrayBuffer, int(byteOffset), status +} + +func GetAllPropertyNames(env Env, object Value, keyMode KeyCollectionMode, keyFilter KeyFilter, keyConversion KeyConversion) (Value, Status) { + var result Value + status := Status(C.napi_get_all_property_names( + C.napi_env(env), + C.napi_value(object), + C.napi_key_collection_mode(keyMode), + C.napi_key_filter(keyFilter), + C.napi_key_conversion(keyConversion), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func HasOwnProperty(env Env, object, key Value) (bool, Status) { + var result bool + status := Status(C.napi_has_own_property( + C.napi_env(env), + C.napi_value(object), + C.napi_value(key), + (*C.bool)(unsafe.Pointer(&result)), + )) + return result, status +} + +func HasProperty(env Env, object, key Value) (bool, Status) { + var result bool + status := Status(C.napi_has_property( + C.napi_env(env), + C.napi_value(object), + C.napi_value(key), + (*C.bool)(unsafe.Pointer(&result)), + )) + return result, status +} + +func GetPropertyNames(env Env, object Value) (Value, Status) { + var result Value + status := Status(C.napi_get_property_names( + C.napi_env(env), + C.napi_value(object), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func DefineProperties(env Env, object Value, properties []PropertyDescriptor) Status { + return Status(C.napi_define_properties( + C.napi_env(env), + C.napi_value(object), + C.size_t(len(properties)), + (*C.napi_property_descriptor)(unsafe.Pointer(&properties[0])), + )) +} + +// Wrap function to use the Finalizer type internally +func Wrap(env Env, jsObject Value, nativeObject unsafe.Pointer, finalize Finalize, finalizeHint unsafe.Pointer) Status { + var result Reference + status := Status(C.napi_wrap( + C.napi_env(env), + C.napi_value(jsObject), + nativeObject, + C.napi_finalize(unsafe.Pointer(&finalize)), + finalizeHint, + (*C.napi_ref)(unsafe.Pointer(&result)), + )) + return status +} + +func Unwrap(env Env, jsObject Value) (unsafe.Pointer, Status) { + var nativeObject unsafe.Pointer + status := Status(C.napi_unwrap( + C.napi_env(env), + C.napi_value(jsObject), + &nativeObject, + )) + return nativeObject, status +} + +func RemoveWrap(env Env, jsObject Value) Status { + var result unsafe.Pointer + return Status(C.napi_remove_wrap( + C.napi_env(env), + C.napi_value(jsObject), + &result, + )) +} + +func OpenHandleScope(env Env) (HandleScope, Status) { + var scope HandleScope + status := Status(C.napi_open_handle_scope( + C.napi_env(env), + (*C.napi_handle_scope)(unsafe.Pointer(&scope)), + )) + return scope, status +} + +func CloseHandleScope(env Env, scope HandleScope) Status { + return Status(C.napi_close_handle_scope( + C.napi_env(env), + C.napi_handle_scope(unsafe.Pointer(&scope)), + )) +} + +func OpenEscapableHandleScope(env Env) (EscapableHandleScope, Status) { + var scope EscapableHandleScope + status := Status(C.napi_open_escapable_handle_scope( + C.napi_env(env), + (*C.napi_escapable_handle_scope)(unsafe.Pointer(&scope)), + )) + return scope, status +} + +func CloseEscapableHandleScope(env Env, scope EscapableHandleScope) Status { + return Status(C.napi_close_escapable_handle_scope( + C.napi_env(env), + C.napi_escapable_handle_scope(unsafe.Pointer(&scope)), + )) +} + +func EscapeHandle(env Env, scope EscapableHandleScope, escapee Value) (Value, Status) { + var result Value + status := Status(C.napi_escape_handle( + C.napi_env(env), + C.napi_escapable_handle_scope(unsafe.Pointer(&scope)), + C.napi_value(escapee), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func CreateReference(env Env, value Value, initialRefcount int) (Reference, Status) { + var ref Reference + status := Status(C.napi_create_reference( + C.napi_env(env), + C.napi_value(value), + C.uint32_t(initialRefcount), + (*C.napi_ref)(unsafe.Pointer(&ref)), + )) + return ref, status +} + +func DeleteReference(env Env, ref Reference) Status { + return Status(C.napi_delete_reference( + C.napi_env(env), + C.napi_ref(unsafe.Pointer(&ref)), + )) +} + +func ReferenceRef(env Env, ref Reference) (int, Status) { + var result C.uint32_t + status := Status(C.napi_reference_ref( + C.napi_env(env), + C.napi_ref(unsafe.Pointer(&ref)), + &result, + )) + return int(result), status +} + +func ReferenceUnref(env Env, ref Reference) (int, Status) { + var result C.uint32_t + status := Status(C.napi_reference_unref( + C.napi_env(env), + C.napi_ref(ref.Ref), + &result, + )) + return int(result), status +} + +func GetReferenceValue(env Env, ref Reference) (Value, Status) { + var result Value + status := Status(C.napi_get_reference_value( + C.napi_env(env), + C.napi_ref(unsafe.Pointer(&ref)), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func GetValueBigIntUint64(env Env, value Value) (uint64, bool, Status) { + var result uint64 + var lossless bool + status := Status(C.napi_get_value_bigint_uint64( + C.napi_env(env), + C.napi_value(value), + (*C.uint64_t)(unsafe.Pointer(&result)), + (*C.bool)(unsafe.Pointer(&lossless)), + )) + return result, lossless, status +} + +func CreateBigIntInt64(env Env, value int64) (Value, Status) { + var result Value + status := Status(C.napi_create_bigint_int64( + C.napi_env(env), + C.int64_t(value), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func CreateBigIntUint64(env Env, value uint64) (Value, Status) { + var result Value + status := Status(C.napi_create_bigint_uint64( + C.napi_env(env), + C.uint64_t(value), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func CreateBigIntWords(env Env, signBit int, wordCount int, words *uint64) (Value, Status) { + var result Value + status := Status(C.napi_create_bigint_words( + C.napi_env(env), + C.int(signBit), + C.size_t(wordCount), + (*C.uint64_t)(unsafe.Pointer(words)), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func IsDate(env Env, value Value) (bool, Status) { + var result bool + status := Status(C.napi_is_date( + C.napi_env(env), + C.napi_value(value), + (*C.bool)(unsafe.Pointer(&result)), + )) + return result, status +} + +func IsDetachedArrayBuffer(env Env, value Value) (bool, Status) { + var result bool + status := Status(C.napi_is_detached_arraybuffer( + C.napi_env(env), + C.napi_value(value), + (*C.bool)(unsafe.Pointer(&result)), + )) + return result, status +} + +func DetachArrayBuffer(env Env, value Value) Status { + return Status(C.napi_detach_arraybuffer( + C.napi_env(env), + C.napi_value(value), + )) +} + +func CreateArrayBuffer(env Env, length int) (Value, *byte, Status) { + var result Value + var data *byte + dataPtr := unsafe.Pointer(&data) + status := Status(C.napi_create_arraybuffer( + C.napi_env(env), + C.size_t(length), + &dataPtr, + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, data, status +} + +func GetArrayBufferInfo(env Env, value Value) (*byte, int, Status) { + var data *byte + var length C.size_t + dataPtr := unsafe.Pointer(&data) + status := Status(C.napi_get_arraybuffer_info( + C.napi_env(env), + C.napi_value(value), + &dataPtr, + &length, + )) + return data, int(length), status +} + +func CreateExternalArrayBuffer(env Env, data unsafe.Pointer, length int, finalize Finalize, finalizeHint unsafe.Pointer) (Value, Status) { + var result Value + finalizer := FinalizeToFinalizer(finalize) + status := Status(C.napi_create_external_arraybuffer( + C.napi_env(env), + data, + C.size_t(length), + C.napi_finalize(unsafe.Pointer(&finalizer)), + finalizeHint, + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func GetElement(env Env, object Value, index int) (Value, Status) { + var result Value + status := Status(C.napi_get_element( + C.napi_env(env), + C.napi_value(object), + C.uint32_t(index), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func GetProperty(env Env, object, key Value) (Value, Status) { + var result Value + status := Status(C.napi_get_property( + C.napi_env(env), + C.napi_value(object), + C.napi_value(key), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func DeleteProperty(env Env, object, key Value) (bool, Status) { + var result bool + status := Status(C.napi_delete_property( + C.napi_env(env), + C.napi_value(object), + C.napi_value(key), + (*C.bool)(unsafe.Pointer(&result)), + )) + return result, status +} + +func SetNamedProperty(env Env, object Value, name string, value Value) Status { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + return Status(C.napi_set_named_property( + C.napi_env(env), + C.napi_value(object), + cname, + C.napi_value(value), + )) +} + +func GetNamedProperty(env Env, object Value, name string) (Value, Status) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + var result Value + status := Status(C.napi_get_named_property( + C.napi_env(env), + C.napi_value(object), + cname, + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func HasNamedProperty(env Env, object Value, name string) (bool, Status) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + var result bool + status := Status(C.napi_has_named_property( + C.napi_env(env), + C.napi_value(object), + cname, + (*C.bool)(unsafe.Pointer(&result)), + )) + return result, status +} + +func HasElement(env Env, object Value, index int) (bool, Status) { + var result bool + status := Status(C.napi_has_element( + C.napi_env(env), + C.napi_value(object), + C.uint32_t(index), + (*C.bool)(unsafe.Pointer(&result)), + )) + return result, status +} + +func DeleteElement(env Env, object Value, index int) (bool, Status) { + var result bool + status := Status(C.napi_delete_element( + C.napi_env(env), + C.napi_value(object), + C.uint32_t(index), + (*C.bool)(unsafe.Pointer(&result)), + )) + return result, status +} + +func ObjectFreeze(env Env, object Value) Status { + return Status(C.napi_object_freeze( + C.napi_env(env), + C.napi_value(object), + )) +} + +func ObjectSeal(env Env, object Value) Status { + return Status(C.napi_object_seal( + C.napi_env(env), + C.napi_value(object), + )) +} + +func ThrowTypeError(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_type_error( + C.napi_env(env), + codeCStr, + msgCCstr, + )) +} + +func ThrowRangeError(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_range_error( + C.napi_env(env), + codeCStr, + msgCCstr, + )) +} + +func CreateTypeError(env Env, code, msg Value) (Value, Status) { + var result Value + status := Status(C.napi_create_type_error( + C.napi_env(env), + C.napi_value(code), + C.napi_value(msg), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func CreateRangeError(env Env, code, msg Value) (Value, Status) { + var result Value + status := Status(C.napi_create_range_error( + C.napi_env(env), + C.napi_value(code), + C.napi_value(msg), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func IsExceptionPending(env Env) (bool, Status) { + var result bool + status := Status(C.napi_is_exception_pending( + C.napi_env(env), + (*C.bool)(unsafe.Pointer(&result)), + )) + return result, status +} + +func GetAndClearLastException(env Env) (Value, Status) { + var result Value + status := Status(C.napi_get_and_clear_last_exception( + C.napi_env(env), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +type CallbackScope struct { + scope C.napi_callback_scope +} + +// CloseCallbackScope Function to close a callback scope +func CloseCallbackScope(env Env, scope CallbackScope) Status { + return Status(C.napi_close_callback_scope( + C.napi_env(env), + scope.scope, + )) +} + +// GetExtendedErrorInfo Function to retrieve extended error information +func GetExtendedErrorInfo(env Env) (*C.napi_extended_error_info, Status) { + var errorInfo *C.napi_extended_error_info + status := Status(C.napi_get_last_error_info( + C.napi_env(env), + &errorInfo, + )) + return errorInfo, status +} + +func CreateInt32(env Env, value int32) (Value, Status) { + var result Value + status := Status(C.napi_create_int32( + C.napi_env(env), + C.int32_t(value), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func CreateUint32(env Env, value uint32) (Value, Status) { + var result Value + status := Status(C.napi_create_uint32( + C.napi_env(env), + C.uint32_t(value), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func CreateInt64(env Env, value int64) (Value, Status) { + var result Value + status := Status(C.napi_create_int64( + C.napi_env(env), + C.int64_t(value), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func CreateStringLatin1(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_latin1( + C.napi_env(env), + cstr, + C.size_t(len([]byte(str))), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func CreateStringUtf16(env Env, str []uint16) (Value, Status) { + var result Value + status := Status(C.napi_create_string_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 CallFunction(env Env, recv Value, fn Value, argc int, argv []Value) (Value, Status) { + var result Value + status := Status(C.napi_call_function( + C.napi_env(env), + C.napi_value(recv), + C.napi_value(fn), + C.size_t(argc), + (*C.napi_value)(unsafe.Pointer(&argv[0])), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func GetNewTarget(env Env, info CallbackInfo) (Value, Status) { + var result Value + status := Status(C.napi_get_new_target( + C.napi_env(env), + C.napi_callback_info(info), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} + +func NewInstance(env Env, constructor Value, argc int, argv []Value) (Value, Status) { + var result Value + status := Status(C.napi_new_instance( + C.napi_env(env), + C.napi_value(constructor), + C.size_t(argc), + (*C.napi_value)(unsafe.Pointer(&argv[0])), + (*C.napi_value)(unsafe.Pointer(&result)), + )) + return result, status +} diff --git a/key_type.go b/key_type.go new file mode 100644 index 0000000..375702f --- /dev/null +++ b/key_type.go @@ -0,0 +1,34 @@ +package napi + +/* +#include +*/ +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 +) diff --git a/node_api.go b/node_api.go index aca723e..33352fa 100644 --- a/node_api.go +++ b/node_api.go @@ -1,6 +1,7 @@ package napi /* +#include #include */ 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 +} diff --git a/property_attrib_type.go b/property_attrib_type.go new file mode 100644 index 0000000..fbfcf0c --- /dev/null +++ b/property_attrib_type.go @@ -0,0 +1,18 @@ +package napi + +/* +#include +*/ +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 +) diff --git a/threadsafe_function_type.go b/threadsafe_function_type.go new file mode 100644 index 0000000..14a4d2e --- /dev/null +++ b/threadsafe_function_type.go @@ -0,0 +1,20 @@ +package napi + +/* +#include +*/ +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 +) diff --git a/typed_array_type.go b/typed_array_type.go new file mode 100644 index 0000000..a643b94 --- /dev/null +++ b/typed_array_type.go @@ -0,0 +1,22 @@ +package napi + +/* +#include +*/ +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 +) diff --git a/types.go b/types.go new file mode 100644 index 0000000..a3e7183 --- /dev/null +++ b/types.go @@ -0,0 +1,41 @@ +package napi + +/* +#include +*/ +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 +} diff --git a/value_type.go b/value_type.go index 3afe0ce..81e8ebf 100644 --- a/value_type.go +++ b/value_type.go @@ -5,7 +5,7 @@ package napi */ import "C" -type ValueType int +type ValueType C.napi_valuetype const ( ValueTypeUndefined ValueType = C.napi_undefined @@ -19,3 +19,30 @@ const ( 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" + } +}