Skip to content

id(web): terminalBytesForKey treats Object.prototype members as special keys — 'toString'/'constructor' send native-function source bytes as world terminal input instead of null #2919

Closed

Description

@dezren39

id(web): terminalBytesForKey treats Object.prototype members as special keys — 'toString'/'constructor' send native-function source bytes as world terminal input instead of null

Evidence (verified this run, main 321dc21)

pkgs/id/web/src/world-keyboard.ts:20-35 — specialKeys is a plain object literal (Record<string, string>), and membership is tested with the in operator, which walks the prototype chain:

if (event.key in specialKeys) {
  ...
  return new TextEncoder().encode(specialKeys[event.key]);
}

The function's own contract (docstring, :23-25) is: "Returns null for browser/OS shortcuts and keys the Roc Key module does not recognize yet." Prototype-member names are not in the table, but in says they are, and the lookup returns the inherited Object.prototype member — a function or object — which TextEncoder.encode string-coerces.

Probe (verbatim copy of the file at this HEAD, md5-verified; laptop ~/git/fleet/probe-2026-10-30-laneA-keyboard/, bun run probe.ts):

key result
Enter "\r" (correct)
F5 null (correct)
toString "function toString() { [native code] }"
constructor "function Object() { [native code] }"
hasOwnProperty "function hasOwnProperty() { [native code] }"
valueOf "function valueOf() { [native code] }"
__proto__ "[object Object]"
isPrototypeOf "function isPrototypeOf() { [native code] }"

Why it matters

The only production caller is pkgs/id/web/src/world.ts:258, which forwards the returned bytes as terminal input to the running world (Roc) program. Any key event whose key is a prototype-member name — synthetic/programmatic events, IME or virtual-keyboard oddities, future callers feeding non-DOM key sources into this exported pure function — injects the JS engine's native-function source text into the world program as if the user typed it, instead of being dropped as unrecognized. This is the same plain-object-lookup class fixed for detectLanguage in #2787 and for LANG_IMPORTS in highlight.ts:284-286 (own-key check with an explanatory comment); world-keyboard.ts was missed, and it uses the even broader in operator.

Acceptance criteria

Dedup: searched open + closed issues for world-keyboard, specialKeys, terminalBytesForKey this run — no hits. #2787 covers highlight.ts only. Sibling filed the same run for mimeToExtension in image-upload.ts (same class, different file/function/caller — independently fixable).

Activity

  1. added
    queue/queuedHas a queued task in the Supabase agent queue
    source/creatorFiled by the new-issue-creator job
    task/triageQueue packet kind: verify, reproduce, and route this item
    priority/lowNice to have; do when convenient
    app/idPackage/app: id (pkgs/ or apps/ in this repo)
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    effort/xsTrivial: expected under 30 minutes of work
    on Oct 31, 2026
  2. dezren39 commented on Oct 31, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

  3. dezren39 commented on Oct 31, 2026

    @dezren39
    MemberAuthor

    Cross-link / dedup correction from the filing run (full dedup results arrived after filing): #732 also covers terminalBytesForKey but is a different bug — modified special keys (Alt+Backspace, Alt+Arrow) being dropped/degraded; this issue is only the prototype-member lookup. #2792 is the open design issue for one own-key rule across dynamic lookups; this filing is a concrete verified instance in world-keyboard.ts for its tracker. Sibling instance: #2920.

  4. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 1, 2026
  5. 54 remaining items

  6. added
    status/parkedDeliberately paused with a recorded resume condition
    and removed
    queue/claimedQueue worker lifecycle state
    on Nov 2, 2026
  7. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    agent-note:v1 — holder: repo-worker-code (OpenChamber scheduled lane), at 2026-11-02T13:51:29Z. event: picked-up; task: 5472; queue: repo-health-code-pilot.

  8. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    agent-note:v1 — holder: repo-worker-code (OpenChamber scheduled lane), at 2026-11-02T13:51:33Z. event: parked; task: 5472; queue: repo-health-code-pilot. Canonical PR #4265 remains open and Drew-owned; hard stop. Resume after explicit handoff/ownership change or PR disposition, then revalidate fresh. PR contents, branch, worktree and source were not inspected or touched; no competing work.

  9. added
    queue/claimedQueue worker lifecycle state
    and removed
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Nov 2, 2026
  10. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  11. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done

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

Metadata

Metadata

Assignees

Labels

app/idPackage/app: id (pkgs/ or apps/ in this repo)effort/xsTrivial: expected under 30 minutes of workkind/bugSomething isn't working (prefixed form of the classic bug label)priority/lowNice to have; do when convenientsource/creatorFiled by the new-issue-creator jobtask/small-fixQueue packet kind: bounded fix with reproduction and targeted tests

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions