Skip to content

[fix] Replace eval() with safe math expression parser#9263

Merged
christian-byrne merged 2 commits intomainfrom
fix/replace-eval-with-math-parser
Mar 4, 2026
Merged

[fix] Replace eval() with safe math expression parser#9263
christian-byrne merged 2 commits intomainfrom
fix/replace-eval-with-math-parser

Conversation

@Myestery
Copy link
Contributor

@Myestery Myestery commented Feb 26, 2026

Summary

Replace eval() in evaluateInput() with a custom recursive descent math parser, eliminating a security concern and enabling the no-eval lint rule.

Changes

  • New: mathParser.ts — recursive descent parser for +, -, *, /, %, (), decimals, unary operators. Zero new dependencies.
  • Modified: widget.ts — replaced eval() call with evaluateMathExpression(), use isFinite() instead of isNaN() to reject Infinity
  • Modified: .oxlintrc.jsonno-eval rule changed from "off" to "error"
  • Tests: 59 parser tests + 23 integration tests covering complex expressions, edge cases, and invalid input

Review Feedback Addressed

  • Renamed unit()primary() for clarity
  • Added modulo (%) operator support
  • Normalized negative zero to positive zero
  • Added depth limit (200) for nested parentheses
  • Used isFinite() instead of isNaN() to reject Infinity/-Infinity
  • Added tests for edge-case number formats, unary-after-binary operators, modulo, depth limits, scientific/hex notation, and Infinity

Fixes #8032
Fixes #9272
Fixes #9273
Fixes #9274
Fixes #9275

┆Issue is synchronized with this Notion page by Unito

Replace eval() in evaluateInput() with a custom recursive descent
parser that only handles arithmetic (+, -, *, /, parentheses, decimals).
Enable no-eval lint rule to prevent future usage.

Fixes #8032
@Myestery Myestery requested a review from a team as a code owner February 26, 2026 22:35
@Myestery Myestery added enhancement New feature or request area:widgets labels Feb 26, 2026
@dosubot dosubot bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Feb 26, 2026
@github-actions
Copy link

github-actions bot commented Feb 26, 2026

🎭 Playwright: ✅ 541 passed, 0 failed · 8 flaky

