Skip to content

fix(codegen): skip third-party components whose class is not linked - #3128

Draft
YevheniiKotyrlo wants to merge 1 commit into
microsoft:mainfrom
YevheniiKotyrlo:fix/macos-component-provider-missing-class
Draft

YevheniiKotyrlo wants to merge 1 commit into
microsoft:mainfrom
YevheniiKotyrlo:fix/macos-component-provider-missing-class

Conversation

@YevheniiKotyrlo

Copy link
Copy Markdown

Summary:

Cherry-pick of react#59067 (acc0cca), without its test-file change, which edits a generate-artifacts-executor-test.js case this branch does not have.

The generated RCTThirdPartyComponentsProvider.mm builds its map from a dictionary literal of NSClassFromString results, so when a component's class is not linked into the app, the literal gets nil and the app aborts at launch:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[1]'

On macOS this happens whenever a dependency's components have no macOS classes: codegen runs with -t ios, so their entries reach the macOS app's provider, and platforms: { macos: null } in react-native.config.js does not keep them out, since the disabled-library filter reads the ios entry. react-native-skia's macOS example aborts at launch this way on 0.81. The provider now maps component names to class names and registers only the classes the runtime has, as RCTModuleProvidersMM.template does for modules.

0.81-stable and 0.83-stable carry the same template, and this commit cherry-picks onto both without conflicts.

Test Plan:

  • generate-artifacts-executor-test.js: its two RCTThirdPartyComponentsProvider.mm snapshots expect the new map. With main's template and generator they fail; with this change the file's 39 tests pass, here and on 0.83-stable with the commit cherry-picked.
  • The provider generated for two components, compiled with Apple clang 21 (macOS 27) into a binary that links only one of their classes:
    • main: NSInvalidArgumentException … attempt to insert nil object from objects[1]
    • this change: registered components: LinkedComponent
  • RNTester builds for macOS, iOS and visionOS (static linkage, Xcode 27), each compiling the provider the new template generates.
  • yarn test-ci, yarn flow-check, yarn lint, yarn format-check and yarn constraints pass.

Not run here: the macOS core prebuild.

Cherry-pick of react#59067 (acc0cca), without its test
file change: this suite has no generateRCTThirdPartyComponents case.

The generated RCTThirdPartyComponentsProvider built its map from a
dictionary literal of NSClassFromString values, so a component whose
library the target does not link inserted nil and threw at launch.
react-native-macos runs codegen with -t ios, so a library's iOS
components reach a macOS target's provider whether or not the library
ships macOS classes.

The provider now maps each component name to its class name and skips a
class that is not found, as RCTModuleProvidersMM.template does for
modules.
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant