Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nil #1

Closed
wants to merge 1 commit into from
Closed

nil #1

wants to merge 1 commit into from

Conversation

robz
Copy link

@robz robz commented Jan 28, 2015

No description provided.

@sophiebits sophiebits changed the title fixed readme step orderding nil Jan 29, 2015
@sophiebits sophiebits closed this Jan 29, 2015
@sophiebits sophiebits deleted the patch-1 branch January 29, 2015 22:08
harrykiselev pushed a commit to harrykiselev/react-native that referenced this pull request Aug 5, 2015
Explain how to open the chat example
ide referenced this pull request in expo/react-native Sep 15, 2015
add react-native android command (wip)
brentvatne pushed a commit that referenced this pull request Nov 9, 2015
chirag04 pushed a commit that referenced this pull request Jan 25, 2016
ekrivopaltsev pushed a commit to ekrivopaltsev/react-native that referenced this pull request Mar 25, 2016
Some keyboard types does not have buttons correspondent for keyReturnType such as Next, Done. It is observable on IPhone for numeric keyboard types. That prevents traversing forms with "number" input fields and impacts end-user experience.

The improvement allows application for adding extra buttons via inputAccessoryView.
Because RCTText is not a project exposed to React application calling all methods to add a handler is done using selectors.

Here is a code fragment which has an example on how to achieve it:
Within application:
facebook#1 Create a keyboard Handle
 KeyboardAccessory keyboardHandler = ^UIView *(UITextField *textField) {
    ReactTextAdapter *kAdapter = [[ReactTextAdapter alloc] init:textField];
    return [kAdapter getInputAccessory];
  };

2. Register an adapter

  Class clz = NSClassFromString(@"RCTTextField");

  SEL selector = NSSelectorFromString(@"registerForKeyboardType:handler:");
  if ([clz respondsToSelector:selector]) {
  [   clz performSelector:selector withObject:[NSNumber numberWithInt:UIKeyboardTypeNumberPad] withObject:keyboardHandler];
  }

facebook#3 Example of Keyboard Adapter

@interface ReactTextAdapter :UIToolbar

-(instancetype) init:(UITextField *)textField;
-(UIView *)getInputAccessory;

@EnD

//
//  ReactTextAdapter.m
//  KeyboardTest
//
//  Created by Krivopaltsev, Eugene on 3/11/16.
//

#import "ReactTextAdapter.h"

@interface ReactTextAdapter()

@Property (nonatomic) UITextField *textField;

//@Property (nonatomic)UIToolbar *toolBar;
@Property (nonatomic)UIBarButtonItem *flexible;

@EnD

@implementation ReactTextAdapter

-(instancetype) init:(UITextField *)textField {
  self = [super init];
  if (self) {
    self.textField = textField;

    [self setBarStyle:UIBarStyleDefault];
    self.translatesAutoresizingMaskIntoConstraints = NO;
    self.flexible = [[UIBarButtonItem alloc]
                     initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
                     target:self action:nil];

    // since there is a next field, add a NEXT button to the picker
    if (self. textField. returnKeyType == UIReturnKeyNext) {
      NSString *nextText = @"Next";
      UIBarButtonItem *nextButton = [[UIBarButtonItem alloc] initWithTitle:nextText
                                                                   style:UIBarButtonItemStyleDone
                                                                  target:self
                                                                  action:@selector(next)];

      self.items = [[NSArray alloc] initWithObjects: self.flexible, nextButton, nil];
    }else if (self.textField. returnKeyType == UIReturnKeyContinue) {

      NSString *continueText = @"Continue";
      UIBarButtonItem *contButton = [[UIBarButtonItem alloc] initWithTitle:continueText
                                                                     style:UIBarButtonItemStyleDone
                                                                    target:self
                                                                    action:@selector(next)];

      self.items = [[NSArray alloc] initWithObjects: self.flexible, contButton, nil];
    }
    else if (self. textField.returnKeyType == UIReturnKeyDone) {

      NSString *doneText = @"Done";
      UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle:doneText
                                                                     style:UIBarButtonItemStyleDone
                                                                    target:self
                                                                    action:@selector(done)];
      doneButton.enabled = YES;

      self.items = [[NSArray alloc] initWithObjects: self.flexible, doneButton, nil];
    }

  }
  return self;
}
-(void) done {
  [self passToReactNative];
  [self.textField resignFirstResponder];
}

-(void) next {
  [self passToReactNative];
}

-(void) passToReactNative {
  SEL selector = @selector(textFieldSubmitEditing);
  if ([self.textField respondsToSelector:selector]) {
    [self.textField performSelector:selector withObject:nil];
  }
}

-(UIView *)getInputAccessory {
  return self;
}
ekrivopaltsev pushed a commit to ekrivopaltsev/react-native that referenced this pull request Mar 25, 2016
Some keyboard types does not have buttons correspondent for keyReturnType such as Next, Done. It is observable on IPhone for numeric keyboard types. That prevents traversing forms with "number" input fields and impacts end-user experience.

The improvement allows application for adding extra buttons via inputAccessoryView.
Because RCTText is not a project exposed to React application calling all methods to add a handler is done using selectors.

Here is a code fragment which has an example on how to achieve it:
Within application:
facebook#1 Create a keyboard Handle
 KeyboardAccessory keyboardHandler = ^UIView *(UITextField *textField) {
    ReactTextAdapter *kAdapter = [[ReactTextAdapter alloc] init:textField];
    return [kAdapter getInputAccessory];
  };

2. Register an adapter

  Class clz = NSClassFromString(@"RCTTextField");

  SEL selector = NSSelectorFromString(@"registerForKeyboardType:handler:");
  if ([clz respondsToSelector:selector]) {
  [   clz performSelector:selector withObject:[NSNumber numberWithInt:UIKeyboardTypeNumberPad] withObject:keyboardHandler];
  }

facebook#3 Example of Keyboard Adapter

@interface ReactTextAdapter :UIToolbar

-(instancetype) init:(UITextField *)textField;
-(UIView *)getInputAccessory;

@EnD

//
//  ReactTextAdapter.m
//  KeyboardTest
//
//  Created by Krivopaltsev, Eugene on 3/11/16.
//

#import "ReactTextAdapter.h"

@interface ReactTextAdapter()

@Property (nonatomic) UITextField *textField;

//@Property (nonatomic)UIToolbar *toolBar;
@Property (nonatomic)UIBarButtonItem *flexible;

@EnD

@implementation ReactTextAdapter

-(instancetype) init:(UITextField *)textField {
  self = [super init];
  if (self) {
    self.textField = textField;

    [self setBarStyle:UIBarStyleDefault];
    self.translatesAutoresizingMaskIntoConstraints = NO;
    self.flexible = [[UIBarButtonItem alloc]
                     initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
                     target:self action:nil];

    // since there is a next field, add a NEXT button to the picker
    if (self. textField. returnKeyType == UIReturnKeyNext) {
      NSString *nextText = @"Next";
      UIBarButtonItem *nextButton = [[UIBarButtonItem alloc] initWithTitle:nextText
                                                                   style:UIBarButtonItemStyleDone
                                                                  target:self
                                                                  action:@selector(next)];

      self.items = [[NSArray alloc] initWithObjects: self.flexible, nextButton, nil];
    }else if (self.textField. returnKeyType == UIReturnKeyContinue) {

      NSString *continueText = @"Continue";
      UIBarButtonItem *contButton = [[UIBarButtonItem alloc] initWithTitle:continueText
                                                                     style:UIBarButtonItemStyleDone
                                                                    target:self
                                                                    action:@selector(next)];

      self.items = [[NSArray alloc] initWithObjects: self.flexible, contButton, nil];
    }
    else if (self. textField.returnKeyType == UIReturnKeyDone) {

      NSString *doneText = @"Done";
      UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle:doneText
                                                                     style:UIBarButtonItemStyleDone
                                                                    target:self
                                                                    action:@selector(done)];
      doneButton.enabled = YES;

      self.items = [[NSArray alloc] initWithObjects: self.flexible, doneButton, nil];
    }

  }
  return self;
}
-(void) done {
  [self passToReactNative];
  [self.textField resignFirstResponder];
}

-(void) next {
  [self passToReactNative];
}

-(void) passToReactNative {
  SEL selector = @selector(textFieldSubmitEditing);
  if ([self.textField respondsToSelector:selector]) {
    [self.textField performSelector:selector withObject:nil];
  }
}

-(UIView *)getInputAccessory {
  return self;
}
@facebook-github-bot
Copy link
Contributor

@robz updated the pull request.

RSNara added a commit to RSNara/react-native that referenced this pull request Nov 21, 2023
Summary:

## Context
In open source, all apps use the same turbomodulemanager delegate (i.e: the default delegate).

This diff introduces the buck infra that makes the oss default delegate work for meta apps.

Concretely, we are going to make React Native use the same  delegate for **all** Meta apps.

Each Meta app will:
1. At build time, generate a unique TMProvider map
2. At app init time, initialize the default delegate with the TMProvider map.

## Implementation
**Step facebook#1:** At build time, generate a unique TMProvider map

**Insight:** Buck genrules can accept, as input, the output of a buck query.

So, here's how we get this done:
1. Buck query (i.e: input to Genrule): Given the app's deps, query all the schemas in the app.
2. Genrule: Read the schemas to generate the TMProvider map. The TMProvider map will also contain **all** the app's C++ module codegen.

Concretely:
1. This diff introduces a macro: rn_codegen_appmodules(deps).
2. rn_codegen_appmodules(deps) generates appmodules.so, which contains the TMProvider map.

**Step facebook#2:** At app init time, initialize the default delegate with the TMProvider map.

This is how we'll initialize the DefaultTurboModuleManagerDelegate:
1. DefaultTurboModuleManagerDelegate will load appmodules.so during init.
2. When loaded, appmodules.so will assign the code-generated TMProvider map to DefaultTurboModuleManagerDelegate.

## Impact
This should allow us to:
1. Get one step closer to getting rid of the `js1 build turbomodule-manager-delegates --target <app>` script
3. Remove the TurboModuleManagerDelegate from React Native's public API. (Because we use one delegate for all React Native apps in Meta and OSS)

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D50988397
RSNara added a commit to RSNara/react-native that referenced this pull request Nov 21, 2023
Summary:

## Context
In open source, all apps use the same turbomodulemanager delegate (i.e: the default delegate).

This diff introduces the buck infra that makes the oss default delegate work for meta apps.

Concretely, we are going to make React Native use the same  delegate for **all** Meta apps.

Each Meta app will:
1. At build time, generate a unique TMProvider map
2. At app init time, initialize the default delegate with the TMProvider map.

## Implementation
**Step facebook#1:** At build time, generate a unique TMProvider map

**Insight:** Buck genrules can accept, as input, the output of a buck query.

So, here's how we get this done:
1. Buck query (i.e: input to Genrule): Given the app's deps, query all the schemas in the app.
2. Genrule: Read the schemas to generate the TMProvider map. The TMProvider map will also contain **all** the app's C++ module codegen.

Concretely:
1. This diff introduces a macro: rn_codegen_appmodules(deps).
2. rn_codegen_appmodules(deps) generates appmodules.so, which contains the TMProvider map.

**Step facebook#2:** At app init time, initialize the default delegate with the TMProvider map.

This is how we'll initialize the DefaultTurboModuleManagerDelegate:
1. DefaultTurboModuleManagerDelegate will load appmodules.so during init.
2. When loaded, appmodules.so will assign the code-generated TMProvider map to DefaultTurboModuleManagerDelegate.

## Impact
This should allow us to:
1. Get one step closer to getting rid of the `js1 build turbomodule-manager-delegates --target <app>` script
3. Remove the TurboModuleManagerDelegate from React Native's public API. (Because we use one delegate for all React Native apps in Meta and OSS)

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D50988397
RSNara added a commit to RSNara/react-native that referenced this pull request Nov 21, 2023
Summary:

## Context
In open source, all apps use the same turbomodulemanager delegate (i.e: the default delegate).

This diff introduces the buck infra that makes the oss default delegate work for meta apps.

Concretely, we are going to make React Native use the same  delegate for **all** Meta apps.

Each Meta app will:
1. At build time, generate a unique TMProvider map
2. At app init time, initialize the default delegate with the TMProvider map.

## Implementation
**Step facebook#1:** At build time, generate a unique TMProvider map

**Insight:** Buck genrules can accept, as input, the output of a buck query.

So, here's how we get this done:
1. Buck query (i.e: input to Genrule): Given the app's deps, query all the schemas in the app.
2. Genrule: Read the schemas to generate the TMProvider map. The TMProvider map will also contain **all** the app's C++ module codegen.

Concretely:
1. This diff introduces a macro: rn_codegen_appmodules(deps).
2. rn_codegen_appmodules(deps) generates appmodules.so, which contains the TMProvider map.

**Step facebook#2:** At app init time, initialize the default delegate with the TMProvider map.

This is how we'll initialize the DefaultTurboModuleManagerDelegate:
1. DefaultTurboModuleManagerDelegate will load appmodules.so during init.
2. When loaded, appmodules.so will assign the code-generated TMProvider map to DefaultTurboModuleManagerDelegate.

## Impact
This should allow us to:
1. Get one step closer to getting rid of the `js1 build turbomodule-manager-delegates --target <app>` script
3. Remove the TurboModuleManagerDelegate from React Native's public API. (Because we use one delegate for all React Native apps in Meta and OSS)

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D50988397
RSNara added a commit to RSNara/react-native that referenced this pull request Nov 21, 2023
Summary:

## Context
In open source, all apps use the same turbomodulemanager delegate (i.e: the default delegate).

This diff introduces the buck infra that makes the oss default delegate work for meta apps.

Concretely, we are going to make React Native use the same  delegate for **all** Meta apps.

Each Meta app will:
1. At build time, generate a unique TMProvider map
2. At app init time, initialize the default delegate with the TMProvider map.

## Implementation
**Step facebook#1:** At build time, generate a unique TMProvider map

**Insight:** Buck genrules can accept, as input, the output of a buck query.

So, here's how we get this done:
1. Buck query (i.e: input to Genrule): Given the app's deps, query all the schemas in the app.
2. Genrule: Read the schemas to generate the TMProvider map. The TMProvider map will also contain **all** the app's C++ module codegen.

