231103.1 · 7f4a9ed91bbecb84e39f4bc8030247ce5116ddf8
Reorganize examples into categorized folders (#341)
* refactor: create directory structure to organize exmaples
* test: update test_all to work with new directory structure
* fix: bug in test_all if no package.json scripts
* test: cleanup output of test_all
* fix: remove default test script that throws from thread_safe_function_with_object_wrap
* fix: remove build_with_cmake from .gitignore
* fix: swith to ' from " and remove subdir from getAllTests call
* test: add extra test cases for npm start and just running the pkgJson.main with node
* refactor: move all examples to src directory
* refactor: add numbers to categories so they are ordered in the src folder
* refactor: simplify getAllExamples in test_all.js
* docs: add directory structure to README.md
* docs: update directory structure to README.md
* docs: update directory structure to README.md
* docs: update directory structure to README.md
* docs: update directory structure example in readme
* add back build_with_cmake
---------
Co-authored-by: legendecas <legendecas@gmail.com>
reading declarations
Changes to src/2-js-to-native-conversion/object-template-demo/napi/node-api-common.h. All files
src/2-js-to-native-conversion/object-template-demo/napi/node-api-common.h
@@ -0,0 +1,141 @@+#include <node_api.h>+#include <initializer_list>+#include <utility>++// Empty value so that macros here are able to return NULL or void+#define NODE_API_RETVAL_NOTHING // Intentionally blank #define++#define GET_AND_THROW_LAST_ERROR(env) \+ do { \+ const napi_extended_error_info* error_info; \+ napi_get_last_error_info((env), &error_info); \+ bool is_pending; \+ const char* err_message = error_info->error_message; \+ napi_is_exception_pending((env), &is_pending); \+ /* If an exception is already pending, don't rethrow it */ \+ if (!is_pending) { \+ const char* error_message = \+ err_message != NULL ? err_message : "empty error message"; \+ napi_throw_error((env), NULL, error_message); \+ } \+ } while (0)++#define NODE_API_ASSERT_BASE(env, assertion, message, ret_val) \+ do { \+ if (!(assertion)) { \+ napi_throw_error( \+ (env), NULL, "assertion (" #assertion ") failed: " message); \+ return ret_val; \+ } \+ } while (0)++// Returns NULL on failed assertion.+// This is meant to be used inside napi_callback methods.+#define NODE_API_ASSERT(env, assertion, message) \+ NODE_API_ASSERT_BASE(env, assertion, message, NULL)++#define NODE_API_CALL_BASE(env, the_call, ret_val) \+ do { \+ if ((the_call) != napi_ok) { \+ GET_AND_THROW_LAST_ERROR((env)); \+ return ret_val; \+ } \+ } while (0)++// Returns NULL if the_call doesn't return napi_ok.+#define NODE_API_CALL(env, the_call) NODE_API_CALL_BASE(env, the_call, NULL)++// Returns empty if the_call doesn't return napi_ok.+#define NODE_API_CALL_RETURN_VOID(env, the_call) \+ NODE_API_CALL_BASE(env, the_call, NODE_API_RETVAL_NOTHING)++#define CHECK_NAPI(...) \+ do { \+ napi_status res__ = (__VA_ARGS__); \+ if (res__ != napi_ok) { \+ return res__; \+ } \+ } while (0)++#define NAPI_CALL(expr) NODE_API_CALL(env, expr);++#ifdef __cpp_lib_span+#include <span>+using std::span;+#else+/**+ * @brief A span of values that can be used to pass arguments to function.+ *+ * For C++20 we should consider to replace it with std::span.+ */+template <typename T>+struct span {+ constexpr span(std::initializer_list<T> il) noexcept+ : data_{const_cast<T*>(il.begin())}, size_{il.size()} {}+ constexpr span(T* data, size_t size) noexcept : data_{data}, size_{size} {}+ [[nodiscard]] constexpr T* data() const noexcept { return data_; }+ [[nodiscard]] constexpr size_t size() const noexcept { return size_; }+ [[nodiscard]] constexpr T* begin() const noexcept { return data_; }+ [[nodiscard]] constexpr T* end() const noexcept { return data_ + size_; }+ const T& operator[](size_t index) const noexcept { return *(data_ + index); }++ private:+ T* data_;+ size_t size_;+};+#endif // __cpp_lib_span++struct RefHolder {+ RefHolder(std::nullptr_t = nullptr) noexcept {}+ explicit RefHolder(napi_env env, napi_value value) : env_(env) {+ // Start with 2 to avoid ever going to 0 that creates a weak ref.+ napi_create_reference(env, value, 2, &ref_);+ }++ // The class is movable.+ RefHolder(RefHolder&& other) noexcept+ : env_(std::exchange(other.env_, nullptr)),+ ref_(std::exchange(other.ref_, nullptr)) {}++ RefHolder& operator=(RefHolder&& other) noexcept {+ if (this != &other) {+ swap(*this, other);+ RefHolder temp(std::move(other));+ }+ return *this;+ }++ // The class is not copyable.+ RefHolder(const RefHolder& other) = delete;+ RefHolder& operator=(const RefHolder& other) = delete;++ ~RefHolder() noexcept {+ if (env_ != nullptr && ref_ != nullptr) {+ uint32_t refCount{};+ napi_reference_unref(env_, ref_, &refCount);+ if (refCount == 1) {+ napi_delete_reference(env_, ref_);+ }+ }+ }++ operator napi_value() const {+ napi_value result{};+ if (ref_ != nullptr) {+ napi_get_reference_value(env_, ref_, &result);+ }+ return result;+ }++ explicit operator bool() const noexcept { return ref_ != nullptr; }++ friend void swap(RefHolder& left, RefHolder& right) noexcept {+ using std::swap;+ swap(left.env_, right.env_);+ swap(left.ref_, right.ref_);+ }++ private:+ napi_env env_{};+ napi_ref ref_{};+};