/** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ #import "RCTNativeModule.h" #import #import #import #import #import #import #import namespace facebook { namespace react { RCTNativeModule::RCTNativeModule(RCTBridge *bridge, RCTModuleData *moduleData) : m_bridge(bridge) , m_moduleData(moduleData) {} std::string RCTNativeModule::getName() { return [m_moduleData.name UTF8String]; } std::vector RCTNativeModule::getMethods() { std::vector descs; for (id method in m_moduleData.methods) { descs.emplace_back( method.JSMethodName.UTF8String, method.functionType == RCTFunctionTypePromise ? "promise" : "async" ); } return descs; } folly::dynamic RCTNativeModule::getConstants() { RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"[RCTNativeModule getConstants] moduleData.exportedConstants", nil); NSDictionary *constants = m_moduleData.exportedConstants; folly::dynamic ret = [RCTConvert folly_dynamic:constants]; RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @""); return ret; } void RCTNativeModule::invoke(unsigned int methodId, folly::dynamic &¶ms) { // 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. // There is no flow event handling here until I can understand it. auto sparams = std::make_shared(std::move(params)); __weak RCTBridge *bridge = m_bridge; dispatch_block_t block = ^{ if (!bridge || !bridge.valid) { return; } id method = m_moduleData.methods[methodId]; if (RCT_DEBUG && !method) { RCTLogError(@"Unknown methodID: %ud for module: %@", methodId, m_moduleData.name); } NSArray *objcParams = convertFollyDynamicToId(*sparams); @try { [method invokeWithBridge:bridge module:m_moduleData.instance arguments:objcParams]; } @catch (NSException *exception) { // Pass on JS exceptions if ([exception.name hasPrefix:RCTFatalExceptionName]) { @throw exception; } NSString *message = [NSString stringWithFormat: @"Exception '%@' was thrown while invoking %@ on target %@ with params %@", exception, method.JSMethodName, m_moduleData.name, objcParams]; RCTFatal(RCTErrorWithMessage(message)); } }; dispatch_queue_t queue = m_moduleData.methodQueue; if (queue == RCTJSThread) { block(); } else if (queue) { dispatch_async(queue, block); } } MethodCallResult RCTNativeModule::callSerializableNativeHook(unsigned int reactMethodId, folly::dynamic &¶ms) { RCTFatal(RCTErrorWithMessage(@"callSerializableNativeHook is not yet supported on iOS")); return folly::none; } } }