Skip to content

atob and btoa should not be marked as legacy #57145

Description

@chee

Affected URL(s)

https://nodejs.org/docs/latest/api/globals.html#atobdata https://nodejs.org/docs/latest/api/buffer.html#bufferatobdata

Description of the problem

hey!

i notice that atob and btoa are marked as Legacy, which states "no longer actively maintained, and other alternatives are available".

some notes on that:

  1. they do seem to still be maintained:
  2. the alternative listed is not an equivalent. atob and btoa are optimized at the C++ level, and do not create an in-memory Buffer in javascript context that then has to be garbage collected (needless, for instance, when ⁠ JSON.parse(atob(b64)))

having these marked as legacy also seems to go against the very good direction node has taken recently of compatibility with web apis like the webstreams api

i think it would be great if these were marked Stability 2! what do you think?

Activity

added
docIssues and PRs related to Node.js documentation.
on Feb 20, 2025

panva commented on Feb 20, 2025

@panva
Member

Even if their legacy status has been somewhat weakened by the fact that they were optimized it stands to say that they were not optimized as much as other methods and their proper replacement being https://github.com/tc39/proposal-arraybuffer-base64 is going to be generally available soon(ish)12.

I don't think we need to be doing any changes here. If anything I'd say we update the new recommendation to be the new Uint8Array methods as soon as they become available in V83 (and soon thereafter in node).

Footnotes

  1. https://caniuse.com/mdn-javascript_builtins_uint8array_frombase64 ↩

  2. https://caniuse.com/mdn-javascript_builtins_uint8array_tobase64 ↩

  3. https://issues.chromium.org/issues/42204568 ↩

added
web-standardsIssues and PRs related to web-platform APIs and standards compliance.
on Feb 20, 2025

chee commented on Feb 20, 2025

@chee
Author

I love the new Uint8Array methods! i've been using them in Firefox, and they're great. Though I still don't think they're a great replacement for every usecase:

this is making a lot more Stuff:

JSON.parse(new TextDecoder().decode(Uint8Array.fromBase64("eyJoZWxsbyI6IndvcmxkIn0=")))

than this:

JSON.parse(atob("eyJoZWxsbyI6IndvcmxkIn0="))

and that can really matter in memory-sensitive applications!

atob and btoa are stable and fantastic at their job. they're also stable in the web platform and deno. i don't know if that matters so much, but i think many of us really appreciate the cross-runtime compatibility.

targos commented on Feb 20, 2025

@targos
Member

But that's not the same! atob and btoa don't work with UTF-8 encoding. This kind of confusion is one of the main reasons that we discourage their use.

targos commented on Feb 20, 2025

@targos
Member

Example to illustrate:

> Buffer.from(JSON.stringify({check: '✓'})).toString('base64')
'eyJjaGVjayI6IuKckyJ9'

> btoa(JSON.stringify({check: '✓'}))
Uncaught:
DOMException [InvalidCharacterError]: Invalid character
    at btoa (node:buffer:1288:11)

JakeChampion commented on Feb 20, 2025

@JakeChampion

But that's not the same! atob and btoa don't work with UTF-8 encoding. This kind of confusion is one of the main reasons that we discourage their use.

Correct, and this fact, that they are not the same was mentioned in the original comment:

  1. the alternative listed is not an equivalent.

Because they are not the same, we can't suggest that someone use the suggested alternative for all use-cases, since those differences might be important for them.

It seems like what we likely want to do here is not mark this as legacy, and also direct to newer APIs for specific scenarios, which is what MDN has chosen to do. This would also align with Deno and with Bun, both of whom do not mark atob btoa as legacy.

Image

panva commented on Feb 20, 2025

@panva
Member

A method marked as legacy has no functional or future deprecation related consequences tho. And it is exactly that, legacy. It's part of the HTML standard, not ECMAScript. It doesn't work with utf-8 inputs and it has considerable drawbacks when you actually want to use it with large inputs and eventually move those in/out of Uint8Array.

Because they are not the same, we can't suggest that someone use the suggested alternative for all use-cases, since those differences might be important for them.

They are the same in that they're compatible in terms of what they accept, and they actually accept more, which is not to the user's detriment.

jasnell commented on Feb 20, 2025

@jasnell
Member

These were marked as Legacy for the simple reason that we want to subtly discourage users from reaching for them while we have better options readily available. When they were proposed to be added there was some disagreement about whether they should be and adding them with the legacy flag was the compromise that was reached. Being marked as legacy means it won't be deprecated or removed but that it's not the thing we recommend that you use. In every other way they are perfectly fine to make use of.

joyeecheung commented on Feb 20, 2025

@joyeecheung
Member

having these marked as legacy also seems to go against the very good direction node has taken recently of compatibility with web apis like the webstreams api

The status of being legacy doesn't really have much to do with compatibility - the fact that they were implemented as legacy features from the beginning is already a choice made with consideration of compatibility. If we are indeed going against this trend then this API would be added in the first place. As @jasnell mentioned the legacy status in the docs is just a way of discouraging usage when there are better alternatives (in this case, the typed array methods or TextDecoder etc. that are capable of handling non-ASCII characters properly).

It seems like a better way forward is to document why it's considered legacy and what's the better alternative instead. We can add a "good first issue" label to see if someone is interested in sending a documentation PR if there's agreed.

joyeecheung commented on Feb 20, 2025

@joyeecheung
Member

Also, I think the fact that the OP states needless, for instance, when ⁠ JSON.parse(atob(b64)) is somewhat concerning already, because it seems to already been giving people an idea that you don't need to worry about what happens when e.g. b64 = Buffer.from('{"a": "测试"}').toString('base64')

JakeChampion commented on Feb 20, 2025

@JakeChampion

I'm just not sure why these needed to be marked 'legacy' within NodeJS when it seems that no other runtime has marked them as legacy, including sites such as MDN. The messaging to the end-user is mixed. I understand wanting to encourage other alternative APIs, can that be achieved whilst also not tagging these functions as 'legacy'?

Also, I think the fact that the OP states needless, for instance, when ⁠ JSON.parse(atob(b64)) is somewhat concerning already, because it seems to already been giving people an idea that you don't need to worry about what happens when e.g. b64 = Buffer.from('{"a": "测试"}').toString('base64')

I would assume the OP shortened the example and was likely using input which is always latin-1 such as HTTP Field Values:

var h = new Headers
h.set('hello', 'world')
h.set('a', 'à') 

JSON.parse(
  atob(
    btoa(
      JSON.stringify(
        Object.fromEntries(
          h.entries()
        )
      )
    )
  )
) // { a: "à", hello: "world" }

chee commented on Feb 20, 2025

@chee
Author

A method marked as legacy has no functional or future deprecation related consequences tho

Being marked as legacy means it won't be deprecated or removed

This is great news! the documentation for "Stability 3" is slightly less firm on that point, stating "unlikely to be removed" and "unmaintained". If it were to say "will continue to be maintained, will not be deprecated or removed, but is discouraged" in the docs I probably wouldn't have come here.

I'll see if I can get manager sign-off on the use of legacy atob to decode serialized latin-1 base 64 strings off the back of the commitments in this thread.

jasnell commented on Feb 21, 2025

@jasnell
Member

The documentation was written to give us long term wiggle room Just In Case but I cannot foresee any circumstance where Node.js would remove atob/btoa or not fix any bugs that may be found, so I'd say you're safe.

chee commented on Feb 21, 2025

@chee
Author

@jasnell thank you <3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    docIssues and PRs related to Node.js documentation.web-standardsIssues and PRs related to web-platform APIs and standards compliance.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions