Code Audit Report
All findings are reviewed for confidence before posting.
Please verify each finding before acting on it.
Repository: diffusionstudio/lottie
Findings: 6 issue(s) found — 🟠 2 high · 🟡 3 medium · 🔵 1 low
1. 🐛 __dirname is undefined in ESM Vite config
| Field |
Details |
| Severity |
🟠 High |
| Type |
Bug |
| File |
vite.config.ts |
| Location |
watchLottie() function (use of __dirname) |
| Confidence |
95% |
Problem:
The Vite configuration file is compiled as an ES module. In Node's ESM environment, the global __dirname variable is not defined, causing a ReferenceError at runtime when the config is loaded. This prevents the dev server from starting and breaks the watchLottie plugin.
Suggested Fix:
Replace __dirname with a reliable directory reference for ESM, e.g.,:
import { fileURLToPath } from 'node:url';
import { dirname } from 'node:path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
Then keep the existing path.resolve calls, or directly compute absolute paths using new URL('public/lottie.json', import.meta.url).pathname.
2. 🐛 Potential use‑after‑dispose in animation loop
| Field |
Details |
| Severity |
🟠 High |
| Type |
Bug |
| File |
src/lib/lottie-player.ts |
| Location |
dispose() |
| Confidence |
92% |
Problem:
dispose() cancels the next scheduled requestAnimationFrame but does not prevent the already‑running tick callback from queuing another frame after the player has been torn down. If tick runs after dispose, it may access this.surface or this.animation which have been set to null, causing runtime errors.
Suggested Fix:
Add a guard flag (e.g., this.isDisposed) that tick checks before scheduling the next frame, and set this flag in dispose(). Also cancel any pending frame before null‑ing resources.
3. 🐛 NaN or invalid zoom factor can corrupt camera state
| Field |
Details |
| Severity |
🟡 Medium |
| Type |
Bug |
| File |
src/lib/camera.ts |
| Location |
zoomAt |
| Confidence |
92% |
Problem:
If factor passed to zoomAt is NaN, zero, or a non-finite number, the clamping logic returns NaN, leading to this.zoom, this.x, and this.y becoming NaN. Subsequent transformations will produce invalid canvas operations and break rendering.
Suggested Fix:
Validate the factor argument before applying the zoom. For example, check if (!Number.isFinite(factor) || factor <= 0) return; or clamp it to a safe range, and ensure next is a finite number before updating the camera state.
4. ⚡ Unconditional requestAnimationFrame loop
| Field |
Details |
| Severity |
🟡 Medium |
| Type |
Performance |
| File |
src/lib/lottie-player.ts |
| Location |
tick (animation loop) |
| Confidence |
85% |
Problem:
The player starts a perpetual requestAnimationFrame loop regardless of whether the scene is dirty or playing. When paused and no slot changes occur, the loop still runs, wasting CPU and battery.
Suggested Fix:
Schedule the next animation frame only when needed: when playing, when dirty, or when input changes. Otherwise, stop the loop and restart it on demand.
5. 🐛 clsx called with array instead of spread arguments
| Field |
Details |
| Severity |
🟡 Medium |
| Type |
Bug |
| File |
src/lib/utils.ts |
| Location |
function cn(...inputs: ClassValue[]) |
| Confidence |
97% |
Problem:
The clsx function expects its class values as separate arguments (variadic), but the code passes a single array (inputs). This results in clsx treating the entire array as one argument, potentially producing incorrect class name strings or ignoring nested values.
Suggested Fix:
Spread the inputs array when calling clsx: return twMerge(clsx(...inputs));
6. 🔒 Unvalidated Lottie JSON input
| Field |
Details |
| Severity |
🔵 Low |
| Type |
Security |
| File |
src/lib/lottie-player.ts |
| Location |
create() |
| Confidence |
81% |
Problem:
create() forwards the raw lottieJson string directly to CanvasKit.MakeManagedAnimation. Malformed or extremely large JSON can cause CanvasKit to allocate excessive memory or throw exceptions, leading to denial‑of‑service.
Suggested Fix:
Validate the JSON size and structure before passing it to CanvasKit, and wrap the call in a try/catch to handle parsing errors gracefully.
About this report
This report was generated using Llama 3.3 70B.
Only findings with ≥80% confidence are included.
False positives are possible — use your own judgment.
Code Audit Report
Repository:
diffusionstudio/lottieFindings: 6 issue(s) found — 🟠 2 high · 🟡 3 medium · 🔵 1 low
1. 🐛 __dirname is undefined in ESM Vite config
vite.config.tsProblem:
The Vite configuration file is compiled as an ES module. In Node's ESM environment, the global __dirname variable is not defined, causing a ReferenceError at runtime when the config is loaded. This prevents the dev server from starting and breaks the watchLottie plugin.
Suggested Fix:
Replace __dirname with a reliable directory reference for ESM, e.g.,:
Then keep the existing path.resolve calls, or directly compute absolute paths using
new URL('public/lottie.json', import.meta.url).pathname.2. 🐛 Potential use‑after‑dispose in animation loop
src/lib/lottie-player.tsProblem:
dispose() cancels the next scheduled requestAnimationFrame but does not prevent the already‑running tick callback from queuing another frame after the player has been torn down. If tick runs after dispose, it may access this.surface or this.animation which have been set to null, causing runtime errors.
Suggested Fix:
Add a guard flag (e.g., this.isDisposed) that tick checks before scheduling the next frame, and set this flag in dispose(). Also cancel any pending frame before null‑ing resources.
3. 🐛 NaN or invalid zoom factor can corrupt camera state
src/lib/camera.tsProblem:
If
factorpassed tozoomAtis NaN, zero, or a non-finite number, the clamping logic returns NaN, leading tothis.zoom,this.x, andthis.ybecoming NaN. Subsequent transformations will produce invalid canvas operations and break rendering.Suggested Fix:
Validate the
factorargument before applying the zoom. For example, checkif (!Number.isFinite(factor) || factor <= 0) return;or clamp it to a safe range, and ensurenextis a finite number before updating the camera state.4. ⚡ Unconditional requestAnimationFrame loop
src/lib/lottie-player.tsProblem:
The player starts a perpetual requestAnimationFrame loop regardless of whether the scene is dirty or playing. When paused and no slot changes occur, the loop still runs, wasting CPU and battery.
Suggested Fix:
Schedule the next animation frame only when needed: when playing, when dirty, or when input changes. Otherwise, stop the loop and restart it on demand.
5. 🐛 clsx called with array instead of spread arguments
src/lib/utils.tsProblem:
The
clsxfunction expects its class values as separate arguments (variadic), but the code passes a single array (inputs). This results inclsxtreating the entire array as one argument, potentially producing incorrect class name strings or ignoring nested values.Suggested Fix:
Spread the
inputsarray when callingclsx:return twMerge(clsx(...inputs));6. 🔒 Unvalidated Lottie JSON input
src/lib/lottie-player.tsProblem:
create() forwards the raw lottieJson string directly to CanvasKit.MakeManagedAnimation. Malformed or extremely large JSON can cause CanvasKit to allocate excessive memory or throw exceptions, leading to denial‑of‑service.
Suggested Fix:
Validate the JSON size and structure before passing it to CanvasKit, and wrap the call in a try/catch to handle parsing errors gracefully.
About this report
This report was generated using Llama 3.3 70B.
Only findings with ≥80% confidence are included.
False positives are possible — use your own judgment.