RCTCxxUtils.mm 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. /*
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. */
  7. #import "RCTCxxUtils.h"
  8. #import <React/RCTFollyConvert.h>
  9. #import <React/RCTModuleData.h>
  10. #import <React/RCTUtils.h>
  11. #import <cxxreact/CxxNativeModule.h>
  12. #import <jsi/jsi.h>
  13. #import "DispatchMessageQueueThread.h"
  14. #import "RCTCxxModule.h"
  15. #import "RCTNativeModule.h"
  16. namespace facebook {
  17. namespace react {
  18. using facebook::jsi::JSError;
  19. std::vector<std::unique_ptr<NativeModule>>
  20. createNativeModules(NSArray<RCTModuleData *> *modules, RCTBridge *bridge, const std::shared_ptr<Instance> &instance)
  21. {
  22. std::vector<std::unique_ptr<NativeModule>> nativeModules;
  23. for (RCTModuleData *moduleData in modules) {
  24. if ([moduleData.moduleClass isSubclassOfClass:[RCTCxxModule class]]) {
  25. nativeModules.emplace_back(std::make_unique<CxxNativeModule>(
  26. instance,
  27. [moduleData.name UTF8String],
  28. [moduleData] { return [(RCTCxxModule *)(moduleData.instance) createModule]; },
  29. std::make_shared<DispatchMessageQueueThread>(moduleData)));
  30. } else {
  31. nativeModules.emplace_back(std::make_unique<RCTNativeModule>(bridge, moduleData));
  32. }
  33. }
  34. return nativeModules;
  35. }
  36. static NSError *errorWithException(const std::exception &e)
  37. {
  38. NSString *msg = @(e.what());
  39. NSMutableDictionary *errorInfo = [NSMutableDictionary dictionary];
  40. const auto *jsError = dynamic_cast<const JSError *>(&e);
  41. if (jsError) {
  42. errorInfo[RCTJSRawStackTraceKey] = @(jsError->getStack().c_str());
  43. msg = [@"Unhandled JS Exception: " stringByAppendingString:msg];
  44. }
  45. NSError *nestedError;
  46. try {
  47. std::rethrow_if_nested(e);
  48. } catch (const std::exception &e) {
  49. nestedError = errorWithException(e);
  50. } catch (...) {
  51. }
  52. if (nestedError) {
  53. msg = [NSString stringWithFormat:@"%@\n\n%@", msg, [nestedError localizedDescription]];
  54. }
  55. errorInfo[NSLocalizedDescriptionKey] = msg;
  56. return [NSError errorWithDomain:RCTErrorDomain code:1 userInfo:errorInfo];
  57. }
  58. NSError *tryAndReturnError(const std::function<void()> &func)
  59. {
  60. try {
  61. @try {
  62. func();
  63. return nil;
  64. } @catch (NSException *exception) {
  65. NSString *message = [NSString stringWithFormat:@"Exception '%@' was thrown from JS thread", exception];
  66. return RCTErrorWithMessage(message);
  67. } @catch (id exception) {
  68. // This will catch any other ObjC exception, but no C++ exceptions
  69. return RCTErrorWithMessage(@"non-std ObjC Exception");
  70. }
  71. } catch (const std::exception &ex) {
  72. return errorWithException(ex);
  73. } catch (...) {
  74. // On a 64-bit platform, this would catch ObjC exceptions, too, but not on
  75. // 32-bit platforms, so we catch those with id exceptions above.
  76. return RCTErrorWithMessage(@"non-std C++ exception");
  77. }
  78. }
  79. NSString *deriveSourceURL(NSURL *url)
  80. {
  81. NSString *sourceUrl;
  82. if (url.isFileURL) {
  83. // Url will contain only path to resource (i.g. file:// will be removed)
  84. sourceUrl = url.path;
  85. } else {
  86. // Url will include protocol (e.g. http://)
  87. sourceUrl = url.absoluteString;
  88. }
  89. return sourceUrl ?: @"";
  90. }
  91. }
  92. }