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

Migrate from native CallInvoker to NativeMethodCallInvoker #37473

Closed
wants to merge 1 commit into from

Conversation

RSNara
Copy link
Contributor

@RSNara RSNara commented May 17, 2023

Summary:

Context

The TurboModule system uses a CallInvoker interface to schedule JavaScript → native, and native → JavaScript calls.

Problem

JavaScript → native and native → JavaScript calls are different. They can have different behaviours/properties. And, in the future, we might want to evolve them differently. e.g:

  • JavaScript → native always have a method name. Native → JavaScript calls don't.
  • Native → JavaScript can have priorities, since D41492849. JavaScript → native don't.

Changes

Instead of tying both types of calls to the CallInvoker abstraction, this diff creates a separate abstraction for Native → JavaScript calls: NativeMethodCallInvoker.

This way, we can evolve both abstractions separately over time:

  • We can evolve the CallInvoker abstraction to suit the needs of JavaScript → native calls.
  • We can evolve the NativeMethodCallInvoker abstraction to suite the needs of native → JavaScript calls.

This ultimately makes TurboModule system more extensible.

Motivation

For the TurboModule interop layer on iOS, React Native needs to execute the "constantsToExport" method on the main queue, when the module requires main queue setup. (implementation: D45924977).

The simplest way to implement this behaviour is to introduce a methodName to CallInvoker, and customize the legacy module's CallInvoker::invokeSync method, like so:

  void invokeSync(std::string methodName, std::function<void()> &&work) override
  {
    if (requiresMainQueueSetup_ && methodName == "getConstants") {
      __block auto retainedWork = std::move(work);
      RCTUnsafeExecuteOnMainQueueSync(^{
        retainedWork();
      });
      return;
    }

    work();
  }

But, customizing CallInvoker to introduce a methodName parameter doesn't make sense: Native → JavaScript calls don't necessarily have method names. So, this diff forks CallInvoker into NativeMethodCallInvoker. That way, we can customize NativeMethodCallInvoker to introduce a method name (which does make sense) and resolve this problem. For the full solution, see D45924977.

NOTE: Now that NativeMethodCallInvoker is different from CallInvoker, it might make sense to re-name CallInvoker back to JSCallInvoker.

Differential Revision: D45891627

@facebook-github-bot facebook-github-bot added CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. p: Facebook Partner: Facebook Partner fb-exported labels May 17, 2023
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D45891627

RSNara added a commit to RSNara/react-native that referenced this pull request May 18, 2023
…37473)

Summary:
Pull Request resolved: facebook#37473

## Context
The TurboModule system uses a CallInvoker interface to schedule JavaScript → native, and native → JavaScript calls.

## Problem
JavaScript → native and native → JavaScript calls are different. They can have different behaviours/properties. And, in the future, we might want to evolve them differently. e.g:
- JavaScript → native **always** have a method name. Native → JavaScript calls don't.
- Native → JavaScript can have priorities, since D41492849. JavaScript → native don't.

## Changes
Instead of tying both types of calls to the CallInvoker abstraction, this diff creates a **separate** abstraction for Native → JavaScript calls: NativeMethodCallInvoker.

This way, we can evolve both abstractions separately over time:
- We can evolve the CallInvoker abstraction to suit the needs of JavaScript → native calls.
- We can evolve the NativeMethodCallInvoker abstraction to suite the needs of native → JavaScript calls.

This ultimately makes TurboModule system more extensible.

## Motivation
For the TurboModule interop layer on iOS, React Native needs to execute the "constantsToExport" method on the main queue, when the module requires main queue setup. (implementation: D45924977).

The simplest way to implement this behaviour is to introduce a `methodName` to CallInvoker, and customize the legacy module's CallInvoker::invokeSync method, like so:

```
  void invokeSync(std::string methodName, std::function<void()> &&work) override
  {
    if (requiresMainQueueSetup_ && methodName == "getConstants") {
      __block auto retainedWork = std::move(work);
      RCTUnsafeExecuteOnMainQueueSync(^{
        retainedWork();
      });
      return;
    }

    work();
  }
```

