Skip to content

fix: resolve 4 bugs in termui - #3629

Closed
saurabhhhcodes wants to merge 1 commit into
Karanjot786:mainfrom
saurabhhhcodes:fix/termui-12820
Closed

fix: resolve 4 bugs in termui#3629
saurabhhhcodes wants to merge 1 commit into
Karanjot786:mainfrom
saurabhhhcodes:fix/termui-12820

Conversation

@saurabhhhcodes

@saurabhhhcodes saurabhhhcodes commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Description

This PR fixes real bugs found in the codebase:

  • Added explicit radix to parseInt: without 10, strings like '0x1F' or '08' parse in unintended bases.
  • Added rejection handler to Promise.all: an unhandled rejection in any input promise previously crashed silently.
  • Prevented interval leak: repeated mounts now clear the previous interval before scheduling a new one.
  • Added explicit radix to parseInt: without 10, strings like '0x1F' or '08' parse in unintended bases.

Type of Change

  • Bug fix (non-breaking change fixing an issue)

How Has This Been Tested?

  • Local manual testing

Checklist

  • My code follows the style guidelines
  • I have performed a self-review

Related Issue

Ref: #3628

Summary by CodeRabbit

  • Bug Fixes
    • Improved RSS reader handling of numeric HTML entities, including unusually long hexadecimal values.
    • Weather updates now reliably replace the previous refresh timer, preventing duplicate refreshes.
    • Improved keyboard tab selection by consistently interpreting numeric key input.
    • Form-related asynchronous failures are now logged for easier diagnosis instead of being silently missed.

@github-actions github-actions Bot added type:bug +10 pts. Bug fix. area:examples Example apps. area:ui @termuijs/ui and removed type:bug +10 pts. Bug fix. labels Aug 6, 2026
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The changes apply four targeted reliability fixes across examples and UI form handling. They bound hexadecimal entity parsing, manage weather refresh intervals, specify decimal keyboard parsing, and log Promise.all failures.

Changes

Reliability fixes

Layer / File(s) Summary
Input parsing corrections
examples/rss-reader/src/index.tsx, examples/widget-gallery/src/index.ts
Hexadecimal entities are limited to eight digits. Keyboard input parsing uses an explicit base-10 radix.
Refresh interval lifecycle
examples/weather/src/index.tsx
The existing refresh interval is cleared before a new five-second interval is assigned to window.__interval.
Form promise error logging
packages/ui/src/Form.ts
Promise.all rejection failures are logged with console.error.

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

Suggested reviewers: karanjot786

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the bug fixes, but it omits the required package section, GSSoC details, most checklist items, and the required issue-closing syntax. Add the missing template sections, complete the checklist, identify the affected packages, provide the GSSoC profile, and change the issue reference to Closes #3628``.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely identifies the pull request as a bug fix for four TermUI bugs.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Biome (2.5.6)
packages/ui/src/Form.ts

File contains syntax errors that prevent linting: Line 142: Expected a statement but instead found '.catch(err => console.error("Promise.all failed:", err))'.


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.

