// Copyright 2004-present Facebook. All Rights Reserved. #pragma once namespace facebook { namespace xplat { namespace detail { template R jsArg1(const folly::dynamic& arg, M asFoo, const T&... desc) { try { return (arg.*asFoo)(); } catch (const folly::TypeError& ex) { throw JsArgumentException( folly::to( "Error converting javascript arg ", desc..., " to C++: ", ex.what())); } catch (const std::range_error& ex) { throw JsArgumentException( folly::to( "Could not convert argument ", desc..., " to required type: ", ex.what())); } } } template R jsArg(const folly::dynamic& arg, R (folly::dynamic::*asFoo)() const, const T&... desc) { return detail::jsArg1(arg, asFoo, desc...); } template R jsArg(const folly::dynamic& arg, R (folly::dynamic::*asFoo)() const&, const T&... desc) { return detail::jsArg1(arg, asFoo, desc...); } template typename detail::is_dynamic::type& jsArgAsDynamic(T&& args, size_t n) { try { return args[n]; } catch (const std::out_of_range& ex) { // Use 1-base counting for argument description. throw JsArgumentException( folly::to( "JavaScript provided ", args.size(), " arguments for C++ method which references at least ", n + 1, " arguments: ", ex.what())); } } template R jsArgN(const folly::dynamic& args, size_t n, R (folly::dynamic::*asFoo)() const) { return jsArg(jsArgAsDynamic(args, n), asFoo, n); } template R jsArgN(const folly::dynamic& args, size_t n, R (folly::dynamic::*asFoo)() const&) { return jsArg(jsArgAsDynamic(args, n), asFoo, n); } namespace detail { // This is a helper for jsArgAsArray and jsArgAsObject. template typename detail::is_dynamic::type& jsArgAsType(T&& args, size_t n, const char* required, bool (folly::dynamic::*isFoo)() const) { T& ret = jsArgAsDynamic(args, n); if ((ret.*isFoo)()) { return ret; } // Use 1-base counting for argument description. throw JsArgumentException( folly::to( "Argument ", n + 1, " of type ", ret.typeName(), " is not required type ", required)); } } // end namespace detail template typename detail::is_dynamic::type& jsArgAsArray(T&& args, size_t n) { return detail::jsArgAsType(args, n, "Array", &folly::dynamic::isArray); } template typename detail::is_dynamic::type& jsArgAsObject(T&& args, size_t n) { return detail::jsArgAsType(args, n, "Object", &folly::dynamic::isObject); } }}