Concretely:
1. This diff introduces a macro: rn_codegen_appmodules(deps).
2. rn_codegen_appmodules(deps) generates appmodules.so, which contains the TMProvider map.

**Step facebook#2:** At app init time, initialize the default delegate with the TMProvider map.

This is how we'll initialize the DefaultTurboModuleManagerDelegate:
1. DefaultTurboModuleManagerDelegate will load appmodules.so during init.
2. When loaded, appmodules.so will assign the code-generated TMProvider map to DefaultTurboModuleManagerDelegate.

## Impact
This should allow us to:
1. Get one step closer to getting rid of the `js1 build turbomodule-manager-delegates --target <app>` script
3. Remove the TurboModuleManagerDelegate from React Native's public API. (Because we use one delegate for all React Native apps in Meta and OSS)

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D50988397
RSNara added a commit to RSNara/react-native that referenced this pull request Nov 22, 2023
Summary:

## Context
In open source, all apps use the same turbomodulemanager delegate (i.e: the default delegate).

This diff introduces the buck infra that makes the oss default delegate work for meta apps.

Concretely, we are going to make React Native use the same  delegate for **all** Meta apps.

Each Meta app will:
1. At build time, generate a unique TMProvider map
2. At app init time, initialize the default delegate with the TMProvider map.

## Implementation
**Step facebook#1:** At build time, generate a unique TMProvider map

**Insight:** Buck genrules can accept, as input, the output of a buck query.

So, here's how we get this done:
1. Buck query (i.e: input to Genrule): Given the app's deps, query all the schemas in the app.
2. Genrule: Read the schemas to generate the TMProvider map. The TMProvider map will also contain **all** the app's C++ module codegen.

Concretely:
1. This diff introduces a macro: rn_codegen_appmodules(deps).
2. rn_codegen_appmodules(deps) generates appmodules.so, which contains the TMProvider map.

**Step facebook#2:** At app init time, initialize the default delegate with the TMProvider map.

This is how we'll initialize the DefaultTurboModuleManagerDelegate:
1. DefaultTurboModuleManagerDelegate will load appmodules.so during init.
2. When loaded, appmodules.so will assign the code-generated TMProvider map to DefaultTurboModuleManagerDelegate.

## Impact
This should allow us to:
1. Get one step closer to getting rid of the `js1 build turbomodule-manager-delegates --target <app>` script
3. Remove the TurboModuleManagerDelegate from React Native's public API. (Because we use one delegate for all React Native apps in Meta and OSS)

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D50988397
RSNara added a commit to RSNara/react-native that referenced this pull request Nov 22, 2023
Summary:

## Context
In open source, all apps use the same turbomodulemanager delegate (i.e: the default delegate).

This diff introduces the buck infra that makes the oss default delegate work for meta apps.

Concretely, we are going to make React Native use the same  delegate for **all** Meta apps.

Each Meta app will:
1. At build time, generate a unique TMProvider map
2. At app init time, initialize the default delegate with the TMProvider map.

## Implementation
**Step facebook#1:** At build time, generate a unique TMProvider map

**Insight:** Buck genrules can accept, as input, the output of a buck query.

So, here's how we get this done:
1. Buck query (i.e: input to Genrule): Given the app's deps, query all the schemas in the app.
2. Genrule: Read the schemas to generate the TMProvider map. The TMProvider map will also contain **all** the app's C++ module codegen.

Concretely:
1. This diff introduces a macro: rn_codegen_appmodules(deps).
2. rn_codegen_appmodules(deps) generates appmodules.so, which contains the TMProvider map.

**Step facebook#2:** At app init time, initialize the default delegate with the TMProvider map.

This is how we'll initialize the DefaultTurboModuleManagerDelegate:
1. DefaultTurboModuleManagerDelegate will load appmodules.so during init.
2. When loaded, appmodules.so will assign the code-generated TMProvider map to DefaultTurboModuleManagerDelegate.

## Impact
This should allow us to:
1. Get one step closer to getting rid of the `js1 build turbomodule-manager-delegates --target <app>` script
3. Remove the TurboModuleManagerDelegate from React Native's public API. (Because we use one delegate for all React Native apps in Meta and OSS)

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D50988397
RSNara added a commit to RSNara/react-native that referenced this pull request Nov 22, 2023
Summary:

## Context
In open source, all apps use the same turbomodulemanager delegate (i.e: the default delegate).

This diff introduces the buck infra that makes the oss default delegate work for meta apps.

Concretely, we are going to make React Native use the same  delegate for **all** Meta apps.

Each Meta app will:
1. At build time, generate a unique TMProvider map
2. At app init time, initialize the default delegate with the TMProvider map.

## Implementation
**Step facebook#1:** At build time, generate a unique TMProvider map

**Insight:** Buck genrules can accept, as input, the output of a buck query.

So, here's how we get this done:
1. Buck query (i.e: input to Genrule): Given the app's deps, query all the schemas in the app.
2. Genrule: Read the schemas to generate the TMProvider map. The TMProvider map will also contain **all** the app's C++ module codegen.

Concretely:
1. This diff introduces a macro: rn_codegen_appmodules(deps).
2. rn_codegen_appmodules(deps) generates appmodules.so, which contains the TMProvider map.

**Step facebook#2:** At app init time, initialize the default delegate with the TMProvider map.

This is how we'll initialize the DefaultTurboModuleManagerDelegate:
1. DefaultTurboModuleManagerDelegate will load appmodules.so during init.
2. When loaded, appmodules.so will assign the code-generated TMProvider map to DefaultTurboModuleManagerDelegate.

## Impact
This should allow us to:
1. Get one step closer to getting rid of the `js1 build turbomodule-manager-delegates --target <app>` script
3. Remove the TurboModuleManagerDelegate from React Native's public API. (Because we use one delegate for all React Native apps in Meta and OSS)

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D50988397
RSNara added a commit to RSNara/react-native that referenced this pull request Nov 22, 2023
Summary:

## Context
In open source, all apps use the same turbomodulemanager delegate (i.e: the default delegate).

This diff introduces the buck infra that makes the oss default delegate work for meta apps.

Concretely, we are going to make React Native use the same  delegate for **all** Meta apps.

Each Meta app will:
1. At build time, generate a unique TMProvider map
2. At app init time, initialize the default delegate with the TMProvider map.

## Implementation
**Step facebook#1:** At build time, generate a unique TMProvider map

**Insight:** Buck genrules can accept, as input, the output of a buck query.

So, here's how we get this done:
1. Buck query (i.e: input to Genrule): Given the app's deps, query all the schemas in the app.
2. Genrule: Read the schemas to generate the TMProvider map. The TMProvider map will also contain **all** the app's C++ module codegen.

Concretely:
1. This diff introduces a macro: rn_codegen_appmodules(deps).
2. rn_codegen_appmodules(deps) generates appmodules.so, which contains the TMProvider map.

**Step facebook#2:** At app init time, initialize the default delegate with the TMProvider map.

This is how we'll initialize the DefaultTurboModuleManagerDelegate:
1. DefaultTurboModuleManagerDelegate will load appmodules.so during init.
2. When loaded, appmodules.so will assign the code-generated TMProvider map to DefaultTurboModuleManagerDelegate.

## Impact
This should allow us to:
1. Get one step closer to getting rid of the `js1 build turbomodule-manager-delegates --target <app>` script
3. Remove the TurboModuleManagerDelegate from React Native's public API. (Because we use one delegate for all React Native apps in Meta and OSS)

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D50988397
RSNara added a commit to RSNara/react-native that referenced this pull request Nov 22, 2023
Summary:

## Context
In open source, all apps use the same turbomodulemanager delegate (i.e: the default delegate).

This diff introduces the buck infra that makes the oss default delegate work for meta apps.

Concretely, we are going to make React Native use the same  delegate for **all** Meta apps.

Each Meta app will:
1. At build time, generate a unique TMProvider map
2. At app init time, initialize the default delegate with the TMProvider map.

## Implementation
**Step facebook#1:** At build time, generate a unique TMProvider map

**Insight:** Buck genrules can accept, as input, the output of a buck query.

So, here's how we get this done:
1. Buck query (i.e: input to Genrule): Given the app's deps, query all the schemas in the app.
2. Genrule: Read the schemas to generate the TMProvider map. The TMProvider map will also contain **all** the app's C++ module codegen.

Concretely:
1. This diff introduces a macro: rn_codegen_appmodules(deps).
2. rn_codegen_appmodules(deps) generates appmodules.so, which contains the TMProvider map.

**Step facebook#2:** At app init time, initialize the default delegate with the TMProvider map.

This is how we'll initialize the DefaultTurboModuleManagerDelegate:
1. DefaultTurboModuleManagerDelegate will load appmodules.so during init.
2. When loaded, appmodules.so will assign the code-generated TMProvider map to DefaultTurboModuleManagerDelegate.

## Impact
This should allow us to:
1. Get one step closer to getting rid of the `js1 build turbomodule-manager-delegates --target <app>` script
3. Remove the TurboModuleManagerDelegate from React Native's public API. (Because we use one delegate for all React Native apps in Meta and OSS)

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D50988397
facebook-github-bot pushed a commit that referenced this pull request Nov 22, 2023
Summary:
Pull Request resolved: #41466

## Context
In open source, all apps use the same turbomodulemanager delegate (i.e: the default delegate).

This diff introduces the buck infra that makes the oss default delegate work for meta apps.

Concretely, we are going to make React Native use the same  delegate for **all** Meta apps.

Each Meta app will:
1. At build time, generate a unique TMProvider map
2. At app init time, initialize the default delegate with the TMProvider map.

## Implementation
**Step #1:** At build time, generate a unique TMProvider map

**Insight:** Buck genrules can accept, as input, the output of a buck query.

So, here's how we get this done:
1. Buck query (i.e: input to Genrule): Given the app's deps, query all the schemas in the app.
2. Genrule: Read the schemas to generate the TMProvider map. The TMProvider map will also contain **all** the app's C++ module codegen.

Concretely:
1. This diff introduces a macro: rn_codegen_appmodules(deps).
2. rn_codegen_appmodules(deps) generates appmodules.so, which contains the TMProvider map.

**Step #2:** At app init time, initialize the default delegate with the TMProvider map.

This is how we'll initialize the DefaultTurboModuleManagerDelegate:
1. DefaultTurboModuleManagerDelegate will load appmodules.so during init.
2. When loaded, appmodules.so will assign the code-generated TMProvider map to DefaultTurboModuleManagerDelegate.

## Impact
This should allow us to:
1. Get one step closer to getting rid of the `js1 build turbomodule-manager-delegates --target <app>` script
3. Remove the TurboModuleManagerDelegate from React Native's public API. (Because we use one delegate for all React Native apps in Meta and OSS)

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D50988397

fbshipit-source-id: 0ca5dec14e2dae89ec97f5d39a182c7937c5c7bf
Othinn pushed a commit to Othinn/react-native that referenced this pull request Jan 9, 2024
Summary:
`UIManager` gets module deadlock when start-up randomly. I think we can move it to the secondary thread safely.

