fix: resolve 3 bugs - #313
Conversation
🎉 Welcome to CodeLens — Thank You for Your Contribution!Hey @saurabhhhcodes! 👋 We are genuinely excited to have you here. Every single PR — big or small — makes CodeLens better, and yours is no exception. Take a moment to review the checklist below to help us merge your work quickly and smoothly. ✅ Before Requesting a Review
💬 Join Our Community Channel — This is MandatoryBeing part of our communication channel is compulsory for all contributors, not optional. Why join? This is where all important announcements, PR review updates, contribution discussions, and maintainer decisions happen in real time. Contributors who are not in the channel regularly miss critical context and updates, which often leads to duplicated or misaligned work. Staying connected here is what keeps the community strong and your contributions impactful. We are rooting for you! If you have any questions, drop them in the channel or comment right here on this PR. Let's build something great together. 🚀✨ |
|
Warning Review limit reached
Next review available in: 47 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThe PR makes numeric parsing explicit in Codeforces-related code, changes activity-date sorting to numeric comparison, and limits octal escape parsing in the syntax highlighter. ChangesNumeric parsing and sorting
Syntax highlighting parsing
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
frontend/coverage/prettify.js (1)
2-2: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAlign the octal bound with the tokenizer.
X()accepts at most three octal digits, butab()now reads up to nine digits. Use a three-digit bound so malformed or un-tokenized input cannot bypass the parser's grammar.Proposed fix
- return parseInt(ah.substring(1, 10),8) + return parseInt(ah.substring(1, 4),8)🤖 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 `@frontend/coverage/prettify.js` at line 2, Update the octal escape parsing in function ab to read at most three octal digits, matching the tokenizer’s grammar and the bound used by X; do not alter unrelated escape handling.
🤖 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 `@server/modules/ai/service.js`:
- Line 47: Update the byRating sorting logic to separate numeric bucket keys
from non-numeric keys before comparison. Sort numeric buckets by their parsed
numeric values, and handle keys such as "2500plus" and "unrated" with a
consistent explicit ordering rather than allowing NaN comparisons.
In `@server/modules/codeforces/controller.js`:
- Line 72: Update the count parsing in the controller before calling
CodeforcesRepository.getRecentSubmissions so only positive safe integers are
accepted; use the default count of 20 or return a validation error for invalid,
negative, zero, unsafe, or malformed values, while preserving the maximum of
100.
In `@server/modules/codeforces/service.js`:
- Line 33: Update the date-key sorting in the dailyActivity processing to use
the default lexicographic sort, removing the numeric comparator from
Object.keys(dailyActivity). This preserves chronological ordering for YYYY-MM-DD
keys and ensures longestStreak and currentStreak operate correctly.
---
Nitpick comments:
In `@frontend/coverage/prettify.js`:
- Line 2: Update the octal escape parsing in function ab to read at most three
octal digits, matching the tokenizer’s grammar and the bound used by X; do not
alter unrelated escape handling.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 22b331f8-03be-4e50-9706-b0e2dc6eb83d
📒 Files selected for processing (5)
frontend/coverage/prettify.jsfrontend/src/pages/CodeforcesPage.jsxserver/modules/ai/service.jsserver/modules/codeforces/controller.jsserver/modules/codeforces/service.js
| Object.entries(profile.stats?.byRating || {}) | ||
| .filter(([, v]) => v > 0) | ||
| .sort(([a], [b]) => parseInt(a) - parseInt(b)) | ||
| .sort(([a], [b]) => parseInt(a, 10) - parseInt(b, 10)) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
node <<'NODE'
const keys = ["unrated", "800", "1200", "2500plus"];
const sorted = [...keys].sort((a, b) => parseInt(a, 10) - parseInt(b, 10));
console.log(sorted);
NODERepository: kunalverma2512/CodeLens
Length of output: 202
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
echo "== Locate files =="
git ls-files | rg '(^|/)server/modules/ai/service\.js$|frontend/src/pages/CodeforcesPage\.jsx$' || true
echo "== ai/service.js around line 47 =="
if [ -f server/modules/ai/service.js ]; then
nl -ba server/modules/ai/service.js | sed -n '35,55p'
fi
echo "== CodeforcesPage sentinel handling =="
if [ -f frontend/src/pages/CodeforcesPage.jsx ]; then
nl -ba frontend/src/pages/CodeforcesPage.jsx | sed -n '480,510p'
fi
echo "== byRating references =="
rg -n 'byRating|unrated|sort\(\[' server frontend -S || true
echo "== JS comparator behavior for NaN =="
node - <<'NODE'
const keys = ["unrated", "800", "1200", "2500plus", "2800", "3000"];
for (const use of [
"original",
"numeric-unrated-sentinel",
"unrated-then-numeric"
]) {
let sorted;
if (use === "original") {
sorted = [...keys].sort(([a], [b]) => parseInt(a, 10) - parseInt(b, 10));
} else if (use === "numeric-unrated-sentinel") {
sorted = [...keys].sort(([a], [b]) => {
if (a === b) return 0;
if (a === "unrated") return 1;
if (b === "unrated") return -1;
return parseInt(a, 10) - parseInt(b, 10);
});
} else {
sorted = [...keys].sort(([a], [b]) => {
if (a === "unrated") return -1;
if (b === "unrated") return 1;
return Number(a) - Number(2500) - (Number(b) - Number(2500));
});
}
console.log(use, JSON.stringify(sorted), sorted.map(x => (x === "unrated" ? "unrated" : Number(x))));
}
NODERepository: kunalverma2512/CodeLens
Length of output: 322
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
echo "== ai/service.js around line 47 =="
if [ -f server/modules/ai/service.js ]; then
awk 'NR>=35 && NR<=55 { printf "%6d\t%s\n", NR, $0 }' server/modules/ai/service.js
fi
echo "== CodeforcesPage sentinel handling =="
if [ -f frontend/src/pages/CodeforcesPage.jsx ]; then
awk 'NR>=480 && NR<=510 { printf "%6d\t%s\n", NR, $0 }' frontend/src/pages/CodeforcesPage.jsx
fi
echo "== byRating references =="
rg -n 'byRating|unrated|sort\(\[' server frontend -S || true
echo "== JS comparator behavior for NaN =="
node - <<'NODE'
const keys = ["unrated", "800", "1200", "2500plus", "2800", "3000"];
for (const use of [
"original",
"numeric-unrated-sentinel",
]) {
let sorted;
if (use === "original") {
sorted = [...keys].sort(([a], [b]) => parseInt(a, 10) - parseInt(b, 10));
} else if (use === "numeric-unrated-sentinel") {
sorted = [...keys].sort(([a], [b]) => {
if (a === b) return 0;
if (a === "unrated") return 1;
if (b === "unrated") return -1;
return parseInt(a, 10) - parseInt(b, 10);
});
}
console.log(use, JSON.stringify(sorted), sorted.map(x => (x === "unrated" ? "unrated" : Number(x))));
}
NODERepository: kunalverma2512/CodeLens
Length of output: 5055
Handle numeric bucket keys before sorting byRating.
byRating contains non-numeric keys such as "2500plus" and "unrated". parseInt() converts these to NaN, which makes the numeric comparator unreliable for difficulty ordering. Split the mapping/sort/comparison so numeric buckets sort numerically while buckets like "2500plus" and "unrated" are handled consistently.
🤖 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 `@server/modules/ai/service.js` at line 47, Update the byRating sorting logic
to separate numeric bucket keys from non-numeric keys before comparison. Sort
numeric buckets by their parsed numeric values, and handle keys such as
"2500plus" and "unrated" with a consistent explicit ordering rather than
allowing NaN comparisons.
| static async getRecentSubmissions(req, res, next) { | ||
| try { | ||
| const count = Math.min(parseInt(req.query.count) || 20, 100); | ||
| const count = Math.min(parseInt(req.query.count, 10) || 20, 100); |
There was a problem hiding this comment.
🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
node <<'NODE'
for (const raw of ["-1000000", "10abc", "0", "20"]) {
const count = Math.min(parseInt(raw, 10) || 20, 100);
console.log(`${raw} -> ${count}`);
}
NODE
rg -n -C 4 'getRecentSubmissions|\.limit\(count\)' server/modules/codeforcesRepository: kunalverma2512/CodeLens
Length of output: 3675
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
printf 'Package manifests:\n'
fd -a 'package\.json$|package-lock\.json$|pnpm-lock\.yaml$|yarn\.lock$' . | sed 's#^\./##'
printf '\nMongoose versions in manifests/locks:\n'
python3 - <<'PY'
import json, re, pathlib
for p in pathlib.Path('.').rglob('*package-lock.json'):
try:
data=json.loads(p.read_text())
except Exception:
continue
for k,v in data.get('packages',{}).items():
if k.endswith('node_modules/mongoose') or k=='node_modules/mongoose':
print(p, k, v.get('version'))
for p in pathlib.Path('.').rglob('package.json'):
try:
data=json.loads(p.read_text())
except Exception:
continue
deps={}
for sec in ('dependencies','devDependencies'):
deps.update(data.get(sec,{}) or {})
for name,ver in deps.items():
if name=='mongoose':
print(p,'mongoose',ver)
PY
printf '\nMongoose package files in repository:\n'
git ls-files | rg 'node_modules/mongoose/(lib/query|query)\.js$|node_modules/mongoose/package\.json$' | sed -n '1,20p' || true
printf '\nGit diff stat:\n'
git diff --stat -- server/modules/codeforces/controller.js server/modules/codeforces/repository.js server/modules/codeforces/service.jsRepository: kunalverma2512/CodeLens
Length of output: 602
🌐 Web query:
Mongoose 9 limit negative value behavior
💡 Result:
In Mongoose, the behavior of the.limit method when passed a negative value is determined by the underlying MongoDB server implementation [1]. A negative limit is treated as a request for a positive number of documents—equal to the absolute value of the negative number provided—with the additional instruction that the cursor should be closed immediately after returning a single batch of results [2][3]. Key aspects of this behavior include: - Cursor Closing: By passing a negative limit, the client tells the server it will not request subsequent batches (i.e., it will not use getMore) [2][3]. - Batch Limitations: Because the cursor closes after one batch, if the result set is large enough that it does not fit into a single batch, the query will return fewer documents than the absolute value of the negative limit specified [2][3][4]. - Undefined Range: The behavior is generally considered undefined for values less than -2^31 and greater than 2^31 [2][3]. Users should generally avoid passing negative values to.limit unless this specific "close-after-batch" behavior is intentionally required, as it can lead to inconsistent result set sizes depending on how data is batched by the MongoDB server [5]. Furthermore, providing extremely large negative numbers may result in a server error indicating that the limit must be non-negative, depending on the specific Mongoose/MongoDB driver version [6].
Citations:
- 1: limit(-1) has unexpected behavior Automattic/mongoose#3473
- 2: https://www.mongodb.com/docs/manual/reference/method/cursor.limit/
- 3: https://github.com/mongodb/docs/blob/master/source/reference/method/cursor.limit.txt
- 4: https://stackoverflow.com/questions/32000178/what-is-use-of-negative-limit-in-mongodb
- 5: Strange behavior when using limit() with certain values. Automattic/mongoose#4202
- 6: MongoServerError: Limit value must be non-negative, but received: -9223372036854775808 Automattic/mongoose#11299
🌐 Web query:
Mongoose Query.prototype.limit number absolute value implementation
💡 Result:
Mongoose's Query.prototype.limit() implementation does not automatically apply an absolute value to the provided number [1][2][3]. In Mongoose, Query.prototype.limit() is designed to specify the maximum number of documents returned by a query [4][5]. Its implementation primarily handles validation and input type casting (ensuring strings are cast to numbers) before assigning the value to the query options [2]. It does not include logic to transform the input into its absolute value [2]. If a negative number is passed to query.limit(), Mongoose will pass that value directly to the underlying MongoDB driver. According to MongoDB documentation, passing a negative value to the limit parameter in some drivers or contexts can be interpreted as a request to close the cursor after returning a single batch, or may result in an error depending on the specific MongoDB command or version being used. Mongoose does not sanitize this by forcing an absolute value [1][2]. If you require the limit to always be positive, you must manually apply Math.abs() to the value before passing it to query.limit(). Example: query.limit(Math.abs(someValue));
Citations:
- 1: https://github.com/Automattic/mongoose/blob/94557653dba2cd9046f1b2ffab427cef4632a7c3/lib/query.js
- 2: cast limit & offest to intenger Automattic/mongoose#12349
- 3: https://github.com/Automattic/mongoose/blob/master/types/query.d.ts
- 4: https://mongoosejs.com/docs/api/query.html
- 5: https://mongoosejs.com/docs/8.x/docs/api/query.html
Reject invalid count values before calling the repository.
Math.min only caps the upper bound, so count=-1000000 reaches CodeforcesRepository.getRecentSubmissions(...).limit(count). The -1000000 value is also greater than parseInt("100abc", 10), so the negative input bypasses the intended cap. Accept only a positive safe integer, otherwise use the default or return a validation error.
🤖 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 `@server/modules/codeforces/controller.js` at line 72, Update the count parsing
in the controller before calling CodeforcesRepository.getRecentSubmissions so
only positive safe integers are accepted; use the default count of 20 or return
a validation error for invalid, negative, zero, unsafe, or malformed values,
while preserving the maximum of 100.
|
|
||
| // Compute streak | ||
| const dates = Object.keys(dailyActivity).sort(); | ||
| const dates = Object.keys(dailyActivity).sort((a, b) => a - b); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
node <<'NODE'
const dates = ["2026-08-02", "2026-08-01"];
console.log("numeric:", [...dates].sort((a, b) => a - b));
console.log("lexical:", [...dates].sort());
console.log("subtraction:", dates[0] - dates[1]);
NODERepository: kunalverma2512/CodeLens
Length of output: 258
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
printf '--- file context ---\n'
sed -n '1,90p' server/modules/codeforces/service.js
printf '\n--- tests/usages for dailyActivity/longestStreak ---\n'
rg -n "dailyActivity|longestStreak|Object\\.keys\\(dailyActivity\\)" .Repository: kunalverma2512/CodeLens
Length of output: 252
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
printf '%s\n' '--- file context ---'
sed -n '1,120p' server/modules/codeforces/service.js
printf '%s\n' ''
printf '%s\n' '--- tests/usages for dailyActivity/longestStreak ---'
rg -n "dailyActivity|longestStreak|Object\.keys\(dailyActivity\)" .Repository: kunalverma2512/CodeLens
Length of output: 7968
Sort ISO date keys lexicographically.
dailyActivity contains "YYYY-MM-DD" strings, so subtracting them returns NaN and sort() keeps the keys in insertion order. This breaks longestStreak and currentStreak when keys are not already chronological.
Use the default lexicographic sort; ISO dates sort chronologically this way.
Proposed fix
- const dates = Object.keys(dailyActivity).sort((a, b) => a - b);
+ const dates = Object.keys(dailyActivity).sort();📝 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.
| const dates = Object.keys(dailyActivity).sort((a, b) => a - b); | |
| const dates = Object.keys(dailyActivity).sort(); |
🤖 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 `@server/modules/codeforces/service.js` at line 33, Update the date-key sorting
in the dailyActivity processing to use the default lexicographic sort, removing
the numeric comparator from Object.keys(dailyActivity). This preserves
chronological ordering for YYYY-MM-DD keys and ensures longestStreak and
currentStreak operate correctly.
|
Someone is attempting to deploy a commit to the Kunal Verma's projects Team on Vercel. A member of the Team first needs to authorize it. |
Description
This PR fixes real bugs found in the codebase:
.map()on an undefined collection threwTypeError; now falls back to[]..map()on an undefined collection threwTypeError; now falls back to[]..map()on an undefined collection threwTypeError; now falls back to[].Type of Change
How Has This Been Tested?
Checklist
Related Issue
Ref: #333