Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F4441675
napi.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
107 KB
Referenced Files
None
Subscribers
None
napi.c
View Options
// TODO: split into multiple files
#include
<compat.h>
// IWYU pragma: keep
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include
<windows.h>
#define NAPI_DLOPEN(name, flags) ((void*)LoadLibraryA(name))
#define NAPI_DLSYM(handle, name) ((void*)GetProcAddress((HMODULE)(handle), (name)))
#define NAPI_DLERROR() "LoadLibrary failed"
#define NAPI_RTLD_NOW 0
#define NAPI_RTLD_LOCAL 0
#define NAPI_RTLD_GLOBAL 0
#else
#include
<dlfcn.h>
#define NAPI_DLOPEN(name, flags) dlopen((name), (flags))
#define NAPI_DLSYM(handle, name) dlsym((handle), (name))
#define NAPI_DLERROR() dlerror()
#define NAPI_RTLD_NOW RTLD_NOW
#define NAPI_RTLD_LOCAL RTLD_LOCAL
#define NAPI_RTLD_GLOBAL RTLD_GLOBAL
#endif
#include
<stdio.h>
#include
<stdlib.h>
#include
<string.h>
#include
<stdint.h>
#include
<uthash.h>
#include
<uv.h>
#if defined(__has_include)
#if __has_include(<uchar.h>)
#include
<uchar.h>
#else
typedef
uint16_t
char16_t
;
#endif
#else
typedef
uint16_t
char16_t
;
#endif
#include
"ant.h"
#include
"descriptors.h"
#include
"errors.h"
#include
"internal.h"
#include
"silver/engine.h"
#include
"modules/buffer.h"
#include
"modules/date.h"
#include
"modules/napi.h"
#include
"gc/roots.h"
#include
"gc/modules.h"
#include
"utf8.h"
typedef
struct
napi_cleanup_hook_entry
{
napi_cleanup_hook
hook
;
void
*
arg
;
struct
napi_cleanup_hook_entry
*
next
;
}
napi_cleanup_hook_entry_t
;
typedef
struct
ant_napi_env__
{
ant_t
*
js
;
napi_extended_error_info
last_error
;
char
last_error_msg
[
256
];
bool
has_pending_exception
;
napi_value
pending_exception
;
uint32_t
version
;
void
*
instance_data
;
node_api_basic_finalize
instance_data_finalize_cb
;
void
*
instance_data_finalize_hint
;
napi_cleanup_hook_entry_t
*
cleanup_hooks
;
struct
napi_ref__
*
refs
;
struct
napi_deferred__
*
deferreds
;
struct
napi_threadsafe_function__
*
tsfns
;
int
open_handle_scopes
;
ant_value_t
*
handle_slots
;
size_t
handle_slots_len
;
size_t
handle_slots_cap
;
}
ant_napi_env_t
;
typedef
struct
napi_callback_binding
{
ant_napi_env_t
*
env
;
napi_callback
cb
;
void
*
data
;
}
napi_callback_binding_t
;
struct
napi_callback_info__
{
ant_napi_env_t
*
env
;
const
napi_value
*
argv
;
size_t
argc
;
napi_value
this_arg
;
napi_value
new_target
;
void
*
data
;
};
struct
napi_ref__
{
ant_napi_env_t
*
env
;
ant_value_t
ref_val
;
napi_value
value
;
uint32_t
refcount
;
struct
napi_ref__
*
next
;
struct
napi_ref__
*
prev
;
};
struct
napi_deferred__
{
ant_napi_env_t
*
env
;
ant_value_t
promise_val
;
bool
settled
;
struct
napi_deferred__
*
next
;
struct
napi_deferred__
*
prev
;
};
struct
napi_handle_scope__
{
ant_napi_env_t
*
env
;
size_t
gc_root_mark
;
size_t
handle_slots_mark
;
};
struct
napi_escapable_handle_scope__
{
ant_napi_env_t
*
env
;
size_t
gc_root_mark
;
size_t
handle_slots_mark
;
bool
escaped
;
ant_value_t
escaped_val
;
};
struct
napi_async_context__
{
ant_napi_env_t
*
env
;
};
struct
napi_callback_scope__
{
ant_napi_env_t
*
env
;
};
typedef
struct
napi_external_entry
{
uint64_t
id
;
void
*
data
;
node_api_basic_finalize
finalize_cb
;
void
*
finalize_hint
;
UT_hash_handle
hh
;
}
napi_external_entry_t
;
typedef
struct
napi_wrap_entry
{
uint64_t
id
;
void
*
native_object
;
node_api_basic_finalize
finalize_cb
;
void
*
finalize_hint
;
void
*
attached_data
;
node_api_basic_finalize
attached_finalize_cb
;
void
*
attached_finalize_hint
;
bool
has_wrap
;
UT_hash_handle
hh
;
}
napi_wrap_entry_t
;
typedef
struct
napi_async_work_impl
{
ant_napi_env_t
*
env
;
napi_async_execute_callback
execute
;
napi_async_complete_callback
complete
;
void
*
data
;
uv_work_t
req
;
bool
queued
;
bool
delete_after_complete
;
}
napi_async_work_impl_t
;
typedef
struct
napi_tsfn_item
{
void
*
data
;
struct
napi_tsfn_item
*
next
;
}
napi_tsfn_item_t
;
struct
napi_threadsafe_function__
{
ant_napi_env_t
*
env
;
ant_value_t
func_val
;
napi_threadsafe_function_call_js
call_js_cb
;
node_api_basic_finalize
thread_finalize_cb
;
void
*
thread_finalize_data
;
void
*
context
;
size_t
max_queue_size
;
size_t
queue_size
;
size_t
thread_count
;
bool
closing
;
bool
aborted
;
uv_async_t
async
;
uv_mutex_t
mutex
;
napi_tsfn_item_t
*
head
;
napi_tsfn_item_t
*
tail
;
struct
napi_threadsafe_function__
*
next
;
struct
napi_threadsafe_function__
*
prev
;
};
typedef
napi_value
(
NAPI_CDECL
*
napi_register_module_v1_fn
)(
napi_env
env
,
napi_value
exports
);
typedef
struct
napi_native_lib
{
void
*
handle
;
struct
napi_native_lib
*
next
;
}
napi_native_lib_t
;
typedef
enum
{
napi_key_include_prototypes
=
0
,
napi_key_own_only
=
1
,
}
napi_key_collection_mode
;
typedef
enum
{
napi_key_all_properties
=
0
,
napi_key_writable
=
1
<<
0
,
napi_key_enumerable
=
1
<<
1
,
napi_key_configurable
=
1
<<
2
,
napi_key_skip_strings
=
1
<<
3
,
napi_key_skip_symbols
=
1
<<
4
,
}
napi_key_filter
;
typedef
enum
{
napi_key_keep_numbers
=
0
,
napi_key_numbers_to_strings
=
1
,
}
napi_key_conversion
;
typedef
struct
{
uint8_t
sign
;
uint8_t
pad
[
3
];
uint32_t
limb_count
;
uint32_t
limbs
[];
}
napi_bigint_payload_t
;
static
ant_napi_env_t
*
g_napi_env
=
NULL
;
static
napi_external_entry_t
*
g_napi_externals
=
NULL
;
static
napi_wrap_entry_t
*
g_napi_wraps
=
NULL
;
static
uint64_t
g_napi_external_next_id
=
1
;
static
uint64_t
g_napi_wrap_next_id
=
1
;
static
napi_native_lib_t
*
g_napi_native_libs
=
NULL
;
static
napi_module
*
g_pending_napi_module
=
NULL
;
static
int64_t
g_napi_external_memory
=
0
;
static
const
napi_node_version
g_napi_node_version
=
{
.
major
=
25
,
.
minor
=
0
,
.
patch
=
0
,
.
release
=
"ant"
,
};
static
const
char
*
napi_status_text
(
napi_status
status
)
{
switch
(
status
)
{
case
napi_ok
:
return
"ok"
;
case
napi_invalid_arg
:
return
"invalid argument"
;
case
napi_object_expected
:
return
"object expected"
;
case
napi_string_expected
:
return
"string expected"
;
case
napi_name_expected
:
return
"name expected"
;
case
napi_function_expected
:
return
"function expected"
;
case
napi_number_expected
:
return
"number expected"
;
case
napi_boolean_expected
:
return
"boolean expected"
;
case
napi_array_expected
:
return
"array expected"
;
case
napi_generic_failure
:
return
"generic failure"
;
case
napi_pending_exception
:
return
"pending exception"
;
case
napi_cancelled
:
return
"cancelled"
;
case
napi_escape_called_twice
:
return
"escape called twice"
;
case
napi_handle_scope_mismatch
:
return
"handle scope mismatch"
;
case
napi_callback_scope_mismatch
:
return
"callback scope mismatch"
;
case
napi_queue_full
:
return
"queue full"
;
case
napi_closing
:
return
"closing"
;
case
napi_bigint_expected
:
return
"bigint expected"
;
case
napi_date_expected
:
return
"date expected"
;
case
napi_arraybuffer_expected
:
return
"arraybuffer expected"
;
case
napi_detachable_arraybuffer_expected
:
return
"detachable arraybuffer expected"
;
case
napi_would_deadlock
:
return
"would deadlock"
;
case
napi_no_external_buffers_allowed
:
return
"no external buffers allowed"
;
case
napi_cannot_run_js
:
return
"cannot run js"
;
default
:
return
"unknown"
;
}}
static
napi_status
napi_set_last_raw
(
napi_env
env
,
napi_status
status
,
const
char
*
message
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
)
return
status
;
const
char
*
msg
=
message
?
message
:
napi_status_text
(
status
);
snprintf
(
nenv
->
last_error_msg
,
sizeof
(
nenv
->
last_error_msg
),
"%s"
,
msg
);
nenv
->
last_error
.
error_message
=
nenv
->
last_error_msg
;
nenv
->
last_error
.
engine_reserved
=
NULL
;
nenv
->
last_error
.
engine_error_code
=
0
;
nenv
->
last_error
.
error_code
=
status
;
if
(
status
!=
napi_ok
)
{
}
return
status
;
}
static
napi_status
napi_set_last
(
napi_env
env
,
napi_status
status
,
const
char
*
message
)
{
return
napi_set_last_raw
(
env
,
status
,
message
);
}
static
ant_napi_env_t
*
napi_get_or_create_env
(
ant_t
*
js
)
{
if
(
!
g_napi_env
)
{
g_napi_env
=
(
ant_napi_env_t
*
)
calloc
(
1
,
sizeof
(
*
g_napi_env
));
if
(
!
g_napi_env
)
return
NULL
;
g_napi_env
->
version
=
8
;
napi_set_last
((
napi_env
)
g_napi_env
,
napi_ok
,
NULL
);
}
g_napi_env
->
js
=
js
;
return
g_napi_env
;
}
napi_env
ant_napi_get_env
(
ant_t
*
js
)
{
return
(
napi_env
)
napi_get_or_create_env
(
js
);
}
void
gc_mark_napi
(
ant_t
*
js
,
gc_mark_fn
mark
)
{
if
(
!
g_napi_env
||
g_napi_env
->
js
!=
js
)
return
;
ant_napi_env_t
*
nenv
=
g_napi_env
;
if
(
nenv
->
has_pending_exception
)
mark
(
js
,
(
ant_value_t
)
nenv
->
pending_exception
);
for
(
struct
napi_ref__
*
r
=
nenv
->
refs
;
r
;
r
=
r
->
next
)
{
if
(
r
->
refcount
>
0
)
mark
(
js
,
r
->
ref_val
);
mark
(
js
,
(
ant_value_t
)
r
->
value
);
}
for
(
struct
napi_deferred__
*
d
=
nenv
->
deferreds
;
d
;
d
=
d
->
next
)
if
(
!
d
->
settled
)
mark
(
js
,
d
->
promise_val
);
for
(
struct
napi_threadsafe_function__
*
t
=
nenv
->
tsfns
;
t
;
t
=
t
->
next
)
mark
(
js
,
t
->
func_val
);
for
(
size_t
i
=
0
;
i
<
nenv
->
handle_slots_len
;
i
++
)
mark
(
js
,
nenv
->
handle_slots
[
i
]);
}
static
inline
napi_value
napi_scope_pin
(
ant_napi_env_t
*
nenv
,
napi_value
val
)
{
ant_value_t
v
=
(
ant_value_t
)
val
;
if
(
!
nenv
||
!
is_object_type
(
v
))
return
val
;
if
(
nenv
->
handle_slots_len
>=
nenv
->
handle_slots_cap
)
{
size_t
new_cap
=
nenv
->
handle_slots_cap
?
nenv
->
handle_slots_cap
*
2
:
256
;
ant_value_t
*
new_slots
=
realloc
(
nenv
->
handle_slots
,
new_cap
*
sizeof
(
ant_value_t
));
if
(
!
new_slots
)
return
val
;
nenv
->
handle_slots
=
new_slots
;
nenv
->
handle_slots_cap
=
new_cap
;
}
nenv
->
handle_slots
[
nenv
->
handle_slots_len
++
]
=
v
;
return
val
;
}
#define NAPI_RETURN(nenv, val) napi_scope_pin((nenv), (napi_value)(val))
static
void
napi_mark_pending_exception
(
napi_env
env
,
napi_value
exception
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
)
return
;
nenv
->
has_pending_exception
=
true
;
nenv
->
pending_exception
=
exception
;
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_throw
(
napi_env
env
,
napi_value
error
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid env"
);
if
(
nenv
->
has_pending_exception
||
nenv
->
js
->
thrown_exists
)
return
napi_set_last
(
env
,
napi_pending_exception
,
"pending exception"
);
js_throw
(
nenv
->
js
,
(
ant_value_t
)
error
);
napi_mark_pending_exception
(
env
,
error
);
return
napi_set_last_raw
(
env
,
napi_ok
,
NULL
);
}
static
napi_status
napi_check_pending_from_result
(
napi_env
env
,
ant_value_t
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid env"
);
if
(
is_err
(
result
)
||
nenv
->
js
->
thrown_exists
)
{
napi_mark_pending_exception
(
env
,
nenv
->
js
->
thrown_exists
?
nenv
->
js
->
thrown_value
:
result
);
napi_set_last_raw
(
env
,
napi_pending_exception
,
"pending exception"
);
return
napi_pending_exception
;
}
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
static
napi_status
napi_return_pending_if_any
(
napi_env
env
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid env"
);
if
(
nenv
->
has_pending_exception
)
{
napi_set_last_raw
(
env
,
napi_pending_exception
,
"pending exception"
);
return
napi_pending_exception
;
}
if
(
nenv
->
js
->
thrown_exists
)
{
napi_mark_pending_exception
(
env
,
(
napi_value
)
nenv
->
js
->
thrown_value
);
napi_set_last_raw
(
env
,
napi_pending_exception
,
"pending exception"
);
return
napi_pending_exception
;
}
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
static
bool
napi_slot_get_u64
(
ant_t
*
js
,
ant_value_t
obj
,
internal_slot_t
slot
,
uint64_t
*
out
)
{
ant_value_t
value
=
js_get_slot
(
obj
,
slot
);
if
(
vtype
(
value
)
!=
T_NUM
)
return
false
;
*
out
=
(
uint64_t
)
js_getnum
(
value
);
return
true
;
}
static
void
napi_slot_set_u64
(
ant_t
*
js
,
ant_value_t
obj
,
internal_slot_t
slot
,
uint64_t
v
)
{
js_set_slot
(
obj
,
slot
,
js_mknum
((
double
)
v
));
}
static
napi_external_entry_t
*
napi_find_external
(
ant_t
*
js
,
napi_value
value
)
{
if
(
!
is_object_type
((
ant_value_t
)
value
))
return
NULL
;
uint64_t
id
=
0
;
if
(
!
napi_slot_get_u64
(
js
,
(
ant_value_t
)
value
,
SLOT_NAPI_EXTERNAL_ID
,
&
id
))
return
NULL
;
napi_external_entry_t
*
entry
=
NULL
;
HASH_FIND
(
hh
,
g_napi_externals
,
&
id
,
sizeof
(
id
),
entry
);
return
entry
;
}
static
napi_wrap_entry_t
*
napi_find_wrap
(
ant_t
*
js
,
napi_value
value
)
{
if
(
!
is_object_type
((
ant_value_t
)
value
))
return
NULL
;
uint64_t
id
=
0
;
if
(
!
napi_slot_get_u64
(
js
,
(
ant_value_t
)
value
,
SLOT_NAPI_WRAP_ID
,
&
id
))
return
NULL
;
napi_wrap_entry_t
*
entry
=
NULL
;
HASH_FIND
(
hh
,
g_napi_wraps
,
&
id
,
sizeof
(
id
),
entry
);
return
entry
;
}
static
bool
napi_get_typedarray_data
(
ant_t
*
js
,
napi_value
value
,
TypedArrayData
**
out
)
{
TypedArrayData
*
ta
=
buffer_get_typedarray_data
((
ant_value_t
)
value
);
if
(
!
ta
||
!
ta
->
buffer
||
ta
->
buffer
->
is_detached
)
return
false
;
*
out
=
ta
;
return
true
;
}
static
bool
napi_to_ant_typedarray_type
(
napi_typedarray_type
in
,
TypedArrayType
*
out
)
{
switch
(
in
)
{
case
napi_int8_array
:
*
out
=
TYPED_ARRAY_INT8
;
return
true
;
case
napi_uint8_array
:
*
out
=
TYPED_ARRAY_UINT8
;
return
true
;
case
napi_uint8_clamped_array
:
*
out
=
TYPED_ARRAY_UINT8_CLAMPED
;
return
true
;
case
napi_int16_array
:
*
out
=
TYPED_ARRAY_INT16
;
return
true
;
case
napi_uint16_array
:
*
out
=
TYPED_ARRAY_UINT16
;
return
true
;
case
napi_int32_array
:
*
out
=
TYPED_ARRAY_INT32
;
return
true
;
case
napi_uint32_array
:
*
out
=
TYPED_ARRAY_UINT32
;
return
true
;
case
napi_float32_array
:
*
out
=
TYPED_ARRAY_FLOAT32
;
return
true
;
case
napi_float64_array
:
*
out
=
TYPED_ARRAY_FLOAT64
;
return
true
;
case
napi_bigint64_array
:
*
out
=
TYPED_ARRAY_BIGINT64
;
return
true
;
case
napi_biguint64_array
:
*
out
=
TYPED_ARRAY_BIGUINT64
;
return
true
;
default
:
return
false
;
}
}
static
napi_typedarray_type
napi_from_ant_typedarray_type
(
TypedArrayType
in
)
{
switch
(
in
)
{
case
TYPED_ARRAY_INT8
:
return
napi_int8_array
;
case
TYPED_ARRAY_UINT8
:
return
napi_uint8_array
;
case
TYPED_ARRAY_UINT8_CLAMPED
:
return
napi_uint8_clamped_array
;
case
TYPED_ARRAY_INT16
:
return
napi_int16_array
;
case
TYPED_ARRAY_UINT16
:
return
napi_uint16_array
;
case
TYPED_ARRAY_INT32
:
return
napi_int32_array
;
case
TYPED_ARRAY_UINT32
:
return
napi_uint32_array
;
case
TYPED_ARRAY_FLOAT32
:
return
napi_float32_array
;
case
TYPED_ARRAY_FLOAT64
:
return
napi_float64_array
;
case
TYPED_ARRAY_BIGINT64
:
return
napi_bigint64_array
;
case
TYPED_ARRAY_BIGUINT64
:
return
napi_biguint64_array
;
default
:
return
napi_uint8_array
;
}
}
static
int
napi_desc_flags
(
napi_property_attributes
attributes
)
{
int
flags
=
0
;
if
(
attributes
&
napi_writable
)
flags
|=
JS_DESC_W
;
if
(
attributes
&
napi_enumerable
)
flags
|=
JS_DESC_E
;
if
(
attributes
&
napi_configurable
)
flags
|=
JS_DESC_C
;
return
flags
;
}
static
ant_value_t
napi_callback_trampoline
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
ant_value_t
current
=
js_getcurrentfunc
(
js
);
ant_value_t
data_slot
=
js_get_slot
(
current
,
SLOT_DATA
);
if
(
vtype
(
data_slot
)
!=
T_NUM
)
return
js_mkundef
();
napi_callback_binding_t
*
binding
=
(
napi_callback_binding_t
*
)(
uintptr_t
)
js_getnum
(
data_slot
);
if
(
!
binding
||
!
binding
->
cb
)
return
js_mkundef
();
ant_napi_env_t
*
nenv
=
binding
->
env
?
binding
->
env
:
napi_get_or_create_env
(
js
);
if
(
!
nenv
)
return
js_mkerr
(
js
,
"napi OOM"
);
struct
napi_callback_info__
info
=
{
.
env
=
nenv
,
.
argv
=
(
const
napi_value
*
)
args
,
.
argc
=
(
size_t
)(
nargs
<
0
?
0
:
nargs
),
.
this_arg
=
(
napi_value
)
js_getthis
(
js
),
.
new_target
=
(
napi_value
)
sv_vm_get_new_target
(
js
->
vm
,
js
),
.
data
=
binding
->
data
,
};
napi_value
ret
=
binding
->
cb
((
napi_env
)
nenv
,
(
napi_callback_info
)
&
info
);
if
(
nenv
->
has_pending_exception
)
{
ant_value_t
ex
=
(
ant_value_t
)
nenv
->
pending_exception
;
nenv
->
has_pending_exception
=
false
;
nenv
->
pending_exception
=
(
napi_value
)
js_mkundef
();
return
js_throw
(
js
,
ex
);
}
if
(
js
->
thrown_exists
)
{
return
js_throw
(
js
,
js
->
thrown_value
);
}
if
((
ant_value_t
)
ret
==
0
)
return
js_mkundef
();
return
(
ant_value_t
)
ret
;
}
static
napi_status
napi_create_function_common
(
napi_env
env
,
const
char
*
utf8name
,
size_t
length
,
napi_callback
cb
,
void
*
data
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
cb
||
!
result
)
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
napi_callback_binding_t
*
binding
=
(
napi_callback_binding_t
*
)
calloc
(
1
,
sizeof
(
*
binding
));
if
(
!
binding
)
return
napi_set_last
(
env
,
napi_generic_failure
,
"out of memory"
);
binding
->
env
=
nenv
;
binding
->
cb
=
cb
;
binding
->
data
=
data
;
ant_value_t
fn
=
js_heavy_mkfun
(
nenv
->
js
,
napi_callback_trampoline
,
ANT_PTR
(
binding
));
js_mark_constructor
(
fn
,
true
);
if
(
utf8name
&&
utf8name
[
0
])
{
size_t
nlen
=
(
length
==
NAPI_AUTO_LENGTH
)
?
strlen
(
utf8name
)
:
length
;
js_set
(
nenv
->
js
,
fn
,
"name"
,
js_mkstr
(
nenv
->
js
,
utf8name
,
nlen
));
}
*
result
=
NAPI_RETURN
(
nenv
,
fn
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
static
ant_value_t
napi_make_string
(
ant_t
*
js
,
const
char
*
s
,
size_t
len
)
{
if
(
!
s
)
return
js_mkstr
(
js
,
""
,
0
);
if
(
len
==
NAPI_AUTO_LENGTH
)
len
=
strlen
(
s
);
return
js_mkstr
(
js
,
s
,
len
);
}
static
bool
napi_checked_add_size
(
size_t
a
,
size_t
b
,
size_t
*
out
)
{
if
(
a
>
SIZE_MAX
-
b
)
return
false
;
*
out
=
a
+
b
;
return
true
;
}
static
bool
napi_checked_mul_size
(
size_t
a
,
size_t
b
,
size_t
*
out
)
{
if
(
a
!=
0
&&
b
>
SIZE_MAX
/
a
)
return
false
;
*
out
=
a
*
b
;
return
true
;
}
static
bool
napi_make_bigint_limbs
(
ant_t
*
js
,
const
uint32_t
*
limbs
,
size_t
count
,
bool
negative
,
ant_value_t
*
out
)
{
uint32_t
zero
=
0
;
if
(
!
out
)
return
false
;
if
(
!
limbs
||
count
==
0
)
{
limbs
=
&
zero
;
count
=
1
;
}
while
(
count
>
1
&&
limbs
[
count
-
1
]
==
0
)
count
--
;
if
(
count
==
1
&&
limbs
[
0
]
==
0
)
negative
=
false
;
if
(
count
>
UINT32_MAX
)
return
false
;
size_t
limbs_bytes
=
0
;
if
(
!
napi_checked_mul_size
(
count
,
sizeof
(
uint32_t
),
&
limbs_bytes
))
return
false
;
size_t
payload_size
=
0
;
if
(
!
napi_checked_add_size
(
offsetof
(
napi_bigint_payload_t
,
limbs
),
limbs_bytes
,
&
payload_size
))
{
return
false
;
}
napi_bigint_payload_t
*
payload
=
(
napi_bigint_payload_t
*
)
js_type_alloc
(
js
,
ANT_ALLOC_BIGINT
,
payload_size
,
_Alignof
(
napi_bigint_payload_t
)
);
if
(
!
payload
)
return
false
;
payload
->
sign
=
negative
?
1
:
0
;
payload
->
pad
[
0
]
=
0
;
payload
->
pad
[
1
]
=
0
;
payload
->
pad
[
2
]
=
0
;
payload
->
limb_count
=
(
uint32_t
)
count
;
memcpy
(
payload
->
limbs
,
limbs
,
limbs_bytes
);
*
out
=
mkval
(
T_BIGINT
,
(
uint64_t
)(
uintptr_t
)
payload
);
return
true
;
}
static
const
napi_bigint_payload_t
*
napi_bigint_payload
(
napi_value
value
)
{
return
(
const
napi_bigint_payload_t
*
)(
uintptr_t
)
vdata
((
ant_value_t
)
value
);
}
static
const
uint32_t
*
napi_bigint_limbs
(
napi_value
value
,
size_t
*
count
)
{
const
napi_bigint_payload_t
*
payload
=
napi_bigint_payload
(
value
);
if
(
!
payload
)
{
if
(
count
)
*
count
=
0
;
return
NULL
;
}
size_t
limb_count
=
payload
->
limb_count
;
if
(
limb_count
==
0
)
limb_count
=
1
;
while
(
limb_count
>
1
&&
payload
->
limbs
[
limb_count
-
1
]
==
0
)
limb_count
--
;
if
(
count
)
*
count
=
limb_count
;
return
payload
->
limbs
;
}
static
bool
napi_bigint_is_negative
(
napi_value
value
)
{
const
napi_bigint_payload_t
*
payload
=
napi_bigint_payload
(
value
);
return
payload
&&
payload
->
sign
==
1
;
}
static
bool
napi_bigint_limbs_is_zero
(
const
uint32_t
*
limbs
,
size_t
count
)
{
return
count
<=
1
&&
(
!
limbs
||
limbs
[
0
]
==
0
);
}
static
uint64_t
napi_bigint_low_u64
(
const
uint32_t
*
limbs
,
size_t
count
)
{
uint64_t
out
=
0
;
if
(
count
>
0
&&
limbs
)
out
|=
(
uint64_t
)
limbs
[
0
];
if
(
count
>
1
&&
limbs
)
out
|=
((
uint64_t
)
limbs
[
1
]
<<
32
);
return
out
;
}
static
bool
napi_parse_index_key
(
const
char
*
str
,
size_t
len
,
uint32_t
*
out
)
{
if
(
!
str
||
len
==
0
)
return
false
;
if
(
len
>
1
&&
str
[
0
]
==
'0'
)
return
false
;
uint64_t
acc
=
0
;
for
(
size_t
i
=
0
;
i
<
len
;
i
++
)
{
if
(
str
[
i
]
<
'0'
||
str
[
i
]
>
'9'
)
return
false
;
acc
=
(
acc
*
10
)
+
(
uint64_t
)(
str
[
i
]
-
'0'
);
if
(
acc
>
UINT32_MAX
)
return
false
;
}
if
(
out
)
*
out
=
(
uint32_t
)
acc
;
return
true
;
}
static
bool
napi_seen_has_key
(
ant_t
*
js
,
ant_value_t
seen
,
ant_value_t
key
)
{
if
(
vtype
(
key
)
==
T_SYMBOL
)
{
return
lkp_sym
(
js
,
seen
,
(
ant_offset_t
)
vdata
(
key
))
!=
0
;
}
size_t
len
=
0
;
const
char
*
str
=
js_getstr
(
js
,
key
,
&
len
);
return
str
&&
lkp
(
js
,
seen
,
str
,
len
)
!=
0
;
}
static
bool
napi_seen_add_key
(
ant_t
*
js
,
ant_value_t
seen
,
ant_value_t
key
)
{
ant_value_t
res
=
js_setprop
(
js
,
seen
,
key
,
js_true
);
return
!
is_err
(
res
);
}
static
bool
napi_key_passes_filter
(
const
ant_shape_prop_t
*
prop
,
napi_key_filter
key_filter
)
{
if
(
!
prop
)
return
false
;
if
((
key_filter
&
napi_key_writable
)
&&
!
(
prop
->
attrs
&
ANT_PROP_ATTR_WRITABLE
))
return
false
;
if
((
key_filter
&
napi_key_enumerable
)
&&
!
(
prop
->
attrs
&
ANT_PROP_ATTR_ENUMERABLE
))
return
false
;
if
((
key_filter
&
napi_key_configurable
)
&&
!
(
prop
->
attrs
&
ANT_PROP_ATTR_CONFIGURABLE
))
return
false
;
return
true
;
}
static
ant_value_t
napi_convert_property_key
(
ant_t
*
js
,
ant_value_t
key
,
napi_key_conversion
key_conversion
)
{
if
(
key_conversion
!=
napi_key_keep_numbers
||
vtype
(
key
)
!=
T_STR
)
return
key
;
size_t
len
=
0
;
const
char
*
str
=
js_getstr
(
js
,
key
,
&
len
);
uint32_t
idx
=
0
;
if
(
!
str
||
!
napi_parse_index_key
(
str
,
len
,
&
idx
))
return
key
;
return
js_mknum
((
double
)
idx
);
}
static
napi_status
napi_create_date_common
(
napi_env
env
,
double
time
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
ant_t
*
js
=
nenv
->
js
;
ant_value_t
ctor
=
js_get
(
js
,
js_glob
(
js
),
"Date"
);
if
(
!
is_callable
(
ctor
))
return
napi_set_last
(
env
,
napi_generic_failure
,
"Date constructor unavailable"
);
ant_value_t
obj
=
js_mkobj
(
js
);
ant_value_t
proto
=
js_get
(
js
,
ctor
,
"prototype"
);
if
(
is_object_type
(
proto
))
js_set_proto_init
(
obj
,
proto
);
ant_value_t
argv
[
1
]
=
{
js_mknum
(
time
)};
ant_value_t
saved
=
js
->
new_target
;
js
->
new_target
=
ctor
;
ant_value_t
out
=
sv_vm_call
(
js
->
vm
,
js
,
ctor
,
obj
,
argv
,
1
,
NULL
,
true
);
js
->
new_target
=
saved
;
if
(
is_err
(
out
)
||
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
out
);
*
result
=
NAPI_RETURN
(
nenv
,
is_object_type
(
out
)
?
out
:
obj
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
static
napi_status
napi_make_error_object
(
napi_env
env
,
const
char
*
name
,
napi_value
msg
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
ant_t
*
js
=
nenv
->
js
;
ant_value_t
message
=
(
ant_value_t
)
msg
;
if
(
vtype
(
message
)
!=
T_STR
)
{
message
=
coerce_to_str
(
js
,
message
);
if
(
is_err
(
message
))
return
napi_check_pending_from_result
(
env
,
message
);
}
ant_value_t
err
=
js_mkobj
(
js
);
js_set
(
js
,
err
,
"name"
,
js_mkstr
(
js
,
name
,
strlen
(
name
)));
js_set
(
js
,
err
,
"message"
,
message
);
ant_value_t
proto
=
js_get_ctor_proto
(
js
,
name
,
strlen
(
name
));
if
(
is_object_type
(
proto
))
js_set_proto_init
(
err
,
proto
);
*
result
=
NAPI_RETURN
(
nenv
,
err
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
static
napi_status
napi_throw_with_message
(
napi_env
env
,
js_err_type_t
err_type
,
const
char
*
msg
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid env"
);
ant_value_t
error
=
js_mkerr_typed
(
nenv
->
js
,
err_type
,
"%s"
,
msg
?
msg
:
""
);
if
(
is_err
(
error
)
&&
nenv
->
js
->
thrown_exists
)
{
napi_mark_pending_exception
(
env
,
(
napi_value
)
nenv
->
js
->
thrown_value
);
return
napi_pending_exception
;
}
if
(
is_err
(
error
))
return
napi_set_last
(
env
,
napi_generic_failure
,
"failed to create error"
);
return
napi_throw
(
env
,
(
napi_value
)
error
);
}
static
void
napi_tsfn_maybe_finish
(
struct
napi_threadsafe_function__
*
tsfn
);
static
void
napi_tsfn_async_cb
(
uv_async_t
*
handle
)
{
struct
napi_threadsafe_function__
*
tsfn
=
(
struct
napi_threadsafe_function__
*
)
handle
->
data
;
if
(
!
tsfn
||
!
tsfn
->
env
||
!
tsfn
->
env
->
js
)
return
;
ant_t
*
js
=
tsfn
->
env
->
js
;
for
(;;)
{
napi_tsfn_item_t
*
item
=
NULL
;
uv_mutex_lock
(
&
tsfn
->
mutex
);
if
(
tsfn
->
head
)
{
item
=
tsfn
->
head
;
tsfn
->
head
=
item
->
next
;
if
(
!
tsfn
->
head
)
tsfn
->
tail
=
NULL
;
tsfn
->
queue_size
--
;
}
bool
done
=
tsfn
->
closing
&&
tsfn
->
queue_size
==
0
;
uv_mutex_unlock
(
&
tsfn
->
mutex
);
if
(
!
item
)
{
if
(
done
)
napi_tsfn_maybe_finish
(
tsfn
);
break
;
}
ant_value_t
cb
=
tsfn
->
func_val
;
if
(
tsfn
->
call_js_cb
)
{
tsfn
->
call_js_cb
((
napi_env
)
tsfn
->
env
,
(
napi_value
)
cb
,
tsfn
->
context
,
item
->
data
);
}
else
if
(
is_callable
(
cb
))
{
sv_vm_call
(
js
->
vm
,
js
,
cb
,
js_mkundef
(),
NULL
,
0
,
NULL
,
false
);
}
free
(
item
);
}
}
static
void
napi_tsfn_close_cb
(
uv_handle_t
*
handle
)
{
struct
napi_threadsafe_function__
*
tsfn
=
(
struct
napi_threadsafe_function__
*
)
handle
->
data
;
if
(
!
tsfn
)
return
;
if
(
tsfn
->
thread_finalize_cb
)
{
tsfn
->
thread_finalize_cb
((
napi_env
)
tsfn
->
env
,
tsfn
->
thread_finalize_data
,
NULL
);
}
if
(
tsfn
->
env
)
{
if
(
tsfn
->
prev
)
tsfn
->
prev
->
next
=
tsfn
->
next
;
else
if
(
tsfn
->
env
->
tsfns
==
tsfn
)
tsfn
->
env
->
tsfns
=
tsfn
->
next
;
if
(
tsfn
->
next
)
tsfn
->
next
->
prev
=
tsfn
->
prev
;
}
if
(
tsfn
->
env
&&
tsfn
->
env
->
js
)
{
tsfn
->
func_val
=
js_mkundef
();
}
uv_mutex_destroy
(
&
tsfn
->
mutex
);
free
(
tsfn
);
}
static
void
napi_tsfn_maybe_finish
(
struct
napi_threadsafe_function__
*
tsfn
)
{
if
(
!
tsfn
)
return
;
uv_close
((
uv_handle_t
*
)
&
tsfn
->
async
,
napi_tsfn_close_cb
);
}
static
void
napi_async_work_execute_cb
(
uv_work_t
*
req
)
{
napi_async_work_impl_t
*
work
=
(
napi_async_work_impl_t
*
)
req
->
data
;
if
(
!
work
||
!
work
->
execute
)
return
;
work
->
execute
((
napi_env
)
work
->
env
,
work
->
data
);
}
static
void
napi_async_work_after_cb
(
uv_work_t
*
req
,
int
status
)
{
napi_async_work_impl_t
*
work
=
(
napi_async_work_impl_t
*
)
req
->
data
;
if
(
!
work
)
return
;
work
->
queued
=
false
;
if
(
work
->
complete
)
{
napi_status
st
=
(
status
==
UV_ECANCELED
)
?
napi_cancelled
:
napi_ok
;
work
->
complete
((
napi_env
)
work
->
env
,
st
,
work
->
data
);
}
if
(
work
->
delete_after_complete
)
free
(
work
);
}
static
ant_value_t
napi_dlopen_common
(
ant_t
*
js
,
ant_value_t
module_obj
,
const
char
*
filename
)
{
napi_env
env
=
ant_napi_get_env
(
js
);
if
(
!
env
)
return
js_mkerr
(
js
,
"napi env allocation failed"
);
if
(
!
is_object_type
(
module_obj
))
return
js_mkerr
(
js
,
"process.dlopen module must be an object"
);
if
(
!
filename
||
!
filename
[
0
])
return
js_mkerr
(
js
,
"process.dlopen filename must be a non-empty string"
);
g_pending_napi_module
=
NULL
;
void
*
handle
=
NAPI_DLOPEN
(
filename
,
NAPI_RTLD_NOW
|
NAPI_RTLD_GLOBAL
|
NAPI_RTLD_LOCAL
);
if
(
!
handle
)
{
const
char
*
msg
=
NAPI_DLERROR
();
return
js_mkerr
(
js
,
"Failed to load native module '%s': %s"
,
filename
,
msg
?
msg
:
"unknown"
);
}
napi_register_module_v1_fn
reg_fn
=
(
napi_register_module_v1_fn
)
NAPI_DLSYM
(
handle
,
"napi_register_module_v1"
);
ant_value_t
exports
=
js_get
(
js
,
module_obj
,
"exports"
);
if
(
!
is_object_type
(
exports
))
{
exports
=
js_mkobj
(
js
);
js_set
(
js
,
module_obj
,
"exports"
,
exports
);
}
ant_value_t
ret
=
js_mkundef
();
if
(
reg_fn
)
ret
=
(
ant_value_t
)
reg_fn
(
env
,
(
napi_value
)
exports
);
else
if
(
g_pending_napi_module
&&
g_pending_napi_module
->
nm_register_func
)
{
ret
=
(
ant_value_t
)
g_pending_napi_module
->
nm_register_func
(
env
,
(
napi_value
)
exports
);
}
else
return
js_mkerr
(
js
,
"No N-API registration entrypoint found in '%s'"
,
filename
);
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
nenv
->
has_pending_exception
||
js
->
thrown_exists
)
{
ant_value_t
ex
=
nenv
->
has_pending_exception
?
(
ant_value_t
)
nenv
->
pending_exception
:
js
->
thrown_value
;
nenv
->
has_pending_exception
=
false
;
nenv
->
pending_exception
=
(
napi_value
)
js_mkundef
();
return
js_throw
(
js
,
ex
);
}
if
(
is_object_type
(
ret
))
exports
=
ret
;
js_set
(
js
,
module_obj
,
"exports"
,
exports
);
js_set
(
js
,
module_obj
,
"loaded"
,
js_true
);
napi_native_lib_t
*
node
=
(
napi_native_lib_t
*
)
calloc
(
1
,
sizeof
(
*
node
));
if
(
node
)
{
node
->
handle
=
handle
;
node
->
next
=
g_napi_native_libs
;
g_napi_native_libs
=
node
;
}
return
exports
;
}
ant_value_t
napi_process_dlopen_js
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
if
(
nargs
<
2
)
return
js_mkerr
(
js
,
"process.dlopen(module, filename) requires 2 arguments"
);
if
(
!
is_object_type
(
args
[
0
]))
return
js_mkerr
(
js
,
"process.dlopen module must be an object"
);
if
(
vtype
(
args
[
1
])
!=
T_STR
)
return
js_mkerr
(
js
,
"process.dlopen filename must be a string"
);
size_t
path_len
=
0
;
const
char
*
path
=
js_getstr
(
js
,
args
[
1
],
&
path_len
);
if
(
!
path
||
path_len
==
0
)
return
js_mkerr
(
js
,
"process.dlopen filename must be non-empty"
);
ant_value_t
loaded
=
napi_dlopen_common
(
js
,
args
[
0
],
path
);
if
(
is_err
(
loaded
))
return
loaded
;
return
js_mkundef
();
}
ant_value_t
napi_load_native_module
(
ant_t
*
js
,
const
char
*
module_path
,
ant_value_t
ns
)
{
if
(
!
module_path
)
return
js_mkerr
(
js
,
"native module path is null"
);
ant_value_t
module_obj
=
js_mkobj
(
js
);
ant_value_t
exports_obj
=
js_mkobj
(
js
);
js_set
(
js
,
module_obj
,
"exports"
,
exports_obj
);
js_set
(
js
,
module_obj
,
"filename"
,
js_mkstr
(
js
,
module_path
,
strlen
(
module_path
)));
js_set
(
js
,
module_obj
,
"id"
,
js_mkstr
(
js
,
module_path
,
strlen
(
module_path
)));
js_set
(
js
,
module_obj
,
"loaded"
,
js_false
);
ant_value_t
process_obj
=
js_get
(
js
,
js_glob
(
js
),
"process"
);
ant_value_t
dlopen_fn
=
is_object_type
(
process_obj
)
?
js_get
(
js
,
process_obj
,
"dlopen"
)
:
js_mkundef
();
if
(
is_callable
(
dlopen_fn
))
{
ant_value_t
argv
[
2
]
=
{
module_obj
,
js_mkstr
(
js
,
module_path
,
strlen
(
module_path
))};
ant_value_t
dl_res
=
sv_vm_call
(
js
->
vm
,
js
,
dlopen_fn
,
process_obj
,
argv
,
2
,
NULL
,
false
);
if
(
is_err
(
dl_res
)
||
js
->
thrown_exists
)
return
js_throw
(
js
,
js
->
thrown_value
);
}
else
{
ant_value_t
load_res
=
napi_dlopen_common
(
js
,
module_obj
,
module_path
);
if
(
is_err
(
load_res
))
return
load_res
;
}
ant_value_t
exports_val
=
js_get
(
js
,
module_obj
,
"exports"
);
if
(
!
is_object_type
(
ns
))
return
exports_val
;
setprop_cstr
(
js
,
ns
,
"default"
,
7
,
exports_val
);
js_set_slot
(
ns
,
SLOT_DEFAULT
,
exports_val
);
if
(
!
is_object_type
(
exports_val
))
return
exports_val
;
ant_iter_t
iter
=
js_prop_iter_begin
(
js
,
exports_val
);
const
char
*
key
=
NULL
;
size_t
key_len
=
0
;
ant_value_t
value
=
js_mkundef
();
while
(
js_prop_iter_next
(
&
iter
,
&
key
,
&
key_len
,
&
value
))
{
if
(
key_len
==
7
&&
memcmp
(
key
,
"default"
,
7
)
==
0
)
continue
;
setprop_cstr
(
js
,
ns
,
key
,
key_len
,
value
);
}
js_prop_iter_end
(
&
iter
);
return
exports_val
;
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_last_error_info
(
node_api_basic_env
env
,
const
napi_extended_error_info
**
result
)
{
if
(
!
env
||
!
result
)
return
napi_invalid_arg
;
*
result
=
&
((
ant_napi_env_t
*
)
env
)
->
last_error
;
return
napi_ok
;
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_undefined
(
napi_env
env
,
napi_value
*
result
)
{
if
(
!
env
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
*
result
=
(
napi_value
)
js_mkundef
();
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_null
(
napi_env
env
,
napi_value
*
result
)
{
if
(
!
env
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
*
result
=
(
napi_value
)
js_mknull
();
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_global
(
napi_env
env
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
*
result
=
NAPI_RETURN
(
nenv
,
js_glob
(
nenv
->
js
));
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_boolean
(
napi_env
env
,
bool
value
,
napi_value
*
result
)
{
if
(
!
env
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
*
result
=
(
napi_value
)
js_bool
(
value
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_object
(
napi_env
env
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
*
result
=
NAPI_RETURN
(
nenv
,
js_mkobj
(
nenv
->
js
));
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_array
(
napi_env
env
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
*
result
=
NAPI_RETURN
(
nenv
,
js_mkarr
(
nenv
->
js
));
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_array_with_length
(
napi_env
env
,
size_t
length
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
ant_value_t
arr
=
js_mkarr
(
nenv
->
js
);
ant_value_t
r
=
js_setprop
(
nenv
->
js
,
arr
,
js_mkstr
(
nenv
->
js
,
"length"
,
6
),
js_mknum
((
double
)
length
)
);
if
(
is_err
(
r
)
||
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
r
);
*
result
=
NAPI_RETURN
(
nenv
,
arr
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_double
(
napi_env
env
,
double
value
,
napi_value
*
result
)
{
if
(
!
env
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
*
result
=
(
napi_value
)
js_mknum
(
value
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_int32
(
napi_env
env
,
int32_t
value
,
napi_value
*
result
)
{
if
(
!
env
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
*
result
=
(
napi_value
)
js_mknum
((
double
)
value
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_uint32
(
napi_env
env
,
uint32_t
value
,
napi_value
*
result
)
{
if
(
!
env
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
*
result
=
(
napi_value
)
js_mknum
((
double
)
value
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_int64
(
napi_env
env
,
int64_t
value
,
napi_value
*
result
)
{
if
(
!
env
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
*
result
=
(
napi_value
)
js_mknum
((
double
)
value
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_string_latin1
(
napi_env
env
,
const
char
*
str
,
size_t
length
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
||
!
str
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
*
result
=
NAPI_RETURN
(
nenv
,
napi_make_string
(
nenv
->
js
,
str
,
length
));
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_string_utf8
(
napi_env
env
,
const
char
*
str
,
size_t
length
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
||
!
str
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
*
result
=
NAPI_RETURN
(
nenv
,
napi_make_string
(
nenv
->
js
,
str
,
length
));
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_date
(
napi_env
env
,
double
time
,
napi_value
*
result
)
{
return
napi_create_date_common
(
env
,
time
,
result
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_bigint_int64
(
napi_env
env
,
int64_t
value
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
uint64_t
magnitude
=
value
<
0
?
(
uint64_t
)(
-
(
value
+
1
))
+
1
:
(
uint64_t
)
value
;
uint32_t
limbs
[
2
]
=
{
(
uint32_t
)(
magnitude
&
0xffffffffu
),
(
uint32_t
)(
magnitude
>>
32
)
};
size_t
count
=
limbs
[
1
]
==
0
?
1
:
2
;
ant_value_t
out
=
js_mkundef
();
if
(
!
napi_make_bigint_limbs
(
nenv
->
js
,
limbs
,
count
,
value
<
0
,
&
out
))
{
return
napi_set_last
(
env
,
napi_generic_failure
,
"out of memory"
);
}
*
result
=
NAPI_RETURN
(
nenv
,
out
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_bigint_uint64
(
napi_env
env
,
uint64_t
value
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
uint32_t
limbs
[
2
]
=
{
(
uint32_t
)(
value
&
0xffffffffu
),
(
uint32_t
)(
value
>>
32
)
};
size_t
count
=
limbs
[
1
]
==
0
?
1
:
2
;
ant_value_t
out
=
js_mkundef
();
if
(
!
napi_make_bigint_limbs
(
nenv
->
js
,
limbs
,
count
,
false
,
&
out
))
{
return
napi_set_last
(
env
,
napi_generic_failure
,
"out of memory"
);
}
*
result
=
NAPI_RETURN
(
nenv
,
out
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_bigint_words
(
napi_env
env
,
int
sign_bit
,
size_t
word_count
,
const
uint64_t
*
words
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
||
(
word_count
>
0
&&
!
words
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
size_t
limb_count
=
1
;
if
(
word_count
>
0
&&
!
napi_checked_mul_size
(
word_count
,
2
,
&
limb_count
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"word count overflow"
);
}
uint32_t
*
limbs
=
(
uint32_t
*
)
calloc
(
limb_count
,
sizeof
(
uint32_t
));
if
(
!
limbs
)
return
napi_set_last
(
env
,
napi_generic_failure
,
"out of memory"
);
if
(
word_count
==
0
)
limbs
[
0
]
=
0
;
else
for
(
size_t
i
=
0
;
i
<
word_count
;
i
++
)
{
limbs
[
i
*
2
]
=
(
uint32_t
)(
words
[
i
]
&
0xffffffffu
);
limbs
[(
i
*
2
)
+
1
]
=
(
uint32_t
)(
words
[
i
]
>>
32
);
}
ant_value_t
out
=
js_mkundef
();
bool
ok
=
napi_make_bigint_limbs
(
nenv
->
js
,
limbs
,
limb_count
,
sign_bit
!=
0
,
&
out
);
free
(
limbs
);
if
(
!
ok
)
return
napi_set_last
(
env
,
napi_generic_failure
,
"out of memory"
);
*
result
=
NAPI_RETURN
(
nenv
,
out
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_symbol
(
napi_env
env
,
napi_value
description
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
const
char
*
desc
=
NULL
;
if
(
vtype
((
ant_value_t
)
description
)
==
T_STR
)
{
desc
=
js_getstr
(
nenv
->
js
,
(
ant_value_t
)
description
,
NULL
);
}
else
if
(
!
is_undefined
((
ant_value_t
)
description
)
&&
!
is_null
((
ant_value_t
)
description
))
{
ant_value_t
s
=
coerce_to_str
(
nenv
->
js
,
(
ant_value_t
)
description
);
if
(
is_err
(
s
)
||
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
s
);
desc
=
js_getstr
(
nenv
->
js
,
s
,
NULL
);
}
*
result
=
NAPI_RETURN
(
nenv
,
js_mksym
(
nenv
->
js
,
desc
));
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_function
(
napi_env
env
,
const
char
*
utf8name
,
size_t
length
,
napi_callback
cb
,
void
*
data
,
napi_value
*
result
)
{
return
napi_create_function_common
(
env
,
utf8name
,
length
,
cb
,
data
,
result
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_error
(
napi_env
env
,
napi_value
code
,
napi_value
msg
,
napi_value
*
result
)
{
return
napi_make_error_object
(
env
,
"Error"
,
msg
,
result
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_type_error
(
napi_env
env
,
napi_value
code
,
napi_value
msg
,
napi_value
*
result
)
{
return
napi_make_error_object
(
env
,
"TypeError"
,
msg
,
result
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_range_error
(
napi_env
env
,
napi_value
code
,
napi_value
msg
,
napi_value
*
result
)
{
return
napi_make_error_object
(
env
,
"RangeError"
,
msg
,
result
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_external
(
napi_env
env
,
void
*
data
,
node_api_basic_finalize
finalize_cb
,
void
*
finalize_hint
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
napi_external_entry_t
*
entry
=
(
napi_external_entry_t
*
)
calloc
(
1
,
sizeof
(
*
entry
));
if
(
!
entry
)
return
napi_set_last
(
env
,
napi_generic_failure
,
"out of memory"
);
entry
->
id
=
g_napi_external_next_id
++
;
entry
->
data
=
data
;
entry
->
finalize_cb
=
finalize_cb
;
entry
->
finalize_hint
=
finalize_hint
;
HASH_ADD
(
hh
,
g_napi_externals
,
id
,
sizeof
(
entry
->
id
),
entry
);
ant_value_t
obj
=
js_mkobj
(
nenv
->
js
);
napi_slot_set_u64
(
nenv
->
js
,
obj
,
SLOT_NAPI_EXTERNAL_ID
,
entry
->
id
);
*
result
=
NAPI_RETURN
(
nenv
,
obj
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_promise
(
napi_env
env
,
napi_deferred
*
deferred
,
napi_value
*
promise
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
deferred
||
!
promise
)
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
struct
napi_deferred__
*
def
=
(
struct
napi_deferred__
*
)
calloc
(
1
,
sizeof
(
*
def
));
if
(
!
def
)
return
napi_set_last
(
env
,
napi_generic_failure
,
"out of memory"
);
ant_value_t
p
=
js_mkpromise
(
nenv
->
js
);
def
->
env
=
nenv
;
def
->
promise_val
=
p
;
def
->
settled
=
false
;
def
->
prev
=
NULL
;
def
->
next
=
nenv
->
deferreds
;
if
(
nenv
->
deferreds
)
nenv
->
deferreds
->
prev
=
def
;
nenv
->
deferreds
=
def
;
*
deferred
=
(
napi_deferred
)
def
;
*
promise
=
(
napi_value
)
p
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_resolve_deferred
(
napi_env
env
,
napi_deferred
deferred
,
napi_value
resolution
)
{
struct
napi_deferred__
*
def
=
(
struct
napi_deferred__
*
)
deferred
;
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
def
||
def
->
settled
)
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid deferred"
);
}
ant_value_t
promise
=
def
->
promise_val
;
js_resolve_promise
(
nenv
->
js
,
promise
,
(
ant_value_t
)
resolution
);
def
->
settled
=
true
;
def
->
promise_val
=
js_mkundef
();
if
(
def
->
prev
)
def
->
prev
->
next
=
def
->
next
;
else
if
(
nenv
->
deferreds
==
def
)
nenv
->
deferreds
=
def
->
next
;
if
(
def
->
next
)
def
->
next
->
prev
=
def
->
prev
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_reject_deferred
(
napi_env
env
,
napi_deferred
deferred
,
napi_value
rejection
)
{
struct
napi_deferred__
*
def
=
(
struct
napi_deferred__
*
)
deferred
;
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
def
||
def
->
settled
)
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid deferred"
);
}
ant_value_t
promise
=
def
->
promise_val
;
js_reject_promise
(
nenv
->
js
,
promise
,
(
ant_value_t
)
rejection
);
def
->
settled
=
true
;
def
->
promise_val
=
js_mkundef
();
if
(
def
->
prev
)
def
->
prev
->
next
=
def
->
next
;
else
if
(
nenv
->
deferreds
==
def
)
nenv
->
deferreds
=
def
->
next
;
if
(
def
->
next
)
def
->
next
->
prev
=
def
->
prev
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_buffer
(
napi_env
env
,
size_t
length
,
void
**
data
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
ArrayBufferData
*
buf
=
create_array_buffer_data
(
length
);
if
(
!
buf
)
return
napi_set_last
(
env
,
napi_generic_failure
,
"allocation failed"
);
ant_value_t
value
=
create_typed_array
(
nenv
->
js
,
TYPED_ARRAY_UINT8
,
buf
,
0
,
length
,
"Buffer"
);
if
(
is_err
(
value
))
return
napi_check_pending_from_result
(
env
,
value
);
if
(
data
)
*
data
=
buf
->
data
;
*
result
=
NAPI_RETURN
(
nenv
,
value
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_buffer_copy
(
napi_env
env
,
size_t
length
,
const
void
*
data
,
void
**
result_data
,
napi_value
*
result
)
{
void
*
buf_ptr
=
NULL
;
napi_status
st
=
napi_create_buffer
(
env
,
length
,
&
buf_ptr
,
result
);
if
(
st
!=
napi_ok
)
return
st
;
if
(
length
>
0
&&
data
&&
buf_ptr
)
memcpy
(
buf_ptr
,
data
,
length
);
if
(
result_data
)
*
result_data
=
buf_ptr
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_external_buffer
(
napi_env
env
,
size_t
length
,
void
*
data
,
node_api_basic_finalize
finalize_cb
,
void
*
finalize_hint
,
napi_value
*
result
)
{
(
void
)
finalize_cb
;
(
void
)
finalize_hint
;
return
napi_create_buffer_copy
(
env
,
length
,
data
,
NULL
,
result
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_arraybuffer
(
napi_env
env
,
size_t
byte_length
,
void
**
data
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
ArrayBufferData
*
ab
=
create_array_buffer_data
(
byte_length
);
if
(
!
ab
)
return
napi_set_last
(
env
,
napi_generic_failure
,
"allocation failed"
);
ant_value_t
ab_obj
=
create_arraybuffer_obj
(
nenv
->
js
,
ab
);
free_array_buffer_data
(
ab
);
if
(
data
)
*
data
=
ab
->
data
;
*
result
=
NAPI_RETURN
(
nenv
,
ab_obj
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_external_arraybuffer
(
napi_env
env
,
void
*
external_data
,
size_t
byte_length
,
node_api_basic_finalize
finalize_cb
,
void
*
finalize_hint
,
napi_value
*
result
)
{
(
void
)
finalize_cb
;
(
void
)
finalize_hint
;
void
*
out
=
NULL
;
napi_status
st
=
napi_create_arraybuffer
(
env
,
byte_length
,
&
out
,
result
);
if
(
st
!=
napi_ok
)
return
st
;
if
(
external_data
&&
out
&&
byte_length
>
0
)
memcpy
(
out
,
external_data
,
byte_length
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_set_instance_data
(
napi_env
env
,
void
*
data
,
node_api_basic_finalize
finalize_cb
,
void
*
finalize_hint
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid env"
);
nenv
->
instance_data
=
data
;
nenv
->
instance_data_finalize_cb
=
finalize_cb
;
nenv
->
instance_data_finalize_hint
=
finalize_hint
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_instance_data
(
napi_env
env
,
void
**
data
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
data
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
*
data
=
nenv
->
instance_data
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_typedarray
(
napi_env
env
,
napi_typedarray_type
type
,
size_t
length
,
napi_value
arraybuffer
,
size_t
byte_offset
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
||
!
is_object_type
((
ant_value_t
)
arraybuffer
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
ArrayBufferData
*
ab
=
buffer_get_arraybuffer_data
((
ant_value_t
)
arraybuffer
);
if
(
!
ab
||
ab
->
is_detached
)
return
napi_set_last
(
env
,
napi_arraybuffer_expected
,
"invalid arraybuffer"
);
TypedArrayType
ta_type
;
if
(
!
napi_to_ant_typedarray_type
(
type
,
&
ta_type
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid typedarray type"
);
}
size_t
element_size
=
1
;
switch
(
ta_type
)
{
case
TYPED_ARRAY_INT16
:
case
TYPED_ARRAY_UINT16
:
element_size
=
2
;
break
;
case
TYPED_ARRAY_INT32
:
case
TYPED_ARRAY_UINT32
:
case
TYPED_ARRAY_FLOAT32
:
element_size
=
4
;
break
;
case
TYPED_ARRAY_FLOAT64
:
case
TYPED_ARRAY_BIGINT64
:
case
TYPED_ARRAY_BIGUINT64
:
element_size
=
8
;
break
;
default
:
break
;
}
size_t
byte_len
=
length
*
element_size
;
if
(
byte_offset
+
byte_len
>
ab
->
length
)
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"typedarray out of bounds"
);
}
ant_value_t
out
=
create_typed_array_with_buffer
(
nenv
->
js
,
ta_type
,
ab
,
byte_offset
,
length
,
buffer_typedarray_type_name
(
ta_type
),
(
ant_value_t
)
arraybuffer
);
if
(
is_err
(
out
))
return
napi_check_pending_from_result
(
env
,
out
);
*
result
=
NAPI_RETURN
(
nenv
,
out
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_reference
(
napi_env
env
,
napi_value
value
,
uint32_t
initial_refcount
,
napi_ref
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
struct
napi_ref__
*
ref
=
(
struct
napi_ref__
*
)
calloc
(
1
,
sizeof
(
*
ref
));
if
(
!
ref
)
return
napi_set_last
(
env
,
napi_generic_failure
,
"out of memory"
);
ref
->
env
=
nenv
;
ref
->
value
=
value
;
ref
->
refcount
=
initial_refcount
;
ref
->
ref_val
=
(
initial_refcount
>
0
)
?
(
ant_value_t
)
value
:
js_mkundef
();
ref
->
prev
=
NULL
;
ref
->
next
=
nenv
->
refs
;
if
(
nenv
->
refs
)
nenv
->
refs
->
prev
=
ref
;
nenv
->
refs
=
ref
;
*
result
=
(
napi_ref
)
ref
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_delete_reference
(
node_api_basic_env
env
,
napi_ref
ref
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
struct
napi_ref__
*
r
=
(
struct
napi_ref__
*
)
ref
;
if
(
!
nenv
||
!
nenv
->
js
||
!
r
)
return
napi_set_last
((
napi_env
)
env
,
napi_invalid_arg
,
"invalid argument"
);
if
(
r
->
prev
)
r
->
prev
->
next
=
r
->
next
;
else
if
(
nenv
->
refs
==
r
)
nenv
->
refs
=
r
->
next
;
if
(
r
->
next
)
r
->
next
->
prev
=
r
->
prev
;
r
->
ref_val
=
js_mkundef
();
free
(
r
);
return
napi_set_last
((
napi_env
)
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_reference_ref
(
napi_env
env
,
napi_ref
ref
,
uint32_t
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
struct
napi_ref__
*
r
=
(
struct
napi_ref__
*
)
ref
;
if
(
!
nenv
||
!
nenv
->
js
||
!
r
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
if
(
r
->
refcount
==
0
)
r
->
ref_val
=
(
ant_value_t
)
r
->
value
;
r
->
refcount
++
;
if
(
result
)
*
result
=
r
->
refcount
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_reference_unref
(
napi_env
env
,
napi_ref
ref
,
uint32_t
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
struct
napi_ref__
*
r
=
(
struct
napi_ref__
*
)
ref
;
if
(
!
nenv
||
!
nenv
->
js
||
!
r
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
if
(
r
->
refcount
==
0
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"reference count already zero"
);
r
->
refcount
--
;
if
(
r
->
refcount
==
0
)
r
->
ref_val
=
js_mkundef
();
if
(
result
)
*
result
=
r
->
refcount
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_reference_value
(
napi_env
env
,
napi_ref
ref
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
struct
napi_ref__
*
r
=
(
struct
napi_ref__
*
)
ref
;
if
(
!
nenv
||
!
nenv
->
js
||
!
r
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
if
(
r
->
refcount
>
0
)
*
result
=
NAPI_RETURN
(
nenv
,
r
->
ref_val
);
else
*
result
=
r
->
value
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_value_double
(
napi_env
env
,
napi_value
value
,
double
*
result
)
{
if
(
!
env
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
if
(
vtype
((
ant_value_t
)
value
)
!=
T_NUM
)
return
napi_set_last
(
env
,
napi_number_expected
,
"number expected"
);
*
result
=
js_getnum
((
ant_value_t
)
value
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_value_int32
(
napi_env
env
,
napi_value
value
,
int32_t
*
result
)
{
if
(
!
env
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
if
(
vtype
((
ant_value_t
)
value
)
!=
T_NUM
)
return
napi_set_last
(
env
,
napi_number_expected
,
"number expected"
);
*
result
=
(
int32_t
)
js_getnum
((
ant_value_t
)
value
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_value_uint32
(
napi_env
env
,
napi_value
value
,
uint32_t
*
result
)
{
if
(
!
env
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
if
(
vtype
((
ant_value_t
)
value
)
!=
T_NUM
)
return
napi_set_last
(
env
,
napi_number_expected
,
"number expected"
);
*
result
=
(
uint32_t
)
js_getnum
((
ant_value_t
)
value
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_value_int64
(
napi_env
env
,
napi_value
value
,
int64_t
*
result
)
{
if
(
!
env
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
if
(
vtype
((
ant_value_t
)
value
)
!=
T_NUM
)
return
napi_set_last
(
env
,
napi_number_expected
,
"number expected"
);
*
result
=
(
int64_t
)
js_getnum
((
ant_value_t
)
value
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_value_bool
(
napi_env
env
,
napi_value
value
,
bool
*
result
)
{
if
(
!
env
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
if
(
vtype
((
ant_value_t
)
value
)
!=
T_BOOL
)
return
napi_set_last
(
env
,
napi_boolean_expected
,
"boolean expected"
);
*
result
=
((
ant_value_t
)
value
==
js_true
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
static
napi_status
napi_get_string_common
(
napi_env
env
,
napi_value
value
,
char
*
buf
,
size_t
bufsize
,
size_t
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid env"
);
if
(
vtype
((
ant_value_t
)
value
)
!=
T_STR
)
return
napi_set_last
(
env
,
napi_string_expected
,
"string expected"
);
size_t
len
=
0
;
const
char
*
str
=
js_getstr
(
nenv
->
js
,
(
ant_value_t
)
value
,
&
len
);
if
(
!
str
)
return
napi_set_last
(
env
,
napi_string_expected
,
"string expected"
);
if
(
result
)
*
result
=
len
;
if
(
!
buf
||
bufsize
==
0
)
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
size_t
n
=
(
len
<
(
bufsize
-
1
))
?
len
:
(
bufsize
-
1
);
memcpy
(
buf
,
str
,
n
);
buf
[
n
]
=
'\0'
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_value_string_utf8
(
napi_env
env
,
napi_value
value
,
char
*
buf
,
size_t
bufsize
,
size_t
*
result
)
{
return
napi_get_string_common
(
env
,
value
,
buf
,
bufsize
,
result
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_value_string_latin1
(
napi_env
env
,
napi_value
value
,
char
*
buf
,
size_t
bufsize
,
size_t
*
result
)
{
return
napi_get_string_common
(
env
,
value
,
buf
,
bufsize
,
result
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_value_string_utf16
(
napi_env
env
,
napi_value
value
,
char16_t
*
buf
,
size_t
bufsize
,
size_t
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid env"
);
if
(
vtype
((
ant_value_t
)
value
)
!=
T_STR
)
return
napi_set_last
(
env
,
napi_string_expected
,
"string expected"
);
size_t
byte_len
=
0
;
const
char
*
str
=
js_getstr
(
nenv
->
js
,
(
ant_value_t
)
value
,
&
byte_len
);
if
(
!
str
)
return
napi_set_last
(
env
,
napi_string_expected
,
"string expected"
);
size_t
utf16_len
=
utf16_strlen
(
str
,
byte_len
);
if
(
result
)
*
result
=
utf16_len
;
if
(
!
buf
||
bufsize
==
0
)
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
size_t
n
=
utf16_len
<
(
bufsize
-
1
)
?
utf16_len
:
(
bufsize
-
1
);
for
(
size_t
i
=
0
;
i
<
n
;
i
++
)
buf
[
i
]
=
(
char16_t
)
utf16_code_unit_at
(
str
,
byte_len
,
i
);
buf
[
n
]
=
0
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_date_value
(
napi_env
env
,
napi_value
value
,
double
*
result
)
{
if
(
!
env
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
if
(
!
is_date_instance
((
ant_value_t
)
value
))
return
napi_set_last
(
env
,
napi_date_expected
,
"date expected"
);
ant_value_t
time_val
=
js_get_slot
((
ant_value_t
)
value
,
SLOT_DATA
);
*
result
=
vtype
(
time_val
)
==
T_NUM
?
js_getnum
(
time_val
)
:
JS_NAN
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_value_bigint_int64
(
napi_env
env
,
napi_value
value
,
int64_t
*
result
,
bool
*
lossless
)
{
if
(
!
env
||
!
result
||
!
lossless
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
if
(
vtype
((
ant_value_t
)
value
)
!=
T_BIGINT
)
return
napi_set_last
(
env
,
napi_bigint_expected
,
"bigint expected"
);
size_t
limb_count
=
0
;
const
uint32_t
*
limbs
=
napi_bigint_limbs
(
value
,
&
limb_count
);
uint64_t
magnitude
=
napi_bigint_low_u64
(
limbs
,
limb_count
);
bool
negative
=
napi_bigint_is_negative
(
value
)
&&
!
napi_bigint_limbs_is_zero
(
limbs
,
limb_count
);
uint64_t
bits
=
negative
?
(
uint64_t
)(
~
magnitude
+
1
)
:
magnitude
;
*
result
=
(
int64_t
)
bits
;
*
lossless
=
limb_count
<=
2
&&
((
!
negative
&&
magnitude
<=
(
uint64_t
)
INT64_MAX
)
||
(
negative
&&
magnitude
<=
(
UINT64_C
(
1
)
<<
63
)));
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_value_bigint_uint64
(
napi_env
env
,
napi_value
value
,
uint64_t
*
result
,
bool
*
lossless
)
{
if
(
!
env
||
!
result
||
!
lossless
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
if
(
vtype
((
ant_value_t
)
value
)
!=
T_BIGINT
)
return
napi_set_last
(
env
,
napi_bigint_expected
,
"bigint expected"
);
size_t
limb_count
=
0
;
const
uint32_t
*
limbs
=
napi_bigint_limbs
(
value
,
&
limb_count
);
uint64_t
magnitude
=
napi_bigint_low_u64
(
limbs
,
limb_count
);
bool
negative
=
napi_bigint_is_negative
(
value
)
&&
!
napi_bigint_limbs_is_zero
(
limbs
,
limb_count
);
*
result
=
negative
?
(
uint64_t
)(
~
magnitude
+
1
)
:
magnitude
;
*
lossless
=
!
negative
&&
limb_count
<=
2
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_value_bigint_words
(
napi_env
env
,
napi_value
value
,
int
*
sign_bit
,
size_t
*
word_count
,
uint64_t
*
words
)
{
if
(
!
env
||
!
word_count
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
if
(
vtype
((
ant_value_t
)
value
)
!=
T_BIGINT
)
return
napi_set_last
(
env
,
napi_bigint_expected
,
"bigint expected"
);
size_t
limb_count
=
0
;
const
uint32_t
*
limbs
=
napi_bigint_limbs
(
value
,
&
limb_count
);
size_t
actual_words
=
limb_count
==
0
?
0
:
(
limb_count
+
1
)
/
2
;
size_t
capacity
=
words
?
*
word_count
:
0
;
if
(
sign_bit
)
{
bool
negative
=
napi_bigint_is_negative
(
value
)
&&
!
napi_bigint_limbs_is_zero
(
limbs
,
limb_count
);
*
sign_bit
=
negative
?
1
:
0
;
}
if
(
words
)
{
size_t
n
=
capacity
<
actual_words
?
capacity
:
actual_words
;
for
(
size_t
i
=
0
;
i
<
n
;
i
++
)
{
uint64_t
lo
=
i
*
2
<
limb_count
?
(
uint64_t
)
limbs
[
i
*
2
]
:
0
;
uint64_t
hi
=
(
i
*
2
+
1
)
<
limb_count
?
(
uint64_t
)
limbs
[
i
*
2
+
1
]
:
0
;
words
[
i
]
=
lo
|
(
hi
<<
32
);
}}
*
word_count
=
actual_words
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_value_external
(
napi_env
env
,
napi_value
value
,
void
**
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
napi_external_entry_t
*
entry
=
napi_find_external
(
nenv
->
js
,
value
);
if
(
!
entry
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"not an external"
);
*
result
=
entry
->
data
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_cb_info
(
napi_env
env
,
napi_callback_info
cbinfo
,
size_t
*
argc
,
napi_value
*
argv
,
napi_value
*
this_arg
,
void
**
data
)
{
struct
napi_callback_info__
*
info
=
(
struct
napi_callback_info__
*
)
cbinfo
;
if
(
!
env
||
!
info
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
if
(
argc
)
{
size_t
requested
=
*
argc
;
if
(
argv
)
{
size_t
ncopy
=
requested
<
info
->
argc
?
requested
:
info
->
argc
;
if
(
ncopy
>
0
)
memcpy
(
argv
,
info
->
argv
,
ncopy
*
sizeof
(
napi_value
));
for
(
size_t
i
=
ncopy
;
i
<
requested
;
i
++
)
argv
[
i
]
=
(
napi_value
)
js_mkundef
();
}
*
argc
=
info
->
argc
;
}
if
(
this_arg
)
*
this_arg
=
info
->
this_arg
;
if
(
data
)
*
data
=
info
->
data
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_new_target
(
napi_env
env
,
napi_callback_info
cbinfo
,
napi_value
*
result
)
{
struct
napi_callback_info__
*
info
=
(
struct
napi_callback_info__
*
)
cbinfo
;
if
(
!
env
||
!
info
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
ant_value_t
nt
=
(
ant_value_t
)
info
->
new_target
;
*
result
=
is_undefined
(
nt
)
?
(
napi_value
)
0
:
info
->
new_target
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_array_length
(
napi_env
env
,
napi_value
value
,
uint32_t
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
ant_value_t
v
=
(
ant_value_t
)
value
;
if
(
vtype
(
v
)
==
T_ARR
)
{
*
result
=
(
uint32_t
)
js_arr_len
(
nenv
->
js
,
v
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
ant_value_t
len
=
js_get
(
nenv
->
js
,
v
,
"length"
);
if
(
is_err
(
len
)
||
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
len
);
if
(
vtype
(
len
)
!=
T_NUM
)
return
napi_set_last
(
env
,
napi_array_expected
,
"array expected"
);
*
result
=
(
uint32_t
)
js_getnum
(
len
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_buffer_info
(
napi_env
env
,
napi_value
value
,
void
**
data
,
size_t
*
length
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid env"
);
TypedArrayData
*
ta
=
NULL
;
if
(
!
napi_get_typedarray_data
(
nenv
->
js
,
value
,
&
ta
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"not a buffer"
);
}
if
(
data
)
*
data
=
ta
->
buffer
->
data
+
ta
->
byte_offset
;
if
(
length
)
*
length
=
ta
->
byte_length
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_arraybuffer_info
(
napi_env
env
,
napi_value
arraybuffer
,
void
**
data
,
size_t
*
byte_length
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid env"
);
if
(
!
is_object_type
((
ant_value_t
)
arraybuffer
))
return
napi_set_last
(
env
,
napi_arraybuffer_expected
,
"arraybuffer expected"
);
ArrayBufferData
*
ab
=
buffer_get_arraybuffer_data
((
ant_value_t
)
arraybuffer
);
if
(
!
ab
||
ab
->
is_detached
)
return
napi_set_last
(
env
,
napi_arraybuffer_expected
,
"arraybuffer expected"
);
if
(
data
)
*
data
=
ab
->
data
;
if
(
byte_length
)
*
byte_length
=
ab
->
length
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_typedarray_info
(
napi_env
env
,
napi_value
typedarray
,
napi_typedarray_type
*
type
,
size_t
*
length
,
void
**
data
,
napi_value
*
arraybuffer
,
size_t
*
byte_offset
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid env"
);
TypedArrayData
*
ta
=
NULL
;
if
(
!
napi_get_typedarray_data
(
nenv
->
js
,
typedarray
,
&
ta
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"typedarray expected"
);
}
if
(
type
)
*
type
=
napi_from_ant_typedarray_type
(
ta
->
type
);
if
(
length
)
*
length
=
ta
->
length
;
if
(
data
)
*
data
=
ta
->
buffer
->
data
+
ta
->
byte_offset
;
if
(
arraybuffer
)
{
ant_value_t
buffer
=
js_get
(
nenv
->
js
,
(
ant_value_t
)
typedarray
,
"buffer"
);
if
(
is_err
(
buffer
)
||
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
buffer
);
*
arraybuffer
=
NAPI_RETURN
(
nenv
,
buffer
);
}
if
(
byte_offset
)
*
byte_offset
=
ta
->
byte_offset
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_prototype
(
napi_env
env
,
napi_value
object
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
ant_value_t
proto
=
js_get_proto
(
nenv
->
js
,
(
ant_value_t
)
object
);
if
(
is_err
(
proto
)
||
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
proto
);
*
result
=
NAPI_RETURN
(
nenv
,
proto
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_property_names
(
napi_env
env
,
napi_value
object
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
||
!
is_object_type
((
ant_value_t
)
object
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
ant_value_t
out
=
js_mkarr
(
nenv
->
js
);
ant_iter_t
iter
=
js_prop_iter_begin
(
nenv
->
js
,
(
ant_value_t
)
object
);
const
char
*
key
=
NULL
;
size_t
key_len
=
0
;
while
(
js_prop_iter_next
(
&
iter
,
&
key
,
&
key_len
,
NULL
))
{
js_arr_push
(
nenv
->
js
,
out
,
js_mkstr
(
nenv
->
js
,
key
,
key_len
));
}
js_prop_iter_end
(
&
iter
);
*
result
=
NAPI_RETURN
(
nenv
,
out
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_all_property_names
(
napi_env
env
,
napi_value
object
,
napi_key_collection_mode
key_mode
,
napi_key_filter
key_filter
,
napi_key_conversion
key_conversion
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
||
!
is_object_type
((
ant_value_t
)
object
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
ant_t
*
js
=
nenv
->
js
;
ant_value_t
out
=
js_mkarr
(
js
);
ant_value_t
seen
=
js_mkobj
(
js
);
ant_value_t
current
=
(
ant_value_t
)
object
;
while
(
is_object_type
(
current
))
{
ant_iter_t
iter
=
js_prop_iter_begin
(
js
,
current
);
ant_value_t
key
=
js_mkundef
();
while
(
js_prop_iter_next_val
(
&
iter
,
&
key
,
NULL
))
{
ant_object_t
*
obj_ptr
=
js_obj_ptr
(
js_as_obj
(
current
));
if
(
!
obj_ptr
||
!
obj_ptr
->
shape
||
iter
.
off
==
0
)
continue
;
const
ant_shape_prop_t
*
prop
=
ant_shape_prop_at
(
obj_ptr
->
shape
,
(
uint32_t
)(
iter
.
off
-
1
));
if
(
!
napi_key_passes_filter
(
prop
,
key_filter
))
continue
;
uint8_t
key_type
=
vtype
(
key
);
if
((
key_filter
&
napi_key_skip_strings
)
&&
key_type
!=
T_SYMBOL
)
continue
;
if
((
key_filter
&
napi_key_skip_symbols
)
&&
key_type
==
T_SYMBOL
)
continue
;
if
(
napi_seen_has_key
(
js
,
seen
,
key
))
continue
;
if
(
!
napi_seen_add_key
(
js
,
seen
,
key
))
{
js_prop_iter_end
(
&
iter
);
return
napi_set_last
(
env
,
napi_generic_failure
,
"failed to collect property names"
);
}
js_arr_push
(
js
,
out
,
napi_convert_property_key
(
js
,
key
,
key_conversion
));
if
(
js
->
thrown_exists
)
{
js_prop_iter_end
(
&
iter
);
return
napi_check_pending_from_result
(
env
,
js_mkundef
());
}}
js_prop_iter_end
(
&
iter
);
if
(
key_mode
==
napi_key_own_only
)
break
;
current
=
js_get_proto
(
js
,
current
);
if
(
is_err
(
current
)
||
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
current
);
}
*
result
=
NAPI_RETURN
(
nenv
,
out
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_version
(
node_api_basic_env
env
,
uint32_t
*
result
)
{
if
(
!
env
||
!
result
)
return
napi_set_last
((
napi_env
)
env
,
napi_invalid_arg
,
"invalid argument"
);
*
result
=
8
;
return
napi_set_last
((
napi_env
)
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_node_version
(
node_api_basic_env
env
,
const
napi_node_version
**
version
)
{
if
(
!
env
||
!
version
)
return
napi_set_last
((
napi_env
)
env
,
napi_invalid_arg
,
"invalid argument"
);
*
version
=
&
g_napi_node_version
;
return
napi_set_last
((
napi_env
)
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_set_property
(
napi_env
env
,
napi_value
object
,
napi_value
key
,
napi_value
value
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
is_object_type
((
ant_value_t
)
object
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
ant_value_t
r
=
js_setprop
(
nenv
->
js
,
(
ant_value_t
)
object
,
(
ant_value_t
)
key
,
(
ant_value_t
)
value
);
if
(
is_err
(
r
)
||
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
r
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_property
(
napi_env
env
,
napi_value
object
,
napi_value
key
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
||
!
is_object_type
((
ant_value_t
)
object
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
ant_value_t
k
=
(
ant_value_t
)
key
;
if
(
vtype
(
k
)
==
T_SYMBOL
)
{
ant_offset_t
off
=
lkp_sym_proto
(
nenv
->
js
,
(
ant_value_t
)
object
,
(
ant_offset_t
)
vdata
(
k
));
ant_value_t
out
=
off
?
js_propref_load
(
nenv
->
js
,
off
)
:
js_mkundef
();
if
(
is_err
(
out
)
||
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
out
);
*
result
=
NAPI_RETURN
(
nenv
,
out
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
ant_value_t
kstr
=
coerce_to_str
(
nenv
->
js
,
k
);
if
(
is_err
(
kstr
))
return
napi_check_pending_from_result
(
env
,
kstr
);
size_t
klen
=
0
;
const
char
*
ks
=
js_getstr
(
nenv
->
js
,
kstr
,
&
klen
);
if
(
!
ks
)
return
napi_set_last
(
env
,
napi_string_expected
,
"string expected"
);
char
*
name
=
(
char
*
)
malloc
(
klen
+
1
);
if
(
!
name
)
return
napi_set_last
(
env
,
napi_generic_failure
,
"out of memory"
);
memcpy
(
name
,
ks
,
klen
);
name
[
klen
]
=
'\0'
;
ant_value_t
out
=
js_getprop_fallback
(
nenv
->
js
,
(
ant_value_t
)
object
,
name
);
free
(
name
);
if
(
is_err
(
out
)
||
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
out
);
*
result
=
NAPI_RETURN
(
nenv
,
out
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_has_property
(
napi_env
env
,
napi_value
object
,
napi_value
key
,
bool
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
||
!
is_object_type
((
ant_value_t
)
object
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
ant_value_t
k
=
(
ant_value_t
)
key
;
if
(
vtype
(
k
)
==
T_SYMBOL
)
{
*
result
=
lkp_sym_proto
(
nenv
->
js
,
(
ant_value_t
)
object
,
(
ant_offset_t
)
vdata
(
k
))
!=
0
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
ant_value_t
kstr
=
coerce_to_str
(
nenv
->
js
,
k
);
if
(
is_err
(
kstr
)
||
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
kstr
);
size_t
len
=
0
;
const
char
*
s
=
js_getstr
(
nenv
->
js
,
kstr
,
&
len
);
*
result
=
s
&&
lkp_proto
(
nenv
->
js
,
(
ant_value_t
)
object
,
s
,
len
)
!=
0
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_delete_property
(
napi_env
env
,
napi_value
object
,
napi_value
key
,
bool
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
||
!
is_object_type
((
ant_value_t
)
object
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
ant_value_t
k
=
(
ant_value_t
)
key
;
ant_value_t
del_result
=
js_mkundef
();
if
(
vtype
(
k
)
==
T_SYMBOL
)
{
del_result
=
js_delete_sym_prop
(
nenv
->
js
,
(
ant_value_t
)
object
,
k
);
}
else
{
ant_value_t
kstr
=
coerce_to_str
(
nenv
->
js
,
k
);
if
(
is_err
(
kstr
)
||
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
kstr
);
size_t
len
=
0
;
const
char
*
s
=
js_getstr
(
nenv
->
js
,
kstr
,
&
len
);
del_result
=
js_delete_prop
(
nenv
->
js
,
(
ant_value_t
)
object
,
s
,
len
);
}
if
(
is_err
(
del_result
)
||
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
del_result
);
*
result
=
js_truthy
(
nenv
->
js
,
del_result
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_set_named_property
(
napi_env
env
,
napi_value
object
,
const
char
*
utf8name
,
napi_value
value
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
utf8name
||
!
is_object_type
((
ant_value_t
)
object
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
js_set
(
nenv
->
js
,
(
ant_value_t
)
object
,
utf8name
,
(
ant_value_t
)
value
);
return
napi_return_pending_if_any
(
env
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_named_property
(
napi_env
env
,
napi_value
object
,
const
char
*
utf8name
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
||
!
utf8name
||
!
is_object_type
((
ant_value_t
)
object
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
ant_value_t
out
=
js_getprop_fallback
(
nenv
->
js
,
(
ant_value_t
)
object
,
utf8name
);
if
(
is_err
(
out
)
||
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
out
);
*
result
=
NAPI_RETURN
(
nenv
,
out
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_has_named_property
(
napi_env
env
,
napi_value
object
,
const
char
*
utf8name
,
bool
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
||
!
utf8name
||
!
is_object_type
((
ant_value_t
)
object
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
*
result
=
lkp_proto
(
nenv
->
js
,
(
ant_value_t
)
object
,
utf8name
,
strlen
(
utf8name
))
!=
0
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_set_element
(
napi_env
env
,
napi_value
object
,
uint32_t
index
,
napi_value
value
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
is_object_type
((
ant_value_t
)
object
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
char
idx
[
32
];
int
n
=
snprintf
(
idx
,
sizeof
(
idx
),
"%u"
,
index
);
if
(
n
<
0
)
return
napi_set_last
(
env
,
napi_generic_failure
,
"index conversion failed"
);
ant_value_t
key
=
js_mkstr
(
nenv
->
js
,
idx
,
(
size_t
)
n
);
ant_value_t
r
=
js_setprop
(
nenv
->
js
,
(
ant_value_t
)
object
,
key
,
(
ant_value_t
)
value
);
if
(
is_err
(
r
)
||
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
r
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_element
(
napi_env
env
,
napi_value
object
,
uint32_t
index
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
||
!
is_object_type
((
ant_value_t
)
object
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
char
idx
[
32
];
snprintf
(
idx
,
sizeof
(
idx
),
"%u"
,
index
);
ant_value_t
out
=
js_get
(
nenv
->
js
,
(
ant_value_t
)
object
,
idx
);
if
(
is_err
(
out
)
||
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
out
);
*
result
=
NAPI_RETURN
(
nenv
,
out
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_has_element
(
napi_env
env
,
napi_value
object
,
uint32_t
index
,
bool
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
||
!
is_object_type
((
ant_value_t
)
object
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
char
idx
[
32
];
snprintf
(
idx
,
sizeof
(
idx
),
"%u"
,
index
);
*
result
=
lkp_proto
(
nenv
->
js
,
(
ant_value_t
)
object
,
idx
,
strlen
(
idx
))
!=
0
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_delete_element
(
napi_env
env
,
napi_value
object
,
uint32_t
index
,
bool
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
||
!
is_object_type
((
ant_value_t
)
object
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
char
idx
[
32
];
snprintf
(
idx
,
sizeof
(
idx
),
"%u"
,
index
);
ant_value_t
del
=
js_delete_prop
(
nenv
->
js
,
(
ant_value_t
)
object
,
idx
,
strlen
(
idx
));
if
(
is_err
(
del
)
||
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
del
);
*
result
=
js_truthy
(
nenv
->
js
,
del
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_define_properties
(
napi_env
env
,
napi_value
object
,
size_t
property_count
,
const
napi_property_descriptor
*
properties
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
is_object_type
((
ant_value_t
)
object
)
||
(
property_count
>
0
&&
!
properties
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
for
(
size_t
i
=
0
;
i
<
property_count
;
i
++
)
{
const
napi_property_descriptor
*
p
=
&
properties
[
i
];
ant_value_t
key
=
js_mkundef
();
const
char
*
key_str
=
NULL
;
size_t
key_len
=
0
;
if
(
p
->
utf8name
)
{
key_str
=
p
->
utf8name
;
key_len
=
strlen
(
p
->
utf8name
);
key
=
js_mkstr
(
nenv
->
js
,
key_str
,
key_len
);
}
else
key
=
(
ant_value_t
)
p
->
name
;
bool
is_symbol
=
(
vtype
(
key
)
==
T_SYMBOL
);
if
(
!
is_symbol
&&
!
key_str
)
{
if
(
vtype
(
key
)
!=
T_STR
)
continue
;
key_str
=
js_getstr
(
nenv
->
js
,
key
,
&
key_len
);
}
ant_value_t
value
=
js_mkundef
();
if
(
p
->
method
)
{
napi_value
fn
=
0
;
napi_status
st
=
napi_create_function_common
(
env
,
p
->
utf8name
,
NAPI_AUTO_LENGTH
,
p
->
method
,
p
->
data
,
&
fn
);
if
(
st
!=
napi_ok
)
return
st
;
value
=
(
ant_value_t
)
fn
;
}
else
if
(
p
->
getter
||
p
->
setter
)
{
napi_value
getter_fn
=
0
;
napi_value
setter_fn
=
0
;
if
(
p
->
getter
)
{
napi_status
st
=
napi_create_function_common
(
env
,
p
->
utf8name
,
NAPI_AUTO_LENGTH
,
p
->
getter
,
p
->
data
,
&
getter_fn
);
if
(
st
!=
napi_ok
)
return
st
;
}
if
(
p
->
setter
)
{
napi_status
st
=
napi_create_function_common
(
env
,
p
->
utf8name
,
NAPI_AUTO_LENGTH
,
p
->
setter
,
p
->
data
,
&
setter_fn
);
if
(
st
!=
napi_ok
)
return
st
;
}
int
flags
=
napi_desc_flags
(
p
->
attributes
);
ant_value_t
desc_obj
=
js_as_obj
((
ant_value_t
)
object
);
if
(
is_symbol
)
{
if
(
p
->
getter
)
js_set_sym_getter_desc
(
nenv
->
js
,
desc_obj
,
key
,
(
ant_value_t
)
getter_fn
,
flags
);
if
(
p
->
setter
)
js_set_sym_setter_desc
(
nenv
->
js
,
desc_obj
,
key
,
(
ant_value_t
)
setter_fn
,
flags
);
}
else
js_set_accessor_desc
(
nenv
->
js
,
desc_obj
,
key_str
,
key_len
,
p
->
getter
?
(
ant_value_t
)
getter_fn
:
js_mkundef
(),
p
->
setter
?
(
ant_value_t
)
setter_fn
:
js_mkundef
(),
flags
);
if
(
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
js_mkundef
());
continue
;
}
else
value
=
(
ant_value_t
)
p
->
value
;
if
(
is_symbol
)
js_set_sym
(
nenv
->
js
,
(
ant_value_t
)
object
,
key
,
value
);
else
{
js_set
(
nenv
->
js
,
(
ant_value_t
)
object
,
key_str
,
value
);
js_set_descriptor
(
nenv
->
js
,
js_as_obj
((
ant_value_t
)
object
),
key_str
,
key_len
,
napi_desc_flags
(
p
->
attributes
));
}
if
(
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
js_mkundef
());
}
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_define_class
(
napi_env
env
,
const
char
*
utf8name
,
size_t
length
,
napi_callback
constructor
,
void
*
data
,
size_t
property_count
,
const
napi_property_descriptor
*
properties
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
constructor
||
!
result
)
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
napi_status
st
=
napi_create_function_common
(
env
,
utf8name
,
length
,
constructor
,
data
,
result
);
if
(
st
!=
napi_ok
)
return
st
;
ant_value_t
ctor
=
(
ant_value_t
)
*
result
;
js_mark_constructor
(
ctor
,
true
);
ant_value_t
proto
=
js_get
(
nenv
->
js
,
ctor
,
"prototype"
);
if
(
is_err
(
proto
)
||
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
proto
);
if
(
!
is_object_type
(
proto
))
{
proto
=
js_mkobj
(
nenv
->
js
);
js_set
(
nenv
->
js
,
ctor
,
"prototype"
,
proto
);
if
(
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
js_mkundef
());
}
for
(
size_t
i
=
0
;
i
<
property_count
;
i
++
)
{
napi_property_descriptor
tmp
=
properties
[
i
];
bool
is_static
=
(
tmp
.
attributes
&
napi_static
)
!=
0
;
tmp
.
attributes
=
(
napi_property_attributes
)(
tmp
.
attributes
&
~
napi_static
);
st
=
napi_define_properties
(
env
,
(
napi_value
)(
is_static
?
ctor
:
proto
),
1
,
&
tmp
);
if
(
st
!=
napi_ok
)
return
st
;
}
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_has_own_property
(
napi_env
env
,
napi_value
object
,
napi_value
key
,
bool
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
||
!
is_object_type
((
ant_value_t
)
object
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
ant_value_t
k
=
(
ant_value_t
)
key
;
if
(
vtype
(
k
)
==
T_SYMBOL
)
{
*
result
=
lkp_sym
(
nenv
->
js
,
(
ant_value_t
)
object
,
(
ant_offset_t
)
vdata
(
k
))
!=
0
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
ant_value_t
kstr
=
coerce_to_str
(
nenv
->
js
,
k
);
if
(
is_err
(
kstr
)
||
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
kstr
);
size_t
len
=
0
;
const
char
*
s
=
js_getstr
(
nenv
->
js
,
kstr
,
&
len
);
*
result
=
s
&&
lkp
(
nenv
->
js
,
(
ant_value_t
)
object
,
s
,
len
)
!=
0
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_typeof
(
napi_env
env
,
napi_value
value
,
napi_valuetype
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
ant_value_t
v
=
(
ant_value_t
)
value
;
uint8_t
t
=
vtype
(
v
);
if
(
napi_find_external
(
nenv
->
js
,
value
))
{
*
result
=
napi_external
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
switch
(
t
)
{
case
T_UNDEF
:
*
result
=
napi_undefined
;
break
;
case
T_NULL
:
*
result
=
napi_null
;
break
;
case
T_BOOL
:
*
result
=
napi_boolean
;
break
;
case
T_NUM
:
*
result
=
napi_number
;
break
;
case
T_STR
:
*
result
=
napi_string
;
break
;
case
T_SYMBOL
:
*
result
=
napi_symbol
;
break
;
case
T_FUNC
:
case
T_CFUNC
:
*
result
=
napi_function
;
break
;
case
T_BIGINT
:
*
result
=
napi_bigint
;
break
;
default
:
*
result
=
napi_object
;
break
;
}
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_is_array
(
napi_env
env
,
napi_value
value
,
bool
*
result
)
{
if
(
!
env
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
*
result
=
vtype
((
ant_value_t
)
value
)
==
T_ARR
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_is_date
(
napi_env
env
,
napi_value
value
,
bool
*
result
)
{
if
(
!
env
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
*
result
=
is_date_instance
((
ant_value_t
)
value
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_is_arraybuffer
(
napi_env
env
,
napi_value
value
,
bool
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
if
(
!
is_object_type
((
ant_value_t
)
value
))
{
*
result
=
false
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
*
result
=
buffer_get_arraybuffer_data
((
ant_value_t
)
value
)
!=
NULL
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_is_buffer
(
napi_env
env
,
napi_value
value
,
bool
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
TypedArrayData
*
ta
=
NULL
;
if
(
!
napi_get_typedarray_data
(
nenv
->
js
,
value
,
&
ta
))
{
*
result
=
false
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
ant_value_t
buffer_proto
=
js_get_ctor_proto
(
nenv
->
js
,
"Buffer"
,
6
);
*
result
=
is_object_type
(
buffer_proto
)
&&
proto_chain_contains
(
nenv
->
js
,
(
ant_value_t
)
value
,
buffer_proto
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_is_typedarray
(
napi_env
env
,
napi_value
value
,
bool
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
TypedArrayData
*
ta
=
NULL
;
*
result
=
napi_get_typedarray_data
(
nenv
->
js
,
value
,
&
ta
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_is_dataview
(
napi_env
env
,
napi_value
value
,
bool
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
if
(
!
is_object_type
((
ant_value_t
)
value
))
{
*
result
=
false
;
}
else
{
*
result
=
buffer_get_dataview_data
((
ant_value_t
)
value
)
!=
NULL
;
}
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_is_error
(
napi_env
env
,
napi_value
value
,
bool
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
if
(
!
is_object_type
((
ant_value_t
)
value
))
{
*
result
=
false
;
}
else
{
ant_value_t
et
=
js_get_slot
((
ant_value_t
)
value
,
SLOT_ERR_TYPE
);
*
result
=
vtype
(
et
)
==
T_NUM
;
}
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_is_promise
(
napi_env
env
,
napi_value
value
,
bool
*
is_promise
)
{
if
(
!
env
||
!
is_promise
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
*
is_promise
=
vtype
((
ant_value_t
)
value
)
==
T_PROMISE
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_instanceof
(
napi_env
env
,
napi_value
object
,
napi_value
constructor
,
bool
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
ant_value_t
r
=
do_instanceof
(
nenv
->
js
,
(
ant_value_t
)
object
,
(
ant_value_t
)
constructor
);
if
(
is_err
(
r
)
||
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
r
);
*
result
=
js_truthy
(
nenv
->
js
,
r
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_strict_equals
(
napi_env
env
,
napi_value
lhs
,
napi_value
rhs
,
bool
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
*
result
=
strict_eq_values
(
nenv
->
js
,
(
ant_value_t
)
lhs
,
(
ant_value_t
)
rhs
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_call_function
(
napi_env
env
,
napi_value
recv
,
napi_value
func
,
size_t
argc
,
const
napi_value
*
argv
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
is_callable
((
ant_value_t
)
func
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
ant_value_t
out
=
sv_vm_call
(
nenv
->
js
->
vm
,
nenv
->
js
,
(
ant_value_t
)
func
,
(
ant_value_t
)
recv
,
(
ant_value_t
*
)
argv
,
(
int
)
argc
,
NULL
,
false
);
if
(
is_err
(
out
)
||
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
out
);
if
(
result
)
*
result
=
NAPI_RETURN
(
nenv
,
out
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_new_instance
(
napi_env
env
,
napi_value
constructor
,
size_t
argc
,
const
napi_value
*
argv
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
||
!
is_callable
((
ant_value_t
)
constructor
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
ant_value_t
ctor
=
(
ant_value_t
)
constructor
;
ant_value_t
obj
=
js_mkobj
(
nenv
->
js
);
ant_value_t
proto
=
js_get
(
nenv
->
js
,
ctor
,
"prototype"
);
if
(
is_object_type
(
proto
))
js_set_proto_init
(
obj
,
proto
);
ant_value_t
saved
=
nenv
->
js
->
new_target
;
nenv
->
js
->
new_target
=
ctor
;
ant_value_t
out
=
sv_vm_call
(
nenv
->
js
->
vm
,
nenv
->
js
,
ctor
,
obj
,
(
ant_value_t
*
)
argv
,
(
int
)
argc
,
NULL
,
true
);
nenv
->
js
->
new_target
=
saved
;
if
(
is_err
(
out
)
||
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
out
);
*
result
=
NAPI_RETURN
(
nenv
,
(
is_object_type
(
out
)
?
out
:
obj
));
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_coerce_to_bool
(
napi_env
env
,
napi_value
value
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
bool
truthy
=
js_truthy
(
nenv
->
js
,
(
ant_value_t
)
value
);
if
(
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
js_mkundef
());
*
result
=
NAPI_RETURN
(
nenv
,
js_bool
(
truthy
));
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_coerce_to_number
(
napi_env
env
,
napi_value
value
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
double
num
=
js_to_number
(
nenv
->
js
,
(
ant_value_t
)
value
);
if
(
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
js_mkundef
());
*
result
=
NAPI_RETURN
(
nenv
,
js_mknum
(
num
));
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_coerce_to_object
(
napi_env
env
,
napi_value
value
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
if
(
is_object_type
((
ant_value_t
)
value
))
{
*
result
=
value
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
ant_value_t
obj_ctor
=
js_get
(
nenv
->
js
,
js_glob
(
nenv
->
js
),
"Object"
);
if
(
is_err
(
obj_ctor
)
||
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
obj_ctor
);
if
(
!
is_callable
(
obj_ctor
))
return
napi_set_last
(
env
,
napi_generic_failure
,
"Object constructor missing"
);
ant_value_t
arg
=
(
ant_value_t
)
value
;
ant_value_t
out
=
sv_vm_call
(
nenv
->
js
->
vm
,
nenv
->
js
,
obj_ctor
,
js_mkundef
(),
&
arg
,
1
,
NULL
,
false
);
if
(
is_err
(
out
)
||
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
out
);
*
result
=
NAPI_RETURN
(
nenv
,
out
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_coerce_to_string
(
napi_env
env
,
napi_value
value
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
ant_value_t
out
=
coerce_to_str
(
nenv
->
js
,
(
ant_value_t
)
value
);
if
(
is_err
(
out
)
||
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
out
);
*
result
=
NAPI_RETURN
(
nenv
,
out
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_throw_error
(
napi_env
env
,
const
char
*
code
,
const
char
*
msg
)
{
(
void
)
code
;
return
napi_throw_with_message
(
env
,
JS_ERR_GENERIC
,
msg
?
msg
:
""
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_throw_type_error
(
napi_env
env
,
const
char
*
code
,
const
char
*
msg
)
{
(
void
)
code
;
return
napi_throw_with_message
(
env
,
JS_ERR_TYPE
,
msg
?
msg
:
""
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_throw_range_error
(
napi_env
env
,
const
char
*
code
,
const
char
*
msg
)
{
(
void
)
code
;
return
napi_throw_with_message
(
env
,
JS_ERR_RANGE
,
msg
?
msg
:
""
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_is_exception_pending
(
napi_env
env
,
bool
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
*
result
=
nenv
->
has_pending_exception
||
nenv
->
js
->
thrown_exists
;
return
napi_set_last_raw
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_and_clear_last_exception
(
napi_env
env
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
if
(
nenv
->
has_pending_exception
)
{
*
result
=
nenv
->
pending_exception
;
nenv
->
has_pending_exception
=
false
;
nenv
->
pending_exception
=
(
napi_value
)
js_mkundef
();
}
else
if
(
nenv
->
js
->
thrown_exists
)
{
*
result
=
NAPI_RETURN
(
nenv
,
nenv
->
js
->
thrown_value
);
nenv
->
js
->
thrown_exists
=
false
;
nenv
->
js
->
thrown_value
=
js_mkundef
();
nenv
->
js
->
thrown_stack
=
js_mkundef
();
}
else
{
*
result
=
NAPI_RETURN
(
nenv
,
js_mkundef
());
}
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
void
NAPI_CDECL
napi_fatal_error
(
const
char
*
location
,
size_t
location_len
,
const
char
*
message
,
size_t
message_len
)
{
fprintf
(
stderr
,
"N-API fatal error at %.*s: %.*s
\n
"
,
(
int
)
location_len
,
location
?
location
:
""
,
(
int
)
message_len
,
message
?
message
:
""
);
abort
();
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_fatal_exception
(
napi_env
env
,
napi_value
err
)
{
return
napi_throw
(
env
,
err
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_wrap
(
napi_env
env
,
napi_value
js_object
,
void
*
native_object
,
node_api_basic_finalize
finalize_cb
,
void
*
finalize_hint
,
napi_ref
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
is_object_type
((
ant_value_t
)
js_object
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
napi_wrap_entry_t
*
entry
=
napi_find_wrap
(
nenv
->
js
,
js_object
);
if
(
!
entry
)
{
entry
=
(
napi_wrap_entry_t
*
)
calloc
(
1
,
sizeof
(
*
entry
));
if
(
!
entry
)
return
napi_set_last
(
env
,
napi_generic_failure
,
"out of memory"
);
entry
->
id
=
g_napi_wrap_next_id
++
;
HASH_ADD
(
hh
,
g_napi_wraps
,
id
,
sizeof
(
entry
->
id
),
entry
);
napi_slot_set_u64
(
nenv
->
js
,
(
ant_value_t
)
js_object
,
SLOT_NAPI_WRAP_ID
,
entry
->
id
);
}
entry
->
native_object
=
native_object
;
entry
->
finalize_cb
=
finalize_cb
;
entry
->
finalize_hint
=
finalize_hint
;
entry
->
has_wrap
=
true
;
if
(
result
)
{
return
napi_create_reference
(
env
,
js_object
,
0
,
result
);
}
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_add_finalizer
(
napi_env
env
,
napi_value
js_object
,
void
*
finalize_data
,
node_api_basic_finalize
finalize_cb
,
void
*
finalize_hint
,
napi_ref
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
is_object_type
((
ant_value_t
)
js_object
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
napi_wrap_entry_t
*
entry
=
napi_find_wrap
(
nenv
->
js
,
js_object
);
if
(
!
entry
)
{
entry
=
(
napi_wrap_entry_t
*
)
calloc
(
1
,
sizeof
(
*
entry
));
if
(
!
entry
)
return
napi_set_last
(
env
,
napi_generic_failure
,
"out of memory"
);
entry
->
id
=
g_napi_wrap_next_id
++
;
HASH_ADD
(
hh
,
g_napi_wraps
,
id
,
sizeof
(
entry
->
id
),
entry
);
napi_slot_set_u64
(
nenv
->
js
,
(
ant_value_t
)
js_object
,
SLOT_NAPI_WRAP_ID
,
entry
->
id
);
}
entry
->
attached_data
=
finalize_data
;
entry
->
attached_finalize_cb
=
finalize_cb
;
entry
->
attached_finalize_hint
=
finalize_hint
;
if
(
result
)
return
napi_create_reference
(
env
,
js_object
,
0
,
result
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_unwrap
(
napi_env
env
,
napi_value
js_object
,
void
**
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
||
!
is_object_type
((
ant_value_t
)
js_object
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
napi_wrap_entry_t
*
entry
=
napi_find_wrap
(
nenv
->
js
,
js_object
);
if
(
!
entry
||
!
entry
->
has_wrap
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"object not wrapped"
);
*
result
=
entry
->
native_object
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_remove_wrap
(
napi_env
env
,
napi_value
js_object
,
void
**
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
is_object_type
((
ant_value_t
)
js_object
))
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
napi_wrap_entry_t
*
entry
=
napi_find_wrap
(
nenv
->
js
,
js_object
);
if
(
!
entry
||
!
entry
->
has_wrap
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"object not wrapped"
);
if
(
result
)
*
result
=
entry
->
native_object
;
entry
->
native_object
=
NULL
;
entry
->
finalize_cb
=
NULL
;
entry
->
finalize_hint
=
NULL
;
entry
->
has_wrap
=
false
;
if
(
!
entry
->
attached_finalize_cb
)
{
HASH_DEL
(
g_napi_wraps
,
entry
);
free
(
entry
);
js_set_slot
((
ant_value_t
)
js_object
,
SLOT_NAPI_WRAP_ID
,
js_mkundef
());
}
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_open_handle_scope
(
napi_env
env
,
napi_handle_scope
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
struct
napi_handle_scope__
*
scope
=
(
struct
napi_handle_scope__
*
)
calloc
(
1
,
sizeof
(
*
scope
));
if
(
!
scope
)
return
napi_set_last
(
env
,
napi_generic_failure
,
"out of memory"
);
scope
->
env
=
nenv
;
scope
->
gc_root_mark
=
gc_root_scope
(
nenv
->
js
);
scope
->
handle_slots_mark
=
nenv
->
handle_slots_len
;
nenv
->
open_handle_scopes
++
;
*
result
=
(
napi_handle_scope
)
scope
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_close_handle_scope
(
napi_env
env
,
napi_handle_scope
scope
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
scope
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
struct
napi_handle_scope__
*
s
=
(
struct
napi_handle_scope__
*
)
scope
;
if
(
nenv
->
js
)
gc_pop_roots
(
nenv
->
js
,
s
->
gc_root_mark
);
nenv
->
handle_slots_len
=
s
->
handle_slots_mark
;
if
(
nenv
->
open_handle_scopes
>
0
)
nenv
->
open_handle_scopes
--
;
free
(
scope
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_open_escapable_handle_scope
(
napi_env
env
,
napi_escapable_handle_scope
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
struct
napi_escapable_handle_scope__
*
scope
=
(
struct
napi_escapable_handle_scope__
*
)
calloc
(
1
,
sizeof
(
*
scope
));
if
(
!
scope
)
return
napi_set_last
(
env
,
napi_generic_failure
,
"out of memory"
);
scope
->
env
=
nenv
;
scope
->
gc_root_mark
=
gc_root_scope
(
nenv
->
js
);
scope
->
handle_slots_mark
=
nenv
->
handle_slots_len
;
scope
->
escaped
=
false
;
scope
->
escaped_val
=
js_mkundef
();
nenv
->
open_handle_scopes
++
;
*
result
=
(
napi_escapable_handle_scope
)
scope
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_close_escapable_handle_scope
(
napi_env
env
,
napi_escapable_handle_scope
scope
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
scope
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
struct
napi_escapable_handle_scope__
*
s
=
(
struct
napi_escapable_handle_scope__
*
)
scope
;
if
(
nenv
->
js
)
gc_pop_roots
(
nenv
->
js
,
s
->
gc_root_mark
);
nenv
->
handle_slots_len
=
s
->
handle_slots_mark
;
if
(
nenv
->
open_handle_scopes
>
0
)
nenv
->
open_handle_scopes
--
;
free
(
scope
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_escape_handle
(
napi_env
env
,
napi_escapable_handle_scope
scope
,
napi_value
escapee
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
struct
napi_escapable_handle_scope__
*
esc
=
(
struct
napi_escapable_handle_scope__
*
)
scope
;
if
(
!
nenv
||
!
nenv
->
js
||
!
esc
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
if
(
esc
->
escaped
)
return
napi_set_last
(
env
,
napi_escape_called_twice
,
"escape already called"
);
esc
->
escaped
=
true
;
esc
->
escaped_val
=
(
ant_value_t
)
escapee
;
gc_push_root
(
nenv
->
js
,
&
esc
->
escaped_val
);
*
result
=
escapee
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_async_work
(
napi_env
env
,
napi_value
async_resource
,
napi_value
async_resource_name
,
napi_async_execute_callback
execute
,
napi_async_complete_callback
complete
,
void
*
data
,
napi_async_work
*
result
)
{
(
void
)
async_resource
;
(
void
)
async_resource_name
;
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
execute
||
!
result
)
{
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
}
napi_async_work_impl_t
*
work
=
(
napi_async_work_impl_t
*
)
calloc
(
1
,
sizeof
(
*
work
));
if
(
!
work
)
return
napi_set_last
(
env
,
napi_generic_failure
,
"out of memory"
);
work
->
env
=
nenv
;
work
->
execute
=
execute
;
work
->
complete
=
complete
;
work
->
data
=
data
;
work
->
req
.
data
=
work
;
*
result
=
(
napi_async_work
)
work
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_delete_async_work
(
napi_env
env
,
napi_async_work
work
)
{
(
void
)
env
;
napi_async_work_impl_t
*
w
=
(
napi_async_work_impl_t
*
)
work
;
if
(
!
w
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
if
(
w
->
queued
)
{
w
->
delete_after_complete
=
true
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
free
(
w
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_queue_async_work
(
node_api_basic_env
env
,
napi_async_work
work
)
{
napi_async_work_impl_t
*
w
=
(
napi_async_work_impl_t
*
)
work
;
if
(
!
env
||
!
w
)
return
napi_set_last
((
napi_env
)
env
,
napi_invalid_arg
,
"invalid argument"
);
if
(
w
->
queued
)
return
napi_set_last
((
napi_env
)
env
,
napi_invalid_arg
,
"already queued"
);
int
rc
=
uv_queue_work
(
uv_default_loop
(),
&
w
->
req
,
napi_async_work_execute_cb
,
napi_async_work_after_cb
);
if
(
rc
!=
0
)
return
napi_set_last
((
napi_env
)
env
,
napi_generic_failure
,
"uv_queue_work failed"
);
w
->
queued
=
true
;
return
napi_set_last
((
napi_env
)
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_cancel_async_work
(
node_api_basic_env
env
,
napi_async_work
work
)
{
napi_async_work_impl_t
*
w
=
(
napi_async_work_impl_t
*
)
work
;
if
(
!
env
||
!
w
)
return
napi_set_last
((
napi_env
)
env
,
napi_invalid_arg
,
"invalid argument"
);
int
rc
=
uv_cancel
((
uv_req_t
*
)
&
w
->
req
);
if
(
rc
!=
0
)
return
napi_set_last
((
napi_env
)
env
,
napi_generic_failure
,
"uv_cancel failed"
);
return
napi_set_last
((
napi_env
)
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_create_threadsafe_function
(
napi_env
env
,
napi_value
func
,
napi_value
async_resource
,
napi_value
async_resource_name
,
size_t
max_queue_size
,
size_t
initial_thread_count
,
void
*
thread_finalize_data
,
napi_finalize
thread_finalize_cb
,
void
*
context
,
napi_threadsafe_function_call_js
call_js_cb
,
napi_threadsafe_function
*
result
)
{
(
void
)
async_resource
;
(
void
)
async_resource_name
;
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
struct
napi_threadsafe_function__
*
tsfn
=
(
struct
napi_threadsafe_function__
*
)
calloc
(
1
,
sizeof
(
*
tsfn
));
if
(
!
tsfn
)
return
napi_set_last
(
env
,
napi_generic_failure
,
"out of memory"
);
tsfn
->
env
=
nenv
;
tsfn
->
call_js_cb
=
call_js_cb
;
tsfn
->
thread_finalize_cb
=
thread_finalize_cb
;
tsfn
->
thread_finalize_data
=
thread_finalize_data
;
tsfn
->
context
=
context
;
tsfn
->
max_queue_size
=
max_queue_size
;
tsfn
->
thread_count
=
initial_thread_count
>
0
?
initial_thread_count
:
1
;
tsfn
->
func_val
=
func
?
(
ant_value_t
)
func
:
js_mkundef
();
uv_mutex_init
(
&
tsfn
->
mutex
);
int
rc
=
uv_async_init
(
uv_default_loop
(),
&
tsfn
->
async
,
napi_tsfn_async_cb
);
if
(
rc
!=
0
)
{
uv_mutex_destroy
(
&
tsfn
->
mutex
);
free
(
tsfn
);
return
napi_set_last
(
env
,
napi_generic_failure
,
"uv_async_init failed"
);
}
tsfn
->
async
.
data
=
tsfn
;
tsfn
->
prev
=
NULL
;
tsfn
->
next
=
nenv
->
tsfns
;
if
(
nenv
->
tsfns
)
nenv
->
tsfns
->
prev
=
tsfn
;
nenv
->
tsfns
=
tsfn
;
*
result
=
(
napi_threadsafe_function
)
tsfn
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_call_threadsafe_function
(
napi_threadsafe_function
func
,
void
*
data
,
napi_threadsafe_function_call_mode
is_blocking
)
{
(
void
)
is_blocking
;
struct
napi_threadsafe_function__
*
tsfn
=
(
struct
napi_threadsafe_function__
*
)
func
;
if
(
!
tsfn
)
return
napi_invalid_arg
;
uv_mutex_lock
(
&
tsfn
->
mutex
);
if
(
tsfn
->
closing
||
tsfn
->
aborted
)
{
uv_mutex_unlock
(
&
tsfn
->
mutex
);
return
napi_closing
;
}
if
(
tsfn
->
max_queue_size
>
0
&&
tsfn
->
queue_size
>=
tsfn
->
max_queue_size
)
{
uv_mutex_unlock
(
&
tsfn
->
mutex
);
return
napi_queue_full
;
}
napi_tsfn_item_t
*
item
=
(
napi_tsfn_item_t
*
)
calloc
(
1
,
sizeof
(
*
item
));
if
(
!
item
)
{
uv_mutex_unlock
(
&
tsfn
->
mutex
);
return
napi_generic_failure
;
}
item
->
data
=
data
;
if
(
!
tsfn
->
head
)
tsfn
->
head
=
item
;
else
tsfn
->
tail
->
next
=
item
;
tsfn
->
tail
=
item
;
tsfn
->
queue_size
++
;
uv_mutex_unlock
(
&
tsfn
->
mutex
);
uv_async_send
(
&
tsfn
->
async
);
return
napi_ok
;
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_release_threadsafe_function
(
napi_threadsafe_function
func
,
napi_threadsafe_function_release_mode
mode
)
{
struct
napi_threadsafe_function__
*
tsfn
=
(
struct
napi_threadsafe_function__
*
)
func
;
if
(
!
tsfn
)
return
napi_invalid_arg
;
uv_mutex_lock
(
&
tsfn
->
mutex
);
if
(
mode
==
napi_tsfn_abort
)
tsfn
->
aborted
=
true
;
if
(
tsfn
->
thread_count
>
0
)
tsfn
->
thread_count
--
;
if
(
tsfn
->
thread_count
==
0
||
tsfn
->
aborted
)
tsfn
->
closing
=
true
;
uv_mutex_unlock
(
&
tsfn
->
mutex
);
uv_async_send
(
&
tsfn
->
async
);
return
napi_ok
;
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_acquire_threadsafe_function
(
napi_threadsafe_function
func
)
{
struct
napi_threadsafe_function__
*
tsfn
=
(
struct
napi_threadsafe_function__
*
)
func
;
if
(
!
tsfn
)
return
napi_invalid_arg
;
uv_mutex_lock
(
&
tsfn
->
mutex
);
if
(
tsfn
->
closing
)
{
uv_mutex_unlock
(
&
tsfn
->
mutex
);
return
napi_closing
;
}
tsfn
->
thread_count
++
;
uv_mutex_unlock
(
&
tsfn
->
mutex
);
return
napi_ok
;
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_ref_threadsafe_function
(
node_api_basic_env
env
,
napi_threadsafe_function
func
)
{
(
void
)
env
;
struct
napi_threadsafe_function__
*
tsfn
=
(
struct
napi_threadsafe_function__
*
)
func
;
if
(
!
tsfn
)
return
napi_invalid_arg
;
uv_ref
((
uv_handle_t
*
)
&
tsfn
->
async
);
return
napi_ok
;
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_unref_threadsafe_function
(
node_api_basic_env
env
,
napi_threadsafe_function
func
)
{
(
void
)
env
;
struct
napi_threadsafe_function__
*
tsfn
=
(
struct
napi_threadsafe_function__
*
)
func
;
if
(
!
tsfn
)
return
napi_invalid_arg
;
uv_unref
((
uv_handle_t
*
)
&
tsfn
->
async
);
return
napi_ok
;
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_threadsafe_function_context
(
napi_threadsafe_function
func
,
void
**
result
)
{
struct
napi_threadsafe_function__
*
tsfn
=
(
struct
napi_threadsafe_function__
*
)
func
;
if
(
!
tsfn
||
!
result
)
return
napi_invalid_arg
;
*
result
=
tsfn
->
context
;
return
napi_ok
;
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_run_script
(
napi_env
env
,
napi_value
script
,
napi_value
*
result
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
nenv
->
js
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
if
(
vtype
((
ant_value_t
)
script
)
!=
T_STR
)
return
napi_set_last
(
env
,
napi_string_expected
,
"script must be string"
);
size_t
len
=
0
;
const
char
*
src
=
js_getstr
(
nenv
->
js
,
(
ant_value_t
)
script
,
&
len
);
if
(
!
src
)
return
napi_set_last
(
env
,
napi_string_expected
,
"script must be string"
);
ant_value_t
out
=
js_eval_bytecode_eval
(
nenv
->
js
,
src
,
len
);
if
(
is_err
(
out
)
||
nenv
->
js
->
thrown_exists
)
return
napi_check_pending_from_result
(
env
,
out
);
*
result
=
NAPI_RETURN
(
nenv
,
out
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_adjust_external_memory
(
node_api_basic_env
env
,
int64_t
change_in_bytes
,
int64_t
*
adjusted_value
)
{
if
(
!
env
)
return
napi_invalid_arg
;
g_napi_external_memory
+=
change_in_bytes
;
if
(
adjusted_value
)
*
adjusted_value
=
g_napi_external_memory
;
return
napi_set_last
((
napi_env
)
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_add_env_cleanup_hook
(
node_api_basic_env
env
,
napi_cleanup_hook
fun
,
void
*
arg
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
fun
)
return
napi_set_last
((
napi_env
)
env
,
napi_invalid_arg
,
"invalid argument"
);
napi_cleanup_hook_entry_t
*
entry
=
(
napi_cleanup_hook_entry_t
*
)
calloc
(
1
,
sizeof
(
*
entry
));
if
(
!
entry
)
return
napi_set_last
((
napi_env
)
env
,
napi_generic_failure
,
"out of memory"
);
entry
->
hook
=
fun
;
entry
->
arg
=
arg
;
entry
->
next
=
nenv
->
cleanup_hooks
;
nenv
->
cleanup_hooks
=
entry
;
return
napi_set_last
((
napi_env
)
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_remove_env_cleanup_hook
(
node_api_basic_env
env
,
napi_cleanup_hook
fun
,
void
*
arg
)
{
ant_napi_env_t
*
nenv
=
(
ant_napi_env_t
*
)
env
;
if
(
!
nenv
||
!
fun
)
return
napi_set_last
((
napi_env
)
env
,
napi_invalid_arg
,
"invalid argument"
);
napi_cleanup_hook_entry_t
**
pp
=
&
nenv
->
cleanup_hooks
;
while
(
*
pp
)
{
if
((
*
pp
)
->
hook
==
fun
&&
(
*
pp
)
->
arg
==
arg
)
{
napi_cleanup_hook_entry_t
*
victim
=
*
pp
;
*
pp
=
victim
->
next
;
free
(
victim
);
return
napi_set_last
((
napi_env
)
env
,
napi_ok
,
NULL
);
}
pp
=
&
(
*
pp
)
->
next
;
}
return
napi_set_last
((
napi_env
)
env
,
napi_invalid_arg
,
"cleanup hook not found"
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_open_callback_scope
(
napi_env
env
,
napi_value
resource_object
,
napi_async_context
context
,
napi_callback_scope
*
result
)
{
(
void
)
resource_object
;
(
void
)
context
;
if
(
!
env
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
struct
napi_callback_scope__
*
scope
=
(
struct
napi_callback_scope__
*
)
calloc
(
1
,
sizeof
(
*
scope
));
if
(
!
scope
)
return
napi_set_last
(
env
,
napi_generic_failure
,
"out of memory"
);
scope
->
env
=
(
ant_napi_env_t
*
)
env
;
*
result
=
(
napi_callback_scope
)
scope
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_close_callback_scope
(
napi_env
env
,
napi_callback_scope
scope
)
{
(
void
)
env
;
if
(
!
scope
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
free
(
scope
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_async_init
(
napi_env
env
,
napi_value
async_resource
,
napi_value
async_resource_name
,
napi_async_context
*
result
)
{
(
void
)
async_resource
;
(
void
)
async_resource_name
;
if
(
!
env
||
!
result
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
struct
napi_async_context__
*
ctx
=
(
struct
napi_async_context__
*
)
calloc
(
1
,
sizeof
(
*
ctx
));
if
(
!
ctx
)
return
napi_set_last
(
env
,
napi_generic_failure
,
"out of memory"
);
ctx
->
env
=
(
ant_napi_env_t
*
)
env
;
*
result
=
(
napi_async_context
)
ctx
;
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_async_destroy
(
napi_env
env
,
napi_async_context
async_context
)
{
(
void
)
env
;
if
(
!
async_context
)
return
napi_set_last
(
env
,
napi_invalid_arg
,
"invalid argument"
);
free
(
async_context
);
return
napi_set_last
(
env
,
napi_ok
,
NULL
);
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_make_callback
(
napi_env
env
,
napi_async_context
async_context
,
napi_value
recv
,
napi_value
func
,
size_t
argc
,
const
napi_value
*
argv
,
napi_value
*
result
)
{
(
void
)
async_context
;
return
napi_call_function
(
env
,
recv
,
func
,
argc
,
argv
,
result
);
}
NAPI_EXTERN
void
NAPI_CDECL
napi_module_register
(
napi_module
*
mod
)
{
g_pending_napi_module
=
mod
;
}
NAPI_EXTERN
napi_status
NAPI_CDECL
napi_get_uv_event_loop
(
node_api_basic_env
env
,
struct
uv_loop_s
**
loop
)
{
if
(
!
env
||
!
loop
)
return
napi_set_last
((
napi_env
)
env
,
napi_invalid_arg
,
"invalid argument"
);
*
loop
=
uv_default_loop
();
return
napi_set_last
((
napi_env
)
env
,
napi_ok
,
NULL
);
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Sat, May 2, 9:11 AM (2 d)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
541694
Default Alt Text
napi.c (107 KB)
Attached To
Mode
rANT Ant
Attached
Detach File
Event Timeline
Log In to Comment