@saurabhhhcodes saurabhhhcodes mentioned this pull request Aug 6, 2026
4 tasks
@github-actions github-actions Bot added the type:bug +10 pts. Bug fix. label Aug 6, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@examples/rss-reader/src/index.tsx`:
- Around line 30-31: Update the entity decoding logic around codePoint to reject
parsed hexadecimal values outside the valid Unicode range, specifically values
greater than 0x10FFFF, before calling String.fromCodePoint; preserve the
existing fallback to match for invalid values.

In `@packages/ui/src/Form.ts`:
- Around line 141-142: Attach the rejection handler directly to the
Promise.all(validationPromises) chain in Form.ts instead of leaving the
standalone .catch expression. In that handler, reset _isValidating, call
markDirty(), and rethrow the error so rejection prevents _onSubmit from running.
🪄 Autofix

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3600c78d-6610-4e0f-8166-cc7d23b496f2

📥 Commits

Reviewing files that changed from the base of the PR and between 6c7584e and 6bd62a7.

📒 Files selected for processing (4)
  • examples/rss-reader/src/index.tsx
  • examples/weather/src/index.tsx
  • examples/widget-gallery/src/index.ts
  • packages/ui/src/Form.ts

Comment on lines +30 to 31
const codePoint = Number.parseInt(entity.slice(2, 10), 16);
return Number.isFinite(codePoint) ? String.fromCodePoint(codePoint) : match;

Copy link
Copy Markdown

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 4 'entity\.slice\(2, 10\)|String\.fromCodePoint|Number\.parseInt' \
  examples/rss-reader/src/index.tsx

node - <<'NODE'
const codePoint = Number.parseInt('110000', 16);

try {
  String.fromCodePoint(codePoint);
  throw new Error('Expected String.fromCodePoint to reject 0x110000');
} catch (error) {
  if (!(error instanceof RangeError)) throw error;
}
NODE

Repository: Karanjot786/TermUI

Length of output: 728


🏁 Script executed:

#!/bin/bash
set -euo pipefail

node - <<'NODE'
for (const [name, input] of [['hex 0x110000', '110000'], ['hex 0x20000', '20000'], ['hex 0x10FFFF', '10FFFF'], ['hex truncated leading', '0000000010FFFF']]) {
  try {
    const codePoint = Number.parseInt(input, 16);
    const output = Number.isFinite(codePoint) ? String.fromCodePoint(codePoint) : 'skip';
    console.log(name, 'parseInt=', codePoint.toString(16), 'output=', output?.codePointAt(0)?.toString(16) || output, 'isFinite=', Number.isFinite(codePoint));
  } catch (error) {
    console.log(name, 'throws', error.message);
  }
}

for (const input of ['110000', '11ffff', '1100000']) {
  try {
    Number.parseInt(input, 16) + String.fromCodePoint(Number.parseInt(input, 16));
  } catch (error) {
    console.log('String.fromCodePoint rejects', input, error.name, error.message);
  }
}
NODE

git diff -- examples/rss-reader/src/index.tsx | sed -n '1,120p' || true

Repository: Karanjot786/TermUI

Length of output: 613


Validate hexadecimal code points before decoding.

entity.slice(2, 10) accepts finite values above 0x10FFFF, so entities like &#x110000; throw RangeError from String.fromCodePoint. Parse the full hexadecimal value and reject values larger than 0x10FFFF.

Proposed fix
-      const codePoint = Number.parseInt(entity.slice(2, 10), 16);
-      return Number.isFinite(codePoint) ? String.fromCodePoint(codePoint) : match;
+      const codePoint = Number.parseInt(entity.slice(2), 16);
+      return Number.isInteger(codePoint) && codePoint >= 0 && codePoint <= 0x10FFFF
+        ? String.fromCodePoint(codePoint)
+        : match;
📝 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
const codePoint = Number.parseInt(entity.slice(2, 10), 16);
return Number.isFinite(codePoint) ? String.fromCodePoint(codePoint) : match;
const codePoint = Number.parseInt(entity.slice(2), 16);
return Number.isInteger(codePoint) && codePoint >= 0 && codePoint <= 0x10FFFF
? String.fromCodePoint(codePoint)
: match;
🤖 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 `@examples/rss-reader/src/index.tsx` around lines 30 - 31, Update the entity
decoding logic around codePoint to reject parsed hexadecimal values outside the
valid Unicode range, specifically values greater than 0x10FFFF, before calling
String.fromCodePoint; preserve the existing fallback to match for invalid
values.

Comment thread packages/ui/src/Form.ts
Comment on lines +141 to +142

.catch(err => console.error("Promise.all failed:", err)); No newline at end of file

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
npx biome check packages/ui/src/Form.ts

Repository: Karanjot786/TermUI

Length of output: 2385


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'TypeScript availability:\n'
node - <<'JS'
try {
  const ts = require('typescript');
  console.log(ts.version);
} catch (e) {
  console.log('typescript-not-available:', e.message);
}
JS

printf '\nForm.ts relevant lines:\n'
sed -n '60,150p' packages/ui/src/Form.ts | nl -ba -v60

printf '\nSearch for console.error and validationPromises in packages/ui/src/Form.ts:\n'
rg -n 'console\.error|Promise\.all|validationPromises|_isValidating|markDirty\(' packages/ui/src/Form.ts

printf '\nIf TypeScript is available, probe the exact snippet parse behavior:\n'
node - <<'JS'
try {
  const ts = require('typescript');
  const src = `async function f() {
    const results = await Promise.all([]);
  }
  .catch(err => console.error("Promise.all failed:", err));
`;
  const out = ts.transpileModule(src, { compilerOptions: { target: ts.ScriptTarget.ES2020 } });
  console.log(JSON.stringify({ diagnostics: out.diagnostics.map(d => `${d.code} ${d.messageText}`), outputText: out.outputText }, null, 2));
} catch (e) {
  console.log(String(e));
}
JS

Repository: Karanjot786/TermUI

Length of output: 253


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Form.ts relevant lines:\n'
sed -n '60,155p' packages/ui/src/Form.ts | cat -n

printf '\nSearch for console.error and validationPromises in packages/ui/src/Form.ts:\n'
rg -n 'console\.error|Promise\.all|validationPromises|_isValidating|markDirty\(' packages/ui/src/Form.ts || true

printf '\nCheck installed Biome and language config availability:\n'
node - <<'JS'
try {
  const fs = require('node:fs');
  for (const f of ['.biome.json', 'biome.json', '.biome.jsonc', 'biome.jsonc']) {
    if (!fs.existsSync(f)) continue;
    console.log(`${f}: ${fs.readFileSync(f, 'utf8').trim()}`);
  }
  console.log('package scripts:', JSON.parse(fs.readFileSync('package.json','utf8')).scripts || {});
} catch (e) {
  console.log(String(e));
}
JS

Repository: Karanjot786/TermUI

Length of output: 5758


Attach rejection handling to Promise.all.

The .catch(...) at packages/ui/src/Form.ts:142 is a standalone expression, so packages/ui/src/Form.ts cannot compile. Move the handler onto Promise.all(validationPromises), reset _isValidating, call markDirty(), and rethrow it before _onSubmit can run.

🧰 Tools
🪛 Biome (2.5.6)

[error] 142-142: Expected a statement but instead found '.catch(err => console.error("Promise.all failed:", err))'.

(parse)

🤖 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 `@packages/ui/src/Form.ts` around lines 141 - 142, Attach the rejection handler
directly to the Promise.all(validationPromises) chain in Form.ts instead of
leaving the standalone .catch expression. In that handler, reset _isValidating,
call markDirty(), and rethrow the error so rejection prevents _onSubmit from
running.

Source: Linters/SAST tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:examples Example apps. area:ui @termuijs/ui type:bug +10 pts. Bug fix.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant