Skip to content

Improving safety checks in diagnostics channel#6160

Merged
jasnell merged 1 commit intomainfrom
jasnell/nodejs_diagnostics_channel_improvements
Feb 24, 2026
Merged

Improving safety checks in diagnostics channel#6160
jasnell merged 1 commit intomainfrom
jasnell/nodejs_diagnostics_channel_improvements

Conversation

@jasnell
Copy link
Copy Markdown
Collaborator

@jasnell jasnell commented Feb 24, 2026

No description provided.

@jasnell jasnell requested a review from anonrig February 24, 2026 20:48
@jasnell jasnell requested review from a team as code owners February 24, 2026 20:48
@jasnell jasnell enabled auto-merge February 24, 2026 20:52
@ask-bonk
Copy link
Copy Markdown
Contributor

ask-bonk bot commented Feb 24, 2026

OK, -Wshadow isn't explicitly enabled. Let me reconsider my findings:

  1. The KJ_IF_SOME(value, value(js)) naming is confusing but works. The existing code in the same file uses similar patterns (double value; in JsNumber::value() and int32_t value; in JsInt32::value() etc.) so it's an established pattern.

  2. The behavioral change in clearTimeout/clearInterval is a bug fix eliminating UB — no compat flag needed.

  3. The isSafeInteger() has a redundant check but it's defensive programming.

  4. One real concern: the isSafeInteger check includes if (!inner->IsNumber()) return false; — since inner is v8::Local<v8::Number>, this condition is always false. This could give a false sense that it handles non-number types, when in reality the type system already guarantees it. But this is defensive, not a bug.

  5. The toSafeInteger accesses inner.As<v8::Number>()->Value() directly instead of going through value(js). This is fine — we already validated via isSafeInteger that the value is safe, and v8::Number::Value() is a simple accessor that can't fail.

Actually, wait — let me re-examine one thing. In the value() method:

kj::Maybe<double> JsNumber::value(Lock& js) const {
  KJ_ASSERT(!inner.IsEmpty());
  double value;
  if (inner->NumberValue(js.v8Context()).To(&value)) {
    return value;
  }
  return kj::none;
}

inner is v8::Local<v8::Number>. NumberValue() on a v8::Number should always succeed. So value() should never return kj::none for a properly constructed JsNumber. But the function signature says kj::Maybe<double> for robustness.

Then in isSafeInteger:

KJ_IF_SOME(value, value(js)) {

This calls this->value(js), gets a kj::Maybe<double>, and unwraps it. Since value(js) on a v8::Number should never fail, the outer return false after the KJ_IF_SOME block should never be reached. But again, defensive programming.

Overall this PR looks solid. The main thing I'd flag is the variable name shadowing for readability, but I need to decide if that's actionable or nitpicky.

Let me check: is there a real risk from the shadowing? In KJ_IF_SOME(value, value(js)), the macro expands to something like:

for (auto _kj_value = value(js); ...) {
  auto& value = _kj_value;  // simplified
  ...
}

Actually, KJ_IF_SOME typically expands to use a unique variable name internally, so value(js) is evaluated first, then the result is stored, and then value is introduced as a name. The function call value(js) correctly calls the member function because the new local isn't in scope yet. So this is safe, just confusing to read.

I think this PR is clean enough that the issues are not actionable per the review criteria. The shadowing is a style preference (and the codebase uses this pattern already), not a logic bug. The IsNumber() guard is defensive, not wrong. The behavioral change in clearTimeout fixes UB without breaking observable behavior.

LGTM

github run

@jasnell jasnell merged commit ec455c1 into main Feb 24, 2026
37 of 40 checks passed
@jasnell jasnell deleted the jasnell/nodejs_diagnostics_channel_improvements branch February 24, 2026 23:02
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.

2 participants