Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,17 @@ auto-generated per-PR notes; this file is the curated, human-readable history.
.move()` (Chrome 110+) so a cancelled/failed export leaves a clearly-labeled,
inspectable partial artifact. Falls back to leaving the plain (non-renamed)
file on browsers without `.move()` support, or if the rename itself fails (#105).
- `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 back to the
global `document`, harmless today only because the two happened to coincide
in both production and tests. `app` now exposes `document` (not `doc`), and
the fallbacks that were provably unreachable (verified per call site against
`makeApp()` / real callers) were dropped; the fallbacks that are
deliberately null/minimal-`app`-tolerant (`detached-view.js`,
`explain-graph.js`, `schema-detail.js`, and `shortcuts.js` — which has a
dedicated `delete app.document` test) were left untouched. (#106)

## [0.1.5] - 2026-06-29

Expand Down
8 changes: 4 additions & 4 deletions src/ui/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export function createApp(env = {}) {
state: createState(),
dom: {},
root: env.root || doc.getElementById('root'),
doc,
document: doc,
token: ss.getItem('oauth_id_token'),
refreshToken: ss.getItem('oauth_refresh_token'),
// Charting seam: the Chart.js constructor (injected so tests stub it) and a
Expand Down Expand Up @@ -1478,7 +1478,7 @@ export function createApp(env = {}) {

/** Build the signed-in shell and mount all regions. */
export function renderApp(app, helpers) {
const { state, doc } = app;
const { state, document: doc } = app;
doc.documentElement.setAttribute('data-theme', state.theme);
doc.documentElement.setAttribute('data-density', state.density);

Expand Down Expand Up @@ -1613,11 +1613,11 @@ export function renderApp(app, helpers) {
// editor being focused so selecting elsewhere (results, address bar) is ignored.
app.syncSelection = () => {
const ta = app.dom.editorTextarea;
const focused = ta && (app.document || document).activeElement === ta;
const focused = ta && app.document.activeElement === ta;
const sel = focused ? ta.value.slice(ta.selectionStart, ta.selectionEnd) : '';
app.state.hasSelection.value = sel.trim() !== '';
};
(app.document || document).addEventListener('selectionchange', app.syncSelection);
app.document.addEventListener('selectionchange', app.syncSelection);
// Reactive repaint of the schema tree — replaces the scattered renderSchema()
// calls: re-runs on schema load, load error, filter text, or expand/collapse.
// Registered here (post-mount) so app.dom.schemaList already exists; the effect
Expand Down
4 changes: 2 additions & 2 deletions src/ui/file-menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export function renderLibraryTitle(app) {
/** Open the File dropdown anchored under the File button (Esc / outside-click close). */
export function openFileMenu(app) {
if (app.dom.fileMenu) return;
const doc = app.document || document;
const doc = app.document;
const list = app.state.savedQueries;
const close = () => {
doc.removeEventListener('keydown', onKey, true);
Expand Down Expand Up @@ -225,7 +225,7 @@ function confirmNew(app) {
}

function openConfirm(app, { title, body, confirmLabel, onConfirm }) {
const doc = app.document || document;
const doc = app.document;
const close = () => {
doc.removeEventListener('keydown', onKey, true);
if (app.dom.fileDialog) { app.dom.fileDialog.remove(); app.dom.fileDialog = null; }
Expand Down
6 changes: 3 additions & 3 deletions src/ui/results.js
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ function scriptOutcomeCell(app, e) {
* primitive is deferred to #60). Escape / backdrop / ✕ closes. Exported for tests.
*/
export function openRowsViewer(app, entry) {
const doc = app.document || document;
const doc = app.document;
let backdrop;
let cancelDrawerDrag = () => {};
const onKey = (ev) => { if (ev.key === 'Escape' && isTopDrawer(doc, backdrop)) close(); };
Expand Down Expand Up @@ -668,7 +668,7 @@ export function renderTable(app, r) {
* Exported for tests.
*/
export function expandDataPane(app, r) {
const mainDoc = (app && app.document) || document;
const mainDoc = app.document;
return openInDetachedTab(app, {
title: 'Data',
mode: 'grid',
Expand Down Expand Up @@ -815,7 +815,7 @@ function attachDrawerResize(app, panel, doc) {
}

export function openCellDetail(app, name, type, value, targetDoc) {
const doc = targetDoc || (app && app.document) || document;
const doc = targetDoc || app.document;
const text = value == null ? '' : String(value);
let backdrop;
let cancelDrawerDrag = () => {};
Expand Down
6 changes: 6 additions & 0 deletions tests/unit/app.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,12 @@ describe('createApp basics', () => {
expect(createApp(env({ faviconHref: undefined })).faviconHref).toBe('data:image/y;base64,BB');
linkEl.remove();
});
it('exposes the injected document as app.document, not just the global document', () => {
const customDoc = document.implementation.createHTMLDocument('');
const app = createApp(env({ document: customDoc, root: customDoc.createElement('div') }));
expect(app.document).toBe(customDoc);
expect(app.document).not.toBe(document);
});
});

describe('renderApp shell', () => {
Expand Down