But, customizing CallInvoker to introduce a `methodName` parameter doesn't make sense: Native → JavaScript calls don't necessarily have method names. So, this diff forks CallInvoker into NativeMethodCallInvoker. That way, we can customize NativeMethodCallInvoker to introduce a method name (which does make sense) and resolve this problem. For the full solution, see D45924977.

NOTE: Now that NativeMethodCallInvoker is different from CallInvoker, it might make sense to re-name CallInvoker back to JSCallInvoker.

Differential Revision: D45891627

fbshipit-source-id: eea9761e4ab99019a5bcaeab2806568aac2bd936
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D45891627

RSNara added a commit to RSNara/react-native that referenced this pull request May 18, 2023
…37473)

Summary:
Pull Request resolved: facebook#37473

## Context
The TurboModule system uses a CallInvoker interface to schedule JavaScript → native, and native → JavaScript calls.

## Problem
JavaScript → native and native → JavaScript calls are different. They can have different behaviours/properties. And, in the future, we might want to evolve them differently. e.g:
- JavaScript → native **always** have a method name. Native → JavaScript calls don't.
- Native → JavaScript can have priorities, since D41492849. JavaScript → native don't.

## Changes
Instead of tying both types of calls to the CallInvoker abstraction, this diff creates a **separate** abstraction for Native → JavaScript calls: NativeMethodCallInvoker.

This way, we can evolve both abstractions separately over time:
- We can evolve the CallInvoker abstraction to suit the needs of JavaScript → native calls.
- We can evolve the NativeMethodCallInvoker abstraction to suite the needs of native → JavaScript calls.

This ultimately makes TurboModule system more extensible.

## Motivation
For the TurboModule interop layer on iOS, React Native needs to execute the "constantsToExport" method on the main queue, when the module requires main queue setup. (implementation: D45924977).

The simplest way to implement this behaviour is to introduce a `methodName` to CallInvoker, and customize the legacy module's CallInvoker::invokeSync method, like so:

```
  void invokeSync(std::string methodName, std::function<void()> &&work) override
  {
    if (requiresMainQueueSetup_ && methodName == "getConstants") {
      __block auto retainedWork = std::move(work);
      RCTUnsafeExecuteOnMainQueueSync(^{
        retainedWork();
      });
      return;
    }

    work();
  }
```

But, customizing CallInvoker to introduce a `methodName` parameter doesn't make sense: Native → JavaScript calls don't necessarily have method names. So, this diff forks CallInvoker into NativeMethodCallInvoker. That way, we can customize NativeMethodCallInvoker to introduce a method name (which does make sense) and resolve this problem. For the full solution, see D45924977.

NOTE: Now that NativeMethodCallInvoker is different from CallInvoker, it might make sense to re-name CallInvoker back to JSCallInvoker.

Differential Revision: D45891627

fbshipit-source-id: 6eca49a2ef452a567966687fd28901e4b76266ca
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D45891627

RSNara added a commit to RSNara/react-native that referenced this pull request May 18, 2023
…37473)

Summary:
Pull Request resolved: facebook#37473

## Context
The TurboModule system uses a CallInvoker interface to schedule JavaScript → native, and native → JavaScript calls.

## Problem
JavaScript → native and native → JavaScript calls are different. They can have different behaviours/properties. And, in the future, we might want to evolve them differently. e.g:
- JavaScript → native **always** have a method name. Native → JavaScript calls don't.
- Native → JavaScript can have priorities, since D41492849. JavaScript → native don't.

## Changes
Instead of tying both types of calls to the CallInvoker abstraction, this diff creates a **separate** abstraction for Native → JavaScript calls: NativeMethodCallInvoker.

This way, we can evolve both abstractions separately over time:
- We can evolve the CallInvoker abstraction to suit the needs of JavaScript → native calls.
- We can evolve the NativeMethodCallInvoker abstraction to suite the needs of native → JavaScript calls.

