Repository navigation
Conversation
Summary:
`RCTBridgeModule.h` had no nullability annotations at all, so `viewRegistry_DEPRECATED` and the other module properties had no explicit nullability qualifier. Once a header has any nullability specifier, clang's `-Wnullability-completeness` requires every pointer in it to be annotated. So this wraps the header in `NS_ASSUME_NONNULL_BEGIN/END` and marks as `nullable` only the pointers that the implementations and callers show can actually be nil:
- Weak module properties (`moduleRegistry`, `viewRegistry_DEPRECATED`, `bundleManager`, `callableJSModules`, `bridge`) are `nullable`, because a weak reference can become nil.
- `RCTPromiseResolveBlock`'s `result` is `nullable`: the header comment already says nil resolves to `undefined`, and modules call `resolve(nil)`.
- All three `RCTPromiseRejectBlock` parameters are `nullable`. `RCTJSErrorFromCodeMessageAndNSError` substitutes defaults for a nil code or message, and modules call `reject(nil, nil, error)`.
- `RCTResponseSenderBlock`'s `response` is `nullable`, because the TurboModule callback converts a nil array into a call with no arguments. `RCTResponseErrorBlock`'s `error` is nonnull, because it exists to report an error.
- `methodsToExport` returns `nullable`, because callers fall back when they get nil, and nothing in fbsource implements it.
- `constantsToExport` is nonnull. Typed implementations return `ModuleConstants<...>` inside `NS_ASSUME_NONNULL` regions, Expo's `EXNativeModulesProxy` declares it `nonnull`, and `RCTTypedModuleConstants.h` documents it as `nonnull`. A `nullable` declaration is a hard "nullability specifier 'nonnull' conflicts with existing specifier 'nullable'" error in those implementations. No implementation in fbsource declares it `nullable`.
- `+moduleName` has no nullability specifier. It sits in a small `#pragma clang assume_nonnull end/begin` gap, with `-Wnullability-completeness` suppressed. `RCT_EXPORT_MODULE` expansions inside `NS_ASSUME_NONNULL` files are implicitly nonnull, but Expo's `EXModuleRegistryHolderReactModule` declares `+ (nullable NSString *)moduleName` and returns nil. So `nonnull`, `nullable`, and `null_unspecified` would each conflict with one of them. `RCTBridgeModuleNameForClass` already handles a nil or empty name.
- `RCTModuleRegistry` `moduleForName:` / `moduleForName:lazilyLoadIfNecessary:` / `moduleForClass:` return `nullable`, because they return nil when no TurboModule registry is set or the module isn't found. The `const char *moduleName` argument stays nonnull: a module lookup needs a name.
- `methodQueue` is nonnull. An override exists to return a queue. Any explicit specifier other than `nonnull` (including `null_unspecified`) is a hard error ("nullability specifier 'nonnull' conflicts with existing specifier") for Objective-C overrides inside `NS_ASSUME_NONNULL` regions, such as Twilight's `TWMHEConfigurationTurboModule`.
- `RCTViewRegistry` `viewForReactTag:` returns `nullable`, because the bridgeless provider returns nil once the surface presenter is gone, and `RCTBridgelessComponentViewProvider`'s return type is `nullable` to match. `addUIBlock:` takes a `nullable` block, because the implementation returns early on nil.
- The `args` and `onComplete` parameters of `RCTCallableJSModules invokeModule:...` and `RCTBridgelessJSModuleMethodInvoker` are `nullable`. The 3-argument overload forwards `NULL` for `onComplete`, and the invoker substitutes `@[]` when `args` is nil.
- Everything else (module/method names, tags, setters, `RCTMethodInfo` names, which always come from string literals) is nonnull through `NS_ASSUME_NONNULL`. There is no `null_unspecified`.
The macro bodies (`RCT_EXPORT_MODULE`, `_RCT_EXTERN_REMAP_METHOD`, ...) expand in implementation files outside the audited region, so they are unaffected.
Changelog:
[iOS][Changed] - Add nullability annotations to `RCTBridgeModule.h`. Module registry and view registry lookups, `methodsToExport`, promise resolve/reject arguments, and weak module properties such as `bridge` and `moduleRegistry` are now `nullable`. `methodQueue` is now nonnull, so Swift overrides must be declared as `DispatchQueue` rather than `DispatchQueue!`.
Reviewed By: christophpurrer, javache
Differential Revision: D126391299
|
@javache has exported this pull request. If you are a Meta employee, you can view the originating Diff in D126391299. |
Collaborator
|
This pull request was successfully merged by generatedunixname1608173377072046 in 08f96fe When will my fix make it into a release? | How to file a pick request? |
|
This pull request has been merged in 08f96fe. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary:
RCTBridgeModule.hhad no nullability annotations at all, soviewRegistry_DEPRECATEDand the other module properties had no explicit nullability qualifier. Once a header has any nullability specifier, clang's-Wnullability-completenessrequires every pointer in it to be annotated. So this wraps the header inNS_ASSUME_NONNULL_BEGIN/ENDand marks asnullableonly the pointers that the implementations and callers show can actually be nil:moduleRegistry,viewRegistry_DEPRECATED,bundleManager,callableJSModules,bridge) arenullable, because a weak reference can become nil.RCTPromiseResolveBlock'sresultisnullable: the header comment already says nil resolves toundefined, and modules callresolve(nil).RCTPromiseRejectBlockparameters arenullable.RCTJSErrorFromCodeMessageAndNSErrorsubstitutes defaults for a nil code or message, and modules callreject(nil, nil, error).RCTResponseSenderBlock'sresponseisnullable, because the TurboModule callback converts a nil array into a call with no arguments.RCTResponseErrorBlock'serroris nonnull, because it exists to report an error.methodsToExportreturnsnullable, because callers fall back when they get nil, and nothing in fbsource implements it.constantsToExportis nonnull. Typed implementations returnModuleConstants<...>insideNS_ASSUME_NONNULLregions, Expo'sEXNativeModulesProxydeclares itnonnull, andRCTTypedModuleConstants.hdocuments it asnonnull. Anullabledeclaration is a hard "nullability specifier 'nonnull' conflicts with existing specifier 'nullable'" error in those implementations. No implementation in fbsource declares itnullable.+moduleNamehas no nullability specifier. It sits in a small#pragma clang assume_nonnull end/begingap, with-Wnullability-completenesssuppressed.RCT_EXPORT_MODULEexpansions insideNS_ASSUME_NONNULLfiles are implicitly nonnull, but Expo'sEXModuleRegistryHolderReactModuledeclares+ (nullable NSString *)moduleNameand returns nil. Sononnull,nullable, andnull_unspecifiedwould each conflict with one of them.RCTBridgeModuleNameForClassalready handles a nil or empty name.RCTModuleRegistrymoduleForName:/moduleForName:lazilyLoadIfNecessary:/moduleForClass:returnnullable, because they return nil when no TurboModule registry is set or the module isn't found. Theconst char *moduleNameargument stays nonnull: a module lookup needs a name.methodQueueis nonnull. An override exists to return a queue. Any explicit specifier other thannonnull(includingnull_unspecified) is a hard error ("nullability specifier 'nonnull' conflicts with existing specifier") for Objective-C overrides insideNS_ASSUME_NONNULLregions, such as Twilight'sTWMHEConfigurationTurboModule.RCTViewRegistryviewForReactTag:returnsnullable, because the bridgeless provider returns nil once the surface presenter is gone, andRCTBridgelessComponentViewProvider's return type isnullableto match.addUIBlock:takes anullableblock, because the implementation returns early on nil.argsandonCompleteparameters ofRCTCallableJSModules invokeModule:...andRCTBridgelessJSModuleMethodInvokerarenullable. The 3-argument overload forwardsNULLforonComplete, and the invoker substitutes@[]whenargsis nil.RCTMethodInfonames, which always come from string literals) is nonnull throughNS_ASSUME_NONNULL. There is nonull_unspecified.The macro bodies (
RCT_EXPORT_MODULE,_RCT_EXTERN_REMAP_METHOD, ...) expand in implementation files outside the audited region, so they are unaffected.Changelog:
[iOS][Changed] - Add nullability annotations to
RCTBridgeModule.h. Module registry and view registry lookups,methodsToExport, promise resolve/reject arguments, and weak module properties such asbridgeandmoduleRegistryare nownullable.methodQueueis now nonnull, so Swift overrides must be declared asDispatchQueuerather thanDispatchQueue!.Reviewed By: christophpurrer, javache
Differential Revision: D126391299