fix(base64_encode): encode large input in browser builds (#969)

The browser base64Encode spread every UTF-8 byte of its input into a
single String.fromCharCode call, one argument per byte, so input past
the engine's argument limit threw: past ~125 KB on V8 ("Maximum call
stack size exceeded") and past 64 KB on engines that cap arguments at
65535, such as QuickJS. It now converts the bytes in 32 KB chunks. The
node build, which encodes with Buffer, is unchanged.

Fixes #967

Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
Josef Guenther
2026-10-02 01:43:08 +08:00
committed by GitHub
co-authored by Claude Opus 5.5
parent 7dfa76b7b2
commit 8aace78beb
2 changed files with 11 additions and 1 deletions
+5
View File
@@ -52,6 +52,11 @@ describe('base64-impl/browser', function () {
it('should encode boolean strings', function () { it('should encode boolean strings', function () {
expect(base64.base64Encode('true')).toBe('dHJ1ZQ==') expect(base64.base64Encode('true')).toBe('dHJ1ZQ==')
}) })
it('should encode a large string', function () {
const str = 'Hello 🌍'.repeat(20000)
expect(base64.base64Encode(str)).toBe(Buffer.from(str).toString('base64'))
})
}) })
describe('#base64Decode()', function () { describe('#base64Decode()', function () {
+6 -1
View File
@@ -1,6 +1,11 @@
export function base64Encode (str: string): string { export function base64Encode (str: string): string {
return btoa(String.fromCharCode(...new TextEncoder().encode(str))) const bytes = new TextEncoder().encode(str)
let binary = ''
for (let i = 0; i < bytes.length; i += 0x8000) {
binary += String.fromCharCode(...bytes.subarray(i, i + 0x8000))
}
return btoa(binary)
} }
export function base64Decode (str: string): string { export function base64Decode (str: string): string {