Add support for `atob()` and `btoa()` functions
jonkoops opened this issue ยท 20 comments
Problem
Much of the existing code in the JavaScript ecosystem, such as packages on NPM contain code that uses the atob()
and btoa()
global functions. And although not strictly part of the ECMAScript specification, it might be worthwhile to support these for the sake of compatibility with the rest of the ecosystem. Other runtimes that are also not strictly web-based such as Node.js, Bun and Deno all support these functions as well.
Solution
Add support for the atob()
and btoa()
global functions to Hermes.
Additional Context
I contribute to jwt-decode
, a popular library (~5.7 million downloads per week) to decode JSON Web Tokens. One of the users logged an issue specifically referencing this issue in React Native, and by extension Hermes (see auth0/jwt-decode#241).
It seems that JSC supports these, which is a pretty strong argument in favor of adding them.
@tmikov My understanding is that these were added to JSC relatively recently, and only to the CLI tool. (in WebKit/WebKit@70ccbd9). So RN users on JSC would likely still need an atob
polyfill.
There seem to be three options:
- Continue using the polyfill, which may be slow if the inputs are large.
- Adding Base64 encoding and decoding to Hermes natively.
- Add an implementation over JSI to RN. But this will be clumsy to write because JSI forces strings to be converted to UTF-8, which means we will force some unnecessary conversions for the binary string. If we do this, we should consider adding functions to convert to/from
std::u16string
.
Issues like this will keep popping up. I think we need to figure out a general way to address them without the overhead of JSI. An optional "library" .so perhaps.
I've been using the JSI based https://github.com/craftzdog/react-native-quick-base64
Issues like this will keep popping up. I think we need to figure out a general way to address them without the overhead of JSI. An optional "library" .so perhaps.
The pure JS polyfills everyone recommends in these threads are even worse than JSI!
Issues like this will keep popping up. I think we need to figure out a general way to address them without the overhead of JSI. An optional "library" .so perhaps.
It's perplexing to me how long the RN runtime has existed without these critical Web APIs. I think it would be uncontroversial to say that the platform is critically incomplete without them. I know it doesn't belong in Hermes and you get these requests here. But why are the runtime team disregarding the lack of these APIs that exist in every web runtime and native platform?
@tmikov Why can't the atob/btoa, crypto, web streams, etc. C++ libraries from Chromium just be inserted into the React Native core and exposed through JSI?
Good news, folks! We have decided to add these to Hermes. We should have them soon. We are also working on a way to handle this in general in Static Hermes, by automatically pulling such functions in only when they are needed.
Of course, we realize that after we commit these new functions, it then takes a significant time for them to actually be usable, because the next RN release needs to happen, and then users need to upgrade to it...
We plan to also address this problem very soon by introducing a stable Hermes ABI, which will allow Hermes to be upgraded freely independently of RN.
That is great news, thanks so much for considering this and the quick and efficient handling of this issue!
Cool, I want to use it. How can I understand in which version it will land and which version used in a react-native project?
@Bardiamist React Native automatically uses the latest Hermes version when they cut a release, so it will be in the next RN release, I guess 0.74.
Is it possible to see versions? 0.12.0
is the latest version of Hermes? It's strage because of more than year ago.
And how to see Hermes used version in react native?
@Bardiamist for now Hermes is distributed as part of RN and has no independent distribution or version. You can see versions as branches in the Hermes repo:
@tmikov just to verify, as I am having some trouble reading the changelog for React Native, has this been released in version 0.73?
@jonkoops No, this commint not in https://github.com/facebook/hermes/tree/rn/0.73-stable
Also I checked that atob
doesn't exist in react-native@0.73.4
just now
Thanks for checking that @Bardiamist. I'll assume this will be landing in version 0.74 then.
How do you check if atob is included ?
0.74 has released by now, would be nice to see if this is settled.
Thanks
One simple way to see whether it is available using the CLI:
echo "print(typeof atob)" | hermes
Now atob
has issue reactwg/react-native-releases#287
But should be fix will be cherry picked soon
@TwistedMinda I am using react-native 0.74.1 atob and btoa are now working for me.
@wh201906 do you have a specific case where the performance of atob()/btoa() is unsatisfactory? On what platform?
The Hermes team doesn't have bandwidth to experiment with faster implementations of these. But if there is a PR that measurably improves performance on all supported platforms without dramatically increasing the binary size (which is very important for a mobile platform), we will consider it.