123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- /*
- * Copyright (c) Facebook, Inc. and its affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
- #import "RCTNativeModule.h"
- #import <React/RCTBridge.h>
- #import <React/RCTBridgeMethod.h>
- #import <React/RCTBridgeModule.h>
- #import <React/RCTCxxUtils.h>
- #import <React/RCTFollyConvert.h>
- #import <React/RCTLog.h>
- #import <React/RCTProfile.h>
- #import <React/RCTUtils.h>
- #ifdef WITH_FBSYSTRACE
- #include <fbsystrace.h>
- #endif
- namespace facebook {
- namespace react {
- static MethodCallResult
- invokeInner(RCTBridge *bridge, RCTModuleData *moduleData, unsigned int methodId, const folly::dynamic ¶ms);
- RCTNativeModule::RCTNativeModule(RCTBridge *bridge, RCTModuleData *moduleData)
- : m_bridge(bridge), m_moduleData(moduleData)
- {
- }
- std::string RCTNativeModule::getName()
- {
- return [m_moduleData.name UTF8String];
- }
- std::vector<MethodDescriptor> RCTNativeModule::getMethods()
- {
- std::vector<MethodDescriptor> descs;
- for (id<RCTBridgeMethod> method in m_moduleData.methods) {
- descs.emplace_back(method.JSMethodName, RCTFunctionDescriptorFromType(method.functionType));
- }
- return descs;
- }
- folly::dynamic RCTNativeModule::getConstants()
- {
- RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"[RCTNativeModule getConstants] moduleData.exportedConstants", nil);
- NSDictionary *constants = m_moduleData.exportedConstants;
- folly::dynamic ret = convertIdToFollyDynamic(constants);
- RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @"");
- return ret;
- }
- void RCTNativeModule::invoke(unsigned int methodId, folly::dynamic &¶ms, int callId)
- {
- // capture by weak pointer so that we can safely use these variables in a callback
- __weak RCTBridge *weakBridge = m_bridge;
- __weak RCTModuleData *weakModuleData = m_moduleData;
- // The BatchedBridge version of this buckets all the callbacks by thread, and
- // queues one block on each. This is much simpler; we'll see how it goes and
- // iterate.
- dispatch_block_t block = [weakBridge, weakModuleData, methodId, params = std::move(params), callId] {
- #ifdef WITH_FBSYSTRACE
- if (callId != -1) {
- fbsystrace_end_async_flow(TRACE_TAG_REACT_APPS, "native", callId);
- }
- #else
- (void)(callId);
- #endif
- invokeInner(weakBridge, weakModuleData, methodId, std::move(params));
- };
- dispatch_queue_t queue = m_moduleData.methodQueue;
- if (queue == RCTJSThread) {
- block();
- } else if (queue) {
- dispatch_async(queue, block);
- }
- #ifdef RCT_DEV
- if (!queue) {
- RCTLog(
- @"Attempted to invoke `%u` (method ID) on `%@` (NativeModule name) without a method queue.",
- methodId,
- m_moduleData.name);
- }
- #endif
- }
- MethodCallResult RCTNativeModule::callSerializableNativeHook(unsigned int reactMethodId, folly::dynamic &¶ms)
- {
- return invokeInner(m_bridge, m_moduleData, reactMethodId, params);
- }
- static MethodCallResult
- invokeInner(RCTBridge *bridge, RCTModuleData *moduleData, unsigned int methodId, const folly::dynamic ¶ms)
- {
- if (!bridge || !bridge.valid || !moduleData) {
- return folly::none;
- }
- id<RCTBridgeMethod> method = moduleData.methods[methodId];
- if (RCT_DEBUG && !method) {
- RCTLogError(@"Unknown methodID: %ud for module: %@", methodId, moduleData.name);
- }
- NSArray *objcParams = convertFollyDynamicToId(params);
- @try {
- id result = [method invokeWithBridge:bridge module:moduleData.instance arguments:objcParams];
- return convertIdToFollyDynamic(result);
- } @catch (NSException *exception) {
- // Pass on JS exceptions
- if ([exception.name hasPrefix:RCTFatalExceptionName]) {
- @throw exception;
- }
- #if RCT_DEBUG
- NSString *message = [NSString
- stringWithFormat:@"Exception '%@' was thrown while invoking %s on target %@ with params %@\ncallstack: %@",
- exception,
- method.JSMethodName,
- moduleData.name,
- objcParams,
- exception.callStackSymbols];
- RCTFatal(RCTErrorWithMessage(message));
- #else
- RCTFatalException(exception);
- #endif
- }
- return folly::none;
- }
- }
- }
|