diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 017061fea..7aab5c56d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -59,10 +59,10 @@ jobs: include: - arch: x86 artifact: subconverter_darwin64 - os: macos-13 + os: macos-26-intel - arch: arm artifact: subconverter_darwinarm - os: macos-14 + os: macos-26 runs-on: ${{ matrix.os }} name: macOS ${{ matrix.arch }} Build steps: diff --git a/include/quickjspp.hpp b/include/quickjspp.hpp deleted file mode 100644 index b1a2e3f25..000000000 --- a/include/quickjspp.hpp +++ /dev/null @@ -1,2232 +0,0 @@ -#pragma once - -#include "quickjs/quickjs.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#if defined(__cpp_rtti) -#define QJSPP_TYPENAME(...) (typeid(__VA_ARGS__).name()) -#else -#define QJSPP_TYPENAME(...) #__VA_ARGS__ -#endif - - -namespace qjs { - -class Context; -class Value; - -/** Exception type. - * Indicates that exception has occured in JS context. - */ -class exception { - JSContext * ctx; -public: - exception(JSContext * ctx) : ctx(ctx) {} - Context & context() const; - - /// Clears and returns the occurred exception. - Value get(); -}; - -/** std::shared_ptr, for compatibility with quickjspp v2. */ -template using shared_ptr = std::shared_ptr; -/** std::make_shared, for compatibility with quickjspp v2. */ -template -shared_ptr make_shared(JSContext *, Args&&... args) -{ - return std::make_shared(std::forward(args)...); -} - -/** Javascript conversion traits. - * Describes how to convert type R to/from JSValue. Second template argument can be used for SFINAE/enable_if type filters. - */ -template -struct js_traits -{ - /** Create an object of C++ type R given JSValue v and JSContext. - * This function is intentionally not implemented. User should implement this function for their own type. - * @param v This value is passed as JSValueConst so it should be freed by the caller. - * @throws exception in case of conversion error - */ - static R unwrap(JSContext * ctx, JSValueConst v) = delete; - - /** Create JSValue from an object of type R and JSContext. - * This function is intentionally not implemented. User should implement this function for their own type. - * @return Returns JSValue which should be freed by the caller or JS_EXCEPTION in case of error. - */ - static JSValue wrap(JSContext * ctx, R value) = delete; -}; - -/** Conversion traits for JSValue (identity). - */ -template <> -struct js_traits -{ - static JSValue unwrap(JSContext * ctx, JSValueConst v) noexcept - { - return JS_DupValue(ctx, v); - } - - static JSValue wrap(JSContext * ctx, JSValue&& v) noexcept - { - return v; - } -}; - -/** Conversion traits for integers. - * Intentionally doesn't define traits for uint64_t since it can be typedefed to JSValue. (@see JS_NAN_BOXING) - */ -template -struct js_traits && sizeof(Int) <= sizeof(int64_t) && !std::is_same_v>> -{ - /// @throws exception - static Int unwrap(JSContext * ctx, JSValueConst v) - { - if constexpr (sizeof(Int) > sizeof(int32_t)) - { - int64_t r; - if(JS_ToInt64(ctx, &r, v)) - throw exception{ctx}; - return static_cast(r); - } - else - { - int32_t r; - if(JS_ToInt32(ctx, &r, v)) - throw exception{ctx}; - return static_cast(r); - } - } - - static JSValue wrap(JSContext * ctx, Int i) noexcept - { - if constexpr (std::is_same_v || sizeof(Int) > sizeof(int32_t)) - return JS_NewInt64(ctx, static_cast(i)); - else - return JS_NewInt32(ctx, static_cast(i)); - } -}; - -/** Conversion traits for boolean. - */ -template <> -struct js_traits -{ - static bool unwrap(JSContext * ctx, JSValueConst v) noexcept - { - // TODO: is this behaviour correct? - return JS_ToBool(ctx, v) > 0; - } - - static JSValue wrap(JSContext * ctx, bool i) noexcept - { - return JS_NewBool(ctx, i); - } -}; - -/** Conversion trait for void. - */ -template <> -struct js_traits -{ - /// @throws exception if jsvalue is neither undefined nor null - static void unwrap(JSContext * ctx, JSValueConst value) - { - if(JS_IsException(value)) - throw exception{ctx}; - } -}; - -/** Conversion traits for float64/double. - */ -template <> -struct js_traits -{ - /// @throws exception - static double unwrap(JSContext * ctx, JSValueConst v) - { - double r; - if(JS_ToFloat64(ctx, &r, v)) - throw exception{ctx}; - return r; - } - - static JSValue wrap(JSContext * ctx, double i) noexcept - { - return JS_NewFloat64(ctx, i); - } -}; - -namespace detail { -/** Fake std::string_view which frees the string on destruction. -*/ -class js_string : public std::string_view -{ - using Base = std::string_view; - JSContext * ctx = nullptr; - - friend struct js_traits; - - js_string(JSContext * ctx, const char * ptr, std::size_t len) : Base(ptr, len), ctx(ctx) {} - -public: - - template - js_string(Args&& ... args) : Base(std::forward(args)...), ctx(nullptr) {} - - js_string(const js_string& other) = delete; - - operator const char *() const - { - return this->data(); - } - - ~js_string() - { - if(ctx) - JS_FreeCString(ctx, this->data()); - } -}; -} // namespace detail - -/** Conversion traits from std::string_view and to detail::js_string. */ -template <> -struct js_traits -{ - static detail::js_string unwrap(JSContext * ctx, JSValueConst v) - { - size_t plen; - const char * ptr = JS_ToCStringLen(ctx, &plen, v); - if(!ptr) - throw exception{ctx}; - return detail::js_string{ctx, ptr, plen}; - } - - static JSValue wrap(JSContext * ctx, std::string_view str) noexcept - { - return JS_NewStringLen(ctx, str.data(), str.size()); - } -}; - -/** Conversion traits for std::string */ -template <> // slower -struct js_traits -{ - static std::string unwrap(JSContext * ctx, JSValueConst v) - { - auto str_view = js_traits::unwrap(ctx, v); - return std::string{str_view.data(), str_view.size()}; - } - - static JSValue wrap(JSContext * ctx, const std::string& str) noexcept - { - return JS_NewStringLen(ctx, str.data(), str.size()); - } -}; - -/** Conversion from const char * */ -template <> -struct js_traits -{ - static JSValue wrap(JSContext * ctx, const char * str) noexcept - { - return JS_NewString(ctx, str); - } - - static detail::js_string unwrap(JSContext * ctx, JSValueConst v) - { - return js_traits::unwrap(ctx, v); - } -}; - - -/** Conversion from const std::variant */ -template -struct js_traits> -{ - static JSValue wrap(JSContext * ctx, std::variant value) noexcept - { - return std::visit([ctx](auto&& value) { - using T = std::decay_t; - return js_traits::wrap(ctx, value); - }, std::move(value)); - } - - - /* Useful type traits */ - template struct is_shared_ptr : std::false_type {}; - template struct is_shared_ptr> : std::true_type {}; - template struct is_string - { - static constexpr bool value = std::is_same_v || std::is_same_v, std::string> || - std::is_same_v, std::string_view>; - }; - template struct is_boolean { static constexpr bool value = std::is_same_v, bool>; }; - template struct is_double { static constexpr bool value = std::is_same_v, double>; }; - template struct is_vector : std::false_type {}; - template struct is_vector> : std::true_type {}; - template struct is_pair : std::false_type {}; - template struct is_pair> : std::true_type {}; - template struct is_variant : std::false_type {}; - template struct is_variant> : std::true_type {}; - - /** Attempt to match common types (integral, floating-point, string, etc.) */ - template