```
(lldb) bt all
* thread facebook#1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
    frame #0: 0x000000010d66a5d6 libsystem_kernel.dylib`__psynch_cvwait + 10
    frame facebook#1: 0x000000010d5f476b libsystem_pthread.dylib`_pthread_cond_wait + 1211
    frame facebook#2: 0x000000010761dfe2 libc++.1.dylib`std::__1::condition_variable::wait(std::__1::unique_lock<std::__1::mutex>&) + 18
    frame facebook#3: 0x00000001034a0a52 RNTester`-[RCTTurboModuleManager _provideObjCModule:moduleHolder:shouldPerfLog:](self=0x00007fafac10e990, _cmd="_provideObjCModule:moduleHolder:shouldPerfLog:", moduleName="AccessibilityManager", moduleHolder=0x0000600003c8cbd8, shouldPerfLog=YES) at RCTTurboModuleManager.mm:599:24
    frame facebook#4: 0x00000001034a0488 RNTester`-[RCTTurboModuleManager _provideObjCModule:](self=0x00007fafac10e990, _cmd="_provideObjCModule:", moduleName="AccessibilityManager") at RCTTurboModuleManager.mm:517:32
    frame facebook#5: 0x00000001034a2cfa RNTester`-[RCTTurboModuleManager moduleForName:warnOnLookupFailure:](self=0x00007fafac10e990, _cmd="moduleForName:warnOnLookupFailure:", moduleName="AccessibilityManager", warnOnLookupFailure=NO) at RCTTurboModuleManager.mm:976:32
    frame facebook#6: 0x00000001030ba6aa RNTester`-[RCTCxxBridge moduleForName:lazilyLoadIfNecessary:](self=0x00007fafac105ab0, _cmd="moduleForName:lazilyLoadIfNecessary:", moduleName="AccessibilityManager", lazilyLoad=YES) at RCTCxxBridge.mm:568:35
  * frame facebook#7: 0x000000010316fa38 RNTester`__26-[RCTUIManager setBridge:]_block_invoke(.block_descriptor=0x000060000055cb40) at RCTUIManager.m:188:55
    frame facebook#8: 0x00000001090cc747 libdispatch.dylib`_dispatch_call_block_and_release + 12
    frame facebook#9: 0x00000001090cd9f7 libdispatch.dylib`_dispatch_client_callout + 8
    frame facebook#10: 0x00000001090dd856 libdispatch.dylib`_dispatch_main_queue_drain + 1362
    frame facebook#11: 0x00000001090dd2f6 libdispatch.dylib`_dispatch_main_queue_callback_4CF + 31
    frame facebook#12: 0x00000001088b4850 CoreFoundation`__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
    frame facebook#13: 0x00000001088af18b CoreFoundation`__CFRunLoopRun + 2463
    frame facebook#14: 0x00000001088ae409 CoreFoundation`CFRunLoopRunSpecific + 557
    frame facebook#15: 0x0000000114ede187 GraphicsServices`GSEventRunModal + 137
    frame facebook#16: 0x0000000128be53a2 UIKitCore`-[UIApplication _run] + 972
    frame facebook#17: 0x0000000128be9e10 UIKitCore`UIApplicationMain + 123
    frame facebook#18: 0x0000000102fb7000 RNTester`main(argc=1, argv=0x00007ff7bcf4fce8) at main.m:15:12
    frame facebook#19: 0x00000001069023ee dyld_sim`start_sim + 10
    frame facebook#20: 0x000000010ea223a6 dyld`start + 1942
  thread facebook#6, name = 'com.apple.uikit.eventfetch-thread'
    frame #0: 0x000000010d667a2e libsystem_kernel.dylib`mach_msg2_trap + 10
    frame facebook#1: 0x000000010d675e4a libsystem_kernel.dylib`mach_msg2_internal + 84
    frame facebook#2: 0x000000010d66eb6e libsystem_kernel.dylib`mach_msg_overwrite + 653
    frame facebook#3: 0x000000010d667d1f libsystem_kernel.dylib`mach_msg + 19
    frame facebook#4: 0x00000001088b45bf CoreFoundation`__CFRunLoopServiceMachPort + 143
    frame facebook#5: 0x00000001088aed47 CoreFoundation`__CFRunLoopRun + 1371
    frame facebook#6: 0x00000001088ae409 CoreFoundation`CFRunLoopRunSpecific + 557
    frame facebook#7: 0x000000010a34ceee Foundation`-[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 213
    frame facebook#8: 0x000000010a34d16c Foundation`-[NSRunLoop(NSRunLoop) runUntilDate:] + 72
    frame facebook#9: 0x0000000128cbd797 UIKitCore`-[UIEventFetcher threadMain] + 518
    frame facebook#10: 0x000000010a377699 Foundation`__NSThread__start__ + 1024
    frame facebook#11: 0x000000010d5f4202 libsystem_pthread.dylib`_pthread_start + 99
    frame facebook#12: 0x000000010d5efbab libsystem_pthread.dylib`thread_start + 15
  thread facebook#9, name = 'com.facebook.react.JavaScript'
    frame #0: 0x000000010d6691e2 libsystem_kernel.dylib`__ulock_wait + 10
    frame facebook#1: 0x00000001090ce319 libdispatch.dylib`_dlock_wait + 46
    frame facebook#2: 0x00000001090ce170 libdispatch.dylib`_dispatch_thread_event_wait_slow + 40
    frame facebook#3: 0x00000001090debb2 libdispatch.dylib`__DISPATCH_WAIT_FOR_QUEUE__ + 371
    frame facebook#4: 0x00000001090de5c9 libdispatch.dylib`_dispatch_sync_f_slow + 240
    frame facebook#5: 0x00000001031847cb RNTester`RCTUnsafeExecuteOnMainQueueSync(block=0x00000001034a0bf0) at RCTUtils.m:277:5
    frame facebook#6: 0x00000001034a0863 RNTester`-[RCTTurboModuleManager _provideObjCModule:moduleHolder:shouldPerfLog:](self=0x00007fafac10e990, _cmd="_provideObjCModule:moduleHolder:shouldPerfLog:", moduleName="AccessibilityManager", moduleHolder=0x0000600003c8cbd8, shouldPerfLog=YES) at RCTTurboModuleManager.mm:571:9
    frame facebook#7: 0x00000001034a0488 RNTester`-[RCTTurboModuleManager _provideObjCModule:](self=0x00007fafac10e990, _cmd="_provideObjCModule:", moduleName="AccessibilityManager") at RCTTurboModuleManager.mm:517:32
    frame facebook#8: 0x00000001034a2cfa RNTester`-[RCTTurboModuleManager moduleForName:warnOnLookupFailure:](self=0x00007fafac10e990, _cmd="moduleForName:warnOnLookupFailure:", moduleName="AccessibilityManager", warnOnLookupFailure=NO) at RCTTurboModuleManager.mm:976:32
    frame facebook#9: 0x00000001030ba6aa RNTester`-[RCTCxxBridge moduleForName:lazilyLoadIfNecessary:](self=0x00007fafac105ab0, _cmd="moduleForName:lazilyLoadIfNecessary:", moduleName="AccessibilityManager", lazilyLoad=YES) at RCTCxxBridge.mm:568:35
    frame facebook#10: 0x000000010366db7c RNTester`-[RCTBaseTextInputViewManager setBridge:](self=0x0000600000b19d60, _cmd="setBridge:", bridge=0x00007fafac105ab0) at RCTBaseTextInputViewManager.mm:104:53
    frame facebook#11: 0x000000010a2c1796 Foundation`-[NSObject(NSKeyValueCoding) setValue:forKey:] + 278
    frame facebook#12: 0x0000000103116f42 RNTester`-[RCTModuleData setBridgeForInstance](self=0x0000600003eb58c0, _cmd="setBridgeForInstance") at RCTModuleData.mm:256:7
    frame facebook#13: 0x0000000103116971 RNTester`-[RCTModuleData setUpInstanceAndBridge:](self=0x0000600003eb58c0, _cmd="setUpInstanceAndBridge:", requestId=10) at RCTModuleData.mm:210:7
    frame facebook#14: 0x0000000103118990 RNTester`-[RCTModuleData instance](self=0x0000600003eb58c0, _cmd="instance") at RCTModuleData.mm:395:7
    frame facebook#15: 0x00000001030ba8b6 RNTester`-[RCTCxxBridge moduleForName:lazilyLoadIfNecessary:](self=0x00007fafac105ab0, _cmd="moduleForName:lazilyLoadIfNecessary:", moduleName="BaseTextInputViewManager", lazilyLoad=YES) at RCTCxxBridge.mm:587:23
    frame facebook#16: 0x00000001030bad90 RNTester`-[RCTCxxBridge moduleForClass:](self=0x00007fafac105ab0, _cmd="moduleForClass:", moduleClass=RCTBaseTextInputViewManager) at RCTCxxBridge.mm:631:10
    frame facebook#17: 0x000000010309bd59 RNTester`-[RCTComponentData manager](self=0x0000600002fbd920, _cmd="manager") at RCTComponentData.m:67:16
    frame facebook#18: 0x00000001030a2831 RNTester`-[RCTComponentData viewConfig](self=0x0000600002fbd920, _cmd="viewConfig") at RCTComponentData.m:518:3
    frame facebook#19: 0x0000000103180216 RNTester`moduleConstantsForComponentData(directEvents=7 key/value pairs, bubblingEvents=2 key/value pairs, componentData=0x0000600002fbd920) at RCTUIManager.m:1568:99
    frame facebook#20: 0x00000001031800ea RNTester`__28-[RCTUIManager getConstants]_block_invoke(.block_descriptor=0x00007000042d35d0, name=@"RCTBaseTextInputView", componentData=0x0000600002fbd920, stop=NO) at RCTUIManager.m:1586:13
    frame facebook#21: 0x000000010889d4fd CoreFoundation`__NSDICTIONARY_IS_CALLING_OUT_TO_A_BLOCK__ + 7
    frame facebook#22: 0x00000001089c9281 CoreFoundation`-[__NSDictionaryM enumerateKeysAndObjectsWithOptions:usingBlock:] + 249
    frame facebook#23: 0x000000010317feb7 RNTester`-[RCTUIManager getConstants](self=0x000060000206d0a0, _cmd="getConstants") at RCTUIManager.m:1582:3
    frame facebook#24: 0x000000010317fdb1 RNTester`-[RCTUIManager constantsToExport](self=0x000060000206d0a0, _cmd="constantsToExport") at RCTUIManager.m:1573:10
    frame facebook#25: 0x000000010311911b RNTester`-[RCTModuleData gatherConstantsAndSignalJSRequireEnding:](self=0x0000600003eb5500, _cmd="gatherConstantsAndSignalJSRequireEnding:", startMarkers=YES) at RCTModuleData.mm:462:28
    frame facebook#26: 0x00000001031193e9 RNTester`-[RCTModuleData exportedConstants](self=0x0000600003eb5500, _cmd="exportedConstants") at RCTModuleData.mm:477:3
    frame facebook#27: 0x0000000103125d09 RNTester`facebook::react::RCTNativeModule::getConstants(this=0x0000600000beac80) at RCTNativeModule.mm:68:42
    frame facebook#28: 0x000000010370a0f2 RNTester`facebook::react::ModuleRegistry::getConfig(this=0x0000600003e913a0, name="UIManager") at ModuleRegistry.cpp:154:30
    frame facebook#29: 0x0000000103797b6e RNTester`facebook::react::JSINativeModules::createModule(this=0x0000600002f8cf78, rt=0x0000600002f8d278, name="UIManager") at JSINativeModules.cpp:81:35
    frame facebook#30: 0x000000010379778c RNTester`facebook::react::JSINativeModules::getModule(this=0x0000600002f8cf78, rt=0x0000600002f8d278, name=0x00007000042d4138) at JSINativeModules.cpp:46:17
    frame facebook#31: 0x000000010378814a RNTester`facebook::react::JSIExecutor::NativeModuleProxy::get(this=0x000060000057ac88, rt=0x0000600002f8d278, name=0x00007000042d4138) at JSIExecutor.cpp:44:27
    frame facebook#32: 0x00000001037448d6 RNTester`facebook::jsi::DecoratedHostObject::get(this=0x0000600001e3e118, (null)=0x0000600003cb8630, name=0x00007000042d4138) at decorator.h:70:22
    frame facebook#33: 0x0000000109667ff7 hermes`facebook::hermes::HermesRuntimeImpl::JsiProxy::get(this=0x0000600000ba4d20, id=(id_ = 4435)) at hermes.cpp:698:20 [opt]
    frame facebook#34: 0x00000001096e7436 hermes`hermes::vm::JSObject::getComputedWithReceiver_RJS(hermes::vm::Handle<hermes::vm::JSObject>, hermes::vm::Runtime&, hermes::vm::Handle<hermes::vm::HermesValue>, hermes::vm::Handle<hermes::vm::HermesValue>) [inlined] hermes::vm::HostObject::get(this=<unavailable>, name=<unavailable>) at HostModel.h:112:24 [opt]
    frame facebook#35: 0x00000001096e742c hermes`hermes::vm::JSObject::getComputedWithReceiver_RJS(selfHandle=<unavailable>, runtime=0x00007fafae026000, nameValHandle=<unavailable>, receiver=Handle<hermes::vm::HermesValue> @ 0x00007000042d4190) at JSObject.cpp:1182:55 [opt]
    frame facebook#36: 0x00000001096cc141 hermes`hermes::vm::CallResult<hermes::vm::HermesValue, (hermes::vm::detail::CallResultSpecialize)2> hermes::vm::Interpreter::interpretFunction<false, false>(hermes::vm::Runtime&, hermes::vm::InterpreterState&) [inlined] hermes::vm::JSObject::getComputed_RJS(selfHandle=<unavailable>, runtime=0x00007fafae026000, nameValHandle=<unavailable>) at JSObject.h:1940:10 [opt]
    frame facebook#37: 0x00000001096cc12f hermes`hermes::vm::CallResult<hermes::vm::HermesValue, (hermes::vm::detail::CallResultSpecialize)2> hermes::vm::Interpreter::interpretFunction<false, false>(runtime=0x00007fafae026000, state=0x00007000042d4470) at Interpreter.cpp:2481:11 [opt]
    frame facebook#38: 0x00000001096c84bc hermes`hermes::vm::Runtime::interpretFunctionImpl(this=0x00007fafae026000, newCodeBlock=0x0000600003068000) at Interpreter.cpp:825:12 [opt]
    frame facebook#39: 0x000000010970fbc8 hermes`hermes::vm::Runtime::runBytecode(this=0x00007fafae026000, bytecode=<unavailable>, flags=<unavailable>, sourceURL=(Data = "http://localhost:8081/js/RNTesterApp.ios.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&app=com.meta.RNTester.localDevelopment", Length = 188), environment=Handle<hermes::vm::Environment> @ 0x00007000042d44d0, thisArg=Handle<hermes::vm::HermesValue> @ 0x00007000042d4630) at Runtime.cpp:1079:11 [opt]
    frame facebook#40: 0x000000010965ac1d hermes`facebook::hermes::HermesRuntimeImpl::evaluatePreparedJavaScript(std::__1::shared_ptr<facebook::jsi::PreparedJavaScript const> const&) [inlined] hermes::vm::Runtime::runBytecode(this=0x00007fafae026000, bytecode=nullptr, runtimeModuleFlags=RuntimeModuleFlags @ rbx, sourceURL=(Data = 0x0000000000000000, Length = 188), environment=<unavailable>) at Runtime.h:277:12 [opt]
    frame facebook#41: 0x000000010965abe7 hermes`facebook::hermes::HermesRuntimeImpl::evaluatePreparedJavaScript(this=0x0000600003cb8630, js=std::__1::shared_ptr<const facebook::jsi::PreparedJavaScript>::element_type @ 0x00006000028d7038 strong=1 weak=1) at hermes.cpp:1494:23 [opt]
    frame facebook#42: 0x000000010965aaa0 hermes`facebook::hermes::HermesRuntime::evaluateJavaScriptWithSourceMap(this=0x0000600003cb8630, buffer=std::__1::shared_ptr<const facebook::jsi::Buffer>::element_type @ 0x00006000009b4590 strong=2 weak=1, sourceMapBuf=nullptr, sourceURL=<unavailable>) at hermes.cpp:1361:22 [opt]
    frame facebook#43: 0x000000010965bdef hermes`facebook::hermes::HermesRuntimeImpl::evaluateJavaScript(this=<unavailable>, buffer=<unavailable>, sourceURL=<unavailable>) at hermes.cpp:1506:10 [opt]
    frame facebook#44: 0x0000000103742ef1 RNTester`facebook::jsi::RuntimeDecorator<facebook::jsi::Runtime, facebook::jsi::Runtime>::evaluateJavaScript(this=0x0000600002f8d278, buffer=std::__1::shared_ptr<const facebook::jsi::Buffer>::element_type @ 0x00006000009b4590 strong=2 weak=1, sourceURL="http://localhost:8081/js/RNTesterApp.ios.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&app=com.meta.RNTester.localDevelopment") at decorator.h:118:20
    frame facebook#45: 0x000000010374086d RNTester`facebook::jsi::WithRuntimeDecorator<facebook::react::(anonymous namespace)::ReentrancyCheck, facebook::jsi::Runtime, facebook::jsi::Runtime>::evaluateJavaScript(this=0x0000600002f8d278, buffer=std::__1::shared_ptr<const facebook::jsi::Buffer>::element_type @ 0x00006000009b4590 strong=2 weak=1, sourceURL="http://localhost:8081/js/RNTesterApp.ios.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&app=com.meta.RNTester.localDevelopment") at decorator.h:530:16
    frame facebook#46: 0x0000000103782c60 RNTester`facebook::react::JSIExecutor::loadBundle(this=0x00007fafabb07990, script=nullptr, sourceURL="http://localhost:8081/js/RNTesterApp.ios.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&app=com.meta.RNTester.localDevelopment") at JSIExecutor.cpp:160:13
    frame facebook#47: 0x0000000103718719 RNTester`facebook::react::NativeToJsBridge::loadBundle(std::__1::unique_ptr<facebook::react::RAMBundleRegistry, std::__1::default_delete<facebook::react::RAMBundleRegistry>>, std::__1::unique_ptr<facebook::react::JSBigString const, std::__1::default_delete<facebook::react::JSBigString const>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>)::$_1::operator()(this=0x0000600001e81fc8, executor=0x00007fafabb07990) at NativeToJsBridge.cpp:144:21
    frame facebook#48: 0x0000000103718600 RNTester`decltype(std::declval<facebook::react::NativeToJsBridge::loadBundle(std::__1::unique_ptr<facebook::react::RAMBundleRegistry, std::__1::default_delete<facebook::react::RAMBundleRegistry>>, std::__1::unique_ptr<facebook::react::JSBigString const, std::__1::default_delete<facebook::react::JSBigString const>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>)::$_1&>()(std::declval<facebook::react::JSExecutor*>())) std::__1::__invoke[abi:v160006]<facebook::react::NativeToJsBridge::loadBundle(std::__1::unique_ptr<facebook::react::RAMBundleRegistry, std::__1::default_delete<facebook::react::RAMBundleRegistry>>, std::__1::unique_ptr<facebook::react::JSBigString const, std::__1::default_delete<facebook::react::JSBigString const>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>)::$_1&, facebook::react::JSExecutor*>(__f=0x0000600001e81fc8, __args=0x00007000042d4aa0) at invoke.h:394:23
    frame facebook#49: 0x00000001037185ad RNTester`void std::__1::__invoke_void_return_wrapper<void, true>::__call<facebook::react::NativeToJsBridge::loadBundle(std::__1::unique_ptr<facebook::react::RAMBundleRegistry, std::__1::default_delete<facebook::react::RAMBundleRegistry>>, std::__1::unique_ptr<facebook::react::JSBigString const, std::__1::default_delete<facebook::react::JSBigString const>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>)::$_1&, facebook::react::JSExecutor*>(__args=0x0000600001e81fc8, __args=0x00007000042d4aa0) at invoke.h:487:9
    frame facebook#50: 0x0000000103718585 RNTester`std::__1::__function::__alloc_func<facebook::react::NativeToJsBridge::loadBundle(std::__1::unique_ptr<facebook::react::RAMBundleRegistry, std::__1::default_delete<facebook::react::RAMBundleRegistry>>, std::__1::unique_ptr<facebook::react::JSBigString const, std::__1::default_delete<facebook::react::JSBigString const>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>)::$_1, std::__1::allocator<facebook::react::NativeToJsBridge::loadBundle(std::__1::unique_ptr<facebook::react::RAMBundleRegistry, std::__1::default_delete<facebook::react::RAMBundleRegistry>>, std::__1::unique_ptr<facebook::react::JSBigString const, std::__1::default_delete<facebook::react::JSBigString const>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>)::$_1>, void (facebook::react::JSExecutor*)>::operator()[abi:v160006](this=0x0000600001e81fc8, __arg=0x00007000042d4aa0) at function.h:185:16
    frame facebook#51: 0x0000000103717311 RNTester`std::__1::__function::__func<facebook::react::NativeToJsBridge::loadBundle(std::__1::unique_ptr<facebook::react::RAMBundleRegistry, std::__1::default_delete<facebook::react::RAMBundleRegistry>>, std::__1::unique_ptr<facebook::react::JSBigString const, std::__1::default_delete<facebook::react::JSBigString const>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>)::$_1, std::__1::allocator<facebook::react::NativeToJsBridge::loadBundle(std::__1::unique_ptr<facebook::react::RAMBundleRegistry, std::__1::default_delete<facebook::react::RAMBundleRegistry>>, std::__1::unique_ptr<facebook::react::JSBigString const, std::__1::default_delete<facebook::react::JSBigString const>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>)::$_1>, void (facebook::react::JSExecutor*)>::operator()(this=0x0000600001e81fc0, __arg=0x00007000042d4aa0) at function.h:356:12
    frame facebook#52: 0x0000000103723f2a RNTester`std::__1::__function::__value_func<void (facebook::react::JSExecutor*)>::operator()[abi:v160006](this=0x0000600002fad4d0, __args=0x00007000042d4aa0) const at function.h:510:16
    frame facebook#53: 0x0000000103723ebd RNTester`std::__1::function<void (facebook::react::JSExecutor*)>::operator()(this=0x0000600002fad4d0, __arg=0x00007fafabb07990) const at function.h:1156:12
    frame facebook#54: 0x0000000103723e97 RNTester`facebook::react::NativeToJsBridge::runOnExecutorQueue(std::__1::function<void (facebook::react::JSExecutor*)>&&)::$_8::operator()(this=0x0000600002fad4b0) const at NativeToJsBridge.cpp:308:9
    frame facebook#55: 0x0000000103723e35 RNTester`decltype(std::declval<facebook::react::NativeToJsBridge::runOnExecutorQueue(std::__1::function<void (facebook::react::JSExecutor*)>&&)::$_8&>()()) std::__1::__invoke[abi:v160006]<facebook::react::NativeToJsBridge::runOnExecutorQueue(std::__1::function<void (facebook::react::JSExecutor*)>&&)::$_8&>(__f=0x0000600002fad4b0) at invoke.h:394:23
    frame facebook#56: 0x0000000103723df5 RNTester`void std::__1::__invoke_void_return_wrapper<void, true>::__call<facebook::react::NativeToJsBridge::runOnExecutorQueue(std::__1::function<void (facebook::react::JSExecutor*)>&&)::$_8&>(__args=0x0000600002fad4b0) at invoke.h:487:9
    frame facebook#57: 0x0000000103723dcd RNTester`std::__1::__function::__alloc_func<facebook::react::NativeToJsBridge::runOnExecutorQueue(std::__1::function<void (facebook::react::JSExecutor*)>&&)::$_8, std::__1::allocator<facebook::react::NativeToJsBridge::runOnExecutorQueue(std::__1::function<void (facebook::react::JSExecutor*)>&&)::$_8>, void ()>::operator()[abi:v160006](this=0x0000600002fad4b0) at function.h:185:16
    frame facebook#58: 0x0000000103722b89 RNTester`std::__1::__function::__func<facebook::react::NativeToJsBridge::runOnExecutorQueue(std::__1::function<void (facebook::react::JSExecutor*)>&&)::$_8, std::__1::allocator<facebook::react::NativeToJsBridge::runOnExecutorQueue(std::__1::function<void (facebook::react::JSExecutor*)>&&)::$_8>, void ()>::operator()(this=0x0000600002fad4a0) at function.h:356:12
    frame facebook#59: 0x00000001030cdd72 RNTester`std::__1::__function::__value_func<void ()>::operator()[abi:v160006](this=0x00006000028f85c0) const at function.h:510:16
    frame facebook#60: 0x00000001030cdd35 RNTester`std::__1::function<void ()>::operator()(this= Lambda in File NativeToJsBridge.cpp at Line 298) const at function.h:1156:12
    frame facebook#61: 0x00000001030e1145 RNTester`facebook::react::tryAndReturnError(func= Lambda in File NativeToJsBridge.cpp at Line 298) at RCTCxxUtils.mm:73:7
    frame facebook#62: 0x000000010310a5c1 RNTester`facebook::react::RCTMessageThread::tryFunc(this=0x00006000028f0018, func= Lambda in File NativeToJsBridge.cpp at Line 298) at RCTMessageThread.mm:68:20
    frame facebook#63: 0x000000010310e823 RNTester`facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1::operator()(this=0x0000600000538d88) const at RCTMessageThread.mm:81:19
    frame facebook#64: 0x000000010310e7c5 RNTester`decltype(std::declval<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1&>()()) std::__1::__invoke[abi:v160006]<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1&>(__f=0x0000600000538d88) at invoke.h:394:23
    frame facebook#65: 0x000000010310e785 RNTester`void std::__1::__invoke_void_return_wrapper<void, true>::__call<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1&>(__args=0x0000600000538d88) at invoke.h:487:9
    frame facebook#66: 0x000000010310e75d RNTester`std::__1::__function::__alloc_func<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1, std::__1::allocator<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1>, void ()>::operator()[abi:v160006](this=0x0000600000538d88) at function.h:185:16
    frame facebook#67: 0x000000010310d709 RNTester`std::__1::__function::__func<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1, std::__1::allocator<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1>, void ()>::operator()(this=0x0000600000538d80) at function.h:356:12
    frame facebook#68: 0x00000001030cdd72 RNTester`std::__1::__function::__value_func<void ()>::operator()[abi:v160006](this=0x00006000028fa690) const at function.h:510:16
    frame facebook#69: 0x00000001030cdd35 RNTester`std::__1::function<void ()>::operator()(this= Lambda in File RCTMessageThread.mm at Line 79) const at function.h:1156:12
    frame facebook#70: 0x000000010310a39a RNTester`invocation function for block in facebook::react::RCTMessageThread::runAsync(.block_descriptor=0x00006000028fa670) at RCTMessageThread.mm:44:7
    frame facebook#71: 0x00000001088b4b06 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
    frame facebook#72: 0x00000001088b42b9 CoreFoundation`__CFRunLoopDoBlocks + 391
    frame facebook#73: 0x00000001088af076 CoreFoundation`__CFRunLoopRun + 2186
    frame facebook#74: 0x00000001088ae409 CoreFoundation`CFRunLoopRunSpecific + 557
    frame facebook#75: 0x00000001030b6ec5 RNTester`+[RCTCxxBridge runRunLoop](self=RCTCxxBridge, _cmd="runRunLoop") at RCTCxxBridge.mm:332:12
    frame facebook#76: 0x000000010a377699 Foundation`__NSThread__start__ + 1024
    frame facebook#77: 0x000000010d5f4202 libsystem_pthread.dylib`_pthread_start + 99
    frame facebook#78: 0x000000010d5efbab libsystem_pthread.dylib`thread_start + 15
  thread facebook#10, name = 'hades'
    frame #0: 0x000000010d66a5d6 libsystem_kernel.dylib`__psynch_cvwait + 10
    frame facebook#1: 0x000000010d5f476b libsystem_pthread.dylib`_pthread_cond_wait + 1211
    frame facebook#2: 0x000000010761dfe2 libc++.1.dylib`std::__1::condition_variable::wait(std::__1::unique_lock<std::__1::mutex>&) + 18
    frame facebook#3: 0x00000001097aee78 hermes`hermes::vm::HadesGC::Executor::worker() [inlined] void std::__1::condition_variable::wait<hermes::vm::HadesGC::Executor::worker()::'lambda'()>(this=0x0000600003cb8300, __lk=0x0000700004358f20, __pred=(unnamed class) @ rbx) at __mutex_base:400:9 [opt]
    frame facebook#4: 0x00000001097aee5a hermes`hermes::vm::HadesGC::Executor::worker(this=0x0000600003cb82c0) at HadesGC.cpp:1084:11 [opt]
    frame facebook#5: 0x00000001097aedba hermes`void* std::__1::__thread_proxy[abi:v160006]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, hermes::vm::HadesGC::Executor::Executor()::'lambda'()>>(void*) [inlined] hermes::vm::HadesGC::Executor::Executor(this=0x00006000009a8ba8)::'lambda'()::operator()() const at HadesGC.cpp:1051:33 [opt]
    frame facebook#6: 0x00000001097aedb5 hermes`void* std::__1::__thread_proxy[abi:v160006]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, hermes::vm::HadesGC::Executor::Executor()::'lambda'()>>(void*) [inlined] decltype(std::declval<hermes::vm::HadesGC::Executor::Executor()::'lambda'()>()()) std::__1::__invoke[abi:v160006]<hermes::vm::HadesGC::Executor::Executor()::'lambda'()>(__f=0x00006000009a8ba8) at invoke.h:394:23 [opt]
    frame facebook#7: 0x00000001097aedb5 hermes`void* std::__1::__thread_proxy[abi:v160006]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, hermes::vm::HadesGC::Executor::Executor()::'lambda'()>>(void*) [inlined] void std::__1::__thread_execute[abi:v160006]<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, hermes::vm::HadesGC::Executor::Executor()::'lambda'()>(__t=size=2, (null)=<unavailable>) at thread:288:5 [opt]
    frame facebook#8: 0x00000001097aedb5 hermes`void* std::__1::__thread_proxy[abi:v160006]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, hermes::vm::HadesGC::Executor::Executor()::'lambda'()>>(__vp=0x00006000009a8ba0) at thread:299:5 [opt]
    frame facebook#9: 0x000000010d5f4202 libsystem_pthread.dylib`_pthread_start + 99
    frame facebook#10: 0x000000010d5efbab libsystem_pthread.dylib`thread_start + 15
  thread facebook#11, name = 'com.apple.CFStream.LegacyThread'
    frame #0: 0x000000010d667a2e libsystem_kernel.dylib`mach_msg2_trap + 10
    frame facebook#1: 0x000000010d675e4a libsystem_kernel.dylib`mach_msg2_internal + 84
    frame facebook#2: 0x000000010d66eb6e libsystem_kernel.dylib`mach_msg_overwrite + 653
    frame facebook#3: 0x000000010d667d1f libsystem_kernel.dylib`mach_msg + 19
    frame facebook#4: 0x00000001088b45bf CoreFoundation`__CFRunLoopServiceMachPort + 143
    frame facebook#5: 0x00000001088aed47 CoreFoundation`__CFRunLoopRun + 1371
    frame facebook#6: 0x00000001088ae409 CoreFoundation`CFRunLoopRunSpecific + 557
    frame facebook#7: 0x00000001088d1e34 CoreFoundation`_legacyStreamRunLoop_workThread + 251
    frame facebook#8: 0x000000010d5f4202 libsystem_pthread.dylib`_pthread_start + 99
    frame facebook#9: 0x000000010d5efbab libsystem_pthread.dylib`thread_start + 15
  thread facebook#12, name = 'com.facebook.SocketRocket.NetworkThread'
    frame #0: 0x000000010d667a2e libsystem_kernel.dylib`mach_msg2_trap + 10
    frame facebook#1: 0x000000010d675e4a libsystem_kernel.dylib`mach_msg2_internal + 84
    frame facebook#2: 0x000000010d66eb6e libsystem_kernel.dylib`mach_msg_overwrite + 653
    frame facebook#3: 0x000000010d667d1f libsystem_kernel.dylib`mach_msg + 19
    frame facebook#4: 0x00000001088b45bf CoreFoundation`__CFRunLoopServiceMachPort + 143
    frame facebook#5: 0x00000001088aed47 CoreFoundation`__CFRunLoopRun + 1371
    frame facebook#6: 0x00000001088ae409 CoreFoundation`CFRunLoopRunSpecific + 557
    frame facebook#7: 0x000000010a34ceee Foundation`-[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 213
    frame facebook#8: 0x000000010381a49b RNTester`-[SRRunLoopThread main](self=0x00006000028e80f0, _cmd="main") at SRRunLoopThread.m:71:16
    frame facebook#9: 0x000000010a377699 Foundation`__NSThread__start__ + 1024
    frame facebook#10: 0x000000010d5f4202 libsystem_pthread.dylib`_pthread_start + 99
    frame facebook#11: 0x000000010d5efbab libsystem_pthread.dylib`thread_start + 15
  thread facebook#13
    frame #0: 0x000000010d5efb88 libsystem_pthread.dylib`start_wqthread
  thread facebook#14, name = 'com.apple.NSURLConnectionLoader'
    frame #0: 0x000000010d667a2e libsystem_kernel.dylib`mach_msg2_trap + 10
    frame facebook#1: 0x000000010d675e4a libsystem_kernel.dylib`mach_msg2_internal + 84
    frame facebook#2: 0x000000010d66eb6e libsystem_kernel.dylib`mach_msg_overwrite + 653
    frame facebook#3: 0x000000010d667d1f libsystem_kernel.dylib`mach_msg + 19
    frame facebook#4: 0x00000001088b45bf CoreFoundation`__CFRunLoopServiceMachPort + 143
    frame facebook#5: 0x00000001088aed47 CoreFoundation`__CFRunLoopRun + 1371
    frame facebook#6: 0x00000001088ae409 CoreFoundation`CFRunLoopRunSpecific + 557
    frame facebook#7: 0x00000001093cf78b CFNetwork`___lldb_unnamed_symbol13826 + 444
    frame facebook#8: 0x000000010a377699 Foundation`__NSThread__start__ + 1024
    frame facebook#9: 0x000000010d5f4202 libsystem_pthread.dylib`_pthread_start + 99
    frame facebook#10: 0x000000010d5efbab libsystem_pthread.dylib`thread_start + 15
  thread facebook#15, name = 'com.apple.CFSocket.private'
    frame #0: 0x000000010d670922 libsystem_kernel.dylib`__select + 10
    frame facebook#1: 0x00000001088c2dcf CoreFoundation`__CFSocketManager + 643
    frame facebook#2: 0x000000010d5f4202 libsystem_pthread.dylib`_pthread_start + 99
    frame facebook#3: 0x000000010d5efbab libsystem_pthread.dylib`thread_start + 15
