Added a test in `src/engine/engine.test.ts` to mock evaluation failure and verify the engine safely catches it, nulls the value, populates the error string, and logs a warning.
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
Removes the 'unsafe-inline' directive from the style-src Content
Security Policy to prevent potential Cross-Site Scripting (XSS)
or malicious style injections. Replaces inline style manipulations
(`style.display = "none"`, `style=""`) with class list toggling
using a new `.d-none` utility class.