The `initDataAndEngine` function in `src/main.ts` was extremely long and handled the initialization of multiple loosely related components (engine, data, extensions, workspace, editor, and search controller).
This commit extracts those distinct responsibilities into their own smaller, self-contained functions (`initEngine`, `initData`, `initExtensions`, `initWorkspace`, `initEditor`, and `initSearchController`), which are now sequentially called by the original `initDataAndEngine` function.
This improves maintainability and readability without altering the underlying logic or initialization order.
Co-authored-by: Horizontal42 <75383519+Horizontal42@users.noreply.github.com>
- vitest actually runs 373 cases across 21 files, not 259
- added workspace.ts, sparkline.ts, logger.ts to the file tree in ARCHITECTURE
- fixes in all four language variants: README + ARCHITECTURE in EN and RU
* perf: Optimize DOM writes in drag mousemove event
Optimizes the drag-and-drop `mousemove` event handler by caching the previously hovered element. The `drag-over` class is now only removed from `prevOver` and added to the new hover target, instead of looping through all `cachedItems` to remove the class on every move. This eliminates layout thrashing and high CPU usage during drag operations.
Co-authored-by: Horizontal42 <75383519+Horizontal42@users.noreply.github.com>
* drop stray benchmark script
---------
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Replaces the deeply nested if-chain inside the Pratt parser loop in `src/engine/parser.ts` with a `switch` statement over token types. Introduces a labeled `loop: for(;;)` to maintain accurate `continue`/`break` semantics while greatly enhancing the visual parsing and extensibility of the logic without hurting evaluation speed.
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Added exported constants `DEC_ZERO` and `DEC_ONE` in `src/engine/types.ts`
and replaced all instances of `new Decimal(0)` and `new Decimal(1)`
across `src/engine/evaluator.ts` with these constants.
This reduces unnecessary memory allocations and garbage collection
overhead in the evaluator engine, especially during hot loops like
goal seek (root finding).
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
- Extracts `data.docs.find((d) => d.id === ...)` into a helper function to deduplicate finding document logic.
- Cleans up an unused `data` parameter on `setupDocInteraction`.
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
* 🔒 [security fix] Remove unsafe path canonicalization in directory gate
🎯 What:
Removed filesystem-level path canonicalization in the DataDirGate check (`canon_or_raw`).
⚠️ Risk:
An attacker could bypass directory authorization by creating a symlink to an authorized directory, allowing them to redirect arbitrary path reads/writes via TOCTOU (Time-of-Check to Time-of-Use) attacks or misleading unverified paths.
🛡️ Solution:
Replaced `fs::canonicalize` with purely lexical path normalization (resolving `.` and `..` in memory) to ensure strict string match validation without following symlinks. Ensure relative paths with `..` that go above the start are handled securely.
Co-authored-by: Horizontal42 <75383519+Horizontal42@users.noreply.github.com>
* 🔒 [security fix] Remove unsafe path canonicalization in directory gate
🎯 What:
Removed filesystem-level path canonicalization in the DataDirGate check (`canon_or_raw`).
⚠️ Risk:
An attacker could bypass directory authorization by creating a symlink to an authorized directory, allowing them to redirect arbitrary path reads/writes via TOCTOU (Time-of-Check to Time-of-Use) attacks or misleading unverified paths.
🛡️ Solution:
Replaced `fs::canonicalize` with purely lexical path normalization (resolving `.` and `..` in memory) to ensure strict string match validation without following symlinks. Ensure relative paths with `..` that go above the start are handled securely without dropping components incorrectly. Added proper Iterator methods to appease clippy.
Co-authored-by: Horizontal42 <75383519+Horizontal42@users.noreply.github.com>
---------
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Extracted `evaluateText` helper function in `src/engine/edge.test.ts` to replace the repeated mapping `eng.evaluateDocument(doc).map((x) => x.text)`.
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Moved the evaluation of `this.sheets()` outside of the `while (changed)` invalidation loop to avoid redundant evaluations and allocations on deep dependency chains.
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Adds a test to `src/workspace.test.ts` to ensure that when `engine.evaluateDocument` throws an exception, the `this.resolving` set is correctly cleaned up in the `finally` block of `doEvaluate`.
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
In `src/ui/search.ts`, numeric threshold searches previously called `doc.text.split("\n")` eagerly on every open document. This commit changes `lines` to be lazily allocated only if an actual numeric search match is found, eliminating unnecessary memory allocations and loop overhead on documents that do not match.
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
* perf: avoid expensive doc stringification for autocomplete
Refactored the autocomplete variable matching logic in `src/ui/editor.ts` to iterate through document lines using CodeMirror's `iterLines()` instead of allocating the entire document string in memory with `toString()`. Also pulled the regex up and introduced a quick `.includes("=")` bailout to skip the regex engine completely for most lines.
Co-authored-by: Horizontal42 <75383519+Horizontal42@users.noreply.github.com>
* drop stray benchmark script
---------
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Adds a test file `src/logger.test.ts` to verify that `logger.info`, `logger.warn`, and `logger.error` correctly call the underlying console methods with the passed arguments.
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
resp.bytes() already pulls the whole body into memory before the 5MB
check ran, so a malicious server could still OOM the process during
download. read_body_capped aborts mid-stream once the cap is hit.
also fix goal-seek probe fallback: it could update lo/hi to a genuine
bracket without ever setting found=true, throwing "no solution" on
cases that do have one.
- Fix race condition in write_atomic_bytes by using unique temp file names
- Fix logic flaw in DataDirGate authorization on migration failures
- Reject invalid padding in base64_decode
- Set size limits on json fetches for rates
- Fix Date math around DST boundaries for tomorrow/yesterday
- Handle division by zero exceptions gracefully in goal seek
- Fix OOM vector for huge hexadecimal number rendering
split bundle config into tauri.{windows,linux,macos}.conf.json so each
platform only carries its own targets; gen-icon emits icon.icns; macos is
ad-hoc signed since arm64 refuses unsigned downloads
- Exported searchAllSheets from src/ui/search.ts
- Added comprehensive unit tests in src/ui/search.test.ts testing full-text and numeric threshold searches