```

## Changelog:

[IOS] [FIXED] - Fix module create dead-lock when start-up

Pull Request resolved: facebook#41194

Test Plan: Null.

Reviewed By: javache

Differential Revision: D50800290

Pulled By: sammy-SC

fbshipit-source-id: b60b8e0681cbec7b7aa8812188c9f7ea5f03966b
Othinn pushed a commit to Othinn/react-native that referenced this pull request Jan 9, 2024
Summary:
Pull Request resolved: facebook#41466

## Context
In open source, all apps use the same turbomodulemanager delegate (i.e: the default delegate).

This diff introduces the buck infra that makes the oss default delegate work for meta apps.

Concretely, we are going to make React Native use the same  delegate for **all** Meta apps.

Each Meta app will:
1. At build time, generate a unique TMProvider map
2. At app init time, initialize the default delegate with the TMProvider map.

## Implementation
**Step facebook#1:** At build time, generate a unique TMProvider map

**Insight:** Buck genrules can accept, as input, the output of a buck query.

So, here's how we get this done:
1. Buck query (i.e: input to Genrule): Given the app's deps, query all the schemas in the app.
2. Genrule: Read the schemas to generate the TMProvider map. The TMProvider map will also contain **all** the app's C++ module codegen.

Concretely:
1. This diff introduces a macro: rn_codegen_appmodules(deps).
2. rn_codegen_appmodules(deps) generates appmodules.so, which contains the TMProvider map.

**Step facebook#2:** At app init time, initialize the default delegate with the TMProvider map.

This is how we'll initialize the DefaultTurboModuleManagerDelegate:
1. DefaultTurboModuleManagerDelegate will load appmodules.so during init.
2. When loaded, appmodules.so will assign the code-generated TMProvider map to DefaultTurboModuleManagerDelegate.

## Impact
This should allow us to:
1. Get one step closer to getting rid of the `js1 build turbomodule-manager-delegates --target <app>` script
3. Remove the TurboModuleManagerDelegate from React Native's public API. (Because we use one delegate for all React Native apps in Meta and OSS)

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D50988397

fbshipit-source-id: 0ca5dec14e2dae89ec97f5d39a182c7937c5c7bf
motiz88 added a commit to motiz88/react-native that referenced this pull request Feb 14, 2024
…gets

Summary:
Changelog: [Internal]

# This diff

1. Provides all Targets with an `executorFromThis()` method, which can be used from within a Target to access a *`this`-scoped main thread executor* = a `std::function` that will execute a callback asynchronously iff the current Target isn't destroyed first.
2. Refactors how (all) Target objects are constructed and retained, from a plain constructor to `static shared_ptr create()`. This is because `executorFromThis()` relies internally on `enable_shared_from_this` plus two-phase construction to populate the executor.
3. Creates utilities for deriving scoped executors from other executors and `shared_ptr`s.

The concept is very much like `RuntimeExecutor` in reverse: the facebook#1 use case is moving from the JS thread back to the main thread - where "main thread" is defined loosely as "anywhere it's legal to call methods on Target/Agent objects, access session state, etc". The actual dispatching mechanism is left up to the owner of each `PageTarget` object; for now we only have an iOS integration, where we use `RCTExecuteOnMainQueue`.

Coupling the ownership/lifetime semantics with task scheduling is helpful, because it avoids the footgun of accidentally/nondeterministically moving `shared_ptr`s (and destructors!) to a different thread/queue .

# This stack
I'm refactoring the way the Runtime concept works in the modern CDP backend to bring it in line with the Page/Instance concepts.

Overall, this will let us:

* Integrate with engines that require us to instantiate a shared Target-like object (e.g. Hermes AsyncDebuggingAPI) in addition to an per-session Agent-like object.
* Access JSI in a CDP context (both at target setup/teardown time and during a CDP session) to implement our own engine-agnostic functionality (`console` interception, `Runtime.addBinding`, etc).
* Manage CDP execution contexts natively in RN, and (down the line) enable first-class debugging support for multiple Runtimes in an Instance.

The core diffs in this stack:

* ~~Introduce a `RuntimeTarget` class similar to `{Page,Instance}Target`. ~~
* ~~Make runtime registration explicit (`InstanceTarget::registerRuntime` similar to `PageTarget::registerInstance`). ~~
* ~~Rename the existing `RuntimeAgent` interface to `RuntimeAgentDelegate`.~~
* ~~Create a new concrete `RuntimeAgent` class similar to `{Page,Instance}Agent`.~~
* ~~Provide `RuntimeTarget` and `RuntimeAgent` with primitives for safe JSI access, namely a `RuntimeExecutor` for scheduling work on the JS thread.~~
  * Provide RuntimeTarget with mechanism for scheduling work on the "main" thread from the JS thread, for when we need to do more than just send a CDP message (which we can already do with the thread-safe `FrontendChannel`) in response to a JS event. *← This diff*

## Architecture diagrams

Before this stack:
https://pxl.cl/4h7m0

After this stack:
https://pxl.cl/4h7m7

Reviewed By: hoxyq

Differential Revision: D53356953

fbshipit-source-id: 57f49d5b5575d361fad1c3fede5cdce1931290d6
motiz88 added a commit to motiz88/react-native that referenced this pull request Feb 14, 2024
…gets

Summary:
Changelog: [Internal]

# This diff

1. Provides all Targets with an `executorFromThis()` method, which can be used from within a Target to access a *`this`-scoped main thread executor* = a `std::function` that will execute a callback asynchronously iff the current Target isn't destroyed first.
2. Refactors how (all) Target objects are constructed and retained, from a plain constructor to `static shared_ptr create()`. This is because `executorFromThis()` relies internally on `enable_shared_from_this` plus two-phase construction to populate the executor.
3. Creates utilities for deriving scoped executors from other executors and `shared_ptr`s.

The concept is very much like `RuntimeExecutor` in reverse: the facebook#1 use case is moving from the JS thread back to the main thread - where "main thread" is defined loosely as "anywhere it's legal to call methods on Target/Agent objects, access session state, etc". The actual dispatching mechanism is left up to the owner of each `PageTarget` object; for now we only have an iOS integration, where we use `RCTExecuteOnMainQueue`.

Coupling the ownership/lifetime semantics with task scheduling is helpful, because it avoids the footgun of accidentally/nondeterministically moving `shared_ptr`s (and destructors!) to a different thread/queue .

# This stack
I'm refactoring the way the Runtime concept works in the modern CDP backend to bring it in line with the Page/Instance concepts. 

Overall, this will let us:

* Integrate with engines that require us to instantiate a shared Target-like object (e.g. Hermes AsyncDebuggingAPI) in addition to an per-session Agent-like object.
* Access JSI in a CDP context (both at target setup/teardown time and during a CDP session) to implement our own engine-agnostic functionality (`console` interception, `Runtime.addBinding`, etc).
* Manage CDP execution contexts natively in RN, and (down the line) enable first-class debugging support for multiple Runtimes in an Instance.

The core diffs in this stack:

* ~~Introduce a `RuntimeTarget` class similar to `{Page,Instance}Target`. ~~
* ~~Make runtime registration explicit (`InstanceTarget::registerRuntime` similar to `PageTarget::registerInstance`). ~~
* ~~Rename the existing `RuntimeAgent` interface to `RuntimeAgentDelegate`.~~
* ~~Create a new concrete `RuntimeAgent` class similar to `{Page,Instance}Agent`.~~
* ~~Provide `RuntimeTarget` and `RuntimeAgent` with primitives for safe JSI access, namely a `RuntimeExecutor` for scheduling work on the JS thread.~~ 
  * Provide RuntimeTarget with mechanism for scheduling work on the "main" thread from the JS thread, for when we need to do more than just send a CDP message (which we can already do with the thread-safe `FrontendChannel`) in response to a JS event. *← This diff*

## Architecture diagrams

Before this stack:
https://pxl.cl/4h7m0

After this stack:
https://pxl.cl/4h7m7

Reviewed By: hoxyq

Differential Revision: D53356953
motiz88 added a commit to motiz88/react-native that referenced this pull request Feb 14, 2024
…to all Targets

Summary:
Changelog: [Internal]

# This diff

1. Provides all Targets with an `executorFromThis()` method, which can be used from within a Target to access a *`this`-scoped main thread executor* = a `std::function` that will execute a callback asynchronously iff the current Target isn't destroyed first.
2. Refactors how (all) Target objects are constructed and retained, from a plain constructor to `static shared_ptr create()`. This is because `executorFromThis()` relies internally on `enable_shared_from_this` plus two-phase construction to populate the executor.
3. Creates utilities for deriving scoped executors from other executors and `shared_ptr`s.

The concept is very much like `RuntimeExecutor` in reverse: the facebook#1 use case is moving from the JS thread back to the main thread - where "main thread" is defined loosely as "anywhere it's legal to call methods on Target/Agent objects, access session state, etc". The actual dispatching mechanism is left up to the owner of each `PageTarget` object; for now we only have an iOS integration, where we use `RCTExecuteOnMainQueue`.

Coupling the ownership/lifetime semantics with task scheduling is helpful, because it avoids the footgun of accidentally/nondeterministically moving `shared_ptr`s (and destructors!) to a different thread/queue .

# This stack
I'm refactoring the way the Runtime concept works in the modern CDP backend to bring it in line with the Page/Instance concepts. 

Overall, this will let us:

* Integrate with engines that require us to instantiate a shared Target-like object (e.g. Hermes AsyncDebuggingAPI) in addition to an per-session Agent-like object.
* Access JSI in a CDP context (both at target setup/teardown time and during a CDP session) to implement our own engine-agnostic functionality (`console` interception, `Runtime.addBinding`, etc).
* Manage CDP execution contexts natively in RN, and (down the line) enable first-class debugging support for multiple Runtimes in an Instance.

The core diffs in this stack:

* ~~Introduce a `RuntimeTarget` class similar to `{Page,Instance}Target`. ~~
* ~~Make runtime registration explicit (`InstanceTarget::registerRuntime` similar to `PageTarget::registerInstance`). ~~
* ~~Rename the existing `RuntimeAgent` interface to `RuntimeAgentDelegate`.~~
* ~~Create a new concrete `RuntimeAgent` class similar to `{Page,Instance}Agent`.~~
* ~~Provide `RuntimeTarget` and `RuntimeAgent` with primitives for safe JSI access, namely a `RuntimeExecutor` for scheduling work on the JS thread.~~ 
  * Provide RuntimeTarget with mechanism for scheduling work on the "main" thread from the JS thread, for when we need to do more than just send a CDP message (which we can already do with the thread-safe `FrontendChannel`) in response to a JS event. *← This diff*

## Architecture diagrams

Before this stack:
https://pxl.cl/4h7m0

After this stack:
https://pxl.cl/4h7m7

Reviewed By: hoxyq

Differential Revision: D53356953
facebook-github-bot pushed a commit that referenced this pull request Feb 14, 2024
…gets

Summary:
Changelog: [Internal]

# This diff

1. Provides all Targets with an `executorFromThis()` method, which can be used from within a Target to access a *`this`-scoped main thread executor* = a `std::function` that will execute a callback asynchronously iff the current Target isn't destroyed first.
2. Refactors how (all) Target objects are constructed and retained, from a plain constructor to `static shared_ptr create()`. This is because `executorFromThis()` relies internally on `enable_shared_from_this` plus two-phase construction to populate the executor.
3. Creates utilities for deriving scoped executors from other executors and `shared_ptr`s.

The concept is very much like `RuntimeExecutor` in reverse: the #1 use case is moving from the JS thread back to the main thread - where "main thread" is defined loosely as "anywhere it's legal to call methods on Target/Agent objects, access session state, etc". The actual dispatching mechanism is left up to the owner of each `PageTarget` object; for now we only have an iOS integration, where we use `RCTExecuteOnMainQueue`.

Coupling the ownership/lifetime semantics with task scheduling is helpful, because it avoids the footgun of accidentally/nondeterministically moving `shared_ptr`s (and destructors!) to a different thread/queue .

# This stack
I'm refactoring the way the Runtime concept works in the modern CDP backend to bring it in line with the Page/Instance concepts.

Overall, this will let us:

* Integrate with engines that require us to instantiate a shared Target-like object (e.g. Hermes AsyncDebuggingAPI) in addition to an per-session Agent-like object.
* Access JSI in a CDP context (both at target setup/teardown time and during a CDP session) to implement our own engine-agnostic functionality (`console` interception, `Runtime.addBinding`, etc).
* Manage CDP execution contexts natively in RN, and (down the line) enable first-class debugging support for multiple Runtimes in an Instance.

The core diffs in this stack:

* ~~Introduce a `RuntimeTarget` class similar to `{Page,Instance}Target`. ~~
* ~~Make runtime registration explicit (`InstanceTarget::registerRuntime` similar to `PageTarget::registerInstance`). ~~
* ~~Rename the existing `RuntimeAgent` interface to `RuntimeAgentDelegate`.~~
* ~~Create a new concrete `RuntimeAgent` class similar to `{Page,Instance}Agent`.~~
* ~~Provide `RuntimeTarget` and `RuntimeAgent` with primitives for safe JSI access, namely a `RuntimeExecutor` for scheduling work on the JS thread.~~
  * Provide RuntimeTarget with mechanism for scheduling work on the "main" thread from the JS thread, for when we need to do more than just send a CDP message (which we can already do with the thread-safe `FrontendChannel`) in response to a JS event. *← This diff*

## Architecture diagrams

Before this stack:
https://pxl.cl/4h7m0

After this stack:
https://pxl.cl/4h7m7

Reviewed By: hoxyq

Differential Revision: D53356953

fbshipit-source-id: 152c784eb64e9b217fc2966743b33f61bd8fd97e
facebook-github-bot pushed a commit that referenced this pull request Jul 16, 2024
…geLoader` (#45454)

Summary:
When running the entire unit test suite of `RNTesterPods` with `TSan`, I saw that occasionally a data race was detected on line 843 of `RCTImageLoader`. It seems the completion handler that does contain the lock around `cancelLoad` is called concurrently with the value being assigned on line 843. Here there is no lock in place.

Here is the output of `TSan` when I comment out my fix:
```
WARNING: ThreadSanitizer: data race (pid=72490)
  Write of size 8 at 0x000144151ce8 by main thread:
    #0 -[RCTImageLoader loadImageWithURLRequest:size:scale:clipped:resizeMode:priority:attribution:progressBlock:partialLoadBlock:completionBlock:] <null> (RNTesterUnitTests:arm64+0x16e8030)
    #1 -[RCTImageLoader loadImageWithURLRequest:size:scale:clipped:resizeMode:priority:progressBlock:partialLoadBlock:completionBlock:] <null> (RNTesterUnitTests:arm64+0x16df8dc)
    #2 -[RCTImageLoader loadImageWithURLRequest:size:scale:clipped:resizeMode:progressBlock:partialLoadBlock:completionBlock:] <null> (RNTesterUnitTests:arm64+0x16df534)
    #3 -[RCTImageLoaderTests testImageLoaderUsesImageURLLoaderWithHighestPriority] <null> (RNTesterUnitTests:arm64+0x7cb8)
    #4 __invoking___ <null> (CoreFoundation:arm64+0x13371c)

  Previous write of size 8 at 0x000144151ce8 by thread T4 (mutexes: write M0):
    #0 __140-[RCTImageLoader loadImageWithURLRequest:size:scale:clipped:resizeMode:priority:attribution:progressBlock:partialLoadBlock:completionBlock:]_block_invoke_2 <null> (RNTesterUnitTests:arm64+0x16e8894)
    #1 __139-[RCTImageLoader _loadImageOrDataWithURLRequest:size:scale:resizeMode:priority:attribution:progressBlock:partialLoadBlock:completionBlock:]_block_invoke <null> (RNTesterUnitTests:arm64+0x16e3430)
    #2 __139-[RCTImageLoader _loadImageOrDataWithURLRequest:size:scale:resizeMode:priority:attribution:progressBlock:partialLoadBlock:completionBlock:]_block_invoke_3 <null> (RNTesterUnitTests:arm64+0x16e52a8)
    #3 __75-[RCTImageLoaderTests testImageLoaderUsesImageURLLoaderWithHighestPriority]_block_invoke_2 <null> (RNTesterUnitTests:arm64+0x7f24)
    #4 -[RCTConcreteImageURLLoader loadImageForURL:size:scale:resizeMode:progressHandler:partialLoadHandler:completionHandler:] <null> (RNTesterUnitTests:arm64+0x6c470)
    #5 __139-[RCTImageLoader _loadImageOrDataWithURLRequest:size:scale:resizeMode:priority:attribution:progressBlock:partialLoadBlock:completionBlock:]_block_invoke.172 <null> (RNTesterUnitTests:arm64+0x16e4964)
    #6 __tsan::invoke_and_release_block(void*) <null> (libclang_rt.tsan_iossim_dynamic.dylib:arm64+0x77ee0)
    #7 _dispatch_client_callout <null> (libdispatch.dylib:arm64+0x3974)

  Location is heap block of size 48 at 0x000144151cc0 allocated by main thread:
    #0 malloc <null> (libclang_rt.tsan_iossim_dynamic.dylib:arm64+0x4fa48)
    #1 _malloc_type_malloc_outlined <null> (libsystem_malloc.dylib:arm64+0xf3ec)
    #2 _call_copy_helpers_excp <null> (libsystem_blocks.dylib:arm64+0x10b4)
    #3 -[RCTImageLoader loadImageWithURLRequest:size:scale:clipped:resizeMode:priority:progressBlock:partialLoadBlock:completionBlock:] <null> (RNTesterUnitTests:arm64+0x16df8dc)
    #4 -[RCTImageLoader loadImageWithURLRequest:size:scale:clipped:resizeMode:progressBlock:partialLoadBlock:completionBlock:] <null> (RNTesterUnitTests:arm64+0x16df534)
    #5 -[RCTImageLoaderTests testImageLoaderUsesImageURLLoaderWithHighestPriority] <null> (RNTesterUnitTests:arm64+0x7cb8)
    #6 __invoking___ <null> (CoreFoundation:arm64+0x13371c)

  Mutex M0 (0x000108f316e8) created at:
    #0 pthread_mutex_init <null> (libclang_rt.tsan_iossim_dynamic.dylib:arm64+0x2cc98)
    #1 -[NSLock init] <null> (Foundation:arm64+0x5ca14c)
    #2 -[RCTImageLoader loadImageWithURLRequest:size:scale:clipped:resizeMode:priority:progressBlock:partialLoadBlock:completionBlock:] <null> (RNTesterUnitTests:arm64+0x16df8dc)
    #3 -[RCTImageLoader loadImageWithURLRequest:size:scale:clipped:resizeMode:progressBlock:partialLoadBlock:completionBlock:] <null> (RNTesterUnitTests:arm64+0x16df534)
    #4 -[RCTImageLoaderTests testImageLoaderUsesImageURLLoaderWithHighestPriority] <null> (RNTesterUnitTests:arm64+0x7cb8)
    #5 __invoking___ <null> (CoreFoundation:arm64+0x13371c)

  Thread T4 (tid=10935088, running) is a GCD worker thread
```

## Changelog:

[iOS][Fixed] Data race in `RCTImageLoader` related to assignment of cancellation block.

Pull Request resolved: #45454

Test Plan: There are already tests in place for `RCTImageLoader`. I hope these will cover the fix.

Reviewed By: realsoelynn

Differential Revision: D59816000

Pulled By: zeyap

fbshipit-source-id: f959d472eb60f83f39ced6711ee395949ab37e7c
facebook-github-bot pushed a commit that referenced this pull request Jul 25, 2024
Summary:
As explained in #45280, `TSan` picks up data races related to concurrent read/write to fields in `RCTCxxBridge`. See this report for reference:
```
WARNING: ThreadSanitizer: data race (pid=19983)
  Write of size 1 at 0x00010af1dfd8 by thread T13:
    #0 -[RCTCxxBridge _flushPendingCalls] <null> (RNTesterUnitTests:arm64+0x42b484)
    #1 __53-[RCTCxxBridge executeSourceCode:withSourceURL:sync:]_block_invoke <null> (RNTesterUnitTests:arm64+0x426050)
    #2 decltype(std::declval<void () block_pointer __strong&>()()) std::__1::__invoke[abi:ue170006]<void () block_pointer __strong&>(&&, decltype(std::declval<void () block_pointer __strong&>()())&&...) <null> (RNTesterUnitTests:arm64+0x456298)
    #3 std::__1::__function::__func<void () block_pointer __strong, std::__1::allocator<std::__1::allocator>, void ()>::operator()() <null> (RNTesterUnitTests:arm64+0x455c6c)
    #4 std::__1::__function::__value_func<void ()>::operator()[abi:ue170006]() const <null> (RNTesterUnitTests:arm64+0x3ce2e4)
    #5 std::__1::function<void ()>::operator()() const <null> (RNTesterUnitTests:arm64+0x3cdfd0)
    #6 facebook::react::tryAndReturnError(std::__1::function<void ()> const&) <null> (RNTesterUnitTests:arm64+0x4af18c)
    #7 facebook::react::RCTMessageThread::tryFunc(std::__1::function<void ()> const&) <null> (RNTesterUnitTests:arm64+0x51595c)
    #8 facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1::operator()() const <null> (RNTesterUnitTests:arm64+0x529df0)
    #9 decltype(std::declval<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1&>()()) std::__1::__invoke[abi:ue170006]<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1&>(facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1&) <null> (RNTesterUnitTests:arm64+0x529b54)
    #10 void std::__1::__invoke_void_return_wrapper<void, true>::__call[abi:ue170006]<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1&>(facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1&) <null> (RNTesterUnitTests:arm64+0x529978)
    #11 std::__1::__function::__alloc_func<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1, std::__1::allocator<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1>, void ()>::operator()[abi:ue170006]() <null> (RNTesterUnitTests:arm64+0x5298dc)
    #12 std::__1::__function::__func<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1, std::__1::allocator<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1>, void ()>::operator()() <null> (RNTesterUnitTests:arm64+0x524518)
    #13 std::__1::__function::__value_func<void ()>::operator()[abi:ue170006]() const <null> (RNTesterUnitTests:arm64+0x3ce2e4)
    #14 std::__1::function<void ()>::operator()() const <null> (RNTesterUnitTests:arm64+0x3cdfd0)
    #15 invocation function for block in facebook::react::RCTMessageThread::runAsync(std::__1::function<void ()>) <null> (RNTesterUnitTests:arm64+0x515384)
    #16 __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ <null> (CoreFoundation:arm64+0x8dc0c)
    #17 __NSThread__start__ <null> (Foundation:arm64+0x645c60)

  Previous read of size 1 at 0x00010af1dfd8 by main thread:
    #0 -[RCTCxxBridge isLoading] <null> (RNTesterUnitTests:arm64+0x43236c)
    #1 -[RCTBridge isLoading] <null> (RNTesterUnitTests:arm64+0x3c0170)
    #2 -[RCTComponentPropsTests setUp] <null> (RNTesterUnitTests:arm64+0xe6f34)
    #3 __70-[XCTestCase _shouldContinueAfterPerformingSetUpSequenceWithSelector:]_block_invoke.134 <null> (XCTestCore:arm64+0x540d8)

  Location is heap block of size 384 at 0x00010af1de80 allocated by main thread:
    #0 calloc <null> (libclang_rt.tsan_iossim_dynamic.dylib:arm64+0x4fc30)
    #1 _malloc_type_calloc_outlined <null> (libsystem_malloc.dylib:arm64+0xf488)
    #2 -[RCTBridge initWithDelegate:bundleURL:moduleProvider:launchOptions:] <null> (RNTesterUnitTests:arm64+0x3bc540)
    #3 -[RCTBridge initWithBundleURL:moduleProvider:launchOptions:] <null> (RNTesterUnitTests:arm64+0x3bc124)
    #4 -[RCTComponentPropsTests setUp] <null> (RNTesterUnitTests:arm64+0xe6b3c)
    #5 __70-[XCTestCase _shouldContinueAfterPerformingSetUpSequenceWithSelector:]_block_invoke.134 <null> (XCTestCore:arm64+0x540d8)

  Thread T13 (tid=11290378, running) created by main thread at:
    #0 pthread_create <null> (libclang_rt.tsan_iossim_dynamic.dylib:arm64+0x2bee4)
    #1 -[NSThread startAndReturnError:] <null> (Foundation:arm64+0x6458f0)
    #2 -[RCTBridge setUp] <null> (RNTesterUnitTests:arm64+0x3bf748)
    #3 -[RCTBridge initWithDelegate:bundleURL:moduleProvider:launchOptions:] <null> (RNTesterUnitTests:arm64+0x3bc540)
    #4 -[RCTBridge initWithBundleURL:moduleProvider:launchOptions:] <null> (RNTesterUnitTests:arm64+0x3bc124)
    #5 -[RCTComponentPropsTests setUp] <null> (RNTesterUnitTests:arm64+0xe6b3c)
    #6 __70-[XCTestCase _shouldContinueAfterPerformingSetUpSequenceWithSelector:]_block_invoke.134 <null> (XCTestCore:arm64+0x540d8)
```

In order to fix the data races, `std::atomic` instead of primitive boolean types.

In order to reproduce my findings and verify fix:

* Clone this branch
* Run setup code as described in README
* Execute `git revert -n 11c09fd`.
* Enable TSan for both RNTester and its test scheme.
* Enable Runtime issue breakpoint for TSan
* Run unit tests
* Observe the TSan breakpoint is hit (possibly other places in the codebase as well) when accessing `_loading`, `_moduleRegistryCreated`, and `_valid`.. Continue execution if other breakpoints are hit before this breakpoint.
* Execute git revert --abort
* Run the tests again and observe the TSan breakpoint does not hit said code again.

NB! While this will fix data races, it will not fix potential race conditions. I have not encountered bugs related to race conditions in `RCTCxxBridge`, but given the nature of how it is made use of concurrently, it is, in my opinion, plausible.

## Changelog:

[iOS][Fixed] Use std::atomic for eliminating races in RCTCxxBridge.

Pull Request resolved: #45558

Test Plan: I believe there are existing Unit tests in place for verifying this fix.

Reviewed By: cipolleschi

Differential Revision: D60233758

Pulled By: dmytrorykun

fbshipit-source-id: 8aa124a0521ad43a5e17b42e0ce6d22ae6b4e667
facebook-github-bot pushed a commit that referenced this pull request Aug 2, 2024
Summary:
In fabric bridgeless mode, when we reload, main thread may block because of dead lock. the backtrace example as below:

```
(lldb) bt
* thread #1, stop reason = signal SIGSTOP
  * frame #0: 0x000000010a5c76f2 libsystem_kernel.dylib`__psynch_mutexwait + 10
    frame #1: 0x00000001099e0a70 libsystem_pthread.dylib`_pthread_mutex_firstfit_lock_wait + 78
    frame #2: 0x00000001099de82b libsystem_pthread.dylib`_pthread_mutex_firstfit_lock_slow + 217
    frame #3: 0x00007ff80030c6b9 libc++.1.dylib`std::__1::mutex::lock() + 9
    frame #4: 0x0000000106968b13 RNTester`std::__1::lock_guard<std::__1::mutex>::lock_guard[abi:ue170006](this=0x00007ff7b95e2478, __m=0x000060000377c958) at lock_guard.h:35:10
    frame #5: 0x00000001069689ed RNTester`std::__1::lock_guard<std::__1::mutex>::lock_guard[abi:ue170006](this=0x00007ff7b95e2478, __m=0x000060000377c958) at lock_guard.h:34:19
    frame #6: 0x00000001070691c1 RNTester`-[RCTInstance invalidate](self=0x000060000377c900, _cmd="invalidate") at RCTInstance.mm:146:31
    frame #7: 0x0000000107060fd2 RNTester`-[RCTHost didReceiveReloadCommand](self=0x0000600003d100f0, _cmd="didReceiveReloadCommand") at RCTHost.mm:317:3
    frame #8: 0x0000000106b005a5 RNTester`RCTTriggerReloadCommandListeners(reason=@"Global hotkey") at RCTReloadCommand.m:57:5
    frame #9: 0x0000000106b86da5 RNTester`__28-[RCTDevSettings initialize]_block_invoke.157(.block_descriptor=0x0000000107496170, params=0x00007ff84002f610) at RCTDevSettings.mm:201:11
    frame #10: 0x0000000106ae658e RNTester`__65-[RCTPackagerConnection reconnectingWebSocket:didReceiveMessage:]_block_invoke.68(.block_descriptor=0x0000600000c82df0) at RCTPackagerConnection.mm:293:9
    frame #11: 0x0000000109a4529d libdispatch.dylib`_dispatch_call_block_and_release + 12
    frame #12: 0x0000000109a4658f libdispatch.dylib`_dispatch_client_callout + 8
    frame #13: 0x0000000109a563ee libdispatch.dylib`_dispatch_main_queue_drain + 1362
    frame #14: 0x0000000109a55e8e libdispatch.dylib`_dispatch_main_queue_callback_4CF + 31
    frame #15: 0x00007ff800429af4 CoreFoundation`__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
    frame #16: 0x00007ff80042442f CoreFoundation`__CFRunLoopRun + 2463
    frame #17: 0x00007ff8004236ad CoreFoundation`CFRunLoopRunSpecific + 557
    frame #18: 0x00007ff8103da08f GraphicsServices`GSEventRunModal + 137
    frame #19: 0x00007ff805cc0ad1 UIKitCore`-[UIApplication _run] + 972
    frame #20: 0x00007ff805cc5551 UIKitCore`UIApplicationMain + 123
    frame #21: 0x00000001069205a0 RNTester`main(argc=1, argv=0x00007ff7b95e3b60) at main.m:15:12
    frame #22: 0x00000001099023e0 dyld_sim`start_sim + 10
    frame #23: 0x0000000116b92366 dyld`start + 1942

(lldb) bt
* thread #3
    frame #0: 0x000000010a5c6b86 libsystem_kernel.dylib`__ulock_wait + 10
    frame #1: 0x0000000109a46eb1 libdispatch.dylib`_dlock_wait + 46
    frame #2: 0x0000000109a46d08 libdispatch.dylib`_dispatch_thread_event_wait_slow + 40
    frame #3: 0x0000000109a5774a libdispatch.dylib`__DISPATCH_WAIT_FOR_QUEUE__ + 371
    frame #4: 0x0000000109a57161 libdispatch.dylib`_dispatch_sync_f_slow + 240
    frame #5: 0x0000000106b3b33b RNTester`RCTUnsafeExecuteOnMainQueueSync(block=0x0000000106f116c0) at RCTUtils.m:291:5
  * frame #6: 0x0000000106f115ad RNTester`-[RCTFabricSurface start](self=0x000000010af0df40, _cmd="start") at RCTFabricSurface.mm:102:3
    frame #7: 0x00000001070601ce RNTester`__108-[RCTHost initWithBundleURLProvider:hostDelegate:turboModuleManagerDelegate:jsEngineProvider:launchOptions:]_block_invoke_2(.block_descriptor=0x0000600000c75590) at RCTHost.mm:211:9
    frame #8: 0x000000010706cdc8 RNTester`-[RCTInstance _loadScriptFromSource:](self=0x000060000377c900, _cmd="_loadScriptFromSource:", source=0x0000600000cd57d0) at RCTInstance.mm:472:5
    frame #9: 0x000000010706ca81 RNTester`__29-[RCTInstance _loadJSBundle:]_block_invoke.120(.block_descriptor=0x0000600000c96d00, error=0x0000000000000000, source=0x0000600000cd57d0) at RCTInstance.mm:452:9
    frame #10: 0x0000000106ab1919 RNTester`invocation function for block in attemptAsynchronousLoadOfBundleAtURL(.block_descriptor=0x00006000017b0fc0, statusCode=200, headers=6 key/value pairs, data=0x00006000002a4760, error=0x0000000000000000, done=YES) block_pointer, void (NSError*, RCTSource*) block_pointer) at RCTJavaScriptLoader.mm:318:9
    frame #11: 0x0000000106ad92a6 RNTester`__80-[RCTMultipartDataTask URLSession:streamTask:didBecomeInputStream:outputStream:]_block_invoke(.block_descriptor=0x000070000035c7a0, headers=6 key/value pairs, content=0x00006000002a4760, done=YES) at RCTMultipartDataTask.m:121:9
    frame #12: 0x0000000106ad9b4f RNTester`-[RCTMultipartStreamReader emitChunk:headers:callback:done:](self=0x00006000002b4220, _cmd="emitChunk:headers:callback:done:", data=0x00006000002a4020, headers=6 key/value pairs, callback=0x0000000106ad9230, done=YES) at RCTMultipartStreamReader.m:57:5
    frame #13: 0x0000000106ada800 RNTester`-[RCTMultipartStreamReader readAllPartsWithCompletionCallback:progressCallback:](self=0x00006000002b4220, _cmd="readAllPartsWithCompletionCallback:progressCallback:", callback=0x0000000106ad9230, progressCallback=0x0000000106ab2a60) at RCTMultipartStreamReader.m:154:7
    frame #14: 0x0000000106ad9130 RNTester`-[RCTMultipartDataTask URLSession:streamTask:didBecomeInputStream:outputStream:](self=0x00006000017b0d40, _cmd="URLSession:streamTask:didBecomeInputStream:outputStream:", session=0x000000010e02a0a0, streamTask=0x000000010c83ba00, inputStream=0x000060000300d4d0, outputStream=0x000060000300c990) at RCTMultipartDataTask.m:119:20
    frame #15: 0x00007ff80479fdf9 CFNetwork`___lldb_unnamed_symbol2876 + 42
    frame #16: 0x0000000109a4529d libdispatch.dylib`_dispatch_call_block_and_release + 12
    frame #17: 0x0000000109a4658f libdispatch.dylib`_dispatch_client_callout + 8
    frame #18: 0x0000000109a4e4ba libdispatch.dylib`_dispatch_lane_serial_drain + 1127
    frame #19: 0x0000000109a4f255 libdispatch.dylib`_dispatch_lane_invoke + 441
    frame #20: 0x0000000109a5c356 libdispatch.dylib`_dispatch_root_queue_drain_deferred_wlh + 318
    frame #21: 0x0000000109a5b751 libdispatch.dylib`_dispatch_workloop_worker_thread + 590
    frame #22: 0x00000001099dfb84 libsystem_pthread.dylib`_pthread_wqthread + 327
    frame #23: 0x00000001099deacf libsystem_pthread.dylib`start_wqthread + 15
```

## Changelog:

[IOS] [FIXED] - Fixes main thread stuck when reload in bridgeless mode

Pull Request resolved: #45486

Test Plan: RNTester, enables fabric, which is very easy to repro by tapping `r`  command multiple times quickly to trigger reload.

Reviewed By: philIip

Differential Revision: D59911929

Pulled By: cipolleschi

fbshipit-source-id: e7e431a11d26c399fa767b6cbf45e16bce24b9a0
facebook-github-bot pushed a commit that referenced this pull request Aug 12, 2024
…#45557)

Summary:
When using `TSan` while running the Unit tests of `RNTester`, there are a few data races picked up. One is described [here](#45280), while this PR deals with a race related to concurrent read/write of `ReactMarker::logTaggedMarkerImpl`. Here is the `TSan` output:

```
WARNING: ThreadSanitizer: data race (pid=5236)
  Read of size 8 at 0x00011a602690 by thread T34:
    #0 std::__1::__function::__value_func<void (facebook::react::ReactMarker::ReactMarkerId, char const*)>::operator bool[abi:ue170006]() const <null> (RNTesterUnitTests:arm64+0x18cd49c)
    #1 std::__1::function<void (facebook::react::ReactMarker::ReactMarkerId, char const*)>::operator bool[abi:ue170006]() const <null> (RNTesterUnitTests:arm64+0x18cd2bc)
    #2 facebook::react::JSIExecutor::initializeRuntime() <null> (RNTesterUnitTests:arm64+0x1c96818)
    #3 facebook::react::NativeToJsBridge::initializeRuntime()::$_0::operator()(facebook::react::JSExecutor*) <null> (RNTesterUnitTests:arm64+0x1a7a074)
    #4 decltype(std::declval<facebook::react::NativeToJsBridge::initializeRuntime()::$_0&>()(std::declval<facebook::react::JSExecutor*>())) std::__1::__invoke[abi:ue170006]<facebook::react::NativeToJsBridge::initializeRuntime()::$_0&, facebook::react::JSExecutor*>(facebook::react::NativeToJsBridge::initializeRuntime()::$_0&, facebook::react::JSExecutor*&&) <null> (RNTesterUnitTests:arm64+0x1a79fbc)
    #5 void std::__1::__invoke_void_return_wrapper<void, true>::__call[abi:ue170006]<facebook::react::NativeToJsBridge::initializeRuntime()::$_0&, facebook::react::JSExecutor*>(facebook::react::NativeToJsBridge::initializeRuntime()::$_0&, facebook::react::JSExecutor*&&) <null> (RNTesterUnitTests:arm64+0x1a79e5c)
    #6 std::__1::__function::__alloc_func<facebook::react::NativeToJsBridge::initializeRuntime()::$_0, std::__1::allocator<facebook::react::NativeToJsBridge::initializeRuntime()::$_0>, void (facebook::react::JSExecutor*)>::operator()[abi:ue170006](facebook::react::JSExecutor*&&) <null> (RNTesterUnitTests:arm64+0x1a79d84)
    #7 std::__1::__function::__func<facebook::react::NativeToJsBridge::initializeRuntime()::$_0, std::__1::allocator<facebook::react::NativeToJsBridge::initializeRuntime()::$_0>, void (facebook::react::JSExecutor*)>::operator()(facebook::react::JSExecutor*&&) <null> (RNTesterUnitTests:arm64+0x1a75250)
    #8 std::__1::__function::__value_func<void (facebook::react::JSExecutor*)>::operator()[abi:ue170006](facebook::react::JSExecutor*&&) const <null> (RNTesterUnitTests:arm64+0x1abac9c)
    #9 std::__1::function<void (facebook::react::JSExecutor*)>::operator()(facebook::react::JSExecutor*) const <null> (RNTesterUnitTests:arm64+0x1aba9d0)
    #10 facebook::react::NativeToJsBridge::runOnExecutorQueue(std::__1::function<void (facebook::react::JSExecutor*)>&&)::$_8::operator()() const <null> (RNTesterUnitTests:arm64+0x1aba8d4)
    #11 decltype(std::declval<facebook::react::NativeToJsBridge::runOnExecutorQueue(std::__1::function<void (facebook::react::JSExecutor*)>&&)::$_8&>()()) std::__1::__invoke[abi:ue170006]<facebook::react::NativeToJsBridge::runOnExecutorQueue(std::__1::function<void (facebook::react::JSExecutor*)>&&)::$_8&>(facebook::react::NativeToJsBridge::runOnExecutorQueue(std::__1::function<void (facebook::react::JSExecutor*)>&&)::$_8&) <null> (RNTesterUnitTests:arm64+0x1aba6d4)
    #12 void std::__1::__invoke_void_return_wrapper<void, true>::__call[abi:ue170006]<facebook::react::NativeToJsBridge::runOnExecutorQueue(std::__1::function<void (facebook::react::JSExecutor*)>&&)::$_8&>(facebook::react::NativeToJsBridge::runOnExecutorQueue(std::__1::function<void (facebook::react::JSExecutor*)>&&)::$_8&) <null> (RNTesterUnitTests:arm64+0x1aba4f8)
    #13 std::__1::__function::__alloc_func<facebook::react::NativeToJsBridge::runOnExecutorQueue(std::__1::function<void (facebook::react::JSExecutor*)>&&)::$_8, std::__1::allocator<facebook::react::NativeToJsBridge::runOnExecutorQueue(std::__1::function<void (facebook::react::JSExecutor*)>&&)::$_8>, void ()>::operator()[abi:ue170006]() <null> (RNTesterUnitTests:arm64+0x1aba45c)
    #14 std::__1::__function::__func<facebook::react::NativeToJsBridge::runOnExecutorQueue(std::__1::function<void (facebook::react::JSExecutor*)>&&)::$_8, std::__1::allocator<facebook::react::NativeToJsBridge::runOnExecutorQueue(std::__1::function<void (facebook::react::JSExecutor*)>&&)::$_8>, void ()>::operator()() <null> (RNTesterUnitTests:arm64+0x1ab4918)
    #15 std::__1::__function::__value_func<void ()>::operator()[abi:ue170006]() const <null> (RNTesterUnitTests:arm64+0x3ce2e4)
    #16 std::__1::function<void ()>::operator()() const <null> (RNTesterUnitTests:arm64+0x3cdfd0)
    #17 facebook::react::tryAndReturnError(std::__1::function<void ()> const&) <null> (RNTesterUnitTests:arm64+0x4af18c)
    #18 facebook::react::RCTMessageThread::tryFunc(std::__1::function<void ()> const&) <null> (RNTesterUnitTests:arm64+0x51595c)
    #19 facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1::operator()() const <null> (RNTesterUnitTests:arm64+0x529df0)
    #20 decltype(std::declval<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1&>()()) std::__1::__invoke[abi:ue170006]<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1&>(facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1&) <null> (RNTesterUnitTests:arm64+0x529b54)
    #21 void std::__1::__invoke_void_return_wrapper<void, true>::__call[abi:ue170006]<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1&>(facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1&) <null> (RNTesterUnitTests:arm64+0x529978)
    #22 std::__1::__function::__alloc_func<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1, std::__1::allocator<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1>, void ()>::operator()[abi:ue170006]() <null> (RNTesterUnitTests:arm64+0x5298dc)
    #23 std::__1::__function::__func<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1, std::__1::allocator<facebook::react::RCTMessageThread::runOnQueue(std::__1::function<void ()>&&)::$_1>, void ()>::operator()() <null> (RNTesterUnitTests:arm64+0x524518)
    #24 std::__1::__function::__value_func<void ()>::operator()[abi:ue170006]() const <null> (RNTesterUnitTests:arm64+0x3ce2e4)
    #25 std::__1::function<void ()>::operator()() const <null> (RNTesterUnitTests:arm64+0x3cdfd0)
    #26 invocation function for block in facebook::react::RCTMessageThread::runAsync(std::__1::function<void ()>) <null> (RNTesterUnitTests:arm64+0x515384)
    #27 __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ <null> (CoreFoundation:arm64+0x8dc0c)
    #28 __NSThread__start__ <null> (Foundation:arm64+0x645c60)

  Previous write of size 8 at 0x00011a602690 by main thread:
    #0 std::__1::__function::__value_func<void (facebook::react::ReactMarker::ReactMarkerId, char const*)>::swap[abi:ue170006](std::__1::__function::__value_func<void (facebook::react::ReactMarker::ReactMarkerId, char const*)>&) <null> (RNTesterUnitTests:arm64+0x43b078)
    #1 std::__1::function<void (facebook::react::ReactMarker::ReactMarkerId, char const*)>::swap(std::__1::function<void (facebook::react::ReactMarker::ReactMarkerId, char const*)>&) <null> (RNTesterUnitTests:arm64+0x433100)
    #2 std::__1::function<void (facebook::react::ReactMarker::ReactMarkerId, char const*)>& std::__1::function<void (facebook::react::ReactMarker::ReactMarkerId, char const*)>::operator=<registerPerformanceLoggerHooks(RCTPerformanceLogger*)::$_1, void>(registerPerformanceLoggerHooks(RCTPerformanceLogger*)::$_1&&) <null> (RNTesterUnitTests:arm64+0x432d50)
    #3 registerPerformanceLoggerHooks(RCTPerformanceLogger*) <null> (RNTesterUnitTests:arm64+0x4170fc)
    #4 -[RCTCxxBridge initWithParentBridge:] <null> (RNTesterUnitTests:arm64+0x416504)
    #5 -[RCTBridge setUp] <null> (RNTesterUnitTests:arm64+0x3bf6f4)
    #6 -[RCTBridge initWithDelegate:bundleURL:moduleProvider:launchOptions:] <null> (RNTesterUnitTests:arm64+0x3bc540)
    #7 -[RCTBridge initWithBundleURL:moduleProvider:launchOptions:] <null> (RNTesterUnitTests:arm64+0x3bc124)
    #8 -[RCTImageLoaderTests testImageLoaderUsesImageURLLoaderWithHighestPriority] <null> (RNTesterUnitTests:arm64+0x7de8)
    #9 __invoking___ <null> (CoreFoundation:arm64+0x13371c)

  Location is global 'facebook::react::ReactMarker::logTaggedMarkerImpl' at 0x00011a602678 (RNTesterUnitTests+0x438a690)

  Thread T34 (tid=11229216, running) created by main thread at:
    #0 pthread_create <null> (libclang_rt.tsan_iossim_dynamic.dylib:arm64+0x2bee4)
    #1 -[NSThread startAndReturnError:] <null> (Foundation:arm64+0x6458f0)
    #2 -[RCTBridge setUp] <null> (RNTesterUnitTests:arm64+0x3bf748)
    #3 -[RCTBridge initWithDelegate:bundleURL:moduleProvider:launchOptions:] <null> (RNTesterUnitTests:arm64+0x3bc540)
    #4 -[RCTBridge initWithBundleURL:moduleProvider:launchOptions:] <null> (RNTesterUnitTests:arm64+0x3bc124)
    #5 -[RCTImageLoaderTests testImageLoaderUsesImageDecoderWithHighestPriority] <null> (RNTesterUnitTests:arm64+0xbe8c)
    #6 __invoking___ <null> (CoreFoundation:arm64+0x13371c)
```

The proposed solution is to wrap `logTaggedMarkerImpl` in a class that has a static getter and setter wherein a read/write lock is employed. It is my understanding that `logTaggedMarkerImpl` is read several times, but only assigned rarely, and thus it seems appropriate with a read/write lock. The getter and setter functions are also inlineable, such that one should not need to make an extra function call when obtaining the `logTaggedMarkerImpl` instance.

In order to reproduce my findings and verify fix:

* Clone this branch
* Run setup code as described in README
* Execute `git revert -n 6599883 83a2a3c`
* Enable TSan for both `RNTester` and its test scheme.
* Enable Runtime issue breakpoint for TSan
* Run unit tests
* Observe the `TSan` breakpoint is hit (possibly other places in the codebase as well) when accessing `logTaggedMarkerImpl`. Continue execution if other breakpoints are hit before this breakpoint.
* Execute `git revert --abort`
* Run the tests again and observe the `TSan` breakpoint does _not_ hit said code again.

## Changelog:

[iOS][Fixed] Data race related to read/write on `ReactMarker::logTaggedMarkerImpl`

Pull Request resolved: #45557

Test Plan: I believe there are existing tests that will cover the proposed changes.

Reviewed By: cipolleschi

Differential Revision: D60525080

Pulled By: dmytrorykun

fbshipit-source-id: 78b0ce2a660af0e29909ff68c018698a9a1e29f8
@cortinico cortinico mentioned this pull request Oct 17, 2024
facebook-github-bot pushed a commit that referenced this pull request Nov 18, 2024
…7655)

Summary:
Because we cancel the request and the callback for the request loading state occurs in a multi-threaded environment, we may still receive the callback even after canceling the request.

 The assert failed like below:
```
(lldb) bt
* thread #48, queue = 'com.apple.root.default-qos', stop reason = signal SIGABRT
    frame #0: 0x0000000106d15008 libsystem_kernel.dylib`__pthread_kill + 8
    frame #1: 0x000000010581f408 libsystem_pthread.dylib`pthread_kill + 256
    frame #2: 0x000000018016c4ec libsystem_c.dylib`abort + 104
    frame #3: 0x000000018016b934 libsystem_c.dylib`__assert_rtn + 268
  * frame #4: 0x00000001073fcd64 React_Fabric`facebook::react::ImageResponseObserverCoordinator::nativeImageResponseComplete(this=0x00006000039bc838, imageResponse=0x000000016ce86970) const at ImageResponseObserverCoordinator.cpp:93:3
    frame #5: 0x00000001057c9a6c React_ImageManager`__42-[RCTImageManager requestImage:surfaceId:]_block_invoke_2(.block_descriptor=0x0000600000da21c0, error=0x0000000000000000, image=0x0000600003034ea0, metadata=0x0000000000000000) at RCTImageManager.mm:76:30
    frame #6: 0x0000000105657188 RCTImage`__140-[RCTImageLoader loadImageWithURLRequest:size:scale:clipped:resizeMode:priority:attribution:progressBlock:partialLoadBlock:completionBlock:]_block_invoke_3(.block_descriptor=0x0000600002c90200, error_=0x0000000000000000, image=0x0000600003034ea0) at RCTImageLoader.mm:831:11
    frame #7: 0x00000001056582e8 RCTImage`__80-[RCTImageLoader decodeImageData:size:scale:clipped:resizeMode:completionBlock:]_block_invoke_2(.block_descriptor=0x000060000267b780, error=0x0000000000000000, image=0x0000600003034ea0) at RCTImageLoader.mm:933:7
    frame #8: 0x0000000105658d60 RCTImage`__80-[RCTImageLoader decodeImageData:size:scale:clipped:resizeMode:completionBlock:]_block_invoke_3.207(.block_descriptor=0x0000600002957e90) at RCTImageLoader.mm:973:13
    frame #9: 0x0000000108560ec0 libdispatch.dylib`_dispatch_call_block_and_release + 24
    frame #10: 0x00000001085627b8 libdispatch.dylib`_dispatch_client_callout + 16
    frame #11: 0x00000001085655f4 libdispatch.dylib`_dispatch_queue_override_invoke + 1312
    frame #12: 0x00000001085763d4 libdispatch.dylib`_dispatch_root_queue_drain + 372
    frame #13: 0x0000000108576f7c libdispatch.dylib`_dispatch_worker_thread2 + 256
    frame #14: 0x000000010581bb38 libsystem_pthread.dylib`_pthread_wqthread + 224
```

![image](https://github.com/user-attachments/assets/7ed1997d-9d48-4631-9a02-0eef28a03cf3)

```
(lldb) bt
* thread #18, queue = 'com.meta.react.turbomodulemanager.queue', stop reason = signal SIGABRT
    frame #0: 0x0000000107ea9008 libsystem_kernel.dylib`__pthread_kill + 8
    frame #1: 0x000000010569b408 libsystem_pthread.dylib`pthread_kill + 256
    frame #2: 0x000000018016c4ec libsystem_c.dylib`abort + 104
    frame #3: 0x000000018016b934 libsystem_c.dylib`__assert_rtn + 268
  * frame #4: 0x00000001072bcae8 React_Fabric`facebook::react::ImageResponseObserverCoordinator::nativeImageResponseProgress(this=0x00006000039bd7a8, progress=-1006, loaded=1006, total=-1) const at ImageResponseObserverCoordinator.cpp:76:3
    frame #5: 0x0000000105615fb8 React_ImageManager`__42-[RCTImageManager requestImage:surfaceId:]_block_invoke.3(.block_descriptor=0x0000600000d26a30, progress=1006, total=-1) at RCTImageManager.mm:89:28
    frame #6: 0x00000001055160fc RCTImage`__64-[RCTImageLoader _loadURLRequest:progressBlock:completionBlock:]_block_invoke.192(.block_descriptor=0x0000600000cd4900, progress=1006, total=-1) at RCTImageLoader.mm:747:7
    frame #7: 0x000000010504bc4c RCTNetwork`__44-[RCTNetworkTask URLRequest:didReceiveData:]_block_invoke.22(.block_descriptor=0x00006000017e0c80) at RCTNetworkTask.mm:201:7
    frame #8: 0x0000000108a24ec0 libdispatch.dylib`_dispatch_call_block_and_release + 24
    frame #9: 0x0000000108a267b8 libdispatch.dylib`_dispatch_client_callout + 16
    frame #10: 0x0000000108a2eaac libdispatch.dylib`_dispatch_lane_serial_drain + 912
    frame #11: 0x0000000108a2f7b0 libdispatch.dylib`_dispatch_lane_invoke + 420
    frame #12: 0x0000000108a3c1f0 libdispatch.dylib`_dispatch_root_queue_drain_deferred_wlh + 324
    frame #13: 0x0000000108a3b75c libdispatch.dylib`_dispatch_workloop_worker_thread + 732
    frame #14: 0x0000000105697b74 libsystem_pthread.dylib`_pthread_wqthread + 284
```

![image](https://github.com/user-attachments/assets/524a3ba2-857e-4f3a-8757-115d3ebadb42)

## Changelog:

[IOS] [FIXED] - Fabric: Fixes image coordinator status assert crash in debug mode

Pull Request resolved: #47655

Test Plan: Very easy to repro, just open RNTester's Image example, and then pop the page. Do this back and forth a few times.

Reviewed By: sammy-SC, rshest

Differential Revision: D66093834

Pulled By: javache

fbshipit-source-id: a2ca36147498725d38a95cc3fcc12a2c18802303
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.

4 participants