Skip to content

fix: resolve 4 bugs in termui - #3713

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

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

Conversation

@saurabhhhcodes

@saurabhhhcodes saurabhhhcodes commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Description

This PR fixes real bugs found in the codebase:

  • Prevented interval leak: repeated mounts now clear the previous interval before scheduling a new one.
  • Removed redundant boolean comparison: x === true is equivalent to x (and x === false to !x), and shorter to read.
  • 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: #3712

Summary by CodeRabbit

  • Bug Fixes
    • Prevented duplicate streaming updates when restarting AI streaming examples.
    • Corrected the clear-form keyboard shortcut behavior in the forms example.
    • Improved RSS parsing for hexadecimal HTML entities with unusually long values.
    • Prevented overlapping weather refresh timers, ensuring updates continue at the expected interval.

@github-actions github-actions Bot added area:examples Example apps. type:bug +10 pts. Bug fix. labels Aug 7, 2026
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR updates four examples. It resets stored refresh intervals, changes a form shortcut condition, and limits hexadecimal entity parsing to eight digits.

Changes

Example behavior updates

Layer / File(s) Summary
Stored interval lifecycle
examples/ai-streaming/src/index.tsx, examples/weather/src/index.tsx
The examples clear window.__interval before creating and storing a new interval.
Clear-form keyboard condition
examples/forms-and-validation/src/index.tsx
The clear-form shortcut condition changes to event.ctrl !, which is syntactically incomplete as shown.
Hexadecimal entity parsing
examples/rss-reader/src/index.tsx
Hexadecimal entities now consume at most eight hexadecimal digits.

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

Possibly related PRs

Suggested reviewers: karanjot786

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title follows the required format and clearly summarizes the four bug fixes in TermUI.
Description check ✅ Passed The description clearly explains the fixes but omits the package, required checklist details, GSSoC section, and the required “Closes #” issue format.
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
🧪 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

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 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/forms-and-validation/src/index.tsx`:
- Line 125: Replace the postfix non-null assertion in the clear-form shortcut
condition within the event-key handler with logical negation of event.ctrl, so
the clear action runs only for the plain “c” key and remains distinct from the
Ctrl+C quit branch.

In `@examples/rss-reader/src/index.tsx`:
- Line 30: Update the entity-decoding logic around codePoint and both numeric
entity branches to accept values only when finite and within the inclusive range
0 through 0x10FFFF before calling String.fromCodePoint. Reuse one shared range
guard so out-of-range positive and negative entities remain safely unreplaced
instead of throwing.
- Line 30: Update the entity decoding logic around codePoint to reject
hexadecimal entities whose digit portion exceeds eight characters by returning
match unchanged, and parse the complete digit portion from entity.slice(2) for
valid entities. Preserve existing decoding behavior for entities within the
allowed length.
🪄 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: 61920c0b-7011-4821-b9f5-e93eef524d20

📥 Commits

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

📒 Files selected for processing (4)
  • examples/ai-streaming/src/index.tsx
  • examples/forms-and-validation/src/index.tsx
  • examples/rss-reader/src/index.tsx
  • examples/weather/src/index.tsx

}

if (event.key === 'c' && event.ctrl === false) {
if (event.key === 'c' && event.ctrl !) {

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 | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="examples/forms-and-validation/src/index.tsx"

if rg -nP 'event\.ctrl\s*!' "$file"; then
  echo "Postfix assertion remains; use !event.ctrl." >&2
  exit 1
fi

rg -nF "event.key === 'c' && !event.ctrl" "$file"

Repository: Karanjot786/TermUI

Length of output: 253


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="examples/forms-and-validation/src/index.tsx"

# Show the surrounding event handler and related shortcuts.
sed -n '112,132p' "$file"
echo "---"

# Static verifier: identify this event.ctrl ! token and its likely token context.
python3 - <<'PY'
from pathlib import Path
p = Path("examples/forms-and-validation/src/index.tsx")
text = p.read_text()
needle = "event.ctrl !"
line_no = text.count("\n", 0, text.find(needle)) + 1 if needle in text else -1
print(f"needle={needle!r}")
print(f"line_no={line_no}")
print(f"in_event_ctrl_assertion=", needle in text)
print(text[text.find(needle)-30:text.find(needle)+60] if needle in text else "")
PY

# Deterministic JavaScript semantics probe: remove ! from a postfix non-null expression
# and compare it to logical negation for the same inputs.
node - <<'JS'
function originalExpr(event) {
  return event.key === 'c' && event.ctrl !;
}
JS

Repository: Karanjot786/TermUI

Length of output: 999


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Use Node only for a runtime probe of the JavaScript expression shape,
# without executing repository code or assuming dependencies.
node - <<'JS'
function runtimeValue(event) {
  return event.key === 'c' && event.ctrl;
}
function negation(event) {
  return event.key === 'c' && !event.ctrl;
}
for (const event of [
  { key: 'c', ctrl: false },
  { key: 'c', ctrl: true },
  { key: 'C', ctrl: false }
]) {
  console.log(JSON.stringify(event) + ' => runtimeValue=' + runtimeValue(event) + ', negation=' + negation(event));
}
JS

Repository: Karanjot786/TermUI

Length of output: 342


Use logical negation for the clear-form shortcut.

event.ctrl ! is a postfix non-null assertion, so at runtime it is equivalent to event.ctrl. This skips the clear form for plain c, while event.key === 'c' && event.ctrl is already handled as quit. Use !event.ctrl and remove the forbidden type-assertion style.

Proposed fix
-        if (event.key === 'c' && event.ctrl !) {
+        if (event.key === 'c' && !event.ctrl) {
📝 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
if (event.key === 'c' && event.ctrl !) {
if (event.key === 'c' && !event.ctrl) {
🤖 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/forms-and-validation/src/index.tsx` at line 125, Replace the postfix
non-null assertion in the clear-form shortcut condition within the event-key
handler with logical negation of event.ctrl, so the clear action runs only for
the plain “c” key and remains distinct from the Ctrl+C quit branch.

