Skip to content

Commit

Permalink
Improve NewArchitectureValidation for AbsoluteBridgeless
Browse files Browse the repository at this point in the history
Summary:
Changelog: [Internal]

- Make the new architecture validation easier to understand by enabling validation with `RCTNewArchitectureSetMinValidationLevel(level)`.
- When `RCT_ONLY_NEW_ARCHITECTURE` flag is enabled:
  - `RCTErrorNewArchitectureValidation` calls `RCTLogAssert` instead of `RCTLogError`.
  - `RCTNewArchitectureValidationPlaceholder` calls `RCTLog`, instead of no-op.

Reviewed By: fkgozali

Differential Revision: D37555667

fbshipit-source-id: 2c725c287a2dec19e8946c7fe5d8fa111e4a17fa
  • Loading branch information
p-sun authored and facebook-github-bot committed Jul 1, 2022
1 parent daea147 commit 64cfc44
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 34 deletions.
16 changes: 10 additions & 6 deletions React/Base/RCTAssert.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,24 +178,24 @@ RCT_EXTERN NSString *RCTFormatStackTrace(NSArray<NSDictionary<NSString *, id> *>
// MARK: - New Architecture Validation

typedef enum {
RCTNotAllowedValidationDisabled = 0,
RCTNotAllowedInAppWideFabric = 1,
RCTNotAllowedInBridgeless = 2,
RCTNotAllowedInBridgeless = 1,
RCTNotAllowedInAppWideFabric = 2,
RCTNotAllowedValidationDisabled = 3,
} RCTNotAllowedValidation;

/**
* Ensure runtime assumptions holds for the new architecture by reporting when assumptions are violated.
* Note: this is work in progress.
*
* When type is RCTNotAllowedInAppWideFabric, validate Fabric assumptions in Bridge or Bridgeless mode.
* When level is RCTNotAllowedInAppWideFabric, validate Fabric assumptions.
* i.e. Report legacy pre-Fabric call sites that should not be used while Fabric is enabled on all surfaces.
*
* When type is RCTNotAllowedInBridgeless, validate Bridgeless assumptions, in Bridgeless mode only.
* When level is RCTNotAllowedInBridgeless, validate Fabric or Bridgeless assumptions.
* i.e. Report Bridge call sites that should not be used while Bridgeless mode is enabled.
*
* Note: enabling this at runtime is not early enough to report issues within ObjC class +load execution.
*/
__attribute__((used)) RCT_EXTERN void RCTNewArchitectureValidationSetEnabled(RCTNotAllowedValidation type);
__attribute__((used)) RCT_EXTERN void RCTNewArchitectureSetMinValidationLevel(RCTNotAllowedValidation level);

// When new architecture validation reporting is enabled, trigger an assertion and crash.
__attribute__((used)) RCT_EXTERN void
Expand All @@ -208,3 +208,7 @@ RCTErrorNewArchitectureValidation(RCTNotAllowedValidation type, id context, NSSt
// When ready, switch to stricter variant above.
__attribute__((used)) RCT_EXTERN void
RCTLogNewArchitectureValidation(RCTNotAllowedValidation type, id context, NSString *extra);
// A placeholder for callsites that frequently fail validation.
// When ready, switch to stricter variant above.
__attribute__((used)) RCT_EXTERN void
RCTNewArchitectureValidationPlaceholder(RCTNotAllowedValidation type, id context, NSString *extra);
71 changes: 43 additions & 28 deletions React/Base/RCTAssert.m
Original file line number Diff line number Diff line change
Expand Up @@ -235,34 +235,25 @@ RCTFatalExceptionHandler RCTGetFatalExceptionHandler(void)
// MARK: - New Architecture Validation - Enable Reporting

#if RCT_ONLY_NEW_ARCHITECTURE
static RCTNotAllowedValidation validationReportingEnabled = RCTNotAllowedInBridgeless;
static RCTNotAllowedValidation minValidationLevel = RCTNotAllowedInBridgeless;
#else
static RCTNotAllowedValidation validationReportingEnabled = RCTNotAllowedValidationDisabled;
static RCTNotAllowedValidation minValidationLevel = RCTNotAllowedValidationDisabled;
#endif

__attribute__((used)) RCT_EXTERN void RCTNewArchitectureValidationSetEnabled(RCTNotAllowedValidation type)
__attribute__((used)) RCT_EXTERN void RCTNewArchitectureSetMinValidationLevel(RCTNotAllowedValidation level)
{
#if RCT_ONLY_NEW_ARCHITECTURE
// Cannot disable the reporting in this mode.
#else
validationReportingEnabled = type;
minValidationLevel = level;
#endif
}

// MARK: - New Architecture Validation - Private

static BOOL shouldEnforceValidation(RCTNotAllowedValidation type)
{
switch (type) {
case RCTNotAllowedInAppWideFabric:
return validationReportingEnabled == RCTNotAllowedInBridgeless ||
validationReportingEnabled == RCTNotAllowedInAppWideFabric;
case RCTNotAllowedInBridgeless:
return validationReportingEnabled == RCTNotAllowedInBridgeless;
case RCTNotAllowedValidationDisabled:
return NO;
}
return NO;
return type >= minValidationLevel;
}

static NSString *stringDescribingContext(id context)
Expand All @@ -284,7 +275,7 @@ static BOOL shouldEnforceValidation(RCTNotAllowedValidation type)
switch (type) {
case RCTNotAllowedValidationDisabled:
RCTAssert(0, @"RCTNotAllowedValidationDisabled not a validation type.");
break;
return nil;
case RCTNotAllowedInAppWideFabric:
notAllowedType = @"Fabric";
break;
Expand All @@ -300,31 +291,55 @@ static BOOL shouldEnforceValidation(RCTNotAllowedValidation type)
extra ?: @""];
}

// MARK: - New Architecture Validation - Public

void RCTEnforceNewArchitectureValidation(RCTNotAllowedValidation type, id context, NSString *extra)
static void
newArchitectureValidationInternal(RCTLogLevel level, RCTNotAllowedValidation type, id context, NSString *extra)
{
if (!shouldEnforceValidation(type)) {
return;
}

RCTAssert(0, @"%@", validationMessage(type, context, extra));
NSString *msg = validationMessage(type, context, extra);
if (msg) {
switch (level) {
case RCTLogLevelInfo:
RCTLogInfo(@"%@", msg);
break;
case RCTLogLevelError:
RCTLogError(@"%@", msg);
break;
case RCTLogLevelFatal:
RCTAssert(0, @"%@", msg);
break;
default:
RCTAssert(0, @"New architecture validation is only for info, error, and fatal levels.");
}
}
}

void RCTErrorNewArchitectureValidation(RCTNotAllowedValidation type, id context, NSString *extra)
// MARK: - New Architecture Validation - Public

void RCTEnforceNewArchitectureValidation(RCTNotAllowedValidation type, id context, NSString *extra)
{
if (!shouldEnforceValidation(type)) {
return;
}
newArchitectureValidationInternal(RCTLogLevelFatal, type, context, extra);
}

RCTLogError(@"%@", validationMessage(type, context, extra));
void RCTErrorNewArchitectureValidation(RCTNotAllowedValidation type, id context, NSString *extra)
{
#if RCT_ONLY_NEW_ARCHITECTURE
newArchitectureValidationInternal(RCTLogLevelFatal, type, context, extra);
#else
newArchitectureValidationInternal(RCTLogLevelError, type, context, extra);
#endif
}

void RCTLogNewArchitectureValidation(RCTNotAllowedValidation type, id context, NSString *extra)
{
if (!shouldEnforceValidation(type)) {
return;
}
newArchitectureValidationInternal(RCTLogLevelInfo, type, context, extra);
}

RCTLogInfo(@"%@", validationMessage(type, context, extra));
void RCTNewArchitectureValidationPlaceholder(RCTNotAllowedValidation type, id context, NSString *extra)
{
#if RCT_ONLY_NEW_ARCHITECTURE
newArchitectureValidationInternal(RCTLogLevelInfo, type, context, extra);
#endif
}

0 comments on commit 64cfc44

Please sign in to comment.