Skip to content

feat: use native alternatives to encode/decode base64#136

Open
mrkishi wants to merge 4 commits intosveltejs:mainfrom
mrkishi:arraybuffer
Open

feat: use native alternatives to encode/decode base64#136
mrkishi wants to merge 4 commits intosveltejs:mainfrom
mrkishi:arraybuffer

Conversation

@mrkishi
Copy link
Member

@mrkishi mrkishi commented Mar 20, 2026

The Typed Array support added in #69 included a js implementation of atob/btoa, because they're deprecated by Node.

These days, we have a couple of reliable (and more performant) alternatives:

  • On modern runtimes (baseline 2025), Uint8Array provides both fromBase64 and toBase64.
  • On Node-compatible runtimes (Bun/Deno/Cloudflare Workers, etc), the global Buffer can be used to perform the conversions.
  • On legacy runtimes, platform-provided atob and btoa are still considerably faster than a pure js implementation.

This PR includes the three options, selected at runtime based on Uint8Array.fromBase64 and process.versions.node availability.

On the version bump

I made this a minor change, but there's a slight modification to the stringified format (to avoid an extra subarray call). Depending on the answer to #130, this might be cause for a major, or the format change could be dropped while keeping the native base64 codecs.

Edit: Since there have been patch releases changing the format, I assume there's been no commitment to keeping it stable.

Benchmarks

On my machine, it benchmarks orders of magnitude faster across small (100 bytes), medium (10kb) and large (1mb) ArrayBuffer workloads.

stringify: small
  time: fastest is b (arraybuffer)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 1064.81ms
    b: ◼◼◼◼◼◼◼              368.03ms
stringify: medium
  time: fastest is b (arraybuffer)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 704.73ms
    b:                      8.22ms
stringify: large
  time: fastest is b (arraybuffer)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 2692.95ms
    b:                      22.10ms



parse: small
  time: fastest is b (arraybuffer)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 1320.86ms
    b: ◼◼◼◼◼◼               425.32ms
parse: medium
  time: fastest is b (arraybuffer)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 900.67ms
    b: ◼                    45.84ms
parse: large
  time: fastest is b (arraybuffer)
    a: ◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼◼ 1470.36ms
    b: ◼                    43.12ms

Alternatives

I believe this supersedes both #90 and #107 since they don't meaningfully improve the encoded size for the performance loss (while they're both faster than status quo, they're still a couple orders slower than native base64).

Stacked on #135 to use the benchmarks.

@changeset-bot
Copy link

changeset-bot bot commented Mar 20, 2026

🦋 Changeset detected

Latest commit: 00fc6db

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
devalue Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

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.

1 participant