diff --git a/source/scriptinterface/NativeWrapperDecls.h b/source/scriptinterface/NativeWrapperDecls.h index 704bb3a2ed..7b3155d97e 100644 --- a/source/scriptinterface/NativeWrapperDecls.h +++ b/source/scriptinterface/NativeWrapperDecls.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2014 Wildfire Games. +/* Copyright (C) 2016 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -18,37 +18,6 @@ #include #include -private: - -/** - * In our interface code (the CONVERT_ARG macro specifically) we require types to be default-constructible. - * This is a workaround to make the current design work with JS::HandleValue types, which have a private constructor. - * JS::HandleValue objects are meant to be implicitly created only from JS::RootedValue objects. - * Generally handles should not be used this way, but in this case we can be sure that the handle will not live longer than its root, - * so it should be OK. - * This solution involves some overhead, but it should be quite small and shouldn't affect performance in practice. - * HandleValue types are just structs with one pointer and fit into a single register. - */ -class HandleWrapper -{ -public: - HandleWrapper() : m_Handle(JS::NullHandleValue) {}; - void set(JS::HandleValue handle) { m_Handle.repoint(handle); } - operator JS::HandleValue() - { - return m_Handle; - } - -private: - JS::HandleValue m_Handle; -}; - -// WrapperIfHandle::Type has the type HandleWrapper for T == JS::HandleValue and -// T for all other types. -// Allows to use default-constructible HandleWrapper types in templates instead of the -// HandleValue type that isn't default-constructible without code duplication. -template struct WrapperIfHandle; - public: // Define lots of useful macros: @@ -71,8 +40,12 @@ public: // 1. On the conceptual side: How to consistently work with optional parameters (or drop them completely?) // 2. On the technical side: Improve error handling, find a better way to ensure parameters are initialized #define CONVERT_ARG(z, i, data) \ - typename WrapperIfHandle::Type a##i; \ - if (! ScriptInterface::FromJSVal::Type>(cx, i < args.length() ? args[i] : JS::UndefinedHandleValue, a##i)) return false; + bool typeConvRet##i; \ + T##i a##i = ScriptInterface::AssignOrFromJSVal( \ + cx, \ + i < args.length() ? args[i] : JS::UndefinedHandleValue, \ + typeConvRet##i); \ + if (!typeConvRet##i) return false; // List-generating macros, named roughly after their first list item #define TYPENAME_T0_HEAD(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_HEAD, typename T) // "typename T0, typename T1, " diff --git a/source/scriptinterface/NativeWrapperDefns.h b/source/scriptinterface/NativeWrapperDefns.h index 560a15d396..19f95f0ef3 100644 --- a/source/scriptinterface/NativeWrapperDefns.h +++ b/source/scriptinterface/NativeWrapperDefns.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2014 Wildfire Games. +/* Copyright (C) 2016 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -16,16 +16,6 @@ */ #include "ps/GameSetup/Config.h" -template struct ScriptInterface::WrapperIfHandle -{ - typedef T Type; -}; - -template <> struct ScriptInterface::WrapperIfHandle -{ - typedef HandleWrapper Type; -}; - // (NativeWrapperDecls.h set up a lot of the macros we use here) // ScriptInterface_NativeWrapper::call(cx, rval, fptr, args...) will call fptr(cbdata, args...), diff --git a/source/scriptinterface/ScriptInterface.cpp b/source/scriptinterface/ScriptInterface.cpp index eeb143bc44..12b8b55760 100644 --- a/source/scriptinterface/ScriptInterface.cpp +++ b/source/scriptinterface/ScriptInterface.cpp @@ -378,13 +378,6 @@ ScriptInterface_impl::~ScriptInterface_impl() JS_DestroyContext(m_cx); } -// Inside ScriptInterface.cpp directly to emphasize that it should only be used/needed internally and not from other code. -template<> bool ScriptInterface::FromJSVal(JSContext* UNUSED(cx), JS::HandleValue v, ScriptInterface::HandleWrapper& out) -{ - out.set(v); - return true; -} - void ScriptInterface_impl::Register(const char* name, JSNative fptr, uint nargs) { JSAutoRequest rq(m_cx); diff --git a/source/scriptinterface/ScriptInterface.h b/source/scriptinterface/ScriptInterface.h index bae8088141..3b23ebe7c2 100644 --- a/source/scriptinterface/ScriptInterface.h +++ b/source/scriptinterface/ScriptInterface.h @@ -375,6 +375,14 @@ public: { AssignOrToJSVal(cx, handle, a); } + + /** + * Converts |val| to T if needed or just returns it if it's a handle. + * This is meant for use in other templates where we want to use the same code for JS::HandleValue and + * other types. + */ + template + static T AssignOrFromJSVal(JSContext* cx, const JS::HandleValue& val, bool& ret); private: @@ -476,6 +484,21 @@ inline void ScriptInterface::AssignOrToJSValUnrooted(JSContext* UNUSE handle.set(a); } +template +inline T ScriptInterface::AssignOrFromJSVal(JSContext* cx, const JS::HandleValue& val, bool& ret) +{ + T retVal; + ret = FromJSVal(cx, val, retVal); + return retVal; +} + +template<> +inline JS::HandleValue ScriptInterface::AssignOrFromJSVal(JSContext* UNUSED(cx), const JS::HandleValue& val, bool& ret) +{ + ret = true; + return val; +} + template bool ScriptInterface::CallFunctionVoid(JS::HandleValue val, const char* name, const T0& a0) {