This ultimately makes TurboModule system more extensible.

## Motivation
For the TurboModule interop layer on iOS, React Native needs to execute the "constantsToExport" method on the main queue, when the module requires main queue setup. (implementation: D45924977).

The simplest way to implement this behaviour is to introduce a `methodName` to CallInvoker, and customize the legacy module's CallInvoker::invokeSync method, like so:

```
  void invokeSync(std::string methodName, std::function<void()> &&work) override
  {
    if (requiresMainQueueSetup_ && methodName == "getConstants") {
      __block auto retainedWork = std::move(work);
      RCTUnsafeExecuteOnMainQueueSync(^{
        retainedWork();
      });
      return;
    }

    work();
  }
```

But, customizing CallInvoker to introduce a `methodName` parameter doesn't make sense: Native → JavaScript calls don't necessarily have method names. So, this diff forks CallInvoker into NativeMethodCallInvoker. That way, we can customize NativeMethodCallInvoker to introduce a method name (which does make sense) and resolve this problem. For the full solution, see D45924977.

NOTE: Now that NativeMethodCallInvoker is different from CallInvoker, it might make sense to re-name CallInvoker back to JSCallInvoker.

Differential Revision: D45891627

fbshipit-source-id: 14a93431bc4674bf0a2eef1738bb77998a99ad07
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D45891627

1 similar comment
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D45891627

RSNara added a commit to RSNara/react-native that referenced this pull request May 18, 2023
…37473)

Summary:
Pull Request resolved: facebook#37473

## Context
The TurboModule system uses a CallInvoker interface to schedule JavaScript → native, and native → JavaScript calls.

## Problem
JavaScript → native and native → JavaScript calls are different. They can have different behaviours/properties. And, in the future, we might want to evolve them differently. e.g:
- JavaScript → native **always** have a method name. Native → JavaScript calls don't.
- Native → JavaScript can have priorities, since D41492849. JavaScript → native don't.

## Changes
Instead of tying both types of calls to the CallInvoker abstraction, this diff creates a **separate** abstraction for Native → JavaScript calls: NativeMethodCallInvoker.

This way, we can evolve both abstractions separately over time:
- We can evolve the CallInvoker abstraction to suit the needs of JavaScript → native calls.
- We can evolve the NativeMethodCallInvoker abstraction to suite the needs of native → JavaScript calls.

This ultimately makes TurboModule system more extensible.

## Motivation
For the TurboModule interop layer on iOS, React Native needs to execute the "constantsToExport" method on the main queue, when the module requires main queue setup. (implementation: D45924977).

The simplest way to implement this behaviour is to introduce a `methodName` to CallInvoker, and customize the legacy module's CallInvoker::invokeSync method, like so:

```
  void invokeSync(std::string methodName, std::function<void()> &&work) override
  {
    if (requiresMainQueueSetup_ && methodName == "getConstants") {
      __block auto retainedWork = std::move(work);
      RCTUnsafeExecuteOnMainQueueSync(^{
        retainedWork();
      });
      return;
    }

    work();
  }
```

But, customizing CallInvoker to introduce a `methodName` parameter doesn't make sense: Native → JavaScript calls don't necessarily have method names. So, this diff forks CallInvoker into NativeMethodCallInvoker. That way, we can customize NativeMethodCallInvoker to introduce a method name (which does make sense) and resolve this problem. For the full solution, see D45924977.

NOTE: Now that NativeMethodCallInvoker is different from CallInvoker, it might make sense to re-name CallInvoker back to JSCallInvoker.

Differential Revision: D45891627

fbshipit-source-id: 9a9a5309fe2681aa5a2523846ffcda6278bd0d4e
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D45891627

RSNara added a commit to RSNara/react-native that referenced this pull request May 18, 2023
…37473)

Summary:
Pull Request resolved: facebook#37473

## Context
The TurboModule system uses a CallInvoker interface to schedule JavaScript → native, and native → JavaScript calls.

