Skip to content

fix: app.doc is dead; app.document is never assigned#115

Merged
BorisTyshkevich merged 1 commit into
mainfrom
fix/app-document-seam-106
Jul 1, 2026
Merged

fix: app.doc is dead; app.document is never assigned#115
BorisTyshkevich merged 1 commit into
mainfrom
fix/app-document-seam-106

Conversation

@BorisTyshkevich

Copy link
Copy Markdown
Collaborator

What & why

Closes #106.

createApp built the app object with a doc: field, but every other module in the codebase (explain-graph.js, results.js, schema-detail.js, file-menu.js, shortcuts.js, and app.js itself) read app.document instead — which was never assigned. app.document || document therefore always silently fell through to the global document. Harmless today only because env.document is unset in production and every test helper coincidentally passes the same global document — but a footgun the injected-seam pattern (CLAUDE.md rule 2) exists to prevent.

Fix:

  • src/ui/app.js: doc:document: doc in the app object literal; renderApp's const { state, doc } = appconst { state, document: doc } = app; two internal app.document || document sites become bare app.document (only ever called against the live, fully-built app).
  • src/ui/file-menu.js (openFileMenu, openConfirm) and src/ui/results.js (openRowsViewer, expandDataPane, openCellDetail) — dropped the now-dead || document fallback, verified per call site against every caller in src/ and tests/ (all go through makeApp(), which always sets document).
  • Left untouched (deliberately null/minimal-app-tolerant, confirmed by dedicated tests): src/ui/detached-view.js, src/ui/explain-graph.js, src/ui/schema-detail.js, and src/ui/shortcuts.js (which has its own delete app.document regression test predating this issue).
  • Added a regression test in tests/unit/app.test.js asserting app.document resolves to an injected custom document, not the global one.

Test plan

  • npm test — 50/50 files, 1283/1283 tests pass, coverage gate holds.
  • npm run builddist/sql.html builds clean; verified the minified output correctly compiled e.document.addEventListener(...).
  • /code-review (3 parallel finder angles + verify) — zero findings.
  • Manual verification against a live ClickHouse cluster (antalya.demo.altinity.cloud, via npm run local + Playwright/Chromium): ran a query, opened the File menu, opened a cell-detail drawer, and expanded a result into a real detached tab (a genuine second document — the exact seam this fix targets). All three worked correctly with no regressions.

Checklist

  • npm test passes (the per-file coverage gate is non-negotiable)
  • Tests added/updated in the same change as the code
  • npm run build succeeds (single-file dist/sql.html)
  • Layers kept honest: pure logic in src/core/, network in src/net/ (injected fetch), DOM in src/ui/
  • No new runtime dependency
  • CHANGELOG.md ([Unreleased]) updated
  • Reconciled affected tracked work — this is a standalone inbox issue, not part of roadmap Roadmap to 1.0.0 #68's phased build order, so no Roadmap to 1.0.0 #68/ADR changes needed

🤖 Generated with Claude Code

https://claude.ai/code/session_01784dKCpk5W7rdpUAwcQnix

createApp built the app object with a `doc` field, but every other module
(explain-graph.js, results.js, schema-detail.js, file-menu.js, shortcuts.js,
app.js itself) read app.document instead — never assigned, so
`app.document || document` silently always fell through to the global
document. Rename app.doc -> app.document and drop the fallbacks that were
provably unreachable; leave the ones intentionally tolerant of a null/minimal
app (detached-view.js, explain-graph.js, schema-detail.js, and
shortcuts.js — which has its own delete-app.document test) untouched.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01784dKCpk5W7rdpUAwcQnix
@BorisTyshkevich BorisTyshkevich merged commit 3193e07 into main Jul 1, 2026
6 checks passed
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.

app.doc is dead; app.document is never assigned (silently falls back to global document everywhere)

1 participant