png-base64.ts

PURPOSE

Chunked binary-to-base64 encoder that survives buffers above ~1 MB. The naive btoa(String.fromCharCode(...bytes)) pattern crashes on large arrays because the spread hits V8’s argument-count limit; this module slices the buffer into 32 KB windows and concatenates the encoded chunks.

OWNS

  • CHUNK = 0x8000 (32 768) — slice size, safely under String.fromCharCode argument limits.
  • bytesToBase64(bytes: Uint8Array): string — only exported symbol.

READS FROM

  • Uint8Array input only. No file, DOM, or store access.

PUSHES TO

  • Returns a base64 string. Caller decides where it goes (data URL, clipboard, download blob).

DOES NOT

  • Decode base64 (encode-only).
  • Validate or sniff PNG headers — name is for the workbench caller’s intent, not for any PNG-specific work here.
  • Stream or chunk the output incrementally; the whole base64 string is built in memory.
  • Use TextDecoder, FileReader, or Blob APIs.

Signals

  • None.

Entry points

  • bytesToBase64(bytes) — called by VFX-workbench export paths that need to embed rendered PNGs into a data URL or copy them to clipboard.

Pattern notes

  • Uses subarray (zero-copy view) rather than slice (copy) per chunk.
  • Cross-runtime fallback: prefers btoa in browsers, falls back to Buffer.from(out, 'binary').toString('base64') under Node so tests can run headless.
  • String.fromCharCode.apply(null, slice as unknown as number[]) — the cast is the standard workaround for apply accepting ArrayLike<number> while TS types the typed-array slice as Uint8Array.

EXTRACT-CANDIDATE

Pure, no engine deps, no workbench-specific logic. Could live in a shared engine/util/base64.ts if any other system ever needs large-buffer base64 (screenshot export, replay packing, telemetry blob upload). Move when the second caller appears.