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

Bridge promises don't handle multiple resolve or reject calls properly #20262

Closed
esprehn opened this issue Jul 18, 2018 · 10 comments
Closed

Bridge promises don't handle multiple resolve or reject calls properly #20262

esprehn opened this issue Jul 18, 2018 · 10 comments
Labels
Bug Ran Commands One of our bots successfully processed a command. Resolution: Locked This issue was locked by the bot. Resolution: PR Submitted A pull request with a fix has been provided.

Comments

@esprehn
Copy link
Contributor

esprehn commented Jul 18, 2018

Environment

Environment:
OS: macOS High Sierra 10.13.5
Node: 8.9.4
Yarn: 1.5.1
npm: 5.6.0
Watchman: 4.7.0
Xcode: Xcode 9.4.1 Build version 9F2000
Android Studio: 3.1 AI-173.4720617

Packages: (wanted => installed)
react: 16.2.0 => 16.2.0
react-native: 0.54.4 => 0.54.4

Description

PromiseImpl and RCTModuleMethod don't handle promise resolution properly. Resolving a promise a second time is supposed to have no effect per ES semantics, similarly rejecting it a second time, or if it's rejected already, should have no effect.

PromiseImpl.resolve a second time will throw an error:

Exception java.lang.RuntimeException: Illegal callback invocation from native module. This callback type only permits a single invocation from native code.
com.facebook.react.bridge.CallbackImpl.invoke (CallbackImpl.java:30)
com.facebook.react.bridge.PromiseImpl.resolve (PromiseImpl.java:32)

For iOS this doesn't crash in ObjC, instead it sends another message over the bridge, but the callbacks are gone, so it incorrectly warns in a dev build (Callback with id ${cbID}: ${module}.${method}() not found) and is correctly a no-op in a release build (though it is inefficient to send the bridge response).

Reproducible Demo

Create a @RectMethod and do resolve() in the Java twice, or do do resolve twice in an ObjC iOS method.

@esprehn
Copy link
Contributor Author

esprehn commented Jul 18, 2018

This happens in the most recent version too. The code is the same.

@hramos
Copy link
Contributor

hramos commented Jul 18, 2018

@esprehn can you update your post accordingly? 0.54.4 is not the latest as of this writing, and we'd like to know the exact version you tested in.

@esprehn
Copy link
Contributor Author

esprehn commented Jul 19, 2018

@hramos It happens in the most recent version as well. The code is here:

The bridge makes the callbacks here:

which contains the throw statement:

throw new RuntimeException("Illegal callback invocation from native "+

None of the related files have been touched since the relicensing in Feb.

For Android this could be fixed by setting mResolve and mReject to null, for iOS I'd need to study the bridge code more, it doesn't have the same kind of Promise abstraction, instead it seems to just pass two blocks into your method.

@esprehn
Copy link
Contributor Author

esprehn commented Jul 31, 2018

This does actually crash on iOS in a debug build, I misread the code:

static BOOL checkCallbackMultipleInvocations(BOOL *didInvoke) {

@react-native-bot react-native-bot added the Ran Commands One of our bots successfully processed a command. label Aug 15, 2018
@react-native-bot
Copy link
Collaborator

I am closing this issue because it does not appear to have been verified on the latest release, and there has been no followup in a while.

If you found this thread after encountering the same issue in the latest release, please feel free to create a new issue with up-to-date information by clicking here.

@esprehn
Copy link
Contributor Author

esprehn commented Aug 15, 2018

This bug still exists. @hramos The bot probably shouldn't close issues with pending PRs?

@hramos
Copy link
Contributor

hramos commented Aug 15, 2018

@esprehn the bot won't close issues with a pending PR, but this issue was not labeled as such at the time of closing. Can you update your original post and make sure it mentions the actual version you tested in? Otherwise the bot might close it again for referring to an older version (0.56 is latest at this time).

@hramos hramos added Resolution: PR Submitted A pull request with a fix has been provided. and removed ⏪Old Version labels Aug 15, 2018
@hramos hramos reopened this Aug 15, 2018
@stale
Copy link

stale bot commented Nov 13, 2018

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as "For Discussion" or "Good first issue" and I will leave it open. Thank you for your contributions.

@stale stale bot added the Stale There has been a lack of activity on this issue and it may be closed soon. label Nov 13, 2018
@esprehn
Copy link
Contributor Author

esprehn commented Nov 17, 2018

This issue still exists. Bridge promises don't follow the spec.

@stale stale bot removed the Stale There has been a lack of activity on this issue and it may be closed soon. label Nov 17, 2018
facebook-github-bot pushed a commit that referenced this issue Dec 10, 2018
Summary:
Promise semantics per JS should allow calling resolve or reject repeatedly without crashing. Only the first one should do anything, but others should be allowed. This change fixes the Java bridge for Android. A separate change is needed for iOS.

Issue #20262
Pull Request resolved: #20303

Differential Revision: D13396975

Pulled By: cpojer

fbshipit-source-id: 81f14f73654fa7c44e043f574a39fda481ace44b
grabbou pushed a commit that referenced this issue Dec 17, 2018
Summary:
Promise semantics per JS should allow calling resolve or reject repeatedly without crashing. Only the first one should do anything, but others should be allowed. This change fixes the Java bridge for Android. A separate change is needed for iOS.

Issue #20262
Pull Request resolved: #20303

Differential Revision: D13396975

Pulled By: cpojer

fbshipit-source-id: 81f14f73654fa7c44e043f574a39fda481ace44b
@hramos hramos removed the Bug Report label Feb 6, 2019
@dulmandakh
Copy link
Contributor

This issue if fixed in 0.59. Thank you

t-nanava pushed a commit to microsoft/react-native-macos that referenced this issue Jun 17, 2019
Summary:
Promise semantics per JS should allow calling resolve or reject repeatedly without crashing. Only the first one should do anything, but others should be allowed. This change fixes the Java bridge for Android. A separate change is needed for iOS.

Issue facebook#20262
Pull Request resolved: facebook#20303

Differential Revision: D13396975

Pulled By: cpojer

fbshipit-source-id: 81f14f73654fa7c44e043f574a39fda481ace44b
@facebook facebook locked as resolved and limited conversation to collaborators Mar 19, 2020
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Mar 19, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug Ran Commands One of our bots successfully processed a command. Resolution: Locked This issue was locked by the bot. Resolution: PR Submitted A pull request with a fix has been provided.
Projects
None yet
Development

No branches or pull requests

4 participants