Skip to content

perf + cleanup pass: debounce, dedup, dead-code removal, builder tests#708

Merged
michaelpporter merged 14 commits into
mainfrom
perf-cleanup
Jun 5, 2026
Merged

perf + cleanup pass: debounce, dedup, dead-code removal, builder tests#708
michaelpporter merged 14 commits into
mainfrom
perf-cleanup

Conversation

@michaelpporter
Copy link
Copy Markdown
Owner

Incremental performance + code-cleanup pass, one item per commit. Build/typecheck clean throughout; test suite 212 → 242.

Resumable log at notes/perf-cleanup-log.md.

Performance

  • 1a Debounce view setting write-backs (TreeView/Matrix/TrailView → existing saveSettingsDebounced, 600ms) — coalesce rapid disk writes.
  • 1b Index date_note period lookups with a per-kind basename → PeriodNote Map (O(n·m) → O(n)).
  • 1c Debounce the opt-in layout_change graph rebuild (was a full rebuild on every CM6 cursor/scroll for opt-in users).

Cleanup

  • 2a Remove dead code (utils/markmap.ts, commented Traverse import, EdgeToAdd type).
  • 2b Replace risky any casts on plugin internals (Dataview registry access, metadataTypeManager.getAssignedWidget) with typed shapes; drop 4 eslint-disable comments.
  • 2c Remove the dead all_files.dataview file-source: drop the field from AllFiles/get_all_files and the 10 unreachable ?.forEach/map branches across 6 builders. Does not touch the dataview-from codeblock feature or the live Dataview API in dataview_note.
  • 3 Extract a shared validate_edge_field helper, replacing the copy-pasted 3-branch field validation at 9 sites across 7 builders. Error codes unchanged (tests assert on code only); message wording unified.

Tests

  • 4 / 4b Add coverage for the 5 previously-untested explicit builders (date_note, traverse_note, folder_note, dataview_note, list_note). date_note tests double as a regression guard for 1b (incl. the week_start monday/sunday edge case). Extended the shared test helpers with an app_extra arg and mock_file listItems/links options.

Verification

bun run build (tsc + svelte-check) and bun run test (242 passing) green at every commit. No vault-visible behavior changes.

Note: a few pre-existing src/ lint warnings remain untouched (folder_note ./files import order, list_note Array<T>, typed_link:97) — not introduced here.

TreeView, Matrix, and TrailView saved settings to disk on every local
$state change. Swap to the existing saveSettingsDebounced() (600ms) to
coalesce rapid disk writes. No behavior change.

Item 1a of the perf-cleanup pass; see notes/perf-cleanup-log.md.
add_period_edges resolved daily->period and finer->coarser targets with
Array.find() inside nested loops (O(n*m) string scans per rebuild). Build
a basename->PeriodNote Map per period kind once and look up via .get().
First-occurrence semantics match the prior find(); edges unchanged.

Item 1b of the perf-cleanup pass.
When the layout_change rebuild trigger is enabled, the handler called
rebuildGraph() directly on every CM6 cursor/scroll event. Route through
the existing rebuildGraphDebounced() (1500ms) like the else branch.
Trigger defaults to false, so only opt-in users were affected.

Item 1c of the perf-cleanup pass.
- delete unused src/utils/markmap.ts (never imported; the Markmap in
  CodeblockMarkmap comes from the markmap-view package)
- drop commented-out Traverse import in src/api/index.ts
- drop commented-out EdgeToAdd type in src/interfaces/graph.ts

Item 2a of the perf-cleanup pass.
- dataview get_api/is_enabled: cast app via a PluginRegistry interface
  instead of 'as any'; use dot notation. (External Dataview integration
  is still live via dataview_note builder + dataview-from codeblocks.)
- getMetdataPropertyType: cast metadataTypeManager to a one-method shape
  for the untyped getAssignedWidget, guarded by the existing 'in' check.