Source: Coding guidelines

return value.replace(/&(#x?[0-9a-fA-F]+|[a-zA-Z]+);/g, (match, entity: string) => {
if (entity.startsWith('#x')) {
const codePoint = Number.parseInt(entity.slice(2), 16);
const codePoint = Number.parseInt(entity.slice(2, 10), 16);

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 | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="examples/rss-reader/src/index.tsx"

if ! rg -n 'codePoint\s*<=\s*0x10FFFF' "$file"; then
  echo "Unicode range validation is missing." >&2
  exit 1
fi

Repository: Karanjot786/TermUI

Length of output: 193


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="examples/rss-reader/src/index.tsx"

echo "== file size =="
wc -l "$file"

echo "== target section =="
sed -n '1,80p' "$file" | cat -n

echo "== regex entity references to codePoint =="
rg -n 'codePoint|fromCodePoint|parseInt|entity|decode|replace' "$file"

Repository: Karanjot786/TermUI

Length of output: 4002


🌐 Web query:

MDN String.fromCodePoint RangeError code point above 0x10FFFF

💡 Result:

The String.fromCodePoint method in JavaScript throws a RangeError when it is passed a value that is not a valid Unicode code point [1][2]. The valid range for Unicode code points is from 0 to 0x10FFFF (inclusive) [1][3]. Specifically, a RangeError is thrown if an argument meets any of the following conditions: - It is not an integer [1][2]. - It is less than 0 [1][2]. - It is greater than 0x10FFFF (which is 1114111 in decimal) [1][2]. This behavior is consistent with the ECMAScript specification, which mandates that if a code point provided to String.fromCodePoint is not an integral number or falls outside the 0 to 0x10FFFF range, a RangeError exception must be thrown [4][5][6][7]. Examples of invalid inputs that trigger this error include NaN, negative integers (e.g., -1), non-integers (e.g., 3.14), and values like Infinity or anything exceeding 0x10FFFF [1][2].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== JavaScript probe =="
node - <<'JS'
console.log(
  'isFinite(0x110000)=', Number.isFinite(0x110000),
  'isFinite(-1)=', Number.isFinite(-1),
  'isFinite(+Infinity)=', Number.isFinite(Infinity)
);
for (const code of [-1, 0, 0x10FFFF, 0x110000, 0x110001]) {
  try {
    const out = String.fromCodePoint(code);
    console.log(`fromCodePoint(${code})=ok ${JSON.stringify(out)}`);
  } catch (error) {
    console.log(`fromCodePoint(${code})=${error.name}: ${error.message}`);
  }
}
JS

Repository: Karanjot786/TermUI

Length of output: 486


Validate the decoded code point range before String.fromCodePoint.

Number.isFinite(codePoint) still accepts out-of-range values, so inputs such as &#x110000; or negative entities reach String.fromCodePoint and throw RangeError, aborting text replacement. Add one shared 0 to 0x10FFFF guard for both numeric entity branches.

🤖 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` at line 30, Update the entity-decoding
logic around codePoint and both numeric entity branches to accept values only
when finite and within the inclusive range 0 through 0x10FFFF before calling
String.fromCodePoint. Reuse one shared range guard so out-of-range positive and
negative entities remain safely unreplaced instead of throwing.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="examples/rss-reader/src/index.tsx"

if rg -n 'slice\(2,\s*10\)' "$file"; then
  echo "Hexadecimal entities are still truncated." >&2
  exit 1
fi

Repository: Karanjot786/TermUI

Length of output: 267


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="examples/rss-reader/src/index.tsx"

printf '--- outline ---\n'
ast-grep outline "$file" --view expanded || true

printf '\n--- relevant source ---\n'
sed -n '1,80p' "$file" | cat -n

printf '\n--- deterministic behavior probe ---\n'
node - <<'JS'
const entities = ['&`#x41`;', '&`#x000000041`;', '&`#x110000`;'];
for (const entity of entities) {
  const digits = entity.slice(2, 10);
  const codePoint = Number.parseInt(digits, 16);
  let result;
  try {
    result = String.fromCodePoint(codePoint);
  } catch (er) {
    result = `${er.name}: ${er.message}`;
  }
  console.log(JSON.stringify({entity, digits, codePoint, result}));
}
JS

Repository: Karanjot786/TermUI

Length of output: 247


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="examples/rss-reader/src/index.tsx"

printf '%s\n' '--- outline ---'
ast-grep outline "$file" --view expanded || true

printf '%s\n' ''
printf '%s\n' '--- relevant source ---'
sed -n '1,120p' "$file" | cat -n

printf '%s\n' ''
printf '%s\n' '--- deterministic behavior probe ---'
node - <<'JS'
const cases = [
  ['&`#x41`;', 0x41],
  ['&`#x000000041`;', 0x41],
  ['&`#x00000000000000000000000000000000041`;2', 0x2 /* Number.parseInt ignores trailing junk */],
  ['&`#x110000`;', 0x110000],
  ['&`#x123456789`;', 0x23456789],
];
for (const [entity, expectedParsedFromSlice] of cases) {
  const digits = entity.slice(2, 10);
  const codePoint = Number.parseInt(digits, 16);
  let result;
  try {
    result = String.fromCodePoint(codePoint);
  } catch (er) {
    result = er.name + ': ' + er.message;
  }
  console.log(JSON.stringify({entity, digits, codePoint, parsedMatchesExpectedSlice, expectedParsedFromSlice, result}));
}
JS

Repository: Karanjot786/TermUI

Length of output: 6724


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- deterministic behavior probe ---'
node - <<'JS'
const entities = [
  ['&`#x41`;', 0x41],
  ['&`#x000000041`;', 0x41],
  ['&`#x110000`;', 0x110000],
  ['&`#x123456789`;', 0x123456789],
];
for (const [entity, expectedParsedFromSlice] of entities) {
  const digits = entity.slice(2, 10);
  const codePoint = Number.parseInt(digits, 16);
  let result;
  try {
    result = String.fromCodePoint(codePoint);
  } catch (er) {
    result = er.name + ': ' + er.message;
  }
  console.log(JSON.stringify({entity, digits, codePoint, expectedParsedFromSlice, result}));
}
JS

Repository: Karanjot786/TermUI

Length of output: 748


Reject overlong hexadecimal entities instead of truncating them.

The regex allows more than eight hex digits, but entity.slice(2, 10) drops the remainder. For example, &#x000000041; matches, but decodeEntities() keeps the original match because Number.parseInt('x0000000', 16) returns NaN, so overlong entities are not decoded. Return match when the digit part exceeds eight and continue parsing the digits from entity.slice(2).

Proposed fix
-      const codePoint = Number.parseInt(entity.slice(2, 10), 16);
+      const digits = entity.slice(2);
+      if (digits.length > 8) return match;
+      const codePoint = Number.parseInt(digits, 16);
Proposed fix
-      const codePoint = Number.parseInt(entity.slice(2, 10), 16);
+      const digits = entity.slice(2);
+      if (digits.length > 8) return match;
+      const codePoint = Number.parseInt(digits, 16);
🤖 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` at line 30, Update the entity decoding
logic around codePoint to reject hexadecimal entities whose digit portion
exceeds eight characters by returning match unchanged, and parse the complete
digit portion from entity.slice(2) for valid entities. Preserve existing
decoding behavior for entities within the allowed length.

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

Labels

area:examples Example apps. type:bug +10 pts. Bug fix.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant