Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Public buffer getChars and translateToString truncate multi-codepoint graphemes

Open
#200 0 comments 0 reactions 0 assignees View on GitHub

@schickling-assistant is already working on this.

Since Oct 1, 2026.

  • #201 by @schickling-assistant — open

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
76/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
typescript, wasm
Domain
frontend, web-dev

Research direction

Start with Buffer.getLine(), BufferCell.getChars(), and translateToString(), then compare their scalar-cell handling with the existing viewport and scrollback grapheme accessors. Reproduce the examples with Bun 1.4.2 and verify that exported buffer text preserves each complete grapheme while retaining existing line snapshot behavior and empty wide-character spacer cells.

Written by the indexing model from the issue text.

Description

Problem

[email protected] public buffer getChars() and translateToString() truncate multi-codepoint graphemes. The real WASM core retains the complete text; this report is specifically about buffer export, not visible canvas rendering or parsing.

Minimal reproduction

After bun add [email protected], run with Bun 1.4.2:

import { Ghostty, Terminal } from 'ghostty-web'
const ghostty = await Ghostty.load()
for (const input of ['ASCII', 'é', '👩‍💻', '👋🏽', '🇺🇸']) {
  const core = ghostty.createTerminal(24, 2)
  const terminal = new Terminal({ ghostty, cols: 24, rows: 2 })
  // Headless setup only: attach the real WASM core to the public buffer wrapper.
  terminal.wasmTerm = core
  core.write(input)
  const line = terminal.buffer.active.getLine(0)
  console.log({ input, buffer: line.translateToString(true),
    firstCell: line.getCell(0).getChars(), core: core.getGraphemeString(0, 0) })
  // Do not dispose these instances: teardown corruption is separately tracked in #141.
}

Expected: buffer export equals input. Actual: ASCII matches, but é becomes e, 👩‍💻 becomes 👩, 👋🏽 becomes 👋, and 🇺🇸 becomes 🇺. The low-level grapheme lookup returns complete text in every case. Reproduced on Linux x64.

Root cause / proposed fix

Buffer.getLine() only forwards scalar cells to BufferLine; BufferCell.getChars() uses String.fromCodePoint(cell.codepoint) without consulting grapheme_len or the existing viewport/scrollback grapheme accessors. translateToString() concatenates these truncated values.

Snapshot complete grapheme text alongside the scalar cells when creating a buffer line, using the appropriate viewport or scrollback lookup. This preserves existing line snapshot behavior and empty wide-character spacer cells.

Repeated open/closed issue and PR searches found no matching buffer-export report. Related but distinct: #141 tracks memory corruption when freeing terminals containing these graphemes; this is not a duplicate report for that teardown bug.

Posted on behalf of @schickling
field value
agent_identity unknown
session dev5.01a09047
agent_persona generalist
agent_supervisor unavailable
agent_tool OMP
agent_tool_version 18.4.4
agent_runtime OMP 18.4.4
agent_model anthropic/claude-opus-5-5
worktree dotfiles/main
tooling_profile dotfiles@7a9494a
Dominant language
TypeScript
Stars
2.9k
Forks
182
PR merge metrics
No merged PRs in 30d

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from coder/ghostty-web

All issues in coder/ghostty-web

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.