Drops 4 eslint-disable comments. Item 2b of the perf-cleanup pass.
The same 3-branch edge-field validation (falsy -> skip, non-string ->
invalid_field_value, unregistered -> invalid_edge_field) was copy-pasted
across the explicit builders. Extract it to validate_field.ts and call it
from folder, dendron, johnny_decimal, tag (field + sibling), list (field
+ neighbour), regex, and traverse builders.

- Error message wording unified to '<field> is not a valid field'; codes
  unchanged (tests assert on code only).
- traverse_note: drop dead 'raw || default_field' fallback (raw is always
  a truthy string there).

Item 3 of the perf-cleanup pass. 68 builder tests green.
Covers add_period_edges (the basename-index refactor): sequential next
edges, finer->coarser up edges (week->month, month->quarter), absent
target, and the daily->period week_start edge case (Sunday maps to the
current ISO week under 'monday', next week under 'sunday'). Plus the
invalid default_field error path. 9 tests; full suite 221 green.

Item 4 of the perf-cleanup pass (date_note portion).
Extend the shared test helpers: make_plugin gains an app_extra arg
(getAbstractFileByPath, resolvedLinks, cachedRead, dataview_pages) and
mock_file gains listItems/links cache options. Add tests for the four
previously-untested explicit builders (+21 tests):

- traverse_note: DFS over resolvedLinks, cycle protection, field errors
- folder_note: folder->sibling edges, recurse on/off, invalid field
- dataview_note: query->page edges, DataArray normalization, missing
  plugin + invalid query errors
- list_note: list-item child edges, field validation errors

Full suite 242 green. Item 4b of the perf-cleanup pass.
get_all_files has hardcoded dataview: null since the Dataview-page file
source was retired, so every all_files.dataview?.forEach/map branch in
the builders was unreachable. Remove the dataview field from AllFiles and
get_all_files, delete the 10 dead branches across 6 builders (date_note,
regex_note, tag_note, dendron_note, johnny_decimal_note, folder_note),
and drop the now-unused IDataview import in files.ts.

Does not touch the dataview-from codeblock feature or the live Dataview
API used by dataview_note. Internal only; 242 tests green.

Item 2c of the perf-cleanup pass.
All pre-existing, surfaced by the obsidianmd branch review:
- drop unnecessary non-null assertions (dataview_from, typed_link)
- unused catch bindings catch (_) -> catch (codeblocks/index, regex_note)
- move DateNoteSetupModal inline styles to a .bc-date-note-setup-warning
  CSS class (no-static-styles-assignment)
- scope MDRC's blanket eslint-disable to no-duplicate-type-constituents

242 tests green.
The obsidian community scorecard flags the blanket /* eslint-disable */
that wasm-pack emits atop wasm/pkg/*.d.ts. The project eslint config
already ignores **/*.d.ts, but the scorecard runs its own pass. Since
these files are generated, fix it in the build: factor the duplicated
post-wasm .gitignore step into a shared wasm:postbuild script that also
strips the eslint-disable line via perl -i, and apply it to the committed
files. Leaves the (unflagged) tslint:disable line.

Item 5b of the perf-cleanup pass.
wasm/pkg/ is generated by wasm-pack but committed so builds don't need a
Rust toolchain. Note that it's regenerated by wasm:build (with the
wasm:postbuild step) and shouldn't be hand-edited.
Removing the disable (prev commit) exposed the wasm-bindgen .d.ts to the
scorecard's full ruleset, which flagged no-explicit-any,
no-unsafe-function-type, and no-misused-new on generated code. Scope the
suppression instead: move the post-wasm step into scripts/wasm-postbuild.mjs,
which writes wasm/pkg/.gitignore and normalizes the generated .d.ts header
to a disable naming exactly those three rules. Satisfies the
'specify rule names' meta-rule while keeping generated bindings unlinted.
Idempotent across wasm-pack regenerations.

Item 5c of the perf-cleanup pass.
@michaelpporter michaelpporter merged commit dbf6563 into main Jun 5, 2026
1 check passed
@michaelpporter michaelpporter deleted the perf-cleanup branch June 5, 2026 14:33
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.

1 participant