-
Notifications
You must be signed in to change notification settings - Fork 24.5k
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
Remove usage of the ... operator in BackHandler #15182
Conversation
@facebook-github-bot label Needs more information Generated by 🚫 dangerJS |
var invokeDefault = true; | ||
var subscriptions = [...backPressSubscriptions].reverse(); | ||
var subscriptions = []; | ||
_backPressSubscriptions.forEach(function(subscription) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should use map
instead of forEach
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used forEach
and unshift
to skip the extra step of reversing the array.
@dantman I tried to find reviewers for this pull request and wanted to ping them to take another look. However, based on the blame information for the files in this pull request I couldn't find any reviewers. This sometimes happens when the files in the pull request are new or don't exist on master anymore. Is this pull request still relevant? If yes could you please rebase? In case you know who has context on this code feel free to mention them in a comment (one person is fine). Thanks for reading and hope you will continue contributing to the project. |
Yet again the tests fail for some reason that has absolutely nothing to do with my commit. |
@dantman What about using |
😩 If we're going to micro-optimize this I might as well do it right with a benchmark instead of making guesses. You're right, However, aside from the set.values is only a small improvement over unshift, and it requires the use of Reverse loop creation comparison using RN Set implementationhttps://jsperf.com/reverse-loop-creation-comparison Reverse loop creation comparison using native Set implementationHere's a version using native a |
@dantman Nice benchmarks :). Since it's not a very hot path I still suggest using values.reverse since that is more readable and avoids using the spread operator + it's still a few times faster than what we had. |
Also it looks like you can just do |
That I believe would require the set[Symbol.iterator], which is what is broken. |
This usage currently causes BackHandler to silently become non-functional when a Symbol polyfill is used. Why? - The [...obj] operator implicitly calls the object's iterator to fill the array - react-native's internal Set polyfill has a load order issue that breaks it whenever a project uses a Symbol polyfill - This means that when BackHandler tries to [...set] a Set of subscriptions the result is always an empty array instead of an array of subscriptions Additionally it's worth noting that the current code is also wastefully inefficient as in order to reverse iterate over subscriptions it: - Clones the Set (which fills it by implicitly running the set's iterator) - Uses [...set] to convert the cloned set into an array (which also implicitly runs the iterator on the clone) - Finally reverses the order of the array This code fixes this problem by replacing the use of multiple Set instance iterators with use of `set.values()` which does not require the set's implicit iterator. Fixes facebook#11968
Ready. |
Thanks! Thinking about it more we should probably try to fix the thing that makes Set fail when including a Symbol polyfill. Let’s still ship this since it’s really simple and still improves the code. |
@facebook-github-bot shipit |
@facebook-github-bot shipit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@janicduplessis is landing this pull request. If you are a Facebook employee, you can view this diff on Phabricator.
changing the BackHandler.android.js doesn't works for me, can anyone please help me in making the back handler work.? |
It's too bad that optimization was prioritized here instead of the removal of set[Symbol.iterator] which was the issue in the first place... I'd say 99% of apps have less than 3 values in _backPressSubscriptions so I don't think we will notice any real-world difference. Thankfully it's pretty easy to pull the fix in a new BackHandler module, see my answer here: #11968 (comment) |
Optimization was not prioritized, the 3rd slowest iteration method was used. Code readability was what was prioritized. And during testing set.values() seemed to work fine (I'd really appreciate some attempt to see what the output of what you're seeing for that is). My fastest example actually also removes iterators completely. |
Would it be possible to fix the set polyfill load order issue instead? I feel like even if we fix it here other similar issues could arise elsewhere. |
It's not actually a load order issue. The issue is there is framework host/space (React) and user space (your app's code). User stuff only runs after host stuff. The host (React) polyfills The fix would be for React Native to ship with a Symbol polyfill. However that is a harder solution, because that's not a matter of just putting a bugfix in RN. That is a matter of changing the decision of what polyfills should be shipped with React Native for all apps, which is something we have to get Facebook to decide. |
It should be possible to add the polyfill using metro’s config file, it will run before any other code. See https://github.com/facebook/react-native/blob/master/rn-cli.config.js#L24 and https://github.com/facebook/react-native/blob/master/rn-get-polyfills.js. You can create your own rn-cli.config.js at the root of your project and extend what polyfills are included. |
@dantman sorry that was a bit harsh, I spent half the day upgrading RN to 0.52 to get this commit and it didn't solve my issue :)
@janicduplessis I'm going to try this approach and report back! |
I gave it a try but couldn't get the bundler to work, it seems |
@cosmith Thanks for trying it out, it sucks that it does not work :( It seems like RN doesn't load a Set / Map polyfill, are you sure require'ing the polyfill before any other code doesn't work? import statements get hoisted at the top of the file so to be sure I would do something like in index.js: require('core-js/es6/symbol');
const React = require('react');
const ReactNative = require('react-native');
... |
@janicduplessis RN has its own custom Set & Map polyfills it loads. These are loaded in the host environment, before index.js is ever required. |
@dantman Oh I see, it gets set in InitializeCore, which does effectively run before the main module. Looks like it is configured here react-native/local-cli/util/Config.js Line 73 in 654fed4
|
Wouldn't it be easier to just add a Symbol polyfill to RN? I tried the rn-cli.config.js approach but I couldn't get it to load the corejs polyfills. |
Guyz please do understand it might not only be the problem with react native. Be careful while integrating it with firebase. |
This usage of
...
currently causes BackHandler to silently become non-functional when aSymbol
polyfill is used.Why?
[...obj]
operator implicitly calls the object's iterator to fill the arraySet
polyfill has a load order issue that breaks it whenever a project uses aSymbol
polyfillBackHandler
tries to[...set]
aSet
of subscriptions the result is always an empty array instead of an array of subscriptionsAdditionally it's worth noting that the current code is also wastefully inefficient as in order to reverse iterate over subscriptions it:
Set
(which fills it by implicitly running the set's iterator)[...set]
to convert the cloned set into an array (which also implicitly runs the iterator on the clone)This code fixes this problem by replacing the use of multiple Set instance iterators with a simple
.forEach
loop that unshifts directly into the final array.Test Plan
I've tested this by opening the repo's RNTester app on Android and tvOS ensuring that the back handler works before changes, the application crashes when I introduce an error (to verify my code changes are being applied to the app), the back handler works and after changes.
Fixes #11968