123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- /*
- * Copyright @ 2019-present 8x8, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
- #import <React/RCTAssert.h>
- #import <React/RCTLog.h>
-
- #import "LogUtils.h"
- #import "ReactUtils.h"
-
- #pragma mark - Utility functions
-
- /**
- * Merges 2 sets of props into a single one.
- */
- NSMutableDictionary* mergeProps(NSDictionary *a, NSDictionary *b) {
- if (a == nil) {
- return [NSMutableDictionary dictionaryWithDictionary:b == nil ? @{} : b];
- }
-
- if (b == nil) {
- return [NSMutableDictionary dictionaryWithDictionary:a];
- }
-
- // Both have values, let's merge them, the strategy is to take the value from a first,
- // then override it with the one from b. If the value is a dictionary, merge them
- // recursively. Same goes for arrays.
- NSMutableDictionary *result = [NSMutableDictionary dictionaryWithDictionary:a];
-
- for (NSString *key in b) {
- id value = b[key];
- id aValue = result[key];
-
- if (aValue == nil) {
- result[key] = value;
- continue;
- }
-
- if ([value isKindOfClass:NSArray.class]) {
- result[key] = [aValue arrayByAddingObjectsFromArray:value];
- } else if ([value isKindOfClass:NSDictionary.class]) {
- result[key] = mergeProps(aValue, value);
- } else {
- result[key] = value;
- }
- }
-
- return result;
- }
-
- /**
- * A `RCTFatalHandler` implementation which swallows JavaScript errors. In the
- * Release configuration, React Native will (intentionally) raise an unhandled
- * `NSException` for an unhandled JavaScript error. This will effectively kill
- * the application. `_RCTFatal` is suitable to be in accord with the Web i.e.
- * not kill the application.
- */
- RCTFatalHandler _RCTFatal = ^(NSError *error) {
- id jsStackTrace = error.userInfo[RCTJSStackTraceKey];
- NSString *name
- = [NSString stringWithFormat:@"%@: %@", RCTFatalExceptionName, error.localizedDescription];
- NSString *message
- = RCTFormatError(error.localizedDescription, jsStackTrace, -1);
- DDLogError(@"FATAL ERROR: %@\n%@", name, message);
- };
-
- /**
- * Helper function to register a fatal error handler for React. Our handler
- * won't kill the process, it will swallow JS errors and print stack traces
- * instead.
- */
- void registerReactFatalErrorHandler() {
- #if !DEBUG
- // In the Release configuration, React Native will (intentionally) raise an
- // unhandled `NSException` for an unhandled JavaScript error. This will
- // effectively kill the application. In accord with the Web, do not kill the
- // application.
- if (!RCTGetFatalHandler()) {
- RCTSetFatalHandler(_RCTFatal);
- }
- #endif
- }
-
- /**
- * A `RTCLogFunction` implementation which uses CocoaLumberjack.
- */
- RCTLogFunction _RCTLog
- = ^(RCTLogLevel level, __unused RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message)
- {
- // Convert RN log levels into Lumberjack's log flags.
- //
- DDLogFlag logFlag;
- switch (level) {
- case RCTLogLevelTrace:
- logFlag = DDLogFlagDebug;
- break;
- case RCTLogLevelInfo:
- logFlag = DDLogFlagInfo;
- break;
- case RCTLogLevelWarning:
- logFlag = DDLogFlagWarning;
- break;
- case RCTLogLevelError:
- logFlag = DDLogFlagError;
- break;
- case RCTLogLevelFatal:
- logFlag = DDLogFlagError;
- break;
- default:
- // Just in case more are added in the future.
- logFlag = DDLogFlagInfo;
- break;
- }
-
- // Build the message object we want to log.
- //
- DDLogMessage *logMessage
- = [[DDLogMessage alloc] initWithMessage:message
- level:LOG_LEVEL_DEF
- flag:logFlag
- context:0
- file:fileName
- function:nil
- line:[lineNumber integerValue]
- tag:nil
- options:0
- timestamp:nil];
-
- // Log the message. Errors are logged synchronously, and other async, as the Lumberjack defaults.
- //
- [DDLog log:logFlag != DDLogFlagError
- message:logMessage];
- };
-
- /**
- * Helper function which registers a React Native log handler.
- */
- void registerReactLogHandler() {
- RCTSetLogFunction(_RCTLog);
- RCTSetLogThreshold(RCTLogLevelInfo);
- }
|