/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #include "NativeCxxModuleExample.h" #include #include #include #include #include namespace facebook::react { namespace { std::string to_string_with_precision(double value, int precision = 2) { std::ostringstream oss; oss << std::setprecision(precision) << std::fixed << value; return oss.str(); } } // namespace NativeCxxModuleExample::NativeCxxModuleExample( std::shared_ptr jsInvoker) : NativeCxxModuleExampleCxxSpec(std::move(jsInvoker)) {} void NativeCxxModuleExample::getValueWithCallback( jsi::Runtime& /*rt*/, const AsyncCallback& callback) { callback({"value from callback!"}); } std::function NativeCxxModuleExample::setValueCallbackWithSubscription( jsi::Runtime& /*rt*/, AsyncCallback callback) { valueCallback_ = std::make_optional(callback); return [&]() { if (valueCallback_.has_value()) { valueCallback_.value()({"value from callback on clean up!"}); valueCallback_ = std::nullopt; } }; } std::vector> NativeCxxModuleExample::getArray( jsi::Runtime& /*rt*/, std::vector> arg) { return arg; } bool NativeCxxModuleExample::getBool(jsi::Runtime& /*rt*/, bool arg) { return arg; } ConstantsStruct NativeCxxModuleExample::getConstants(jsi::Runtime& /*rt*/) { return ConstantsStruct{true, 69, "react-native"}; } CustomEnumInt NativeCxxModuleExample::getCustomEnum( jsi::Runtime& /*rt*/, CustomEnumInt arg) { return arg; } std::shared_ptr NativeCxxModuleExample::getCustomHostObject( jsi::Runtime& /*rt*/) { return std::make_shared( std::make_shared("answer", 42)); } std::string NativeCxxModuleExample::consumeCustomHostObject( jsi::Runtime& /*rt*/, std::shared_ptr arg) { auto value = arg->getValue(); return value->a_ + std::to_string(value->b_); } BinaryTreeNode NativeCxxModuleExample::getBinaryTreeNode( jsi::Runtime& /*rt*/, BinaryTreeNode arg) { return arg; } GraphNode NativeCxxModuleExample::getGraphNode( jsi::Runtime& /*rt*/, GraphNode arg) { if (arg.neighbors) { arg.neighbors->emplace_back(GraphNode{.label = "top"}); arg.neighbors->emplace_back(GraphNode{.label = "down"}); } return arg; } NativeCxxModuleExampleEnumInt NativeCxxModuleExample::getNumEnum( jsi::Runtime& /*rt*/, NativeCxxModuleExampleEnumInt arg) { return arg; } NativeCxxModuleExampleEnumStr NativeCxxModuleExample::getStrEnum( jsi::Runtime& /*rt*/, NativeCxxModuleExampleEnumNone /*arg*/) { return NativeCxxModuleExampleEnumStr::SB; } std::map> NativeCxxModuleExample::getMap( jsi::Runtime& /*rt*/, std::map> arg) { return arg; } double NativeCxxModuleExample::getNumber(jsi::Runtime& /*rt*/, double arg) { return arg; } ObjectStruct NativeCxxModuleExample::getObject( jsi::Runtime& /*rt*/, ObjectStruct arg) { return arg; } std::set NativeCxxModuleExample::getSet( jsi::Runtime& /*rt*/, std::set arg) { return arg; } std::string NativeCxxModuleExample::getString( jsi::Runtime& /*rt*/, std::string arg) { return arg; } std::string NativeCxxModuleExample::getUnion( jsi::Runtime& rt, float x, const std::string& y, jsi::Object z) { std::string result = "x: " + to_string_with_precision(x) + ", y: " + y + ", z: { "; if (z.hasProperty(rt, "value")) { result += "value: "; result += to_string_with_precision(z.getProperty(rt, "value").getNumber(), 0); } else if (z.hasProperty(rt, "low")) { result += "low: "; result += z.getProperty(rt, "low").getString(rt).utf8(rt); } result += " }"; return result; } ValueStruct NativeCxxModuleExample::getValue( jsi::Runtime& /*rt*/, double x, std::string y, ObjectStruct z) { ValueStruct result{x, std::move(y), std::move(z)}; return result; } AsyncPromise NativeCxxModuleExample::getValueWithPromise( jsi::Runtime& rt, bool error) { auto promise = AsyncPromise(rt, jsInvoker_); if (error) { promise.reject("intentional promise rejection"); } else { promise.resolve("result!"); } return promise; } std::optional NativeCxxModuleExample::getWithWithOptionalArgs( jsi::Runtime& /*rt*/, std::optional optionalArg) { return optionalArg; } void NativeCxxModuleExample::voidFunc(jsi::Runtime& /*rt*/) { // Emit some events emitOnPress(); emitOnClick("value from callback on click!"); emitOnChange(ObjectStruct{1, "two", std::nullopt}); emitOnSubmit( std::vector{ ObjectStruct{1, "two", std::nullopt}, ObjectStruct{3, "four", std::nullopt}, ObjectStruct{5, "six", std::nullopt}}); emitOnEvent(NativeCxxModuleExampleEnumNone::NA); } AsyncPromise<> NativeCxxModuleExample::voidPromise(jsi::Runtime& rt) { AsyncPromise<> promise(rt, jsInvoker_); promise.resolve(); return promise; } void NativeCxxModuleExample::setMenu(jsi::Runtime& /*rt*/, MenuItem menuItem) { menuItem.onPress("value", true); if (menuItem.items) { for (const auto& subMenuItem : *menuItem.items) { subMenuItem.onPress("another value", false); } } } void NativeCxxModuleExample::emitCustomDeviceEvent( jsi::Runtime& /*rt*/, const std::string& eventName) { // Test emitting device events (RCTDeviceEventEmitter.emit) from C++ // TurboModule with arbitrary arguments. This can be called from any thread emitDeviceEvent( eventName, [jsInvoker = jsInvoker_]( jsi::Runtime& rt, std::vector& args) { args.emplace_back( jsi::Array::createWithElements( rt, jsi::Value(true), jsi::Value(42), jsi::String::createFromAscii(rt, "stringArg"), bridging::toJs( rt, CustomDeviceEvent{"one", 2, std::nullopt}, jsInvoker))); }); } void NativeCxxModuleExample::voidFuncThrows(jsi::Runtime& /*rt*/) { throw std::runtime_error("Intentional exception from Cxx voidFuncThrows"); }; ObjectStruct NativeCxxModuleExample::getObjectThrows( jsi::Runtime& /*rt*/, const ObjectStruct& /*arg*/) { throw std::runtime_error("Intentional exception from Cxx getObjectThrows"); }; AsyncPromise<> NativeCxxModuleExample::promiseThrows(jsi::Runtime& /*rt*/) { throw std::runtime_error("Intentional exception from Cxx promiseThrows"); }; void NativeCxxModuleExample::voidFuncAssert(jsi::Runtime& /*rt*/) { react_native_assert(false && "Intentional assert from Cxx voidFuncAssert"); }; ObjectStruct NativeCxxModuleExample::getObjectAssert( jsi::Runtime& /*rt*/, const ObjectStruct& /*arg*/) { react_native_assert(false && "Intentional assert from Cxx getObjectAssert"); // Asserts disabled return {}; }; AsyncPromise<> NativeCxxModuleExample::promiseAssert(jsi::Runtime& rt) { react_native_assert(false && "Intentional assert from Cxx promiseAssert"); // Asserts disabled auto promise = AsyncPromise<>(rt, jsInvoker_); promise.reject("Asserts disabled"); return promise; }; } // namespace facebook::react