Index: source/scriptinterface/FunctionWrapper.h =================================================================== --- source/scriptinterface/FunctionWrapper.h +++ source/scriptinterface/FunctionWrapper.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2022 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -25,6 +25,7 @@ #include #include +#include class ScriptInterface; @@ -89,7 +90,7 @@ * @param went_ok - true if the conversion succeeded and went_ok was true before, false otherwise. */ template - static std::tuple DoConvertFromJS(const ScriptRequest& rq, JS::CallArgs& args, bool& went_ok) + static T DoConvertFromJS(const ScriptRequest& rq, JS::CallArgs& args, bool& went_ok) { // No need to convert JS values. if constexpr (std::is_same_v) @@ -97,12 +98,12 @@ // Default-construct values that aren't passed by JS. // TODO: this should perhaps be removed, as it's distinct from C++ default values and kind of tricky. if (idx >= args.length()) - return std::forward_as_tuple(JS::UndefinedHandleValue); + return JS::UndefinedHandleValue; else { // GCC (at least < 9) & VS17 prints warnings if arguments are not used in some constexpr branch. UNUSED2(rq); UNUSED2(args); UNUSED2(went_ok); - return std::forward_as_tuple(args[idx]); // This passes the null handle value if idx is beyond the length of args. + return args[idx]; // This passes the null handle value if idx is beyond the length of args. } } else @@ -110,29 +111,29 @@ // Default-construct values that aren't passed by JS. // TODO: this should perhaps be removed, as it's distinct from C++ default values and kind of tricky. if (idx >= args.length()) - return std::forward_as_tuple(T{}); + return {}; else { T ret; went_ok &= Script::FromJSVal(rq, args[idx], ret); - return std::forward_as_tuple(ret); + return ret; } } } /** - * Recursive wrapper: calls DoConvertFromJS for type T and recurses. + * Wrapper: calls DoConvertFromJS for each element in T. */ - template - static std::tuple DoConvertFromJS(const ScriptRequest& rq, JS::CallArgs& args, bool& went_ok) + template + static T DoConvertFromJS(std::index_sequence, const ScriptRequest& rq, JS::CallArgs& args, + bool& went_ok) { - return std::tuple_cat(DoConvertFromJS(rq, args, went_ok), DoConvertFromJS(rq, args, went_ok)); + return {DoConvertFromJS>(rq, args, went_ok)...}; } /** - * ConvertFromJS is a wrapper around DoConvertFromJS, and serves to: - * - unwrap the tuple types as a parameter pack - * - handle specific cases for the first argument (ScriptRequest, ...). + * ConvertFromJS is a wrapper around DoConvertFromJS, and handles specific cases for the + * first argument (ScriptRequest, ...). * * Trick: to unpack the types of the tuple as a parameter pack, we deduce them from the function signature. * To do that, we want the tuple in the arguments, but we don't want to actually have to default-instantiate, @@ -141,42 +142,25 @@ template static std::tuple ConvertFromJS(const ScriptRequest& rq, JS::CallArgs& args, bool& went_ok, std::tuple*) { - if constexpr (sizeof...(Types) == 0) - { - // GCC (at least < 9) & VS17 prints warnings if arguments are not used in some constexpr branch. - UNUSED2(rq); UNUSED2(args); UNUSED2(went_ok); - return {}; - } - else - return DoConvertFromJS<0, Types...>(rq, args, went_ok); + return DoConvertFromJS>(std::index_sequence_for(), rq, args, + went_ok); } // Overloads for ScriptRequest& first argument. template static std::tuple ConvertFromJS(const ScriptRequest& rq, JS::CallArgs& args, bool& went_ok, std::tuple*) { - if constexpr (sizeof...(Types) == 0) - { - // GCC (at least < 9) & VS17 prints warnings if arguments are not used in some constexpr branch. - UNUSED2(args); UNUSED2(went_ok); - return std::forward_as_tuple(rq); - } - else - return std::tuple_cat(std::forward_as_tuple(rq), DoConvertFromJS<0, Types...>(rq, args, went_ok)); + return std::tuple_cat(std::tie(rq), DoConvertFromJS>( + std::index_sequence_for(), rq, args, went_ok)); } // Overloads for ScriptInterface& first argument. template static std::tuple ConvertFromJS(const ScriptRequest& rq, JS::CallArgs& args, bool& went_ok, std::tuple*) { - if constexpr (sizeof...(Types) == 0) - { - // GCC (at least < 9) & VS17 prints warnings if arguments are not used in some constexpr branch. - UNUSED2(rq); UNUSED2(args); UNUSED2(went_ok); - return std::forward_as_tuple(rq.GetScriptInterface()); - } - else - return std::tuple_cat(std::forward_as_tuple(rq.GetScriptInterface()), DoConvertFromJS<0, Types...>(rq, args, went_ok)); + return std::tuple_cat(std::tie(rq.GetScriptInterface()), + DoConvertFromJS>(std::index_sequence_for(), rq, args, + went_ok)); } /////////////////////////////////////////////////////////////////////////// @@ -205,20 +189,14 @@ static inline IgnoreResult_t IgnoreResult; /** - * Recursive helper to call AssignOrToJSVal + * Helper to call AssignOrToJSVal */ - template - static void AssignOrToJSValHelper(const ScriptRequest& rq, JS::MutableHandleValueVector argv, const T& a, const Ts&... params) - { - Script::ToJSVal(rq, argv[i], a); - AssignOrToJSValHelper(rq, argv, params...); - } - - template - static void AssignOrToJSValHelper(const ScriptRequest& UNUSED(rq), JS::MutableHandleValueVector UNUSED(argv)) + template + static void AssignOrToJSValHelper(const ScriptRequest& rq, + [[maybe_unused]] JS::MutableHandleValueVector argv, const Ts&... params) { - static_assert(sizeof...(Ts) == 0); - // Nop, for terminating the template recursion. + size_t idx = 0; + (Script::ToJSVal(rq, argv[idx++], params),...); } /** @@ -242,7 +220,7 @@ JS::RootedValueVector argv(rq.cx); ignore_result(argv.resize(sizeof...(Args))); - AssignOrToJSValHelper<0>(rq, &argv, args...); + AssignOrToJSValHelper(rq, &argv, args...); bool success; if constexpr (std::is_same_v)