Skip to content

fix: empty catch in BrandingUtils and JSON.parse safety in browserTabsTracking - #42044

Closed
PedroHenrique0713 wants to merge 5 commits into
appsmithorg:releasefrom
PedroHenrique0713:fix/branding-and-tabs
Closed

fix: empty catch in BrandingUtils and JSON.parse safety in browserTabsTracking#42044
PedroHenrique0713 wants to merge 5 commits into
appsmithorg:releasefrom
PedroHenrique0713:fix/branding-and-tabs

Conversation

@PedroHenrique0713

@PedroHenrique0713 PedroHenrique0713 commented Jul 23, 2026

Copy link
Copy Markdown

Empty catch swallowed corrupted localStorage silently. browserTabsTracking JSON.parse without try/catch crashes module.

Summary by CodeRabbit

  • Bug Fixes

    • Improved handling when list-based widgets do not contain a child canvas.
    • Prevented browser tab tracking from failing when stored data is invalid.
    • Improved resilience when form configuration or evaluation data contains errors or is incomplete.
    • Preserved evaluation state more reliably when no updates are available.
  • Documentation

    • Added clarification around safe value handling during evaluation processing.

  When evaluation produced an empty tree, parsedUpdates[0] was undefined
  and accessing .rhs threw TypeError. Now checks .length before access.
… widget children

  When a ListWidget had no children, mainContainerId was set to empty
  string '' instead of undefined. Downstream code treating '' as a valid
  widget ID produced silent failures.
@PedroHenrique0713
PedroHenrique0713 requested a review from a team as a code owner July 23, 2026 21:33
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The changes update ListWidgetV2 binding defaults, make browser tab parsing tolerant of invalid storage data, guard empty evaluation updates, and document form evaluation and function serialization behavior.

Changes

Runtime robustness updates

Layer / File(s) Summary
Widget binding fallback
app/client/src/sagas/WidgetOperationUtils.ts
mainContainerId now becomes undefined when a ListWidgetV2 has no child container.
Evaluation worker safeguards
app/client/src/workers/Evaluation/handlers/evalTree.ts, app/client/src/workers/Evaluation/formEval.ts, app/client/src/workers/Evaluation/helpers.ts
Empty evaluation updates no longer access a missing element, form evaluation documents skipped errors, and function preservation during JSON serialization is documented.
Browser tab parsing fallback
app/client/src/utils/editor/browserTabsTracking.ts
Invalid local-storage JSON now produces an empty tab data object instead of throwing.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested labels: Task

Poem

Empty trees find gentle guards,
Lost tabs return with empty cards.
Widgets point where children lie,
Functions survive the JSON sky.
Quiet catches skip the scars.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is too brief and does not follow the required template sections like Description, Fixes, Automation, or Communication. Reformat the PR body to match the template and add the missing sections, including issue reference, automation details, and the communication checkbox.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title captures the main error-handling fixes, including browserTabsTracking JSON.parse safety, and is broadly aligned with the PR intent.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
app/client/src/workers/Evaluation/helpers.ts (1)

114-116: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Clarify that functions are restored as strings, not callable functions.

fnValue.toString() is reinjected after the JSON round-trip, and the accompanying tests confirm the resulting value is function source text. Please describe these as “function source strings” rather than saying functions are preserved.

Suggested wording
-  // Functions are preserved (collected before, re-injected after), but other
-  // non-JSON-safe types may be lost.
+  // Function source strings are collected before and re-injected after the
+  // JSON round-trip; the resulting values are not callable functions.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/client/src/workers/Evaluation/helpers.ts` around lines 114 - 116, Update
the explanatory comments near the JSON round-trip helper to state that functions
are collected and re-injected as function source strings, not preserved as
callable functions; keep the existing notes about other non-JSON-safe types
unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/client/src/utils/editor/browserTabsTracking.ts`:
- Line 11: Update the currentTabs initialization and trackOpenEditorTabs parsing
flow to parse storage JSON as unknown, then validate that the result is a
non-null, non-array object whose values are all strings before treating it as
TabData. For invalid shapes, including null, primitives, arrays, or non-string
values, retain the empty-object fallback so Object.values in trackOpenEditorTabs
cannot throw.

---

Nitpick comments:
In `@app/client/src/workers/Evaluation/helpers.ts`:
- Around line 114-116: Update the explanatory comments near the JSON round-trip
helper to state that functions are collected and re-injected as function source
strings, not preserved as callable functions; keep the existing notes about
other non-JSON-safe types unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: fd743343-f800-4eaa-86a1-aa861c786997

📥 Commits

Reviewing files that changed from the base of the PR and between 583811d and 12d0814.

📒 Files selected for processing (5)
  • app/client/src/sagas/WidgetOperationUtils.ts
  • app/client/src/utils/editor/browserTabsTracking.ts
  • app/client/src/workers/Evaluation/formEval.ts
  • app/client/src/workers/Evaluation/handlers/evalTree.ts
  • app/client/src/workers/Evaluation/helpers.ts

const getCurrentTabs = (): TabData => {
const currentTabsJSON = localStorage.getItem(LOCAL_STORAGE_KEY) || "{}";
const currentTabs: TabData = JSON.parse(currentTabsJSON);
let currentTabs: TabData = {}; try { currentTabs = JSON.parse(currentTabsJSON); } catch { /* use empty default */ }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Validate the parsed storage shape before treating it as TabData.

JSON.parse can successfully return null, an array, or a primitive. For example, stored "null" bypasses this catch, then Object.values(currentTabs) in trackOpenEditorTabs throws and can interrupt editor startup. Parse into unknown and accept only a non-null, non-array object with string values; otherwise return {}.

Proposed fix
-  let currentTabs: TabData = {}; try { currentTabs = JSON.parse(currentTabsJSON); } catch { /* use empty default */ }
+  let parsedTabs: unknown;
+  try {
+    parsedTabs = JSON.parse(currentTabsJSON);
+  } catch {
+    return {};
+  }
+
+  if (
+    !parsedTabs ||
+    typeof parsedTabs !== "object" ||
+    Array.isArray(parsedTabs) ||
+    !Object.values(parsedTabs).every(value => typeof value === "string")
+  ) {
+    return {};
+  }
+
+  const currentTabs = parsedTabs as TabData;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let currentTabs: TabData = {}; try { currentTabs = JSON.parse(currentTabsJSON); } catch { /* use empty default */ }
let parsedTabs: unknown;
try {
parsedTabs = JSON.parse(currentTabsJSON);
} catch {
return {};
}
if (
!parsedTabs ||
typeof parsedTabs !== "object" ||
Array.isArray(parsedTabs) ||
!Object.values(parsedTabs).every(value => typeof value === "string")
) {
return {};
}
const currentTabs = parsedTabs as TabData;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/client/src/utils/editor/browserTabsTracking.ts` at line 11, Update the
currentTabs initialization and trackOpenEditorTabs parsing flow to parse storage
JSON as unknown, then validate that the result is a non-null, non-array object
whose values are all strings before treating it as TabData. For invalid shapes,
including null, primitives, arrays, or non-string values, retain the
empty-object fallback so Object.values in trackOpenEditorTabs cannot throw.

Source: Coding guidelines

@PedroHenrique0713

Copy link
Copy Markdown
Author

Closing this one. I opened a stack of PRs in this repo today and, because each branch was cut from the previous one instead of from the base, they overlap: this PR carries the commits of the earlier ones as well. I am consolidating the work in #42033 and will resubmit the remaining fixes individually, on top of the base branch, once that one has been reviewed. Sorry for the noise.

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