fix(runtime): make timer IDs 1-based to avoid sentinel collision#5379
fix(runtime): make timer IDs 1-based to avoid sentinel collision#5379iammdzaidalam wants to merge 2 commits into
Conversation
Test262 conformance changes
Tested main commit: |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #5379 +/- ##
===========================================
+ Coverage 47.24% 59.80% +12.56%
===========================================
Files 476 566 +90
Lines 46892 62935 +16043
===========================================
+ Hits 22154 37641 +15487
- Misses 24738 25294 +556 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
I'm pretty sure these kinds of tests are already in our WPT suite, they're just disabled. It might be better to enable those instead.
There was a problem hiding this comment.
Hi @jedel1043, Checked the WPT runner, the timers category isn't enabled yet so those tests aren't actually running. Only console, encoding, url and fetch are set up. Want me to enable those instead of keeping the custom tests here?
There was a problem hiding this comment.
Yes... that's literally what I said...
There was a problem hiding this comment.
Quick question, at line 87 in core/runtime/src/interval.rs, why are we clamping the delay here instead of following the WebIDL long conversion behavior?
let delay = u64::from(delay.clamp_finite(0, u32::MAX));I was trying the WPT timers suite locally, and tests like type-long-settimeout / type-long-setinterval fail because values like Math.pow(2, 32) seem to get clamped to u32::MAX instead of wrapping back to 0, so Boa ends up scheduling a ~49 day timeout.
Feels like that’s a separate timer/WebIDL issue beyond the timer ID collision fix, but I wanted to check if the current behavior here was intentional.
There was a problem hiding this comment.
i mean if you run : cargo run -p boa_cli -- -e "setTimeout(() => console.log('Should fire instantly!'), Math.pow(2, 32));" ... hangs and does absolutely nothing
while something like node : node -e "setTimeout(() => console.log('Should fire instantly!'), Math.pow(2, 32));" prints:
TimeoutOverflowWarning: 4294967296 does not fit into a 32-bit signed integer.
Timeout duration was set to 1.
Should fire instantly!
There was a problem hiding this comment.
No direction, since even the runtime itself has no direction :)
It started (and still is) as a testing environment to see if you can use Boa to build a runtime, but it shouldn't be used in production
There was a problem hiding this comment.
Timeout is conformant because the spec just says that value is the number of milliseconds to wait to trigger the function. There's no mention of 32 bits.
There was a problem hiding this comment.
There was a problem hiding this comment.
sorry for the late reply, i tried switching the delay conversion to ToInt32 since the spec uses long there. And with that, Math.pow(2, 32) wraps to 0 and fires instantly locally. Timer tests pass too.
is it a right approach? should I keep this separate from the id fix or put it in this PR?
There was a problem hiding this comment.
Yes that would be the right approach.
Signed-off-by: iammdzaidalam <161572905+iammdzaidalam@users.noreply.github.com>
c5c9a90 to
ea51866
Compare
…sues Signed-off-by: iammdzaidalam <161572905+iammdzaidalam@users.noreply.github.com>
|
hello @hansl @jedel1043, updated the pr.
also had to fix a windows WPT path issue, add If needed i can split the last part. |
Closes #5378
Problem
IntervalInnerState::next_id()returns the internal counter before incrementing it. Since the counter starts at0viaDefault, the first valid timer gets handle0:At the same time, both
set_timeoutandset_intervalreturnOk(0)when no callback is provided. That makes the first real timer and the "nothing was scheduled" sentinel indistinguishable. It also violates WHATWG HTML timer semantics, which require positive timer handles, and breaks common JavaScript code that treats a returned timer ID as truthy.Fix
Update
next_id()to increment the counter before returning it, so valid timer IDs become 1-based again. This preserves0for the no-callback sentinel and restores the pre-#5289 behavior.Tests
timer_ids_are_positive_and_uniqueasserts that timer IDs returned bysetTimeoutandsetIntervalare greater than0and unique.no_callback_returns_zero_sentinelasserts thatsetTimeout()with no callback still returns0and does not collide with a valid timer ID.Verification
cargo test -p boa_runtimecargo run -p boa_cli -- -e "console.log(setTimeout(() => {}, 10)); console.log(setTimeout(() => {}, 10)); console.log(setTimeout())"Before the fix, the first valid timer returned
0. After the fix, the output is1,2,0.