## Problem
JavaScript → native and native → JavaScript calls are different. They can have different behaviours/properties. And, in the future, we might want to evolve them differently. e.g:
- JavaScript → native **always** have a method name. Native → JavaScript calls don't.
- Native → JavaScript can have priorities, since D41492849. JavaScript → native don't.

## Changes
Instead of tying both types of calls to the CallInvoker abstraction, this diff creates a **separate** abstraction for Native → JavaScript calls: NativeMethodCallInvoker.

This way, we can evolve both abstractions separately over time:
- We can evolve the CallInvoker abstraction to suit the needs of JavaScript → native calls.
- We can evolve the NativeMethodCallInvoker abstraction to suite the needs of native → JavaScript calls.

This ultimately makes TurboModule system more extensible.

## Motivation
For the TurboModule interop layer on iOS, React Native needs to execute the "constantsToExport" method on the main queue, when the module requires main queue setup. (implementation: D45924977).

The simplest way to implement this behaviour is to introduce a `methodName` to CallInvoker, and customize the legacy module's CallInvoker::invokeSync method, like so:

```
  void invokeSync(std::string methodName, std::function<void()> &&work) override
  {
    if (requiresMainQueueSetup_ && methodName == "getConstants") {
      __block auto retainedWork = std::move(work);
      RCTUnsafeExecuteOnMainQueueSync(^{
        retainedWork();
      });
      return;
    }

    work();
  }
```

But, customizing CallInvoker to introduce a `methodName` parameter doesn't make sense: Native → JavaScript calls don't necessarily have method names. So, this diff forks CallInvoker into NativeMethodCallInvoker. That way, we can customize NativeMethodCallInvoker to introduce a method name (which does make sense) and resolve this problem. For the full solution, see D45924977.

NOTE: Now that NativeMethodCallInvoker is different from CallInvoker, it might make sense to re-name CallInvoker back to JSCallInvoker.

Differential Revision: D45891627

fbshipit-source-id: 85296a17fe66af5655277b126a13323ae25203e9
@RSNara RSNara force-pushed the export-D45891627 branch 2 times, most recently from 3a36c5d to 27f8a2e Compare May 22, 2023 17:32
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D45891627

@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D45891627

RSNara added a commit to RSNara/react-native that referenced this pull request May 22, 2023
…37473)

Summary:
Pull Request resolved: facebook#37473

## Context
The TurboModule system uses a CallInvoker interface to schedule JavaScript → native, and native → JavaScript calls.

## Problem
JavaScript → native and native → JavaScript calls are different. They can have different behaviours/properties. And, in the future, we might want to evolve them differently. e.g:
- JavaScript → native **always** have a method name. Native → JavaScript calls don't.
- Native → JavaScript can have priorities, since D41492849. JavaScript → native don't.

## Changes
Instead of tying both types of calls to the CallInvoker abstraction, this diff creates a **separate** abstraction for Native → JavaScript calls: NativeMethodCallInvoker.

This way, we can evolve both abstractions separately over time:
- We can evolve the CallInvoker abstraction to suit the needs of JavaScript → native calls.
- We can evolve the NativeMethodCallInvoker abstraction to suite the needs of native → JavaScript calls.

This ultimately makes TurboModule system more extensible.

## Motivation
For the TurboModule interop layer on iOS, React Native needs to execute the "constantsToExport" method on the main queue, when the module requires main queue setup. (implementation: D45924977).

The simplest way to implement this behaviour is to introduce a `methodName` to CallInvoker, and customize the legacy module's CallInvoker::invokeSync method, like so:

```
  void invokeSync(std::string methodName, std::function<void()> &&work) override
  {
    if (requiresMainQueueSetup_ && methodName == "getConstants") {
      __block auto retainedWork = std::move(work);
      RCTUnsafeExecuteOnMainQueueSync(^{
        retainedWork();
      });
      return;
    }

    work();
  }
```