📊 Browser Reports
  • chromium: View Report (✅ 528 / ❌ 0 / ⚠️ 8 / ⏭️ 10)
  • chromium-2x: View Report (✅ 2 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • chromium-0.5x: View Report (✅ 1 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • mobile-chrome: View Report (✅ 10 / ❌ 0 / ⚠️ 0 / ⏭️ 0)

@github-actions
Copy link

github-actions bot commented Feb 26, 2026

🎨 Storybook: ✅ Built — View Storybook

Details

⏰ Completed at: 02/27/2026, 03:34:28 AM UTC

Links

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 26, 2026

📝 Walkthrough

Walkthrough

Replaces runtime use of eval() with a new arithmetic parser and exposes evaluateInput; adds tests for the parser and widget evaluation; updates ESLint to disallow eval.

Changes

Cohort / File(s) Summary
Lint config
/.oxlintrc.json
Changed ESLint rule "no-eval" from "off" to "error", enforcing no eval() usage.
Math parser
src/lib/litegraph/src/utils/mathParser.ts, src/lib/litegraph/src/utils/mathParser.test.ts
Added evaluateMathExpression implementing a tokenizer + recursive-descent evaluator (supports +, -, *, /, %, unary, parentheses, decimals) and comprehensive tests covering valid expressions, edge cases, depth limits, and invalid inputs returning undefined.
Widget integration & tests
src/lib/litegraph/src/utils/widget.ts, src/lib/litegraph/src/utils/widget.test.ts, src/lib/litegraph/src/litegraph.ts
Replaced prior eval/regex logic in evaluateInput to use evaluateMathExpression, added finite-value guards and fallback numeric parsing; exported evaluateInput from the litegraph public module; added tests for numeric strings, expressions, invalid inputs, and special numeric values.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I swapped the sly old eval away,
Tokens hop and numbers play,
Parentheses bow, operators sing,
Safe math blooms—no scary thing.
A rabbit cheers this tidy day. 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: replacing eval() with a safe math expression parser, which is the primary objective of this PR.
Description check ✅ Passed The description follows the template with all required sections (Summary, Changes, Review Focus) completed. It clearly explains what was changed, why, and includes issue references.
Linked Issues check ✅ Passed The PR successfully addresses issue #8032 by implementing a custom recursive descent math parser as a replacement for eval(), meeting all coding requirements including expression evaluation support and improved security.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the stated objective: mathParser.ts implements the evaluator, widget.ts integrates it, .oxlintrc.json enforces no-eval, and comprehensive tests validate the solution.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/replace-eval-with-math-parser

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

github-actions bot commented Feb 26, 2026

📦 Bundle: 4.46 MB gzip 🔴 +429 B

Details

Summary

  • Raw size: 20.9 MB baseline 20.9 MB — 🔴 +2.43 kB
  • Gzip: 4.46 MB baseline 4.46 MB — 🔴 +429 B
  • Brotli: 3.44 MB baseline 3.44 MB — 🔴 +647 B
  • Bundles: 228 current • 228 baseline • 109 added / 109 removed

Category Glance
Other 🔴 +2.43 kB (7.86 MB) · Vendor & Third-Party ⚪ 0 B (8.84 MB) · Data & Services ⚪ 0 B (2.55 MB) · Graph Workspace ⚪ 0 B (1.02 MB) · Panels & Settings ⚪ 0 B (435 kB) · Views & Navigation ⚪ 0 B (72.1 kB) · + 5 more

App Entry Points — 17.9 kB (baseline 17.9 kB) • ⚪ 0 B

Main entry bundles and manifests

File Before After Δ Raw Δ Gzip Δ Brotli
assets/index-DGzw6eH6.js (new) 17.9 kB 🔴 +17.9 kB 🔴 +6.34 kB 🔴 +5.51 kB
assets/index-DXKalwHv.js (removed) 17.9 kB 🟢 -17.9 kB 🟢 -6.35 kB 🟢 -5.54 kB

Status: 1 added / 1 removed

Graph Workspace — 1.02 MB (baseline 1.02 MB) • ⚪ 0 B

Graph editor runtime, canvas, workflow orchestration

File Before After Δ Raw Δ Gzip Δ Brotli
assets/GraphView-B2Uf7gcT.js (new) 1.02 MB 🔴 +1.02 MB 🔴 +218 kB 🔴 +164 kB
assets/GraphView-CLJH3d6j.js (removed) 1.02 MB 🟢 -1.02 MB 🟢 -218 kB 🟢 -164 kB

Status: 1 added / 1 removed

Views & Navigation — 72.1 kB (baseline 72.1 kB) • ⚪ 0 B

Top-level views, pages, and routed surfaces

File Before After Δ Raw Δ Gzip Δ Brotli
assets/CloudSurveyView-BPqauF-b.js (removed) 15.5 kB 🟢 -15.5 kB 🟢 -3.32 kB 🟢 -2.82 kB
assets/CloudSurveyView-DZ6Jsgp_.js (new) 15.5 kB 🔴 +15.5 kB 🔴 +3.32 kB 🔴 +2.82 kB
assets/CloudLoginView-BAOYnGWo.js (new) 11.4 kB 🔴 +11.4 kB 🔴 +3.19 kB 🔴 +2.82 kB
assets/CloudLoginView-DHy70UKj.js (removed) 11.4 kB 🟢 -11.4 kB 🟢 -3.19 kB 🟢 -2.82 kB
assets/CloudSignupView-CoVaDYju.js (removed) 9.37 kB 🟢 -9.37 kB 🟢 -2.69 kB 🟢 -2.35 kB
assets/CloudSignupView-DX3adZop.js (new) 9.37 kB 🔴 +9.37 kB 🔴 +2.69 kB 🔴 +2.36 kB
assets/UserCheckView-CDvKBoRe.js (new) 8.41 kB 🔴 +8.41 kB 🔴 +2.23 kB 🔴 +1.94 kB
assets/UserCheckView-N8V7NGRf.js (removed) 8.41 kB 🟢 -8.41 kB 🟢 -2.23 kB 🟢 -1.95 kB
assets/CloudLayoutView-BofECmUK.js (new) 6.43 kB 🔴 +6.43 kB 🔴 +2.1 kB 🔴 +1.83 kB
assets/CloudLayoutView-Cye0fmjv.js (removed) 6.43 kB 🟢 -6.43 kB 🟢 -2.1 kB 🟢 -1.83 kB
assets/CloudForgotPasswordView-Cy9Gy1Et.js (removed) 5.56 kB 🟢 -5.56 kB 🟢 -1.93 kB 🟢 -1.71 kB
assets/CloudForgotPasswordView-WUmlpnhd.js (new) 5.56 kB 🔴 +5.56 kB 🔴 +1.93 kB 🔴 +1.7 kB
assets/CloudAuthTimeoutView-5_SA0q_c.js (new) 4.91 kB 🔴 +4.91 kB 🔴 +1.77 kB 🔴 +1.55 kB
assets/CloudAuthTimeoutView-D11K0gy7.js (removed) 4.91 kB 🟢 -4.91 kB 🟢 -1.77 kB 🟢 -1.54 kB
assets/CloudSubscriptionRedirectView-B82fMExI.js (removed) 4.75 kB 🟢 -4.75 kB 🟢 -1.79 kB 🟢 -1.58 kB
assets/CloudSubscriptionRedirectView-C5ld8gRq.js (new) 4.75 kB 🔴 +4.75 kB 🔴 +1.78 kB 🔴 +1.58 kB
assets/UserSelectView--LCL0ETi.js (removed) 4.5 kB 🟢 -4.5 kB 🟢 -1.64 kB 🟢 -1.47 kB
assets/UserSelectView-CGHbcFWD.js (new) 4.5 kB 🔴 +4.5 kB 🔴 +1.64 kB 🔴 +1.46 kB
assets/CloudSorryContactSupportView-Bypca0av.js 1.02 kB 1.02 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/layout-CI4MZk1L.js 296 B 296 B ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 9 added / 9 removed

Panels & Settings — 435 kB (baseline 435 kB) • ⚪ 0 B

Configuration panels, inspectors, and settings screens

File Before After Δ Raw Δ Gzip Δ Brotli
assets/SecretsPanel-Bxv-pZsH.js (new) 21.5 kB 🔴 +21.5 kB 🔴 +5.3 kB 🔴 +4.66 kB
assets/SecretsPanel-q3FcwGiJ.js (removed) 21.5 kB 🟢 -21.5 kB 🟢 -5.3 kB 🟢 -4.67 kB
assets/LegacyCreditsPanel-BvgGql65.js (new) 20.6 kB 🔴 +20.6 kB 🔴 +5.56 kB 🔴 +4.89 kB
assets/LegacyCreditsPanel-eRcoOfit.js (removed) 20.6 kB 🟢 -20.6 kB 🟢 -5.56 kB 🟢 -4.89 kB
assets/SubscriptionPanel-Be3bWHxb.js (new) 18.2 kB 🔴 +18.2 kB 🔴 +4.65 kB 🔴 +4.09 kB
assets/SubscriptionPanel-zeyIgJgH.js (removed) 18.2 kB 🟢 -18.2 kB 🟢 -4.66 kB 🟢 -4.09 kB
assets/KeybindingPanel-BlYTkzNU.js (removed) 12.3 kB 🟢 -12.3 kB 🟢 -3.52 kB 🟢 -3.12 kB
assets/KeybindingPanel-DfVp8Tvr.js (new) 12.3 kB 🔴 +12.3 kB 🔴 +3.51 kB 🔴 +3.12 kB
assets/AboutPanel-DAonBU6n.js (removed) 9.79 kB 🟢 -9.79 kB 🟢 -2.73 kB 🟢 -2.45 kB
assets/AboutPanel-Ddbvxf_l.js (new) 9.79 kB 🔴 +9.79 kB 🔴 +2.73 kB 🔴 +2.45 kB
assets/ExtensionPanel-C-NXj1K5.js (new) 9.38 kB 🔴 +9.38 kB 🔴 +2.64 kB 🔴 +2.36 kB
assets/ExtensionPanel-DeLRWUQS.js (removed) 9.38 kB 🟢 -9.38 kB 🟢 -2.65 kB 🟢 -2.36 kB
assets/ServerConfigPanel-C_YVgzxw.js (removed) 6.44 kB 🟢 -6.44 kB 🟢 -2.13 kB 🟢 -1.91 kB
assets/ServerConfigPanel-LzBr1HDQ.js (new) 6.44 kB 🔴 +6.44 kB 🔴 +2.12 kB 🔴 +1.91 kB
assets/UserPanel-DwZJ1nKx.js (new) 6.16 kB 🔴 +6.16 kB 🔴 +1.99 kB 🔴 +1.75 kB
assets/UserPanel-vyAKmLVZ.js (removed) 6.16 kB 🟢 -6.16 kB 🟢 -1.99 kB 🟢 -1.77 kB
assets/cloudRemoteConfig-BTNHpUTJ.js (removed) 1.44 kB 🟢 -1.44 kB 🟢 -707 B 🟢 -613 B
assets/cloudRemoteConfig-ByiTo8Jn.js (new) 1.44 kB 🔴 +1.44 kB 🔴 +706 B 🔴 +612 B
assets/refreshRemoteConfig-CVrtThRw.js (new) 1.14 kB 🔴 +1.14 kB 🔴 +519 B 🔴 +468 B
assets/refreshRemoteConfig-DDE8-TVM.js (removed) 1.14 kB 🟢 -1.14 kB 🟢 -518 B 🟢 -464 B
assets/config-CGn5JFmU.js 996 B 996 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-B5oF6TeI.js 29.9 kB 29.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-BVYOg4dh.js 24.5 kB 24.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-CBEvSL1z.js 38.5 kB 38.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-CGx1t8IZ.js 27.8 kB 27.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-CNcb_4nC.js 30.5 kB 30.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-Cx1dZM6H.js 23.9 kB 23.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-Dw-QS6Nb.js 27.9 kB 27.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-DXxgnCSn.js 32.4 kB 32.4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-GRFn4guL.js 34.2 kB 34.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-mgwKIVQ2.js 28.8 kB 28.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-s83B801I.js 28.7 kB 28.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 10 added / 10 removed

User & Accounts — 16 kB (baseline 16 kB) • ⚪ 0 B

Authentication, profile, and account management bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/auth-BDUC6mnC.js (new) 3.4 kB 🔴 +3.4 kB 🔴 +1.18 kB 🔴 +992 B
assets/auth-CAsnmUWm.js (removed) 3.4 kB 🟢 -3.4 kB 🟢 -1.18 kB 🟢 -986 B
assets/SignUpForm-Bg0DJa4i.js (removed) 3.01 kB 🟢 -3.01 kB 🟢 -1.23 kB 🟢 -1.09 kB
assets/SignUpForm-J06FukZy.js (new) 3.01 kB 🔴 +3.01 kB 🔴 +1.23 kB 🔴 +1.09 kB
assets/UpdatePasswordContent-C7wiG5my.js (removed) 2.37 kB 🟢 -2.37 kB 🟢 -1.07 kB 🟢 -944 B
assets/UpdatePasswordContent-RQOViubW.js (new) 2.37 kB 🔴 +2.37 kB 🔴 +1.07 kB 🔴 +944 B
assets/firebaseAuthStore-BDwyy-Pf.js (removed) 788 B 🟢 -788 B 🟢 -390 B 🟢 -347 B
assets/firebaseAuthStore-DS1bXHNB.js (new) 788 B 🔴 +788 B 🔴 +388 B 🔴 +352 B
assets/auth-ByAX3TqU.js (new) 357 B 🔴 +357 B 🔴 +226 B 🔴 +217 B
assets/auth-Dc_x5XPm.js (removed) 357 B 🟢 -357 B 🟢 -225 B 🟢 -222 B
assets/PasswordFields-DLbVLg8O.js 4.51 kB 4.51 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WorkspaceProfilePic-D6ioir1T.js 1.57 kB 1.57 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 5 added / 5 removed

Editors & Dialogs — 736 B (baseline 736 B) • ⚪ 0 B

Modals, dialogs, drawers, and in-app editors

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useSubscriptionDialog-BtyYGl3S.js (new) 736 B 🔴 +736 B 🔴 +379 B 🔴 +331 B
assets/useSubscriptionDialog-C_7Os5Sm.js (removed) 736 B 🟢 -736 B 🟢 -379 B 🟢 -328 B

Status: 1 added / 1 removed

UI Components — 47.1 kB (baseline 47.1 kB) • ⚪ 0 B

Reusable component library chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useTerminalTabs-b5EhDnML.js (new) 9.84 kB 🔴 +9.84 kB 🔴 +3.39 kB 🔴 +3 kB
assets/useTerminalTabs-CYdXSbFM.js (removed) 9.84 kB 🟢 -9.84 kB 🟢 -3.4 kB 🟢 -2.99 kB
assets/ComfyQueueButton-6eHogFJU.js (removed) 8.02 kB 🟢 -8.02 kB 🟢 -2.49 kB 🟢 -2.23 kB
assets/ComfyQueueButton-CL_M2P2A.js (new) 8.02 kB 🔴 +8.02 kB 🔴 +2.49 kB 🔴 +2.24 kB
assets/SubscribeButton-DmIaD58h.js (new) 2.48 kB 🔴 +2.48 kB 🔴 +1.07 kB 🔴 +930 B
assets/SubscribeButton-DuOX1pVE.js (removed) 2.48 kB 🟢 -2.48 kB 🟢 -1.07 kB 🟢 -933 B
assets/cloudFeedbackTopbarButton-Bcy70998.js (new) 1.59 kB 🔴 +1.59 kB 🔴 +853 B 🔴 +764 B
assets/cloudFeedbackTopbarButton-Jbz0bXod.js (removed) 1.59 kB 🟢 -1.59 kB 🟢 -853 B 🟢 -734 B
assets/ComfyQueueButton-CpsD-nbV.js (removed) 793 B 🟢 -793 B 🟢 -394 B 🟢 -349 B
assets/ComfyQueueButton-DqHJHvYC.js (new) 793 B 🔴 +793 B 🔴 +394 B 🔴 +353 B
assets/Button-D1z3poyI.js 2.98 kB 2.98 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/CloudBadge-BEnZAylJ.js 1.24 kB 1.24 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/FormSearchInput-Bg4LklDe.js 3.73 kB 3.73 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/ScrubableNumberInput-DecBFGbM.js 5.94 kB 5.94 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/TopbarBadge-CJNpTEnW.js 7.44 kB 7.44 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/UserAvatar-CnQQLXB-.js 1.17 kB 1.17 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetButton-sg8Jj4MY.js 1.84 kB 1.84 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 5 added / 5 removed

Data & Services — 2.55 MB (baseline 2.55 MB) • ⚪ 0 B

Stores, services, APIs, and repositories

File Before After Δ Raw Δ Gzip Δ Brotli
assets/dialogService-Bsq-4umq.js (new) 1.75 MB 🔴 +1.75 MB 🔴 +393 kB 🔴 +296 kB
assets/dialogService-D733saDq.js (removed) 1.75 MB 🟢 -1.75 MB 🟢 -393 kB 🟢 -296 kB
assets/api-CxoTE_n9.js (new) 678 kB 🔴 +678 kB 🔴 +153 kB 🔴 +122 kB
assets/api-zUxn3URu.js (removed) 678 kB 🟢 -678 kB 🟢 -153 kB 🟢 -122 kB
assets/load3dService-C8w63a4G.js (new) 91 kB 🔴 +91 kB 🔴 +19.1 kB 🔴 +16.4 kB
assets/load3dService-CDOlGP9X.js (removed) 91 kB 🟢 -91 kB 🟢 -19.1 kB 🟢 -16.4 kB
assets/extensionStore-DcmAXh8u.js (new) 12.1 kB 🔴 +12.1 kB 🔴 +4.21 kB 🔴 +3.71 kB
assets/extensionStore-Q6ON6TqC.js (removed) 12.1 kB 🟢 -12.1 kB 🟢 -4.21 kB 🟢 -3.7 kB
assets/releaseStore-Bf9VXZlv.js (new) 7.96 kB 🔴 +7.96 kB 🔴 +2.22 kB 🔴 +1.95 kB
assets/releaseStore-BrSdMTBu.js (removed) 7.96 kB 🟢 -7.96 kB 🟢 -2.22 kB 🟢 -1.95 kB
assets/keybindingService-CQYC18Gk.js (new) 6.52 kB 🔴 +6.52 kB 🔴 +1.71 kB 🔴 +1.48 kB
assets/keybindingService-DqMuSjLQ.js (removed) 6.52 kB 🟢 -6.52 kB 🟢 -1.71 kB 🟢 -1.48 kB
assets/bootstrapStore-BnY4vGAc.js (new) 2.08 kB 🔴 +2.08 kB 🔴 +869 B 🔴 +786 B
assets/bootstrapStore-xVVAdXRy.js (removed) 2.08 kB 🟢 -2.08 kB 🟢 -872 B 🟢 -792 B
assets/userStore-CuufLKNo.js (new) 1.85 kB 🔴 +1.85 kB 🔴 +717 B 🔴 +669 B
assets/userStore-DA8KGaEz.js (removed) 1.85 kB 🟢 -1.85 kB 🟢 -720 B 🟢 -630 B
assets/audioService-DjriZqiR.js (removed) 1.73 kB 🟢 -1.73 kB 🟢 -848 B 🟢 -725 B
assets/audioService-uMe4IvL_.js (new) 1.73 kB 🔴 +1.73 kB 🔴 +848 B 🔴 +729 B
assets/releaseStore-DrnGxjnP.js (new) 760 B 🔴 +760 B 🔴 +385 B 🔴 +347 B
assets/releaseStore-s9QzCMM0.js (removed) 760 B 🟢 -760 B 🟢 -385 B 🟢 -341 B
assets/settingStore-_8u1jfDB.js (removed) 744 B 🟢 -744 B 🟢 -387 B 🟢 -343 B
assets/settingStore-DJRpAAQ4.js (new) 744 B 🔴 +744 B 🔴 +387 B 🔴 +381 B
assets/workflowDraftStore-DlE1yovN.js (new) 736 B 🔴 +736 B 🔴 +379 B 🔴 +338 B
assets/workflowDraftStore-DRIzXZWo.js (removed) 736 B 🟢 -736 B 🟢 -379 B 🟢 -333 B
assets/dialogService-C9Irwka9.js (removed) 725 B 🟢 -725 B 🟢 -367 B 🟢 -325 B
assets/dialogService-OgNixsG3.js (new) 725 B 🔴 +725 B 🔴 +367 B 🔴 +357 B
assets/serverConfigStore-EPk4OtIK.js 2.32 kB 2.32 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 13 added / 13 removed

Utilities & Hooks — 55.5 kB (baseline 55.5 kB) • ⚪ 0 B

Helpers, composables, and utility bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useLoad3d-F4e86B2q.js (new) 14.6 kB 🔴 +14.6 kB 🔴 +3.63 kB 🔴 +3.21 kB
assets/useLoad3d-YAFK_WqF.js (removed) 14.6 kB 🟢 -14.6 kB 🟢 -3.63 kB 🟢 -3.21 kB
assets/useLoad3dViewer-8sWDYqho.js (removed) 14.1 kB 🟢 -14.1 kB 🟢 -3.15 kB 🟢 -2.8 kB
assets/useLoad3dViewer-D_VQnrzN.js (new) 14.1 kB 🔴 +14.1 kB 🔴 +3.15 kB 🔴 +2.79 kB
assets/useFeatureFlags-B2wUfUQZ.js (new) 4.14 kB 🔴 +4.14 kB 🔴 +1.24 kB 🔴 +1.06 kB
assets/useFeatureFlags-DMLfNasb.js (removed) 4.14 kB 🟢 -4.14 kB 🟢 -1.24 kB 🟢 -1.06 kB
assets/useWorkspaceUI-Dt_7V7IP.js (removed) 3 kB 🟢 -3 kB 🟢 -821 B 🟢 -703 B
assets/useWorkspaceUI-ifyXT97O.js (new) 3 kB 🔴 +3 kB 🔴 +822 B 🔴 +700 B
assets/subscriptionCheckoutUtil-CrdqZFPX.js (removed) 2.53 kB 🟢 -2.53 kB 🟢 -1.06 kB 🟢 -925 B
assets/subscriptionCheckoutUtil-D8CjKdJl.js (new) 2.53 kB 🔴 +2.53 kB 🔴 +1.06 kB 🔴 +954 B
assets/useErrorHandling-9v-Rhyhy.js (new) 1.5 kB 🔴 +1.5 kB 🔴 +628 B 🔴 +530 B
assets/useErrorHandling-CzoGFuuS.js (removed) 1.5 kB 🟢 -1.5 kB 🟢 -629 B 🟢 -534 B
assets/useWorkspaceSwitch-7DzprOqd.js (removed) 1.25 kB 🟢 -1.25 kB 🟢 -543 B 🟢 -478 B
assets/useWorkspaceSwitch-Cn3QO4Y3.js (new) 1.25 kB 🔴 +1.25 kB 🔴 +544 B 🔴 +483 B
assets/useLoad3d-BVFRO9gZ.js (new) 859 B 🔴 +859 B 🔴 +424 B 🔴 +382 B
assets/useLoad3d-C2TV94YH.js (removed) 859 B 🟢 -859 B 🟢 -425 B 🟢 -384 B
assets/audioUtils-BeXiNSEM.js (removed) 858 B 🟢 -858 B 🟢 -500 B 🟢 -404 B
assets/audioUtils-DWBqumXN.js (new) 858 B 🔴 +858 B 🔴 +501 B 🔴 +402 B
assets/useLoad3dViewer-BXMZdDWY.js (new) 838 B 🔴 +838 B 🔴 +410 B 🔴 +376 B
assets/useLoad3dViewer-DGC_WHo5.js (removed) 838 B 🟢 -838 B 🟢 -410 B 🟢 -371 B
assets/useCurrentUser-DRvygyjU.js (removed) 722 B 🟢 -722 B 🟢 -371 B 🟢 -332 B
assets/useCurrentUser-DSAYbWxR.js (new) 722 B 🔴 +722 B 🔴 +373 B 🔴 +331 B
assets/_plugin-vue_export-helper-ralzwvFM.js 315 B 315 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/colorUtil-CY7QMUhQ.js 7 kB 7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/envUtil-Clzmwvt4.js 466 B 466 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/markdownRendererUtil-Cddas8Zl.js 1.56 kB 1.56 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/SkeletonUtils-BputJAFn.js 133 B 133 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/useExternalLink-Cf_cbLlH.js 1.66 kB 1.66 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 11 added / 11 removed

Vendor & Third-Party — 8.84 MB (baseline 8.84 MB) • ⚪ 0 B

External libraries and shared vendor chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/vendor-axios-Cp6hch1I.js 70.7 kB 70.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-chart-BxkFiWzp.js 399 kB 399 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-firebase-BvMr43CG.js 836 kB 836 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-i18n-DNX73mqE.js 133 kB 133 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-markdown-D5S6AC80.js 103 kB 103 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-other-DrYd4O-6.js 1.52 MB 1.52 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-primevue-BnCPTL0g.js 1.73 MB 1.73 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-reka-ui-DVmi2O2Z.js 388 kB 388 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-sentry-SQwstEKc.js 182 kB 182 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-three-LBLOE6BD.js 1.8 MB 1.8 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-tiptap-BnYkbQDM.js 634 kB 634 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-vue-core-DtiQ1dr9.js 311 kB 311 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-vueuse-D2jVNnmE.js 113 kB 113 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-xterm-MKpa1ZAW.js 374 kB 374 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-yjs-CP_4YO8u.js 143 kB 143 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-zod-DcCUUPIi.js 109 kB 109 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
Other — 7.86 MB (baseline 7.86 MB) • 🔴 +2.43 kB

Bundles that do not match a named category

File Before After Δ Raw Δ Gzip Δ Brotli
assets/core-CKiKIcnd.js (new) 73.4 kB 🔴 +73.4 kB 🔴 +18.9 kB 🔴 +16.2 kB
assets/core-Rc5-s_9C.js (removed) 73.4 kB 🟢 -73.4 kB 🟢 -18.9 kB 🟢 -16.2 kB
assets/groupNode-ajB3dRmT.js (new) 71.8 kB 🔴 +71.8 kB 🔴 +17.7 kB 🔴 +15.5 kB
assets/groupNode-Bf_p_Km2.js (removed) 71.8 kB 🟢 -71.8 kB 🟢 -17.7 kB 🟢 -15.6 kB
assets/WidgetSelect-BEZ8lP9V.js (new) 58.1 kB 🔴 +58.1 kB 🔴 +12.4 kB 🔴 +10.7 kB
assets/WidgetSelect-BJmOrVrX.js (removed) 58.1 kB 🟢 -58.1 kB 🟢 -12.4 kB 🟢 -10.7 kB
assets/SubscriptionRequiredDialogContentWorkspace-DYoRl0ZQ.js (new) 46.3 kB 🔴 +46.3 kB 🔴 +8.65 kB 🔴 +7.51 kB
assets/SubscriptionRequiredDialogContentWorkspace-zf_Mg0AX.js (removed) 46.3 kB 🟢 -46.3 kB 🟢 -8.65 kB 🟢 -7.53 kB
assets/WidgetPainter-B2RQHnxr.js (removed) 32.5 kB 🟢 -32.5 kB 🟢 -7.96 kB 🟢 -7.06 kB
assets/WidgetPainter-EiRPQ2r2.js (new) 32.5 kB 🔴 +32.5 kB 🔴 +7.96 kB 🔴 +7.08 kB
assets/Load3DControls-COgQodcN.js (new) 30.9 kB 🔴 +30.9 kB 🔴 +5.34 kB 🔴 +4.64 kB
assets/Load3DControls-CYNadTqr.js (removed) 30.9 kB 🟢 -30.9 kB 🟢 -5.34 kB 🟢 -4.65 kB
assets/WorkspacePanelContent-Dihx-n1S.js (new) 29.3 kB 🔴 +29.3 kB 🔴 +6.14 kB 🔴 +5.4 kB
assets/WorkspacePanelContent-o_UC3iH9.js (removed) 29.3 kB 🟢 -29.3 kB 🟢 -6.14 kB 🟢 -5.42 kB
assets/SubscriptionRequiredDialogContent-BLaRkSTj.js (new) 25.7 kB 🔴 +25.7 kB 🔴 +6.57 kB 🔴 +5.79 kB
assets/SubscriptionRequiredDialogContent-Bra7HAnc.js (removed) 25.7 kB 🟢 -25.7 kB 🟢 -6.57 kB 🟢 -5.78 kB
assets/Load3dViewerContent-BiZgorV0.js (new) 23 kB 🔴 +23 kB 🔴 +5.17 kB 🔴 +4.49 kB
assets/Load3dViewerContent-CkwJGfEc.js (removed) 23 kB 🟢 -23 kB 🟢 -5.18 kB 🟢 -4.5 kB
assets/WidgetImageCrop-isuGlaLc.js (new) 22.1 kB 🔴 +22.1 kB 🔴 +5.5 kB 🔴 +4.84 kB
assets/WidgetImageCrop-UPdkWySn.js (removed) 22.1 kB 🟢 -22.1 kB 🟢 -5.51 kB 🟢 -4.84 kB
assets/SubscriptionPanelContentWorkspace-C8q_QWT-.js (removed) 21.6 kB 🟢 -21.6 kB 🟢 -5.05 kB 🟢 -4.45 kB
assets/SubscriptionPanelContentWorkspace-DTW8qoYq.js (new) 21.6 kB 🔴 +21.6 kB 🔴 +5.05 kB 🔴 +4.46 kB
assets/CurrentUserPopoverWorkspace-D8xYf0AN.js (new) 19.9 kB 🔴 +19.9 kB 🔴 +4.88 kB 🔴 +4.34 kB
assets/CurrentUserPopoverWorkspace-DKU9vI41.js (removed) 19.9 kB 🟢 -19.9 kB 🟢 -4.88 kB 🟢 -4.34 kB
assets/SignInContent-BmlBe7Pg.js (new) 18.9 kB 🔴 +18.9 kB 🔴 +4.75 kB 🔴 +4.16 kB
assets/SignInContent-BVZ8Z59x.js (removed) 18.9 kB 🟢 -18.9 kB 🟢 -4.76 kB 🟢 -4.17 kB
assets/WidgetInputNumber-CQrW8o9l.js (new) 18.7 kB 🔴 +18.7 kB 🔴 +4.75 kB 🔴 +4.22 kB
assets/WidgetInputNumber-Vzye6kQQ.js (removed) 18.7 kB 🟢 -18.7 kB 🟢 -4.75 kB 🟢 -4.22 kB
assets/WidgetRecordAudio-B2Zlbvhh.js (removed) 17.3 kB 🟢 -17.3 kB 🟢 -4.94 kB 🟢 -4.43 kB
assets/WidgetRecordAudio-CJ-rG8iP.js (new) 17.3 kB 🔴 +17.3 kB 🔴 +4.94 kB 🔴 +4.42 kB
assets/Load3D-BDe9_rzl.js (removed) 16.2 kB 🟢 -16.2 kB 🟢 -4.03 kB 🟢 -3.52 kB
assets/Load3D-BuGY__al.js (new) 16.2 kB 🔴 +16.2 kB 🔴 +4.03 kB 🔴 +3.51 kB
assets/load3d-DiEQ8biQ.js (removed) 14.7 kB 🟢 -14.7 kB 🟢 -4.19 kB 🟢 -3.64 kB
assets/load3d-DssVwB2i.js (new) 14.7 kB 🔴 +14.7 kB 🔴 +4.18 kB 🔴 +3.63 kB
assets/AudioPreviewPlayer-1mjtp54d.js (new) 10.9 kB 🔴 +10.9 kB 🔴 +3.19 kB 🔴 +2.85 kB
assets/AudioPreviewPlayer-DbKKBXlI.js (removed) 10.9 kB 🟢 -10.9 kB 🟢 -3.19 kB 🟢 -2.86 kB
assets/changeTracker-ByafqIV1.js (removed) 9.38 kB 🟢 -9.38 kB 🟢 -2.89 kB 🟢 -2.55 kB
assets/changeTracker-JfYDSljE.js (new) 9.38 kB 🔴 +9.38 kB 🔴 +2.89 kB 🔴 +2.55 kB
assets/nodeTemplates-B87fP1E-.js (removed) 9.29 kB 🟢 -9.29 kB 🟢 -3.26 kB 🟢 -2.86 kB
assets/nodeTemplates-Cvasafl3.js (new) 9.29 kB 🔴 +9.29 kB 🔴 +3.25 kB 🔴 +2.87 kB
assets/InviteMemberDialogContent-_5eWYOgr.js (removed) 7.38 kB 🟢 -7.38 kB 🟢 -2.29 kB 🟢 -2 kB
assets/InviteMemberDialogContent-DmSVsw_R.js (new) 7.38 kB 🔴 +7.38 kB 🔴 +2.29 kB 🔴 +2 kB
assets/Load3DConfiguration-BTslGgbD.js (new) 6.27 kB 🔴 +6.27 kB 🔴 +1.91 kB 🔴 +1.68 kB
assets/Load3DConfiguration-DPrcGdNk.js (removed) 6.27 kB 🟢 -6.27 kB 🟢 -1.91 kB 🟢 -1.68 kB
assets/CreateWorkspaceDialogContent-BScNgOrt.js (removed) 5.53 kB 🟢 -5.53 kB 🟢 -1.99 kB 🟢 -1.73 kB
assets/CreateWorkspaceDialogContent-Cac2_wJG.js (new) 5.53 kB 🔴 +5.53 kB 🔴 +1.99 kB 🔴 +1.74 kB
assets/onboardingCloudRoutes-BlMyh472.js (new) 5.41 kB 🔴 +5.41 kB 🔴 +1.83 kB 🔴 +1.6 kB
assets/onboardingCloudRoutes-BlZAAPNm.js (removed) 5.41 kB 🟢 -5.41 kB 🟢 -1.83 kB 🟢 -1.59 kB
assets/FreeTierDialogContent-cCq7wUhn.js (new) 5.39 kB 🔴 +5.39 kB 🔴 +1.89 kB 🔴 +1.67 kB
assets/FreeTierDialogContent-DSk2ew__.js (removed) 5.39 kB 🟢 -5.39 kB 🟢 -1.9 kB 🟢 -1.67 kB
assets/EditWorkspaceDialogContent-DL3n7BTl.js (new) 5.33 kB 🔴 +5.33 kB 🔴 +1.94 kB 🔴 +1.7 kB
assets/EditWorkspaceDialogContent-ZIE12vXf.js (removed) 5.33 kB 🟢 -5.33 kB 🟢 -1.95 kB 🟢 -1.7 kB
assets/ValueControlPopover-CQKpoyUt.js (new) 4.92 kB 🔴 +4.92 kB 🔴 +1.76 kB 🔴 +1.58 kB
assets/ValueControlPopover-CzBiDe7Y.js (removed) 4.92 kB 🟢 -4.92 kB 🟢 -1.76 kB 🟢 -1.57 kB
assets/Preview3d-B8t47hqK.js (new) 4.81 kB 🔴 +4.81 kB 🔴 +1.56 kB 🔴 +1.36 kB
assets/Preview3d-yzLS6S6b.js (removed) 4.81 kB 🟢 -4.81 kB 🟢 -1.56 kB 🟢 -1.36 kB
assets/CancelSubscriptionDialogContent-B8xFSOYl.js (new) 4.79 kB 🔴 +4.79 kB 🔴 +1.78 kB 🔴 +1.56 kB
assets/CancelSubscriptionDialogContent-DSSugk0x.js (removed) 4.79 kB 🟢 -4.79 kB 🟢 -1.78 kB 🟢 -1.57 kB
assets/DeleteWorkspaceDialogContent-D1S_oF3s.js (new) 4.23 kB 🔴 +4.23 kB 🔴 +1.63 kB 🔴 +1.42 kB
assets/DeleteWorkspaceDialogContent-DL0NTnx_.js (removed) 4.23 kB 🟢 -4.23 kB 🟢 -1.63 kB 🟢 -1.42 kB
assets/WidgetWithControl-BBQEO-ZT.js (removed) 4.1 kB 🟢 -4.1 kB 🟢 -1.77 kB 🟢 -1.59 kB
assets/WidgetWithControl-CU1WCTQA.js (new) 4.1 kB 🔴 +4.1 kB 🔴 +1.77 kB 🔴 +1.58 kB
assets/LeaveWorkspaceDialogContent-CGLCgewy.js (new) 4.06 kB 🔴 +4.06 kB 🔴 +1.57 kB 🔴 +1.37 kB
assets/LeaveWorkspaceDialogContent-DWL0rGxd.js (removed) 4.06 kB 🟢 -4.06 kB 🟢 -1.58 kB 🟢 -1.37 kB
assets/RemoveMemberDialogContent-CSMRPxEW.js (new) 4.04 kB 🔴 +4.04 kB 🔴 +1.52 kB 🔴 +1.33 kB
assets/RemoveMemberDialogContent-DskSoTLd.js (removed) 4.04 kB 🟢 -4.04 kB 🟢 -1.52 kB 🟢 -1.33 kB
assets/RevokeInviteDialogContent-DgpQy8VM.js (new) 3.95 kB 🔴 +3.95 kB 🔴 +1.54 kB 🔴 +1.35 kB
assets/RevokeInviteDialogContent-DQb9EY9A.js (removed) 3.95 kB 🟢 -3.95 kB 🟢 -1.54 kB 🟢 -1.35 kB
assets/InviteMemberUpsellDialogContent-8EH74D3h.js (new) 3.82 kB 🔴 +3.82 kB 🔴 +1.4 kB 🔴 +1.23 kB
assets/InviteMemberUpsellDialogContent-Ck95sx3k.js (removed) 3.82 kB 🟢 -3.82 kB 🟢 -1.4 kB 🟢 -1.23 kB
assets/tierBenefits--dxH8IF_.js (new) 3.66 kB 🔴 +3.66 kB 🔴 +1.3 kB 🔴 +1.17 kB
assets/tierBenefits-NRu8Bp6O.js (removed) 3.66 kB 🟢 -3.66 kB 🟢 -1.3 kB 🟢 -1.16 kB
assets/saveMesh-DocE-MUM.js (removed) 3.38 kB 🟢 -3.38 kB 🟢 -1.45 kB 🟢 -1.29 kB
assets/saveMesh-DqH7NkQv.js (new) 3.38 kB 🔴 +3.38 kB 🔴 +1.45 kB 🔴 +1.29 kB
assets/cloudSessionCookie-Cc2mArVw.js (removed) 3.1 kB 🟢 -3.1 kB 🟢 -1.09 kB 🟢 -955 B
assets/cloudSessionCookie-DnVCPfWw.js (new) 3.1 kB 🔴 +3.1 kB 🔴 +1.09 kB 🔴 +954 B
assets/widget-DIRwAHBY.js (new) 3.01 kB 🔴 +3.01 kB 🔴 +989 B 🔴 +877 B
assets/GlobalToast-6RHnhzBW.js (new) 2.91 kB 🔴 +2.91 kB 🔴 +1.21 kB 🔴 +1.03 kB
assets/GlobalToast-CCXSeCZj.js (removed) 2.91 kB 🟢 -2.91 kB 🟢 -1.21 kB 🟢 -1.04 kB
assets/SubscribeToRun-B2ujY8d_.js (new) 2.2 kB 🔴 +2.2 kB 🔴 +1.01 kB 🔴 +888 B
assets/SubscribeToRun-CQhL1-92.js (removed) 2.2 kB 🟢 -2.2 kB 🟢 -1.01 kB 🟢 -873 B
assets/CloudRunButtonWrapper-B4MGCL8e.js (removed) 1.68 kB 🟢 -1.68 kB 🟢 -786 B 🟢 -704 B
assets/CloudRunButtonWrapper-C_LAltId.js (new) 1.68 kB 🔴 +1.68 kB 🔴 +782 B 🔴 +703 B
assets/previousFullPath-BfQbt1kt.js (new) 1.39 kB 🔴 +1.39 kB 🔴 +649 B 🔴 +576 B
assets/previousFullPath-BpKAYTJ2.js (removed) 1.39 kB 🟢 -1.39 kB 🟢 -651 B 🟢 -555 B
assets/cloudBadges-C5Ah-fJ5.js (removed) 1.37 kB 🟢 -1.37 kB 🟢 -700 B 🟢 -614 B
assets/cloudBadges-C6krjLXU.js (new) 1.37 kB 🔴 +1.37 kB 🔴 +699 B 🔴 +612 B
assets/cloudSubscription-Bs23Z-CY.js (new) 1.33 kB 🔴 +1.33 kB 🔴 +653 B 🔴 +564 B
assets/cloudSubscription-CM6ssGnP.js (removed) 1.33 kB 🟢 -1.33 kB 🟢 -654 B 🟢 -567 B
assets/Load3D-BC16DtSX.js (new) 1.07 kB 🔴 +1.07 kB 🔴 +497 B 🔴 +445 B
assets/Load3D-BNC4aJNH.js (removed) 1.07 kB 🟢 -1.07 kB 🟢 -496 B 🟢 -447 B
assets/nightlyBadges-a-eQ1enX.js (removed) 1 kB 🟢 -1 kB 🟢 -529 B 🟢 -476 B
assets/nightlyBadges-DGmUzC48.js (new) 1 kB 🔴 +1 kB 🔴 +531 B 🔴 +481 B
assets/Load3dViewerContent-BEiS4SNM.js (new) 993 B 🔴 +993 B 🔴 +468 B 🔴 +416 B
assets/Load3dViewerContent-CRYmZsD5.js (removed) 993 B 🟢 -993 B 🟢 -469 B 🟢 -422 B
assets/SubscriptionPanelContentWorkspace-CaJ8jiCn.js (removed) 920 B 🟢 -920 B 🟢 -438 B 🟢 -378 B
assets/SubscriptionPanelContentWorkspace-ij26rae9.js (new) 920 B 🔴 +920 B 🔴 +437 B 🔴 +380 B
assets/graphHasMissingNodes-CDFYSLQR.js (new) 761 B 🔴 +761 B 🔴 +373 B 🔴 +329 B
assets/graphHasMissingNodes-I19aSmDz.js (removed) 761 B 🟢 -761 B 🟢 -372 B 🟢 -323 B
assets/changeTracker-CDN0VYFv.js (removed) 757 B 🟢 -757 B 🟢 -384 B 🟢 -338 B
assets/changeTracker-SObj5ZEL.js (new) 757 B 🔴 +757 B 🔴 +385 B 🔴 +370 B
assets/WidgetLegacy-ClSaWgiI.js (new) 745 B 🔴 +745 B 🔴 +384 B 🔴 +365 B
assets/WidgetLegacy-Cx_XoDJj.js (removed) 745 B 🟢 -745 B 🟢 -385 B 🟢 -336 B
assets/widget-NeEr3XWN.js (removed) 586 B 🟢 -586 B 🟢 -362 B 🟢 -297 B
assets/WidgetInputNumber-bR4G1DsN.js (new) 469 B 🔴 +469 B 🔴 +265 B 🔴 +228 B
assets/WidgetInputNumber-Jx2ZW9bu.js (removed) 469 B 🟢 -469 B 🟢 -264 B 🟢 -228 B
assets/AnimationControls-e1OB6oJR.js 4.61 kB 4.61 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/ApiNodesSignInContent-BKNHRD6l.js 2.69 kB 2.69 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/auto-BTnZwrs2.js 1.7 kB 1.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/BaseViewTemplate-DQKI7wOs.js 1.78 kB 1.78 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/comfy-logo-single-D9MrYETV.js 198 B 198 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/ComfyOrgHeader-CuEodz4y.js 910 B 910 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-B-AdR9IA.js 17.5 kB 17.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-CbkxT8K8.js 16.1 kB 16.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-CJGmjcIS.js 15.9 kB 15.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-CMaLgTTb.js 16.7 kB 16.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-Cw07MMbJ.js 18.8 kB 18.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-D7EtdE6o.js 16.9 kB 16.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-DknEFpK3.js 15.2 kB 15.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-Ds6WuXnw.js 16.1 kB 16.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-Dvq-F-mb.js 17.5 kB 17.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-pUOay9Eo.js 15.1 kB 15.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-u2AZ8xU4.js 16.1 kB 16.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/constants-htt0vt7m.js 579 B 579 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/i18n-Bcia7X9c.js 199 B 199 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/i18n-DI0OPWoR.js 531 kB 531 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-B_Wsy2zX.js 151 kB 151 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-BgoL-5j1.js 171 kB 171 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-BgP6H8V2.js 178 kB 178 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-BHnRTSDV.js 153 kB 153 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-BVdfMmEN.js 148 kB 148 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-CplVY01V.js 185 kB 185 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-D3J6T63F.js 207 kB 207 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-D8ud0Hl5.js 130 kB 130 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-DEL_HfgI.js 156 kB 156 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-DQyIQ6JB.js 148 kB 148 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-Y59dVx3K.js 131 kB 131 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/Media3DTop-Dqa2c7nZ.js 1.82 kB 1.82 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaAudioTop-DLiWNcHw.js 1.43 kB 1.43 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaImageTop-BLQErkwF.js 1.75 kB 1.75 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaOtherTop-NQGNpa4H.js 1.02 kB 1.02 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaTextTop-0crUoXWV.js 1.01 kB 1.01 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaVideoTop-sJMrm9jB.js 2.77 kB 2.77 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-4cn4-gG9.js 448 kB 448 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-B5k4lNE3.js 398 kB 398 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-BJNVnuoz.js 402 kB 402 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-bylbcqSc.js 448 kB 448 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CU0-WQTL.js 489 kB 489 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-D1sHTs_-.js 362 kB 362 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-DedOJsaf.js 414 kB 414 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-QD8mdHRS.js 366 kB 366 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-Rqekep7N.js 397 kB 397 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-rUOYRJo0.js 394 kB 394 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-wEnA0xcT.js 389 kB 389 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/OBJLoader2WorkerModule-DTMpvldF.js 109 kB 109 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/Popover-BIYdg9E5.js 3.65 kB 3.65 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/rolldown-runtime-DLICfi3-.js 1.97 kB 1.97 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/SelectValue-C_7cycpB.js 8.94 kB 8.94 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/signInSchema-CtKEtoXB.js 1.53 kB 1.53 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/Slider-DVkw5nPu.js 3.52 kB 3.52 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/src-CbNGuSYA.js 251 B 251 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/SubscriptionBenefits-DVSfLULk.js 2.01 kB 2.01 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/telemetry-zZf2dHJ2.js 226 B 226 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/types-DT3N7am7.js 204 B 204 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/VideoPlayOverlay-D-ZhKuWc.js 1.35 kB 1.35 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetBoundingBox-BYbwNME9.js 283 B 283 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetBoundingBox-GzA4D-L-.js 3.19 kB 3.19 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetChart-BtoXUSiF.js 2.21 kB 2.21 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetColorPicker-DCbDfd19.js 2.9 kB 2.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetCurve-CIcV8pqy.js 9.36 kB 9.36 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetGalleria-DZSYhGzO.js 3.61 kB 3.61 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetImageCompare-oYMwrOjF.js 7 kB 7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetInputText-0CncUIzA.js 1.86 kB 1.86 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetLayoutField-TvCt3ARa.js 1.98 kB 1.98 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetMarkdown-Cqdttdn1.js 2.93 kB 2.93 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/widgetPropFilter-DN03zIgB.js 1.1 kB 1.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetTextarea-B7IIifV6.js 3.96 kB 3.96 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetToggleSwitch-CTquGMvp.js 6.8 kB 6.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/widgetTypes-Br_tbhcL.js 393 B 393 B ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 53 added / 53 removed

@github-actions
Copy link

github-actions bot commented Feb 26, 2026

⚡ Performance Report

Metric Baseline PR Δ
canvas-idle: style recalcs 124 121 -2% ⚪
canvas-idle: layouts 0 0 +0% ⚪
canvas-idle: task duration 599ms 389ms -35% 🟢
canvas-mouse-sweep: style recalcs 179 196 +9% ⚪
canvas-mouse-sweep: layouts 12 12 +0% ⚪
canvas-mouse-sweep: task duration 919ms 1162ms +27% 🔴
dom-widget-clipping: style recalcs 45 46 +2% ⚪
dom-widget-clipping: layouts 0 1 new 🔴
dom-widget-clipping: task duration 394ms 379ms -4% ⚪
Raw data
{
  "timestamp": "2026-02-27T03:36:19.733Z",
  "gitSha": "97196ad689996968c5b9e7f57a0b31628819039e",
  "branch": "fix/replace-eval-with-math-parser",
  "measurements": [
    {
      "name": "canvas-idle",
      "durationMs": 2004.1259999999852,
      "styleRecalcs": 121,
      "styleRecalcDurationMs": 19.762,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 388.805,
      "heapDeltaBytes": -3178344
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 2174.387999999965,
      "styleRecalcs": 196,
      "styleRecalcDurationMs": 65.492,
      "layouts": 12,
      "layoutDurationMs": 3.5820000000000003,
      "taskDurationMs": 1162.085,
      "heapDeltaBytes": -3864548
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 590.6239999999912,
      "styleRecalcs": 46,
      "styleRecalcDurationMs": 17.31,
      "layouts": 1,
      "layoutDurationMs": 0.25300000000000006,
      "taskDurationMs": 378.611,
      "heapDeltaBytes": 8308568
    }
  ]
}

- Rename unit() to primary() for clarity
- Add modulo (%) operator support
- Normalize negative zero to positive zero
- Add depth limit (200) for nested parentheses
- Use isFinite() instead of isNaN() to reject Infinity
- Add tests for edge cases, unary-after-binary, modulo, depth limit, scientific/hex notation, and Infinity

Fixes #9272
Fixes #9273
Fixes #9274
Fixes #9275
@Myestery Myestery assigned christian-byrne and unassigned Myestery Feb 27, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/lib/litegraph/src/utils/mathParser.test.ts (1)

77-83: Consider typing the complex expression test data for type safety.

The as number assertion on line 82 is needed because TypeScript infers string | number for the tuple. You could eliminate this by explicitly typing the test data array.

🔧 Optional: Type the test data array
-  test.each([
+  test.each<[string, number]>([
     ['2 /2+3 * 4.75- -6', 21.25],
     // ... other cases
   ])('complex expression: %s', (input, expected) => {
-    expect(evaluateMathExpression(input)).toBeCloseTo(expected as number)
+    expect(evaluateMathExpression(input)).toBeCloseTo(expected)
   })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/litegraph/src/utils/mathParser.test.ts` around lines 77 - 83, The
test data array for the parameterized test is currently inferred as (string |
number) tuples forcing the use of `as number` in the assertion; explicitly
annotate the test data as an array of string-number tuples (e.g., type it as
[string, number][] or readonly [string, number][] depending on immutability) so
the parameter `expected` is inferred as number and you can remove the `as
number` cast in the expect call that uses evaluateMathExpression.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/lib/litegraph/src/utils/mathParser.test.ts`:
- Around line 77-83: The test data array for the parameterized test is currently
inferred as (string | number) tuples forcing the use of `as number` in the
assertion; explicitly annotate the test data as an array of string-number tuples
(e.g., type it as [string, number][] or readonly [string, number][] depending on
immutability) so the parameter `expected` is inferred as number and you can
remove the `as number` cast in the expect call that uses evaluateMathExpression.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 257adb5 and 1f0b74e.

📒 Files selected for processing (4)
  • src/lib/litegraph/src/utils/mathParser.test.ts
  • src/lib/litegraph/src/utils/mathParser.ts
  • src/lib/litegraph/src/utils/widget.test.ts
  • src/lib/litegraph/src/utils/widget.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/lib/litegraph/src/utils/widget.ts
  • src/lib/litegraph/src/utils/mathParser.ts
  • src/lib/litegraph/src/utils/widget.test.ts

Copy link
Contributor

@christian-byrne christian-byrne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@christian-byrne christian-byrne merged commit df71295 into main Mar 4, 2026
33 checks passed
@christian-byrne christian-byrne deleted the fix/replace-eval-with-math-parser branch March 4, 2026 22:04
Myestery added a commit that referenced this pull request Mar 5, 2026
## Summary
Replace `eval()` in `evaluateInput()` with a custom recursive descent
math parser, eliminating a security concern and enabling the `no-eval`
lint rule.

## Changes
- **New**: `mathParser.ts` — recursive descent parser for `+`, `-`, `*`,
`/`, `%`, `()`, decimals, unary operators. Zero new dependencies.
- **Modified**: `widget.ts` — replaced `eval()` call with
`evaluateMathExpression()`, use `isFinite()` instead of `isNaN()` to
reject `Infinity`
- **Modified**: `.oxlintrc.json` — `no-eval` rule changed from `"off"`
to `"error"`
- **Tests**: 59 parser tests + 23 integration tests covering complex
expressions, edge cases, and invalid input

## Review Feedback Addressed
- Renamed `unit()` → `primary()` for clarity
- Added modulo (`%`) operator support
- Normalized negative zero to positive zero
- Added depth limit (200) for nested parentheses
- Used `isFinite()` instead of `isNaN()` to reject
`Infinity`/`-Infinity`
- Added tests for edge-case number formats, unary-after-binary
operators, modulo, depth limits, scientific/hex notation, and `Infinity`

Fixes #8032
Fixes #9272
Fixes #9273
Fixes #9274
Fixes #9275

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9263-fix-Replace-eval-with-safe-math-expression-parser-3136d73d3650812f9f8dea21d1ea4f06)
by [Unito](https://www.unito.io)
@christian-byrne christian-byrne added the core/1.40 Backport PRs for core 1.40 label Mar 8, 2026
@christian-byrne christian-byrne added the needs-backport Fix/change that needs to be cherry-picked to the current feature freeze branch label Mar 8, 2026
@github-actions
Copy link

github-actions bot commented Mar 8, 2026

⚠️ Backport to core/1.40 failed

Reason: Merge conflicts detected during cherry-pick of df71295

📄 Conflicting files
src/lib/litegraph/src/litegraph.ts
src/lib/litegraph/src/utils/widget.test.ts
🤖 Prompt for AI Agents
Backport PR #9263 (https://github.com/Comfy-Org/ComfyUI_frontend/pull/9263) to core/1.40.
Cherry-pick merge commit df712953a3462ebaf9b3b22e4cfe9701e97e1b71 onto new branch
backport-9263-to-core-1.40 from origin/core/1.40.
Resolve conflicts in: src/lib/litegraph/src/litegraph.ts src/lib/litegraph/src/utils/widget.test.ts .
For test snapshots (browser_tests/**/*-snapshots/), accept PR version if
changed in original PR, else keep target. For package.json versions, keep
target branch. For pnpm-lock.yaml, regenerate with pnpm install.
Ask user for non-obvious conflicts.
Create PR titled "[backport core/1.40] <original title>" with label "backport".
See .github/workflows/pr-backport.yaml for workflow details.

cc @Myestery

1 similar comment
@github-actions
Copy link

github-actions bot commented Mar 8, 2026

⚠️ Backport to core/1.40 failed

Reason: Merge conflicts detected during cherry-pick of df71295

📄 Conflicting files
src/lib/litegraph/src/litegraph.ts
src/lib/litegraph/src/utils/widget.test.ts
🤖 Prompt for AI Agents
Backport PR #9263 (https://github.com/Comfy-Org/ComfyUI_frontend/pull/9263) to core/1.40.
Cherry-pick merge commit df712953a3462ebaf9b3b22e4cfe9701e97e1b71 onto new branch
backport-9263-to-core-1.40 from origin/core/1.40.
Resolve conflicts in: src/lib/litegraph/src/litegraph.ts src/lib/litegraph/src/utils/widget.test.ts .
For test snapshots (browser_tests/**/*-snapshots/), accept PR version if
changed in original PR, else keep target. For package.json versions, keep
target branch. For pnpm-lock.yaml, regenerate with pnpm install.
Ask user for non-obvious conflicts.
Create PR titled "[backport core/1.40] <original title>" with label "backport".
See .github/workflows/pr-backport.yaml for workflow details.

cc @Myestery

christian-byrne pushed a commit that referenced this pull request Mar 8, 2026
Replace `eval()` in `evaluateInput()` with a custom recursive descent
math parser, eliminating a security concern and enabling the `no-eval`
lint rule.

- **New**: `mathParser.ts` — recursive descent parser for `+`, `-`, `*`,
`/`, `%`, `()`, decimals, unary operators. Zero new dependencies.
- **Modified**: `widget.ts` — replaced `eval()` call with
`evaluateMathExpression()`, use `isFinite()` instead of `isNaN()` to
reject `Infinity`
- **Modified**: `.oxlintrc.json` — `no-eval` rule changed from `"off"`
to `"error"`
- **Tests**: 59 parser tests + 23 integration tests covering complex
expressions, edge cases, and invalid input

- Renamed `unit()` → `primary()` for clarity
- Added modulo (`%`) operator support
- Normalized negative zero to positive zero
- Added depth limit (200) for nested parentheses
- Used `isFinite()` instead of `isNaN()` to reject
`Infinity`/`-Infinity`
- Added tests for edge-case number formats, unary-after-binary
operators, modulo, depth limits, scientific/hex notation, and `Infinity`

Fixes #8032
Fixes #9272
Fixes #9273
Fixes #9274
Fixes #9275

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9263-fix-Replace-eval-with-safe-math-expression-parser-3136d73d3650812f9f8dea21d1ea4f06)
by [Unito](https://www.unito.io)
christian-byrne added a commit that referenced this pull request Mar 8, 2026
…arser (#9263) (#9575)

Backport of #9263 to core/1.40. Security fix — removes eval() usage.

Conflicts resolved: added new exports to litegraph.ts barrel, added new
test imports in widget.test.ts.

**Original PR:** #9263
**Pipeline ticket:** 15e1f241-efaa-4fe5-88ca-4ccc7bfb3345

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9575-backport-core-1-40-fix-Replace-eval-with-safe-math-expression-parser-9263-31d6d73d365081099903f24d1d6584cc)
by [Unito](https://www.unito.io)

Co-authored-by: Johnpaul Chiwetelu <49923152+Myestery@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:widgets core/1.40 Backport PRs for core 1.40 enhancement New feature or request needs-backport Fix/change that needs to be cherry-picked to the current feature freeze branch size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

2 participants