RCTAssert.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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 <Foundation/Foundation.h>
  8. #import <React/RCTDefines.h>
  9. /*
  10. * Defined in RCTUtils.m
  11. */
  12. RCT_EXTERN BOOL RCTIsMainQueue(void);
  13. /**
  14. * This is the main assert macro that you should use. Asserts should be compiled out
  15. * in production builds. You can customize the assert behaviour by setting a custom
  16. * assert handler through `RCTSetAssertFunction`.
  17. */
  18. #ifndef NS_BLOCK_ASSERTIONS
  19. #define RCTAssert(condition, ...) \
  20. do { \
  21. if ((condition) == 0) { \
  22. _RCTAssertFormat(#condition, __FILE__, __LINE__, __func__, __VA_ARGS__); \
  23. if (RCT_NSASSERT) { \
  24. [[NSAssertionHandler currentHandler] handleFailureInFunction:(NSString * _Nonnull) @(__func__) \
  25. file:(NSString * _Nonnull) @(__FILE__) \
  26. lineNumber:__LINE__ \
  27. description:__VA_ARGS__]; \
  28. } \
  29. } \
  30. } while (false)
  31. #else
  32. #define RCTAssert(condition, ...) \
  33. do { \
  34. } while (false)
  35. #endif
  36. RCT_EXTERN void _RCTAssertFormat(const char *, const char *, int, const char *, NSString *, ...)
  37. NS_FORMAT_FUNCTION(5, 6);
  38. /**
  39. * Report a fatal condition when executing. These calls will _NOT_ be compiled out
  40. * in production, and crash the app by default. You can customize the fatal behaviour
  41. * by setting a custom fatal handler through `RCTSetFatalHandler` and
  42. * `RCTSetFatalExceptionHandler`.
  43. */
  44. RCT_EXTERN void RCTFatal(NSError *error);
  45. RCT_EXTERN void RCTFatalException(NSException *exception);
  46. /**
  47. * The default error domain to be used for React errors.
  48. */
  49. RCT_EXTERN NSString *const RCTErrorDomain;
  50. /**
  51. * JS Stack trace provided as part of an NSError's userInfo
  52. */
  53. RCT_EXTERN NSString *const RCTJSStackTraceKey;
  54. /**
  55. * Raw JS Stack trace string provided as part of an NSError's userInfo
  56. */
  57. RCT_EXTERN NSString *const RCTJSRawStackTraceKey;
  58. /**
  59. * Name of fatal exceptions generated by RCTFatal
  60. */
  61. RCT_EXTERN NSString *const RCTFatalExceptionName;
  62. /**
  63. * A block signature to be used for custom assertion handling.
  64. */
  65. typedef void (^RCTAssertFunction)(
  66. NSString *condition,
  67. NSString *fileName,
  68. NSNumber *lineNumber,
  69. NSString *function,
  70. NSString *message);
  71. typedef void (^RCTFatalHandler)(NSError *error);
  72. typedef void (^RCTFatalExceptionHandler)(NSException *exception);
  73. /**
  74. * Convenience macro for asserting that a parameter is non-nil/non-zero.
  75. */
  76. #define RCTAssertParam(name) RCTAssert(name, @"'%s' is a required parameter", #name)
  77. /**
  78. * Convenience macro for asserting that we're running on main queue.
  79. */
  80. #define RCTAssertMainQueue() RCTAssert(RCTIsMainQueue(), @"This function must be called on the main queue")
  81. /**
  82. * Convenience macro for asserting that we're running off the main queue.
  83. */
  84. #define RCTAssertNotMainQueue() RCTAssert(!RCTIsMainQueue(), @"This function must not be called on the main queue")
  85. /**
  86. * These methods get and set the current assert function called by the RCTAssert
  87. * macros. You can use these to replace the standard behavior with custom assert
  88. * functionality.
  89. */
  90. RCT_EXTERN void RCTSetAssertFunction(RCTAssertFunction assertFunction);
  91. RCT_EXTERN RCTAssertFunction RCTGetAssertFunction(void);
  92. /**
  93. * This appends additional code to the existing assert function, without
  94. * replacing the existing functionality. Useful if you just want to forward
  95. * assert info to an extra service without changing the default behavior.
  96. */
  97. RCT_EXTERN void RCTAddAssertFunction(RCTAssertFunction assertFunction);
  98. /**
  99. * This method temporarily overrides the assert function while performing the
  100. * specified block. This is useful for testing purposes (to detect if a given
  101. * function asserts something) or to suppress or override assertions temporarily.
  102. */
  103. RCT_EXTERN void RCTPerformBlockWithAssertFunction(void (^block)(void), RCTAssertFunction assertFunction);
  104. /**
  105. * These methods get and set the current fatal handler called by the `RCTFatal`
  106. * and `RCTFatalException` methods.
  107. */
  108. RCT_EXTERN void RCTSetFatalHandler(RCTFatalHandler fatalHandler);
  109. RCT_EXTERN RCTFatalHandler RCTGetFatalHandler(void);
  110. RCT_EXTERN void RCTSetFatalExceptionHandler(RCTFatalExceptionHandler fatalExceptionHandler);
  111. RCT_EXTERN RCTFatalExceptionHandler RCTGetFatalExceptionHandler(void);
  112. /**
  113. * Get the current thread's name (or the current queue, if in debug mode)
  114. */
  115. RCT_EXTERN NSString *RCTCurrentThreadName(void);
  116. /**
  117. * Helper to get generate exception message from NSError
  118. */
  119. RCT_EXTERN NSString *
  120. RCTFormatError(NSString *message, NSArray<NSDictionary<NSString *, id> *> *stacktrace, NSUInteger maxMessageLength);
  121. /**
  122. * Formats a JS stack trace for logging.
  123. */
  124. RCT_EXTERN NSString *RCTFormatStackTrace(NSArray<NSDictionary<NSString *, id> *> *stackTrace);
  125. /**
  126. * Convenience macro to assert which thread is currently running (DEBUG mode only)
  127. */
  128. #if DEBUG
  129. #define RCTAssertThread(thread, format...) \
  130. _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") RCTAssert( \
  131. [(id)thread isKindOfClass:[NSString class]] \
  132. ? [RCTCurrentThreadName() isEqualToString:(NSString *)thread] \
  133. : [(id)thread isKindOfClass:[NSThread class]] ? [NSThread currentThread] == (NSThread *)thread \
  134. : dispatch_get_current_queue() == (dispatch_queue_t)thread, \
  135. format); \
  136. _Pragma("clang diagnostic pop")
  137. #else
  138. #define RCTAssertThread(thread, format...) \
  139. do { \
  140. } while (0)
  141. #endif