But, customizing CallInvoker to introduce a `methodName` parameter doesn't make sense: Native → JavaScript calls don't necessarily have method names. So, this diff forks CallInvoker into NativeMethodCallInvoker. That way, we can customize NativeMethodCallInvoker to introduce a method name (which does make sense) and resolve this problem. For the full solution, see D45924977.

NOTE: Now that NativeMethodCallInvoker is different from CallInvoker, it might make sense to re-name CallInvoker back to JSCallInvoker.

Changelog:
[Category][Breaking] - Introduce NativeMethodCallInvoker to replace the TurboModule system's native CallInvoker

Reviewed By: javache

Differential Revision: D45891627

fbshipit-source-id: f7993cb5f7a2bba9d07a7dc8322ed5472a4036b7
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D45891627

…37473)

Summary:
Pull Request resolved: facebook#37473

## Context
The TurboModule system uses a CallInvoker interface to schedule JavaScript → native, and native → JavaScript calls.

## Problem
JavaScript → native and native → JavaScript calls are different. They can have different behaviours/properties. And, in the future, we might want to evolve them differently. e.g:
- JavaScript → native **always** have a method name. Native → JavaScript calls don't.
- Native → JavaScript can have priorities, since D41492849. JavaScript → native don't.

## Changes
Instead of tying both types of calls to the CallInvoker abstraction, this diff creates a **separate** abstraction for Native → JavaScript calls: NativeMethodCallInvoker.

This way, we can evolve both abstractions separately over time:
- We can evolve the CallInvoker abstraction to suit the needs of JavaScript → native calls.
- We can evolve the NativeMethodCallInvoker abstraction to suite the needs of native → JavaScript calls.

This ultimately makes TurboModule system more extensible.

## Motivation
For the TurboModule interop layer on iOS, React Native needs to execute the "constantsToExport" method on the main queue, when the module requires main queue setup. (implementation: D45924977).

The simplest way to implement this behaviour is to introduce a `methodName` to CallInvoker, and customize the legacy module's CallInvoker::invokeSync method, like so:

```
  void invokeSync(std::string methodName, std::function<void()> &&work) override
  {
    if (requiresMainQueueSetup_ && methodName == "getConstants") {
      __block auto retainedWork = std::move(work);
      RCTUnsafeExecuteOnMainQueueSync(^{
        retainedWork();
      });
      return;
    }

    work();
  }
```

But, customizing CallInvoker to introduce a `methodName` parameter doesn't make sense: Native → JavaScript calls don't necessarily have method names. So, this diff forks CallInvoker into NativeMethodCallInvoker. That way, we can customize NativeMethodCallInvoker to introduce a method name (which does make sense) and resolve this problem. For the full solution, see D45924977.

NOTE: Now that NativeMethodCallInvoker is different from CallInvoker, it might make sense to re-name CallInvoker back to JSCallInvoker.

Changelog:
[Category][Breaking] - Introduce NativeMethodCallInvoker to replace the TurboModule system's native CallInvoker

Reviewed By: javache

Differential Revision: D45891627

fbshipit-source-id: b650738d2333e8728c6e96c7f7ac3e6a899136e3
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D45891627

@analysis-bot
Copy link

Platform Engine Arch Size (bytes) Diff
android hermes arm64-v8a 8,736,531 +3,104
android hermes armeabi-v7a 8,047,436 +2,805
android hermes x86 9,226,730 +3,206
android hermes x86_64 9,078,558 +3,030
android jsc arm64-v8a 9,301,288 +3,120
android jsc armeabi-v7a 8,489,765 +2,818
android jsc x86 9,362,551 +3,224
android jsc x86_64 9,618,493 +3,052

Base commit: d470dee
Branch: main

@facebook-github-bot facebook-github-bot added the Merged This PR has been merged. label May 23, 2023
@facebook-github-bot
Copy link
Contributor

This pull request has been merged in b70f186.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. fb-exported Merged This PR has been merged. p: Facebook Partner: Facebook Partner
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants