@auto_js/napi 0.0.7 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CMakeLists.txt +12 -1
- package/api/finalizer.cc +12 -14
- package/api/napi_scheduler.cc +3 -3
- package/api/napi_scheduler.h.cc +7 -6
- package/api/threadsafe_function.cc +10 -9
- package/api/uv_dlib.cc +4 -3
- package/handle/reference.cc +2 -2
- package/handle/remote.cc +1 -0
- package/handle/types.cc +10 -0
- package/package.json +4 -4
- package/support/host.cc +190 -81
- package/support/host.h.cc +26 -10
- package/support/promise.cc +8 -6
- package/support/win32_delay_load_hook.cc +12 -0
- package/transfer/visit.cc +88 -79
- package/value/array_buffer.cc +3 -5
- package/value/primitive.h.cc +13 -0
- package/support/host_shim.cc +0 -42
package/CMakeLists.txt
CHANGED
|
@@ -18,7 +18,6 @@ target_sources(${napi_js}
|
|
|
18
18
|
api/uv_dlib.cc
|
|
19
19
|
api/uv_scheduler.cc
|
|
20
20
|
support/environment.cc
|
|
21
|
-
support/host_shim.cc
|
|
22
21
|
support/host.cc
|
|
23
22
|
support/initialize.cc
|
|
24
23
|
transfer/accept.cc
|
|
@@ -69,3 +68,15 @@ target_sources(${napi_js}
|
|
|
69
68
|
value/record.h.cc
|
|
70
69
|
value/value.cc
|
|
71
70
|
)
|
|
71
|
+
|
|
72
|
+
# Enable "delay load" for win32 otherwise the dll will attempt to load node.exe from PATH as a
|
|
73
|
+
# shared library and then start invoking functions from it.
|
|
74
|
+
if(WIN32)
|
|
75
|
+
set(napi_js_delay_load ${napi_js}_delay_load)
|
|
76
|
+
add_library(${napi_js_delay_load} STATIC)
|
|
77
|
+
set_target_properties(${napi_js_delay_load} PROPERTIES CXX_VISIBILITY_PRESET default)
|
|
78
|
+
target_sources(${napi_js_delay_load} PUBLIC support/win32_delay_load_hook.cc)
|
|
79
|
+
target_link_libraries(${napi_js_delay_load} PUBLIC delayimp.lib)
|
|
80
|
+
target_link_libraries(${napi_js} PUBLIC ${napi_js_delay_load})
|
|
81
|
+
target_link_options(${napi_js_delay_load} PUBLIC "-Wl,/DELAYLOAD:node.exe")
|
|
82
|
+
endif()
|
package/api/finalizer.cc
CHANGED
|
@@ -7,15 +7,14 @@ namespace js::napi {
|
|
|
7
7
|
|
|
8
8
|
// Generic finalizer for basic `std::unique_ptr<T>`
|
|
9
9
|
template <class Env, class Type, class Deleter>
|
|
10
|
-
auto make_finalizer(std::type_identity<Env> /*type*/, std::unique_ptr<Type, Deleter
|
|
10
|
+
auto make_finalizer(std::type_identity<Env> /*type*/, std::unique_ptr<Type, Deleter> unique) {
|
|
11
11
|
if constexpr (std::is_empty_v<Deleter>) {
|
|
12
12
|
// Finalizer uses a default-constructed deleter
|
|
13
13
|
auto finalize = [](Env /*env*/, void* data, void* /*hint*/) -> void {
|
|
14
14
|
Deleter deleter{};
|
|
15
15
|
deleter(static_cast<Type*>(data));
|
|
16
16
|
};
|
|
17
|
-
|
|
18
|
-
return std::tuple{finalize, nullptr, release};
|
|
17
|
+
return std::tuple{finalize, nullptr, std::move(unique)};
|
|
19
18
|
} else {
|
|
20
19
|
static_assert(std::is_trivially_destructible_v<Deleter>);
|
|
21
20
|
static_assert(sizeof(Deleter) == sizeof(void*));
|
|
@@ -23,28 +22,26 @@ auto make_finalizer(std::type_identity<Env> /*type*/, std::unique_ptr<Type, Dele
|
|
|
23
22
|
auto finalize = [](Env /*env*/, void* data, void* hint) -> void {
|
|
24
23
|
std::bit_cast<Deleter>(hint)(static_cast<Type*>(data));
|
|
25
24
|
};
|
|
26
|
-
|
|
27
|
-
return std::tuple{finalize, std::bit_cast<void*>(unique->get_deleter()), release};
|
|
25
|
+
return std::tuple{finalize, std::bit_cast<void*>(unique.get_deleter()), std::move(unique)};
|
|
28
26
|
}
|
|
29
27
|
}
|
|
30
28
|
|
|
31
29
|
// Generic finalizer for `std::shared_ptr<T>`
|
|
32
30
|
template <class Env, class Type>
|
|
33
|
-
auto make_finalizer(std::type_identity<Env> /*type*/, std::shared_ptr<Type
|
|
31
|
+
auto make_finalizer(std::type_identity<Env> /*type*/, std::shared_ptr<Type> shared) {
|
|
34
32
|
// `shared_ptr<T>*` is passed as the finalizer hint
|
|
35
33
|
using shared_ptr_type = std::shared_ptr<Type>;
|
|
36
|
-
auto* ptr = shared
|
|
37
|
-
auto ptr_ptr = std::make_unique<shared_ptr_type>(std::move(
|
|
34
|
+
auto* ptr = shared.get();
|
|
35
|
+
auto ptr_ptr = std::make_unique<shared_ptr_type>(std::move(shared));
|
|
38
36
|
auto finalize = [](Env /*env*/, void* /*data*/, void* hint) -> void {
|
|
39
37
|
delete static_cast<shared_ptr_type*>(hint);
|
|
40
38
|
};
|
|
41
|
-
|
|
42
|
-
return std::tuple{finalize, ptr_ptr.get(), std::move(release)};
|
|
39
|
+
return std::tuple{finalize, ptr_ptr.get(), std::move(ptr_ptr)};
|
|
43
40
|
}
|
|
44
41
|
|
|
45
42
|
// Apply a finalizer to the given smart pointer type
|
|
46
43
|
template <class Pointer, class Apply>
|
|
47
|
-
auto apply_finalizer(Pointer
|
|
44
|
+
auto apply_finalizer(Pointer smart_ptr, Apply apply) -> decltype(auto) {
|
|
48
45
|
using element_type = Pointer::element_type;
|
|
49
46
|
constexpr auto napi_env_type = []() consteval -> auto {
|
|
50
47
|
if constexpr (std::invocable<Apply, element_type*, node_api_basic_finalize, void*>) {
|
|
@@ -54,11 +51,12 @@ auto apply_finalizer(Pointer unique, Apply apply) -> decltype(auto) {
|
|
|
54
51
|
return type<napi_env>;
|
|
55
52
|
}
|
|
56
53
|
}();
|
|
57
|
-
auto
|
|
54
|
+
auto* pointer = smart_ptr.get();
|
|
55
|
+
auto [ finalize, hint, releasable ] = make_finalizer(napi_env_type, std::move(smart_ptr));
|
|
58
56
|
auto result = util::regular_return{[ & ] -> decltype(auto) {
|
|
59
|
-
return apply(
|
|
57
|
+
return apply(pointer, finalize, hint);
|
|
60
58
|
}}();
|
|
61
|
-
release();
|
|
59
|
+
releasable.release();
|
|
62
60
|
return *std::move(result);
|
|
63
61
|
}
|
|
64
62
|
|
package/api/napi_scheduler.cc
CHANGED
|
@@ -10,11 +10,11 @@ napi_scheduler::napi_scheduler(napi_env env) :
|
|
|
10
10
|
fn_.unref(env);
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
napi_scheduler::operator bool() const {
|
|
13
|
+
napi_scheduler::operator bool() const noexcept {
|
|
14
14
|
return bool{fn_};
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
auto napi_scheduler::close(threadsafe_function_type::close_callback close) -> void {
|
|
17
|
+
auto napi_scheduler::close(threadsafe_function_type::close_callback close) noexcept -> void {
|
|
18
18
|
fn_.close(close);
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -32,7 +32,7 @@ auto napi_scheduler::increment_ref(node_api_basic_env env) const -> void {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
auto napi_scheduler::storage::operator()(napi_env env, napi_value value, task_type& task) -> void {
|
|
35
|
+
auto napi_scheduler::storage::operator()(napi_env env, napi_value value, task_type& task) noexcept -> void {
|
|
36
36
|
task(env, value);
|
|
37
37
|
}
|
|
38
38
|
|
package/api/napi_scheduler.h.cc
CHANGED
|
@@ -10,21 +10,22 @@ namespace js::napi {
|
|
|
10
10
|
export class napi_scheduler {
|
|
11
11
|
private:
|
|
12
12
|
struct storage;
|
|
13
|
-
using task_type = util::move_only_function<auto(napi_env, napi_value)->void>;
|
|
13
|
+
using task_type = util::move_only_function<auto(napi_env, napi_value) noexcept -> void>;
|
|
14
14
|
using threadsafe_function_type = threadsafe_function_of<storage, task_type>;
|
|
15
15
|
|
|
16
16
|
public:
|
|
17
|
+
napi_scheduler() = default;
|
|
17
18
|
explicit napi_scheduler(napi_env env);
|
|
18
|
-
auto operator()(auto task, auto&&... args) const -> bool;
|
|
19
|
-
explicit operator bool() const;
|
|
20
|
-
auto close(threadsafe_function_type::close_callback close) -> void;
|
|
19
|
+
auto operator()(auto task, auto&&... args) const noexcept -> bool;
|
|
20
|
+
explicit operator bool() const noexcept;
|
|
21
|
+
auto close(threadsafe_function_type::close_callback close) noexcept -> void;
|
|
21
22
|
auto decrement_ref(node_api_basic_env env) const -> void;
|
|
22
23
|
auto increment_ref(node_api_basic_env env) const -> void;
|
|
23
24
|
|
|
24
25
|
private:
|
|
25
26
|
struct storage {
|
|
26
27
|
storage() = default;
|
|
27
|
-
auto operator()(napi_env env, napi_value value, task_type& task) -> void;
|
|
28
|
+
auto operator()(napi_env env, napi_value value, task_type& task) noexcept -> void;
|
|
28
29
|
int refs{};
|
|
29
30
|
};
|
|
30
31
|
|
|
@@ -43,7 +44,7 @@ export class napi_schedulable {
|
|
|
43
44
|
|
|
44
45
|
// ---
|
|
45
46
|
|
|
46
|
-
auto napi_scheduler::operator()(auto task, auto&&... args) const -> bool {
|
|
47
|
+
auto napi_scheduler::operator()(auto task, auto&&... args) const noexcept -> bool {
|
|
47
48
|
return fn_(
|
|
48
49
|
[ task = std::move(task),
|
|
49
50
|
... args = std::forward<decltype(args)>(args) ](
|
|
@@ -13,6 +13,7 @@ class threadsafe_function_of : util::non_copyable {
|
|
|
13
13
|
public:
|
|
14
14
|
using close_callback = util::function_ref<auto()->void>;
|
|
15
15
|
|
|
16
|
+
threadsafe_function_of() = default;
|
|
16
17
|
explicit threadsafe_function_of(auto& env, napi_value value, auto&&... args);
|
|
17
18
|
threadsafe_function_of(const threadsafe_function_of&);
|
|
18
19
|
threadsafe_function_of(threadsafe_function_of&&) noexcept;
|
|
@@ -20,12 +21,12 @@ class threadsafe_function_of : util::non_copyable {
|
|
|
20
21
|
auto operator=(const threadsafe_function_of&) -> threadsafe_function_of& = delete;
|
|
21
22
|
auto operator=(threadsafe_function_of&&) -> threadsafe_function_of& = delete;
|
|
22
23
|
|
|
23
|
-
auto close(close_callback callback) -> void;
|
|
24
|
+
auto close(close_callback callback) noexcept -> void;
|
|
24
25
|
auto ref(node_api_basic_env env) const -> void;
|
|
25
26
|
auto unref(node_api_basic_env env) const -> void;
|
|
26
|
-
auto operator()(Message message) const -> bool;
|
|
27
|
-
auto operator*() const -> Context& { return get(); }
|
|
28
|
-
explicit operator bool() const { return tsfn_ != nullptr; }
|
|
27
|
+
auto operator()(Message message) const noexcept -> bool;
|
|
28
|
+
auto operator*() const noexcept -> Context& { return get(); }
|
|
29
|
+
explicit operator bool() const noexcept { return tsfn_ != nullptr; }
|
|
29
30
|
|
|
30
31
|
private:
|
|
31
32
|
struct storage : Context {
|
|
@@ -36,11 +37,11 @@ class threadsafe_function_of : util::non_copyable {
|
|
|
36
37
|
private:
|
|
37
38
|
close_callback close_hook_{[] -> void {}};
|
|
38
39
|
};
|
|
39
|
-
auto get() const -> storage&;
|
|
40
|
+
auto get() const noexcept -> storage&;
|
|
40
41
|
|
|
41
42
|
constexpr static auto trivial_message =
|
|
42
43
|
std::is_trivially_destructible_v<Message> && sizeof(Message) <= sizeof(void*);
|
|
43
|
-
mutable napi_threadsafe_function tsfn_;
|
|
44
|
+
mutable napi_threadsafe_function tsfn_{};
|
|
44
45
|
};
|
|
45
46
|
|
|
46
47
|
// ---
|
|
@@ -98,7 +99,7 @@ threadsafe_function_of<Context, Message>::~threadsafe_function_of() {
|
|
|
98
99
|
}
|
|
99
100
|
|
|
100
101
|
template <class Context, class Message>
|
|
101
|
-
auto threadsafe_function_of<Context, Message>::close(close_callback callback) -> void {
|
|
102
|
+
auto threadsafe_function_of<Context, Message>::close(close_callback callback) noexcept -> void {
|
|
102
103
|
get().close_hook_ = callback;
|
|
103
104
|
napi::invoke0_noexcept(napi_release_threadsafe_function, std::exchange(tsfn_, nullptr), napi_tsfn_abort);
|
|
104
105
|
}
|
|
@@ -114,7 +115,7 @@ auto threadsafe_function_of<Context, Message>::unref(node_api_basic_env env) con
|
|
|
114
115
|
}
|
|
115
116
|
|
|
116
117
|
template <class Context, class Message>
|
|
117
|
-
auto threadsafe_function_of<Context, Message>::operator()(Message message) const -> bool {
|
|
118
|
+
auto threadsafe_function_of<Context, Message>::operator()(Message message) const noexcept -> bool {
|
|
118
119
|
auto check = [ & ](napi_status status) {
|
|
119
120
|
switch (status) {
|
|
120
121
|
case napi_ok:
|
|
@@ -147,7 +148,7 @@ auto threadsafe_function_of<Context, Message>::operator()(Message message) const
|
|
|
147
148
|
}
|
|
148
149
|
|
|
149
150
|
template <class Context, class Message>
|
|
150
|
-
auto threadsafe_function_of<Context, Message>::get() const -> storage& {
|
|
151
|
+
auto threadsafe_function_of<Context, Message>::get() const noexcept -> storage& {
|
|
151
152
|
auto* context = napi::invoke_noexcept(napi_get_threadsafe_function_context, tsfn_);
|
|
152
153
|
return *reinterpret_cast<storage*>(context);
|
|
153
154
|
}
|
package/api/uv_dlib.cc
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
module napi_js;
|
|
2
2
|
import :api.uv_dlib;
|
|
3
|
+
import :support.host;
|
|
3
4
|
import util;
|
|
4
5
|
|
|
5
6
|
namespace js::napi {
|
|
6
7
|
|
|
7
8
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
|
|
8
9
|
uv_dlib::uv_dlib(const std::string& filename) {
|
|
9
|
-
if (
|
|
10
|
-
throw js::runtime_error{util::transcode_string<char16_t>(std::string_view{
|
|
10
|
+
if (host_uv_dlopen(filename.c_str(), &lib_) != 0) {
|
|
11
|
+
throw js::runtime_error{util::transcode_string<char16_t>(std::string_view{host_uv_dlerror(&lib_)})};
|
|
11
12
|
}
|
|
12
13
|
}
|
|
13
14
|
|
|
@@ -20,7 +21,7 @@ auto uv_dlib::operator=(uv_dlib&& right) noexcept -> uv_dlib& {
|
|
|
20
21
|
|
|
21
22
|
uv_dlib::~uv_dlib() {
|
|
22
23
|
if (lib_.handle != nullptr) {
|
|
23
|
-
|
|
24
|
+
host_uv_dlclose(&lib_);
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
27
|
|
package/handle/reference.cc
CHANGED
|
@@ -14,7 +14,7 @@ class reference_handle : util::non_copyable {
|
|
|
14
14
|
env_{env},
|
|
15
15
|
ref_{napi::invoke(napi_create_reference, env, value, 1)} {}
|
|
16
16
|
|
|
17
|
-
[[nodiscard]] auto env() const ->
|
|
17
|
+
[[nodiscard]] auto env() const -> node_api_basic_env {
|
|
18
18
|
return env_;
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -64,7 +64,7 @@ class reference_handle : util::non_copyable {
|
|
|
64
64
|
explicit operator bool() const { return ref_ != nullptr; }
|
|
65
65
|
|
|
66
66
|
private:
|
|
67
|
-
|
|
67
|
+
node_api_basic_env env_{};
|
|
68
68
|
napi_ref ref_{};
|
|
69
69
|
};
|
|
70
70
|
|
package/handle/remote.cc
CHANGED
|
@@ -23,6 +23,7 @@ class remote : protected reference_handle {
|
|
|
23
23
|
public:
|
|
24
24
|
using unique_remote = std::unique_ptr<remote, util::function_constant<expire>>;
|
|
25
25
|
|
|
26
|
+
remote() = default;
|
|
26
27
|
remote(private_constructor /*private*/, const environment& env, value_of<Tag> value, napi_scheduler scheduler) :
|
|
27
28
|
reference_handle{napi_env{env}, napi_value{value}},
|
|
28
29
|
scheduler_{std::move(scheduler)} {}
|
package/handle/types.cc
CHANGED
|
@@ -63,6 +63,16 @@ struct value_specialization<boolean_tag> : value_defaults<boolean_tag> {
|
|
|
63
63
|
using bound_type = class bound_value_for_boolean;
|
|
64
64
|
};
|
|
65
65
|
|
|
66
|
+
template <>
|
|
67
|
+
struct value_specialization<false_tag> : value_defaults<false_tag> {
|
|
68
|
+
using bound_type = class bound_value_for_false;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
template <>
|
|
72
|
+
struct value_specialization<true_tag> : value_defaults<true_tag> {
|
|
73
|
+
using bound_type = class bound_value_for_true;
|
|
74
|
+
};
|
|
75
|
+
|
|
66
76
|
template <>
|
|
67
77
|
struct value_specialization<number_tag> : value_defaults<number_tag> {
|
|
68
78
|
using bound_type = class bound_value_for_number;
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@auto_js/napi",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"author": "https://github.com/laverdet/",
|
|
5
5
|
"description": "Automatic JavaScript to N-API bindings",
|
|
6
6
|
"homepage": "https://github.com/laverdet/isolated-vm/tree/experimental/packages/auto_js/napi",
|
|
7
7
|
"license": "ISC",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@auto_js/js": "^0.0.
|
|
10
|
-
"@auto_js/napi_exports": "^0.0.
|
|
11
|
-
"@auto_js/v8_exports": "^0.0.
|
|
9
|
+
"@auto_js/js": "^0.0.8",
|
|
10
|
+
"@auto_js/napi_exports": "^0.0.8",
|
|
11
|
+
"@auto_js/v8_exports": "^0.0.6"
|
|
12
12
|
},
|
|
13
13
|
"repository": {
|
|
14
14
|
"type": "git",
|
package/support/host.cc
CHANGED
|
@@ -6,31 +6,45 @@ namespace js::napi {
|
|
|
6
6
|
util::lockable_with<bool, {.shared = true}> host_environment_initialized;
|
|
7
7
|
|
|
8
8
|
// Addressof operations
|
|
9
|
-
constexpr auto direct_handle_address =
|
|
10
|
-
|
|
9
|
+
constexpr auto direct_handle_address = [](napi_value value) noexcept -> void* { return value; };
|
|
10
|
+
constexpr auto indirect_handle_address = [](napi_value value) noexcept -> void* { return *reinterpret_cast<void**>(value); };
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
// Fast functions which are supported on all platforms
|
|
13
|
+
// nb: Bun exports these v8 functions, but they crash with the `std::bit_cast<v8::Local<T>>` trick.
|
|
14
|
+
auto v8_is_false(napi_env /*env*/, napi_value value) -> bool {
|
|
15
|
+
return std::bit_cast<v8::Local<v8::Value>>(value)->IsFalse();
|
|
16
|
+
}
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
auto v8_is_null(napi_env /*env*/, napi_value value) -> bool {
|
|
19
|
+
return std::bit_cast<v8::Local<v8::Value>>(value)->IsNull();
|
|
20
|
+
}
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
auto v8_is_true(napi_env /*env*/, napi_value value) -> bool {
|
|
23
|
+
return std::bit_cast<v8::Local<v8::Value>>(value)->IsTrue();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
auto v8_is_undefined(napi_env /*env*/, napi_value value) -> bool {
|
|
27
|
+
return std::bit_cast<v8::Local<v8::Value>>(value)->IsUndefined();
|
|
28
|
+
}
|
|
21
29
|
|
|
22
|
-
|
|
23
|
-
|
|
30
|
+
auto napi_fast_is_false(napi_env env, napi_value value) -> bool {
|
|
31
|
+
return value == napi::invoke(napi_get_boolean, env, false);
|
|
32
|
+
}
|
|
24
33
|
|
|
25
|
-
|
|
26
|
-
|
|
34
|
+
auto napi_fast_is_null(napi_env env, napi_value value) -> bool {
|
|
35
|
+
return value == napi::invoke(napi_get_null, env);
|
|
36
|
+
}
|
|
27
37
|
|
|
28
|
-
|
|
29
|
-
|
|
38
|
+
auto napi_fast_is_true(napi_env env, napi_value value) -> bool {
|
|
39
|
+
return value == napi::invoke(napi_get_boolean, env, true);
|
|
40
|
+
}
|
|
30
41
|
|
|
31
|
-
|
|
32
|
-
|
|
42
|
+
auto napi_fast_is_undefined(napi_env env, napi_value value) -> bool {
|
|
43
|
+
return value == napi::invoke(napi_get_undefined, env);
|
|
44
|
+
}
|
|
33
45
|
|
|
46
|
+
// Extended fast functions
|
|
47
|
+
// nb: Bun exports these v8 functions, but they crash with the `std::bit_cast<v8::Local<T>>` trick.
|
|
34
48
|
auto fast_is_array(napi_value value) -> bool {
|
|
35
49
|
return std::bit_cast<v8::Local<v8::Value>>(value)->IsArray();
|
|
36
50
|
}
|
|
@@ -39,18 +53,10 @@ auto fast_is_bigint(napi_value value) -> bool {
|
|
|
39
53
|
return std::bit_cast<v8::Local<v8::Value>>(value)->IsBigInt();
|
|
40
54
|
}
|
|
41
55
|
|
|
42
|
-
auto fast_is_boolean(napi_value value) -> bool {
|
|
43
|
-
return std::bit_cast<v8::Local<v8::Value>>(value)->IsBoolean();
|
|
44
|
-
}
|
|
45
|
-
|
|
46
56
|
auto fast_is_function(napi_value value) -> bool {
|
|
47
57
|
return std::bit_cast<v8::Local<v8::Value>>(value)->IsFunction();
|
|
48
58
|
}
|
|
49
59
|
|
|
50
|
-
auto fast_is_null(napi_value value) -> bool {
|
|
51
|
-
return std::bit_cast<v8::Local<v8::Value>>(value)->IsNull();
|
|
52
|
-
}
|
|
53
|
-
|
|
54
60
|
auto fast_is_number(napi_value value) -> bool {
|
|
55
61
|
return std::bit_cast<v8::Local<v8::Value>>(value)->IsNumber();
|
|
56
62
|
}
|
|
@@ -63,13 +69,56 @@ auto fast_is_string(napi_value value) -> bool {
|
|
|
63
69
|
return std::bit_cast<v8::Local<v8::Value>>(value)->IsString();
|
|
64
70
|
}
|
|
65
71
|
|
|
66
|
-
|
|
67
|
-
|
|
72
|
+
// Bug fixes
|
|
73
|
+
auto napi_is_object_array_buffer(napi_env env, value_of<object_tag> value) -> bool {
|
|
74
|
+
return napi::invoke(napi_is_arraybuffer, env, value);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
auto napi_is_data_block_array_buffer(napi_env env, value_of<data_block_tag> value) -> bool {
|
|
78
|
+
return napi_is_object_array_buffer(env, value);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
auto bun_is_data_block_array_buffer(napi_env env, value_of<data_block_tag> value) -> bool {
|
|
82
|
+
// https://github.com/oven-sh/bun/issues/32624
|
|
83
|
+
auto* string = napi::invoke(napi_coerce_to_string, env, value);
|
|
84
|
+
auto length = napi::invoke(napi_get_value_string_latin1, env, string, nullptr, 0);
|
|
85
|
+
// '[object ArrayBuffer]'
|
|
86
|
+
return length == 20;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
auto bun_is_object_array_buffer(napi_env env, value_of<object_tag> value) -> bool {
|
|
90
|
+
if (napi::invoke(napi_is_arraybuffer, env, value)) {
|
|
91
|
+
return bun_is_data_block_array_buffer(env, value_of<data_block_tag>::from(value));
|
|
92
|
+
} else {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Optional value inspectors.
|
|
98
|
+
auto v8_is_number_int32(value_of<number_tag> value) -> std::optional<bool> {
|
|
99
|
+
return std::bit_cast<v8::Local<v8::Number>>(value)->IsInt32();
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
auto v8_is_string_one_byte(value_of<string_tag> value) -> std::optional<bool> {
|
|
103
|
+
return std::bit_cast<v8::Local<v8::String>>(value)->IsOneByte();
|
|
68
104
|
}
|
|
69
105
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
106
|
+
auto node_api_maybe_is_shared_array_buffer(napi_env env, value_of<object_tag> value) -> std::optional<bool> {
|
|
107
|
+
return napi::invoke(node_api_is_sharedarraybuffer, env, value);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
auto bun_maybe_is_shared_array_buffer(napi_env env, value_of<object_tag> value) -> std::optional<bool> {
|
|
111
|
+
if (napi::invoke(napi_is_arraybuffer, env, value)) {
|
|
112
|
+
return !bun_is_data_block_array_buffer(env, value_of<data_block_tag>::from(value));
|
|
113
|
+
} else {
|
|
114
|
+
return std::nullopt;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
constexpr auto unknown_maybe_is = [](auto...) -> std::optional<bool> { return std::nullopt; };
|
|
119
|
+
|
|
120
|
+
// 'SharedArrayBuffer' functions
|
|
121
|
+
auto v8_make_shared_array_buffer(js::shared_array_buffer::shared_pointer_type data, std::size_t byte_length) -> value_of<shared_array_buffer_tag> {
|
|
73
122
|
auto backing_store = [ & ]() -> auto {
|
|
74
123
|
// v8 does not call the deleter `byte_length` is zero. So the heap-allocated shared_ptr trick
|
|
75
124
|
// does not work in that case.
|
|
@@ -93,31 +142,28 @@ constexpr auto v8_make_shared_array_buffer =
|
|
|
93
142
|
return value_of<shared_array_buffer_tag>::from(std::bit_cast<napi_value>(shared_array_buffer));
|
|
94
143
|
};
|
|
95
144
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
145
|
+
auto v8_shared_array_buffer_get_byte_length(value_of<shared_array_buffer_tag> buffer) -> std::size_t {
|
|
146
|
+
return std::bit_cast<v8::Local<v8::SharedArrayBuffer>>(napi_value{buffer})->ByteLength();
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
auto v8_shared_array_buffer_get_backing_store(value_of<shared_array_buffer_tag> buffer) -> std::shared_ptr<std::byte[]> {
|
|
150
|
+
auto backing_store = std::bit_cast<v8::Local<v8::SharedArrayBuffer>>(buffer)->GetBackingStore();
|
|
151
|
+
auto* data = reinterpret_cast<std::byte*>(backing_store->Data());
|
|
152
|
+
// NOLINTNEXTLINE(modernize-avoid-c-arrays)
|
|
153
|
+
return std::shared_ptr<std::byte[]>{std::move(backing_store), data};
|
|
100
154
|
};
|
|
101
155
|
|
|
102
156
|
// 'ArrayBufferView' constructors
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
[](value_of<shared_array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> value_of<data_view_tag> {
|
|
157
|
+
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
|
|
158
|
+
auto v8_make_sab_data_view(value_of<shared_array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> value_of<data_view_tag> {
|
|
106
159
|
auto buffer_local = std::bit_cast<v8::Local<v8::SharedArrayBuffer>>(napi_value{buffer});
|
|
107
160
|
auto view_local = v8::DataView::New(buffer_local, byte_offset, length);
|
|
108
161
|
return value_of<data_view_tag>::from(std::bit_cast<napi_value>(view_local));
|
|
109
162
|
};
|
|
110
163
|
|
|
111
|
-
constexpr auto unknown_make_sab_data_view =
|
|
112
|
-
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
|
|
113
|
-
[](value_of<shared_array_buffer_tag> /*buffer*/, std::size_t /*byte_offset*/, std::size_t /*length*/) -> value_of<data_view_tag> {
|
|
114
|
-
throw js::type_error{u"SharedArrayBuffer is not supported in this environment"};
|
|
115
|
-
};
|
|
116
|
-
|
|
117
164
|
template <class Type>
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
[](value_of<shared_array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> value_of<typed_array_tag_of<Type>> {
|
|
165
|
+
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
|
|
166
|
+
auto v8_make_sab_typed_array_of(value_of<shared_array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> value_of<typed_array_tag_of<Type>> {
|
|
121
167
|
using constructor_type = type_t<util::overloaded{
|
|
122
168
|
[](std::type_identity<double>) -> std::type_identity<v8::Float64Array> { return {}; },
|
|
123
169
|
[](std::type_identity<float>) -> std::type_identity<v8::Float32Array> { return {}; },
|
|
@@ -138,12 +184,26 @@ constexpr auto v8_make_sab_typed_array_of =
|
|
|
138
184
|
};
|
|
139
185
|
|
|
140
186
|
template <class Type>
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
[](value_of<shared_array_buffer_tag> /*buffer*/, std::size_t /*byte_offset*/, std::size_t /*length*/) -> value_of<typed_array_tag_of<Type>> {
|
|
187
|
+
// NOLINTNEXTLINE(performance-unnecessary-value-param)
|
|
188
|
+
constexpr auto unknown_sab_throw = [](auto...) -> Type {
|
|
144
189
|
throw js::type_error{u"SharedArrayBuffer is not supported in this environment"};
|
|
145
190
|
};
|
|
146
191
|
|
|
192
|
+
// Dynamic libraries
|
|
193
|
+
constexpr auto node_uv_dlerror =
|
|
194
|
+
[](const uv_lib_t* lib) -> const char* { return uv_dlerror(lib); };
|
|
195
|
+
constexpr auto node_uv_dlopen =
|
|
196
|
+
[](const char* filename, uv_lib_t* lib) -> int { return uv_dlopen(filename, lib); };
|
|
197
|
+
constexpr auto node_uv_dlclose =
|
|
198
|
+
[](uv_lib_t* lib) -> void { uv_dlclose(lib); };
|
|
199
|
+
|
|
200
|
+
constexpr auto unknown_uv_dlerror =
|
|
201
|
+
[](const uv_lib_t* /*lib*/) -> const char* { return "Dynamic libraries are not supported in this environment"; };
|
|
202
|
+
constexpr auto unknown_uv_dlopen =
|
|
203
|
+
[](const char* /*filename*/, uv_lib_t* /*lib*/) -> int { return -1; };
|
|
204
|
+
constexpr auto unknown_uv_dlclose =
|
|
205
|
+
[](uv_lib_t* /*lib*/) -> void { std::unreachable(); };
|
|
206
|
+
|
|
147
207
|
auto initialize_host_environment(napi_env env) -> void {
|
|
148
208
|
if (!*host_environment_initialized.read()) {
|
|
149
209
|
if (auto lock = host_environment_initialized.write(); !*lock) {
|
|
@@ -168,44 +228,53 @@ auto initialize_host_environment(napi_env env) -> void {
|
|
|
168
228
|
handle_addressof = indirect_handle_address;
|
|
169
229
|
}
|
|
170
230
|
|
|
171
|
-
//
|
|
172
|
-
auto
|
|
231
|
+
// Get `globalThis.process`
|
|
232
|
+
auto* process_global = [ & ]() -> napi_value {
|
|
173
233
|
auto* global = napi::invoke(napi_get_global, env);
|
|
174
234
|
constexpr auto process_cw = util::make_consteval_string_view(util::cw<"process">);
|
|
175
235
|
auto* process_str = napi::invoke(node_api_create_property_key_latin1, env, process_cw.data(), process_cw.length());
|
|
176
236
|
auto* process = napi::invoke(napi_get_property, env, global, process_str);
|
|
177
237
|
if (napi::invoke(napi_typeof, env, process) == napi_object) {
|
|
178
|
-
|
|
179
|
-
auto* is_bun_str = napi::invoke(node_api_create_property_key_latin1, env, is_bun_cw.data(), is_bun_cw.length());
|
|
180
|
-
auto* is_bun = napi::invoke(napi_get_property, env, process, is_bun_str);
|
|
181
|
-
auto* is_bun_bool = napi::invoke(napi_coerce_to_bool, env, is_bun);
|
|
182
|
-
return napi::invoke(napi_get_value_bool, env, is_bun_bool);
|
|
238
|
+
return process;
|
|
183
239
|
} else {
|
|
240
|
+
return nullptr;
|
|
241
|
+
}
|
|
242
|
+
}();
|
|
243
|
+
|
|
244
|
+
// Detect bun via `process.isBun`
|
|
245
|
+
auto is_bun = process_global == nullptr ? false : [ & ]() -> bool {
|
|
246
|
+
constexpr auto is_bun_cw = util::make_consteval_string_view(util::cw<"isBun">);
|
|
247
|
+
auto* is_bun_str = napi::invoke(node_api_create_property_key_latin1, env, is_bun_cw.data(), is_bun_cw.length());
|
|
248
|
+
auto* is_bun = napi::invoke(napi_get_property, env, process_global, is_bun_str);
|
|
249
|
+
auto* is_bun_bool = napi::invoke(napi_coerce_to_bool, env, is_bun);
|
|
250
|
+
return napi::invoke(napi_get_value_bool, env, is_bun_bool);
|
|
251
|
+
}();
|
|
252
|
+
|
|
253
|
+
// Detect deno via `process.versions.deno`
|
|
254
|
+
auto is_deno = process_global == nullptr ? false : [ & ]() -> bool {
|
|
255
|
+
constexpr auto versions_cw = util::make_consteval_string_view(util::cw<"versions">);
|
|
256
|
+
auto* versions_str = napi::invoke(node_api_create_property_key_latin1, env, versions_cw.data(), versions_cw.length());
|
|
257
|
+
auto* versions = napi::invoke(napi_get_property, env, process_global, versions_str);
|
|
258
|
+
if (napi::invoke(napi_typeof, env, versions) != napi_object) {
|
|
184
259
|
return false;
|
|
185
260
|
}
|
|
261
|
+
constexpr auto deno_cw = util::make_consteval_string_view(util::cw<"deno">);
|
|
262
|
+
auto* deno_str = napi::invoke(node_api_create_property_key_latin1, env, deno_cw.data(), deno_cw.length());
|
|
263
|
+
auto* deno = napi::invoke(napi_get_property, env, versions, deno_str);
|
|
264
|
+
auto* deno_bool = napi::invoke(napi_coerce_to_bool, env, deno);
|
|
265
|
+
return napi::invoke(napi_get_value_bool, env, deno_bool);
|
|
186
266
|
}();
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
make_sab_typed_array_of<std::uint16_t> = unknown_make_sab_typed_array_of<std::uint16_t>;
|
|
199
|
-
make_sab_typed_array_of<std::uint32_t> = unknown_make_sab_typed_array_of<std::uint32_t>;
|
|
200
|
-
make_sab_typed_array_of<std::uint64_t> = unknown_make_sab_typed_array_of<std::uint64_t>;
|
|
201
|
-
make_sab_typed_array_of<std::uint8_t> = unknown_make_sab_typed_array_of<std::uint8_t>;
|
|
202
|
-
make_shared_array_buffer = unknown_make_shared_array_buffer;
|
|
203
|
-
maybe_fast_is_number_int32 = unknown_maybe_fast_is_number_int32;
|
|
204
|
-
maybe_fast_is_string_one_byte = unknown_maybe_fast_is_string_one_byte;
|
|
205
|
-
maybe_is_shared_array_buffer = unknown_maybe_is_shared_array_buffer;
|
|
206
|
-
} else {
|
|
207
|
-
has_fast_is_functions = true;
|
|
208
|
-
make_sab_data_view = v8_make_sab_data_view;
|
|
267
|
+
|
|
268
|
+
auto is_nodejs = !is_bun && !is_deno;
|
|
269
|
+
if (is_nodejs) {
|
|
270
|
+
has_extended_fast_is_functions = true;
|
|
271
|
+
fast_is_false = v8_is_false;
|
|
272
|
+
fast_is_null = v8_is_null;
|
|
273
|
+
fast_is_true = v8_is_true;
|
|
274
|
+
fast_is_undefined = v8_is_undefined;
|
|
275
|
+
host_uv_dlclose = node_uv_dlclose;
|
|
276
|
+
host_uv_dlerror = node_uv_dlerror;
|
|
277
|
+
host_uv_dlopen = node_uv_dlopen;
|
|
209
278
|
make_sab_typed_array_of<double> = v8_make_sab_typed_array_of<double>;
|
|
210
279
|
make_sab_typed_array_of<float> = v8_make_sab_typed_array_of<float>;
|
|
211
280
|
make_sab_typed_array_of<js::float16_t> = v8_make_sab_typed_array_of<js::float16_t>;
|
|
@@ -219,9 +288,49 @@ auto initialize_host_environment(napi_env env) -> void {
|
|
|
219
288
|
make_sab_typed_array_of<std::uint64_t> = v8_make_sab_typed_array_of<std::uint64_t>;
|
|
220
289
|
make_sab_typed_array_of<std::uint8_t> = v8_make_sab_typed_array_of<std::uint8_t>;
|
|
221
290
|
make_shared_array_buffer = v8_make_shared_array_buffer;
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
291
|
+
maybe_is_number_int32 = v8_is_number_int32;
|
|
292
|
+
maybe_is_shared_array_buffer = node_api_maybe_is_shared_array_buffer;
|
|
293
|
+
maybe_is_string_latin1 = v8_is_string_one_byte;
|
|
294
|
+
shared_array_buffer_get_backing_store = v8_shared_array_buffer_get_backing_store;
|
|
295
|
+
shared_array_buffer_get_byte_length = v8_shared_array_buffer_get_byte_length;
|
|
296
|
+
} else {
|
|
297
|
+
has_extended_fast_is_functions = false;
|
|
298
|
+
fast_is_false = napi_fast_is_false;
|
|
299
|
+
fast_is_null = napi_fast_is_null;
|
|
300
|
+
fast_is_true = napi_fast_is_true;
|
|
301
|
+
fast_is_undefined = napi_fast_is_undefined;
|
|
302
|
+
host_uv_dlclose = unknown_uv_dlclose;
|
|
303
|
+
host_uv_dlerror = unknown_uv_dlerror;
|
|
304
|
+
host_uv_dlopen = unknown_uv_dlopen;
|
|
305
|
+
make_sab_data_view = unknown_sab_throw<value_of<data_view_tag>>;
|
|
306
|
+
make_sab_typed_array_of<double> = unknown_sab_throw<value_of<typed_array_tag_of<double>>>;
|
|
307
|
+
make_sab_typed_array_of<float> = unknown_sab_throw<value_of<typed_array_tag_of<float>>>;
|
|
308
|
+
make_sab_typed_array_of<js::float16_t> = unknown_sab_throw<value_of<typed_array_tag_of<js::float16_t>>>;
|
|
309
|
+
make_sab_typed_array_of<js::uint8_clamped_t> = unknown_sab_throw<value_of<typed_array_tag_of<js::uint8_clamped_t>>>;
|
|
310
|
+
make_sab_typed_array_of<std::int16_t> = unknown_sab_throw<value_of<typed_array_tag_of<std::int16_t>>>;
|
|
311
|
+
make_sab_typed_array_of<std::int32_t> = unknown_sab_throw<value_of<typed_array_tag_of<std::int32_t>>>;
|
|
312
|
+
make_sab_typed_array_of<std::int64_t> = unknown_sab_throw<value_of<typed_array_tag_of<std::int64_t>>>;
|
|
313
|
+
make_sab_typed_array_of<std::int8_t> = unknown_sab_throw<value_of<typed_array_tag_of<std::int8_t>>>;
|
|
314
|
+
make_sab_typed_array_of<std::uint16_t> = unknown_sab_throw<value_of<typed_array_tag_of<std::uint16_t>>>;
|
|
315
|
+
make_sab_typed_array_of<std::uint32_t> = unknown_sab_throw<value_of<typed_array_tag_of<std::uint32_t>>>;
|
|
316
|
+
make_sab_typed_array_of<std::uint64_t> = unknown_sab_throw<value_of<typed_array_tag_of<std::uint64_t>>>;
|
|
317
|
+
make_sab_typed_array_of<std::uint8_t> = unknown_sab_throw<value_of<typed_array_tag_of<std::uint8_t>>>;
|
|
318
|
+
make_shared_array_buffer = unknown_sab_throw<value_of<shared_array_buffer_tag>>;
|
|
319
|
+
maybe_is_number_int32 = unknown_maybe_is;
|
|
320
|
+
maybe_is_shared_array_buffer = unknown_maybe_is;
|
|
321
|
+
maybe_is_string_latin1 = unknown_maybe_is;
|
|
322
|
+
// NOLINTNEXTLINE(modernize-avoid-c-arrays)
|
|
323
|
+
shared_array_buffer_get_backing_store = unknown_sab_throw<std::shared_ptr<std::byte[]>>;
|
|
324
|
+
shared_array_buffer_get_byte_length = unknown_sab_throw<std::size_t>;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// Bug fixes
|
|
328
|
+
is_data_block_array_buffer = napi_is_data_block_array_buffer;
|
|
329
|
+
is_object_array_buffer = napi_is_object_array_buffer;
|
|
330
|
+
if (is_bun) {
|
|
331
|
+
is_data_block_array_buffer = bun_is_data_block_array_buffer;
|
|
332
|
+
is_object_array_buffer = bun_is_object_array_buffer;
|
|
333
|
+
maybe_is_shared_array_buffer = bun_maybe_is_shared_array_buffer;
|
|
225
334
|
}
|
|
226
335
|
}
|
|
227
336
|
}
|
package/support/host.h.cc
CHANGED
|
@@ -7,25 +7,36 @@ namespace js::napi {
|
|
|
7
7
|
// Addressof operation
|
|
8
8
|
auto (*handle_addressof)(napi_value handle) noexcept -> void* = nullptr;
|
|
9
9
|
|
|
10
|
-
//
|
|
11
|
-
auto (*
|
|
12
|
-
auto (*
|
|
13
|
-
auto (*
|
|
10
|
+
// Fast functions which are supported on all platforms
|
|
11
|
+
auto (*fast_is_false)(napi_env env, napi_value value) -> bool;
|
|
12
|
+
auto (*fast_is_null)(napi_env env, napi_value value) -> bool;
|
|
13
|
+
auto (*fast_is_true)(napi_env env, napi_value value) -> bool;
|
|
14
|
+
auto (*fast_is_undefined)(napi_env env, napi_value value) -> bool;
|
|
14
15
|
|
|
15
|
-
//
|
|
16
|
-
auto
|
|
16
|
+
// Extended fast functions
|
|
17
|
+
auto has_extended_fast_is_functions = false;
|
|
17
18
|
auto fast_is_array(napi_value value) -> bool;
|
|
18
19
|
auto fast_is_bigint(napi_value value) -> bool;
|
|
19
|
-
auto fast_is_boolean(napi_value value) -> bool;
|
|
20
20
|
auto fast_is_function(napi_value value) -> bool;
|
|
21
|
-
auto fast_is_null(napi_value value) -> bool;
|
|
22
21
|
auto fast_is_number(napi_value value) -> bool;
|
|
23
22
|
auto fast_is_object(napi_value value) -> bool;
|
|
24
23
|
auto fast_is_string(napi_value value) -> bool;
|
|
25
|
-
auto fast_is_undefined(napi_value value) -> bool;
|
|
26
24
|
|
|
27
|
-
//
|
|
25
|
+
// Bug fixes
|
|
26
|
+
auto (*is_object_array_buffer)(napi_env env, value_of<object_tag> value) -> bool = nullptr;
|
|
27
|
+
auto (*is_data_block_array_buffer)(napi_env env, value_of<data_block_tag> value) -> bool = nullptr;
|
|
28
|
+
|
|
29
|
+
// Optional value inspectors. int32 & latin1 will select optimized representations, and
|
|
30
|
+
// shared_array_buffer is required for support of that value type.
|
|
31
|
+
auto (*maybe_is_number_int32)(value_of<number_tag> value) -> std::optional<bool> = nullptr;
|
|
32
|
+
auto (*maybe_is_string_latin1)(value_of<string_tag> value) -> std::optional<bool> = nullptr;
|
|
33
|
+
auto (*maybe_is_shared_array_buffer)(napi_env env, value_of<object_tag> value) -> std::optional<bool> = nullptr;
|
|
34
|
+
|
|
35
|
+
// 'SharedArrayBuffer' functions
|
|
28
36
|
auto (*make_shared_array_buffer)(js::shared_array_buffer::shared_pointer_type data, std::size_t byte_length) -> value_of<shared_array_buffer_tag> = nullptr;
|
|
37
|
+
auto (*shared_array_buffer_get_byte_length)(value_of<shared_array_buffer_tag> buffer) -> std::size_t = nullptr;
|
|
38
|
+
// NOLINTNEXTLINE(modernize-avoid-c-arrays)
|
|
39
|
+
auto (*shared_array_buffer_get_backing_store)(value_of<shared_array_buffer_tag> buffer) -> std::shared_ptr<std::byte[]> = nullptr;
|
|
29
40
|
|
|
30
41
|
// 'ArrayBufferView' constructors
|
|
31
42
|
auto (*make_sab_data_view)(value_of<shared_array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> value_of<data_view_tag> = nullptr;
|
|
@@ -50,6 +61,11 @@ template make_sab_typed_array_constructor<std::uint32_t>* make_sab_typed_array_o
|
|
|
50
61
|
template make_sab_typed_array_constructor<std::uint64_t>* make_sab_typed_array_of<std::uint64_t>;
|
|
51
62
|
template make_sab_typed_array_constructor<std::uint8_t>* make_sab_typed_array_of<std::uint8_t>;
|
|
52
63
|
|
|
64
|
+
// uv dlfcn wrappers
|
|
65
|
+
auto (*host_uv_dlerror)(const uv_lib_t* lib) -> const char*;
|
|
66
|
+
auto (*host_uv_dlopen)(const char* filename, uv_lib_t* lib) -> int;
|
|
67
|
+
auto (*host_uv_dlclose)(uv_lib_t* lib) -> void;
|
|
68
|
+
|
|
53
69
|
// Once per process, this detects the host environment (nodejs vs bun)
|
|
54
70
|
auto initialize_host_environment(napi_env env) -> void;
|
|
55
71
|
|
package/support/promise.cc
CHANGED
|
@@ -42,7 +42,8 @@ class resolver {
|
|
|
42
42
|
|
|
43
43
|
// Fulfill using direct resolution value. Note it still needs try/catch (in `fulfill`) because
|
|
44
44
|
// the `transfer` operation could fail.
|
|
45
|
-
|
|
45
|
+
template <class Type>
|
|
46
|
+
auto resolve(Type value) noexcept(std::is_nothrow_move_constructible_v<Type>) -> void {
|
|
46
47
|
using expected_type = std::expected<decltype(value), js::error_value>;
|
|
47
48
|
schedule(
|
|
48
49
|
[](Environment& /*env*/, auto value) -> expected_type {
|
|
@@ -53,7 +54,7 @@ class resolver {
|
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
// Fulfill using thrown error.
|
|
56
|
-
auto reject(js::error_value error) -> void {
|
|
57
|
+
auto reject(js::error_value error) noexcept -> void {
|
|
57
58
|
using expected_type = std::expected<std::monostate, js::error_value>;
|
|
58
59
|
schedule(
|
|
59
60
|
[](Environment& /*env*/, js::error_value error) -> expected_type {
|
|
@@ -64,10 +65,11 @@ class resolver {
|
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
private:
|
|
67
|
-
|
|
68
|
+
template <class Operation, class... Args>
|
|
69
|
+
auto schedule(Operation operation, Args&&... args) noexcept(std::is_nothrow_move_constructible_v<Operation> && (std::is_nothrow_move_constructible_v<Args> && ...)) -> void {
|
|
68
70
|
auto scheduler = std::move(scheduler_);
|
|
69
71
|
scheduler(
|
|
70
|
-
[](napi_env env, napi_value /*nothing*/, napi_deferred deferred, auto operation, auto&&... args) {
|
|
72
|
+
[](napi_env env, napi_value /*nothing*/, napi_deferred deferred, auto operation, auto&&... args) noexcept {
|
|
71
73
|
auto& environment = napi::environment::unsafe_get_environment_as<Environment>(env);
|
|
72
74
|
environment.scheduler().decrement_ref(env);
|
|
73
75
|
try {
|
|
@@ -81,10 +83,10 @@ class resolver {
|
|
|
81
83
|
}
|
|
82
84
|
} catch (const napi::pending_error& /*error*/) {
|
|
83
85
|
auto* exception = napi::invoke(napi_get_and_clear_last_exception, env);
|
|
84
|
-
napi::
|
|
86
|
+
napi::invoke0_noexcept(napi_reject_deferred, env, deferred, exception);
|
|
85
87
|
} catch (const js::error& error) {
|
|
86
88
|
auto exception = js::transfer_in_strict<napi_value>(error, environment);
|
|
87
|
-
napi::
|
|
89
|
+
napi::invoke0_noexcept(napi_reject_deferred, env, deferred, exception);
|
|
88
90
|
}
|
|
89
91
|
},
|
|
90
92
|
deferred_,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#define WIN32_LEAN_AND_MEAN
|
|
2
|
+
#include <windows.h>
|
|
3
|
+
#include <delayimp.h>
|
|
4
|
+
import std;
|
|
5
|
+
|
|
6
|
+
const auto __pfnDliNotifyHook2 = PfnDliHook{[](unsigned event, DelayLoadInfo* info) -> FARPROC {
|
|
7
|
+
if (event == dliNotePreLoadLibrary && std::string_view{info->szDll} == "node.exe") {
|
|
8
|
+
return reinterpret_cast<FARPROC>(GetModuleHandle(nullptr));
|
|
9
|
+
} else {
|
|
10
|
+
return nullptr;
|
|
11
|
+
}
|
|
12
|
+
}};
|
package/transfer/visit.cc
CHANGED
|
@@ -134,7 +134,7 @@ struct visit_value : reference_map_t<Reference, reference_map_type> {
|
|
|
134
134
|
|
|
135
135
|
template <class Accept>
|
|
136
136
|
auto operator()(value_of<number_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
|
|
137
|
-
if (
|
|
137
|
+
if (maybe_is_number_int32(subject).value_or(false)) {
|
|
138
138
|
return immediate(value_of<number_tag_of<std::int32_t>>::from(subject), accept);
|
|
139
139
|
} else {
|
|
140
140
|
return immediate(value_of<number_tag_of<double>>::from(subject), accept);
|
|
@@ -153,85 +153,94 @@ struct visit_value : reference_map_t<Reference, reference_map_type> {
|
|
|
153
153
|
// Check the reference map, and lookup type via napi
|
|
154
154
|
return lookup_or_visit(subject, [ & ]() -> accept_target_t<Accept> {
|
|
155
155
|
// This is the pure-napi implementation
|
|
156
|
-
auto slow_path =
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
156
|
+
auto slow_path = util::overloaded{
|
|
157
|
+
[ & ]() -> accept_target_t<Accept> {
|
|
158
|
+
auto type_of = napi::invoke(napi_typeof, napi_env{*this}, subject);
|
|
159
|
+
switch (type_of) {
|
|
160
|
+
case napi_undefined:
|
|
161
|
+
return (*this)(value_of<undefined_tag>::from(subject), accept);
|
|
162
|
+
case napi_null:
|
|
163
|
+
return (*this)(value_of<null_tag>::from(subject), accept);
|
|
164
|
+
case napi_boolean:
|
|
165
|
+
return (*this)(value_of<boolean_tag>::from(subject), accept);
|
|
166
|
+
case napi_number:
|
|
167
|
+
return (*this)(value_of<number_tag>::from(subject), accept);
|
|
168
|
+
case napi_string:
|
|
169
|
+
return immediate(value_of<string_tag>::from(subject), accept);
|
|
170
|
+
case napi_symbol:
|
|
171
|
+
return immediate(value_of<symbol_tag>::from(subject), accept);
|
|
172
|
+
case napi_object:
|
|
173
|
+
return immediate(value_of<object_tag>::from(subject), accept);
|
|
174
|
+
case napi_function:
|
|
175
|
+
return immediate(value_of<function_tag>::from(subject), accept);
|
|
176
|
+
case napi_external:
|
|
177
|
+
return immediate(value_of<external_tag>::from(subject), accept);
|
|
178
|
+
case napi_bigint:
|
|
179
|
+
return immediate(value_of<bigint_tag>::from(subject), accept);
|
|
180
|
+
}
|
|
181
|
+
std::unreachable();
|
|
182
|
+
},
|
|
183
|
+
|
|
184
|
+
[](auto /*tag*/, auto next) -> accept_target_t<Accept> { return next(); },
|
|
181
185
|
};
|
|
182
186
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
return fast_is_number(subject) ? (*this)(value_of<number_tag>::from(subject), accept) : next();
|
|
199
|
-
},
|
|
200
|
-
[ & ](string_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
201
|
-
return fast_is_string(subject) ? immediate(value_of<string_tag>::from(subject), accept) : next();
|
|
202
|
-
},
|
|
203
|
-
[ & ](bigint_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
204
|
-
return fast_is_bigint(subject) ? immediate(value_of<bigint_tag>::from(subject), accept) : next();
|
|
205
|
-
},
|
|
206
|
-
[ & ](date_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
207
|
-
return napi::invoke(napi_is_date, napi_env{*this}, subject) ? immediate(value_of<date_tag>::from(subject), accept) : next();
|
|
208
|
-
},
|
|
209
|
-
[ & ](list_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
210
|
-
return fast_is_array(subject) ? immediate(value_of<list_tag>::from(subject), accept) : next();
|
|
211
|
-
},
|
|
212
|
-
[ & ](object_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
213
|
-
// nb: You can't really skip the subsequent is promise, is date, is arraybuffer, etc
|
|
214
|
-
// checks. We don't really want to accept those types here, I don't think..
|
|
215
|
-
return fast_is_object(subject) ? immediate(value_of<object_tag>::from(subject), accept) : next();
|
|
216
|
-
},
|
|
217
|
-
[ & ](function_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
218
|
-
return fast_is_function(subject) ? immediate(value_of<function_tag>::from(subject), accept) : next();
|
|
219
|
-
},
|
|
220
|
-
|
|
221
|
-
// Skip these, otherwise `number_tag` and `string_tag` are invoked twice, which we don't
|
|
222
|
-
// differentiate between.
|
|
223
|
-
[]<class Type>(number_tag_of<Type> /*tag*/, auto next) -> accept_target_t<Accept> { return next(); },
|
|
224
|
-
[]<class Type>(string_tag_of<Type> /*tag*/, auto next) -> accept_target_t<Accept> { return next(); },
|
|
225
|
-
|
|
226
|
-
// Unknown tag
|
|
227
|
-
[](auto /*tag*/, auto next) -> accept_target_t<Accept> { return next(); },
|
|
228
|
-
|
|
229
|
-
// Slow path
|
|
230
|
-
slow_path,
|
|
187
|
+
// Universal fast checks
|
|
188
|
+
auto fast_path = util::overloaded{
|
|
189
|
+
[ & ](undefined_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
190
|
+
return fast_is_undefined(napi_env{*this}, subject) ? (*this)(value_of<undefined_tag>::from(subject), accept) : next();
|
|
191
|
+
},
|
|
192
|
+
[ & ](null_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
193
|
+
return fast_is_null(napi_env{*this}, subject) ? (*this)(value_of<null_tag>::from(subject), accept) : next();
|
|
194
|
+
},
|
|
195
|
+
[ & ](boolean_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
196
|
+
if (fast_is_false(napi_env{*this}, subject)) {
|
|
197
|
+
return (*this)(value_of<false_tag>::from(subject), accept);
|
|
198
|
+
} else if (fast_is_true(napi_env{*this}, subject)) {
|
|
199
|
+
return (*this)(value_of<true_tag>::from(subject), accept);
|
|
200
|
+
} else {
|
|
201
|
+
return next();
|
|
231
202
|
}
|
|
232
|
-
|
|
203
|
+
},
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
// Extended fast checks
|
|
207
|
+
auto extended_fast_path = util::overloaded{
|
|
208
|
+
[ & ](number_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
209
|
+
return fast_is_number(subject) ? (*this)(value_of<number_tag>::from(subject), accept) : next();
|
|
210
|
+
},
|
|
211
|
+
[ & ](string_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
212
|
+
return fast_is_string(subject) ? immediate(value_of<string_tag>::from(subject), accept) : next();
|
|
213
|
+
},
|
|
214
|
+
[ & ](bigint_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
215
|
+
return fast_is_bigint(subject) ? immediate(value_of<bigint_tag>::from(subject), accept) : next();
|
|
216
|
+
},
|
|
217
|
+
[ & ](date_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
218
|
+
return napi::invoke(napi_is_date, napi_env{*this}, subject) ? immediate(value_of<date_tag>::from(subject), accept) : next();
|
|
219
|
+
},
|
|
220
|
+
[ & ](list_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
221
|
+
return fast_is_array(subject) ? immediate(value_of<list_tag>::from(subject), accept) : next();
|
|
222
|
+
},
|
|
223
|
+
[ & ](object_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
224
|
+
// nb: You can't really skip the subsequent is promise, is date, is arraybuffer, etc
|
|
225
|
+
// checks. We don't really want to accept those types here, I don't think..
|
|
226
|
+
return fast_is_object(subject) ? immediate(value_of<object_tag>::from(subject), accept) : next();
|
|
227
|
+
},
|
|
228
|
+
[ & ](function_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
229
|
+
return fast_is_function(subject) ? immediate(value_of<function_tag>::from(subject), accept) : next();
|
|
230
|
+
},
|
|
231
|
+
|
|
232
|
+
// Skip these, otherwise `number_tag` and `string_tag` are invoked twice, which we don't
|
|
233
|
+
// differentiate between.
|
|
234
|
+
[]<class Type>(number_tag_of<Type> /*tag*/, auto next) -> accept_target_t<Accept> { return next(); },
|
|
235
|
+
[]<class Type>(string_tag_of<Type> /*tag*/, auto next) -> accept_target_t<Accept> { return next(); },
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
if (has_extended_fast_is_functions) {
|
|
239
|
+
auto traverse = util::overloaded{fast_path, extended_fast_path, slow_path};
|
|
240
|
+
return util::template_traverse(accept_tags_of_v<Accept>, traverse);
|
|
233
241
|
} else {
|
|
234
|
-
|
|
242
|
+
auto traverse = util::overloaded{fast_path, slow_path};
|
|
243
|
+
return util::template_traverse(accept_tags_of_v<Accept>, traverse);
|
|
235
244
|
}
|
|
236
245
|
});
|
|
237
246
|
}
|
|
@@ -272,7 +281,7 @@ struct visit_value : reference_map_t<Reference, reference_map_type> {
|
|
|
272
281
|
// strings
|
|
273
282
|
template <class Accept>
|
|
274
283
|
auto immediate(value_of<string_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
|
|
275
|
-
if (
|
|
284
|
+
if (maybe_is_string_latin1(subject).value_or(false)) {
|
|
276
285
|
return accept_tagged(value_of<string_tag_of<char>>::from(subject), accept);
|
|
277
286
|
} else {
|
|
278
287
|
return accept_tagged(value_of<string_tag_of<char16_t>>::from(subject), accept);
|
|
@@ -298,7 +307,7 @@ struct visit_value : reference_map_t<Reference, reference_map_type> {
|
|
|
298
307
|
return immediate(value_of<data_view_tag>::from(subject), accept);
|
|
299
308
|
} else if (maybe_is_shared_array_buffer(env_.get(), subject).value_or(false)) {
|
|
300
309
|
return immediate(value_of<shared_array_buffer_tag>::from(subject), accept);
|
|
301
|
-
} else if (
|
|
310
|
+
} else if (is_object_array_buffer(env_.get(), subject)) {
|
|
302
311
|
return immediate(value_of<array_buffer_tag>::from(subject), accept);
|
|
303
312
|
} else if (napi::invoke(napi_is_promise, napi_env{*this}, subject)) {
|
|
304
313
|
return immediate(value_of<promise_tag>::from(subject), accept);
|
|
@@ -316,7 +325,7 @@ struct visit_value : reference_map_t<Reference, reference_map_type> {
|
|
|
316
325
|
// data blocks
|
|
317
326
|
template <class Accept>
|
|
318
327
|
auto immediate(value_of<data_block_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
|
|
319
|
-
if (
|
|
328
|
+
if (is_data_block_array_buffer(env_.get(), subject)) {
|
|
320
329
|
return immediate(value_of<array_buffer_tag>::from(subject), accept);
|
|
321
330
|
} else {
|
|
322
331
|
return immediate(value_of<shared_array_buffer_tag>::from(subject), accept);
|
package/value/array_buffer.cc
CHANGED
|
@@ -24,11 +24,9 @@ bound_value_for_array_buffer::operator js::array_buffer() const {
|
|
|
24
24
|
|
|
25
25
|
// `bound_value_for_shared_array_buffer`
|
|
26
26
|
bound_value_for_shared_array_buffer::operator js::shared_array_buffer() const {
|
|
27
|
-
auto
|
|
28
|
-
auto backing_store =
|
|
29
|
-
|
|
30
|
-
auto data_shared_ptr = std::shared_ptr<js::shared_array_buffer::array_type>{std::move(backing_store), data};
|
|
31
|
-
return js::shared_array_buffer{local->ByteLength(), std::move(data_shared_ptr)};
|
|
27
|
+
auto byte_length = shared_array_buffer_get_byte_length(value_of{*this});
|
|
28
|
+
auto backing_store = shared_array_buffer_get_backing_store(value_of{*this});
|
|
29
|
+
return js::shared_array_buffer{byte_length, std::move(backing_store)};
|
|
32
30
|
}
|
|
33
31
|
|
|
34
32
|
// `value_for_typed_array`
|
package/value/primitive.h.cc
CHANGED
|
@@ -13,6 +13,19 @@ class bound_value_for_boolean : public bound_value_next<boolean_tag> {
|
|
|
13
13
|
using bound_value_next<boolean_tag>::bound_value_next;
|
|
14
14
|
[[nodiscard]] explicit operator bool() const;
|
|
15
15
|
};
|
|
16
|
+
|
|
17
|
+
class bound_value_for_false : public bound_value_next<false_tag> {
|
|
18
|
+
public:
|
|
19
|
+
using bound_value_next<false_tag>::bound_value_next;
|
|
20
|
+
[[nodiscard]] constexpr explicit operator bool() const { return false; }
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
class bound_value_for_true : public bound_value_next<true_tag> {
|
|
24
|
+
public:
|
|
25
|
+
using bound_value_next<true_tag>::bound_value_next;
|
|
26
|
+
[[nodiscard]] constexpr explicit operator bool() const { return true; }
|
|
27
|
+
};
|
|
28
|
+
|
|
16
29
|
// number
|
|
17
30
|
class bound_value_for_number : public bound_value_next<number_tag> {
|
|
18
31
|
public:
|
package/support/host_shim.cc
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import std;
|
|
2
|
-
|
|
3
|
-
// NOLINTBEGIN(bugprone-macro-parentheses)
|
|
4
|
-
#if _WIN64
|
|
5
|
-
// I couldn't get this to work.
|
|
6
|
-
// https://stackoverflow.com/questions/2290587/gcc-style-weak-linking-in-visual-studio
|
|
7
|
-
#define SHIM(NAME)
|
|
8
|
-
#else
|
|
9
|
-
#define SHIM(NAME) \
|
|
10
|
-
__attribute__((weak)) __attribute__((visibility("default"))) auto NAME = nullptr;
|
|
11
|
-
#endif
|
|
12
|
-
// NOLINTEND(bugprone-macro-parentheses)
|
|
13
|
-
|
|
14
|
-
extern "C" {
|
|
15
|
-
const void* shim_nullptr = nullptr;
|
|
16
|
-
// NOLINTBEGIN(bugprone-reserved-identifier)
|
|
17
|
-
SHIM(_ZN2v810Int16Array3NewENS_5LocalINS_17SharedArrayBufferEEEmm)
|
|
18
|
-
SHIM(_ZN2v810Int32Array3NewENS_5LocalINS_17SharedArrayBufferEEEmm)
|
|
19
|
-
SHIM(_ZN2v810Uint8Array3NewENS_5LocalINS_17SharedArrayBufferEEEmm)
|
|
20
|
-
SHIM(_ZN2v811Uint16Array3NewENS_5LocalINS_17SharedArrayBufferEEEmm)
|
|
21
|
-
SHIM(_ZN2v811Uint32Array3NewENS_5LocalINS_17SharedArrayBufferEEEmm)
|
|
22
|
-
SHIM(_ZN2v812BackingStoreD1Ev)
|
|
23
|
-
SHIM(_ZN2v812Float16Array3NewENS_5LocalINS_17SharedArrayBufferEEEmm)
|
|
24
|
-
SHIM(_ZN2v812Float32Array3NewENS_5LocalINS_17SharedArrayBufferEEEmm)
|
|
25
|
-
SHIM(_ZN2v812Float64Array3NewENS_5LocalINS_17SharedArrayBufferEEEmm)
|
|
26
|
-
SHIM(_ZN2v813BigInt64Array3NewENS_5LocalINS_17SharedArrayBufferEEEmm)
|
|
27
|
-
SHIM(_ZN2v814BigUint64Array3NewENS_5LocalINS_17SharedArrayBufferEEEmm)
|
|
28
|
-
SHIM(_ZN2v817SharedArrayBuffer15GetBackingStoreEv)
|
|
29
|
-
SHIM(_ZN2v817SharedArrayBuffer15NewBackingStoreEPvmPFvS1_mS1_ES1_)
|
|
30
|
-
SHIM(_ZN2v817SharedArrayBuffer3NewEPNS_7IsolateENSt3__110shared_ptrINS_12BackingStoreEEE)
|
|
31
|
-
SHIM(_ZN2v817Uint8ClampedArray3NewENS_5LocalINS_17SharedArrayBufferEEEmm)
|
|
32
|
-
SHIM(_ZN2v87Isolate10GetCurrentEv)
|
|
33
|
-
SHIM(_ZN2v88DataView3NewENS_5LocalINS_17SharedArrayBufferEEEmm)
|
|
34
|
-
SHIM(_ZN2v89Int8Array3NewENS_5LocalINS_17SharedArrayBufferEEEmm)
|
|
35
|
-
SHIM(_ZNK2v812BackingStore4DataEv)
|
|
36
|
-
SHIM(_ZNK2v817SharedArrayBuffer10ByteLengthEv)
|
|
37
|
-
SHIM(_ZNK2v85Value7IsInt32Ev)
|
|
38
|
-
SHIM(_ZNK2v85Value8IsNumberEv)
|
|
39
|
-
SHIM(_ZNK2v86String9IsOneByteEv)
|
|
40
|
-
SHIM(node_api_is_sharedarraybuffer)
|
|
41
|
-
// NOLINTEND(bugprone-reserved-identifier)
|
|
42
|
-
}
|