diff --git a/Libraries/EventEmitter/RCTDeviceEventEmitter.js b/Libraries/EventEmitter/RCTDeviceEventEmitter.js index 65fe57da7b3a3c..256983291888be 100644 --- a/Libraries/EventEmitter/RCTDeviceEventEmitter.js +++ b/Libraries/EventEmitter/RCTDeviceEventEmitter.js @@ -21,4 +21,12 @@ type RCTDeviceEventDefinitions = $FlowFixMe; * * NativeModules that emit events should instead subclass `NativeEventEmitter`. */ -export default (new EventEmitter(): IEventEmitter); +const RCTDeviceEventEmitter: IEventEmitter = + new EventEmitter(); + +Object.defineProperty(global, '__rctDeviceEventEmitter', { + configurable: true, + value: RCTDeviceEventEmitter, +}); + +export default (RCTDeviceEventEmitter: IEventEmitter); diff --git a/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.cpp b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.cpp index 89ac90bcd8362a..87e0eabcd55f51 100644 --- a/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.cpp +++ b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.cpp @@ -36,5 +36,29 @@ jsi::Value TurboModule::get( return result; } +void TurboModule::emitDeviceEvent( + jsi::Runtime &runtime, + const std::string &eventName, + ArgFactory argFactory) { + jsInvoker_->invokeAsync([&runtime, eventName, argFactory]() { + jsi::Value emitter = + runtime.global().getProperty(runtime, "__rctDeviceEventEmitter"); + if (!emitter.isUndefined()) { + jsi::Object emitterObject = emitter.asObject(runtime); + // TODO: consider caching these + jsi::Function emitFunction = + emitterObject.getPropertyAsFunction(runtime, "emit"); + std::vector args; + args.emplace_back( + jsi::String::createFromAscii(runtime, eventName.c_str())); + if (argFactory) { + argFactory(runtime, args); + } + emitFunction.callWithThis( + runtime, emitterObject, (const jsi::Value *)args.data(), args.size()); + } + }); +} + } // namespace react } // namespace facebook diff --git a/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.h b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.h index 866a0b4d4921d5..6a8bba7b5fa742 100644 --- a/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.h +++ b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.h @@ -83,6 +83,26 @@ class JSI_EXPORT TurboModule : public facebook::jsi::HostObject { }; std::unordered_map methodMap_; + using ArgFactory = + std::function &args)>; + + /** + * Calls RCTDeviceEventEmitter.emit to JavaScript, with given event name and + * an optional list of arguments. + * If present, argFactory is a callback used to construct extra arguments, + * e.g. + * + * emitDeviceEvent(rt, "myCustomEvent", + * [](jsi::Runtime& rt, std::vector& args) { + * args.emplace_back(jsi::Value(true)); + * args.emplace_back(jsi::Value(42)); + * }); + */ + void emitDeviceEvent( + jsi::Runtime &runtime, + const std::string &eventName, + ArgFactory argFactory = nullptr); + private: friend class TurboCxxModule; friend class TurboModuleBinding;