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

Use synchronous native module calls when New Architecture is enabled #2152

Merged
merged 5 commits into from
Jun 11, 2024

Conversation

yousif-bugsnag
Copy link
Contributor

@yousif-bugsnag yousif-bugsnag commented Jun 5, 2024

Goal

In RN 0.74 New Architecture (bridgeless mode), once an exception is thrown, async promises are no longer being resolved. This means JS exceptions are not being reported, because post-error communication with the native layer to capture native state and send an exception for delivery is not able to run.

This PR fixes the issue by making calls to the native layer synchronous when the New Architecture is enabled.

As part of this, RN 0.74 has been added to the test matrix and the e2e tests have been updated accordingly.

Design

Synchronous native methods

There are 2 explicitly async (i.e. promise-returning) methods involved in post-error communication:

  • getPayloadInfo (used in plugin-react-native-event-sync)
  • dispatch (used in delivery-react-native)

These have been converted to synchronous methods and separate async versions getPayloadInfoAsync and dispatchAsync added. Both packages have been updated to use the synchronous methods when the New Arch is enabled.

For the remaining native module methods, a preprocessor directive is used on iOS to export those methods as synchronous when the new architecture is enabled (on iOS, void native methods that don't return a value in JS are also asynchronous unless exported on the native side with RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD)

Testing

React Native 0.74 has now been added to the test matrix. A new step definition has been added to support testing payload values for a given architecture (old vs new) and RN version combination.

@yousif-bugsnag yousif-bugsnag marked this pull request as ready for review June 5, 2024 14:29
@yousif-bugsnag yousif-bugsnag requested review from lemnik and gingerbenw and removed request for lemnik June 5, 2024 14:29
Copy link

github-actions bot commented Jun 5, 2024

@bugsnag/browser bundle size diff

Minified Minfied + Gzipped
Before 43.80 kB 13.43 kB
After 43.80 kB 13.43 kB
± No change No change

code coverage diff

<temporarily disabled>

Generated by 🚫 dangerJS against ba8507f

@yousif-bugsnag yousif-bugsnag force-pushed the PLAT-12175/sync-tm-methods branch 2 times, most recently from 2584263 to 72f6971 Compare June 5, 2024 14:42
Copy link
Member

@gingerbenw gingerbenw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems good to me from the js/feature side of things, I can't say I fully understand the java/impl functions, but they seem clear enough

Comment on lines +153 to +195
# Tests that the given payload value is correct for the target arch and RN version combination.
# This step will assume the expected and payload values are strings.
#
# The DataTable used for this step should have the headers `arch` `version` and `value`
# The `arch` column must contain either `old` or `new`
# The `version` column should contain the version of the app to test the value against, or `default` for unspecified versions
# The `value` column should contain the expected value for the given arch and version combination
#
# | arch | version | value |
# | new | 0.74 | Error |
# | new | default | java.lang.RuntimeException |
# | old | default | java.lang.RuntimeException |
#
# If the expected value is set to "@null", the check will be for null
# If the expected value is set to "@not_null", the check will be for a non-null value
Then('the event {string} equals the version-dependent string:') do |field_path, table|
payload = Maze::Server.errors.current[:body]
payload_value = Maze::Helper.read_key_path(payload, "events.0.#{field_path}")
expected_values = table.hashes


arch = ENV['RCT_NEW_ARCH_ENABLED'] == 'true' ? 'new' : 'old'
arch_values = expected_values.select do |hash|
hash['arch'] == arch
end

raise("There is no expected value for the current arch \"#{arch}\"") if arch_values.empty?

current_version = ENV['RN_VERSION']
version_values = arch_values.select do |hash|
hash['version'] == current_version
end

if version_values.empty?
version_values = arch_values.select { |hash| hash['version'] == 'default' }
end

raise("There is no expected value for the current version \"#{current_version}\"") if version_values.empty?
raise("Multiple expected values found for arch \"#{arch}\" and version \"#{current_version}\"") if version_values.length() > 1

expected_value = version_values[0]['value']
assert_equal_with_nullability(expected_value, payload_value)
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👌🏻

@yousif-bugsnag yousif-bugsnag force-pushed the PLAT-12175/sync-tm-methods branch from 72f6971 to 51d86ec Compare June 6, 2024 10:01
@yousif-bugsnag yousif-bugsnag force-pushed the PLAT-12175/sync-tm-methods branch from 51d86ec to 5949754 Compare June 10, 2024 11:02
@yousif-bugsnag yousif-bugsnag force-pushed the PLAT-12175/sync-tm-methods branch from 5949754 to ba8507f Compare June 10, 2024 11:05
Copy link
Contributor

@lemnik lemnik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

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.

3 participants