Skip to content

Commit e07f142

Browse files
committed
fix(android): setInterval impl to match c++ and prevent drift
1 parent 9914454 commit e07f142

File tree

1 file changed

+19
-8
lines changed

1 file changed

+19
-8
lines changed

packages/core/timer/index.android.ts

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,23 +58,35 @@ export function clearTimeout(id: number): void {
5858
}
5959

6060
export function setInterval(callback: Function, milliseconds = 0, ...args): number {
61-
// Cast to Number
6261
milliseconds += 0;
6362

6463
const id = createHandlerAndGetId();
6564
const handler = timeoutHandler;
6665
const invoke = () => callback(...args);
6766
const zoneBound = zonedCallback(invoke);
68-
const startOffset = milliseconds > 0 ? Date.now() % milliseconds : 0;
69-
function nextCallMs() {
70-
return milliseconds > 0 ? milliseconds - ((Date.now() - startOffset) % milliseconds) : milliseconds;
71-
}
67+
let nextDueTime = Date.now() + milliseconds;
7268

7369
const runnable = new java.lang.Runnable({
7470
run: () => {
71+
const executionStart = Date.now();
7572
zoneBound();
73+
7674
if (timeoutCallbacks[id]) {
77-
handler.postDelayed(runnable, long(nextCallMs()));
75+
const executionTime = Date.now() - executionStart;
76+
77+
// Update the next due time based on when this callback was supposed to execute
78+
nextDueTime += milliseconds;
79+
80+
// If the callback took longer than the interval, skip ahead to avoid catch-up
81+
const now = Date.now();
82+
if (nextDueTime <= now) {
83+
// Calculate how many intervals we should skip
84+
const missedIntervals = Math.floor((now - nextDueTime) / milliseconds);
85+
nextDueTime += (missedIntervals + 1) * milliseconds;
86+
}
87+
88+
const delay = Math.max(0, nextDueTime - now);
89+
handler.postDelayed(runnable, long(delay));
7890
}
7991
},
8092
});
@@ -84,8 +96,7 @@ export function setInterval(callback: Function, milliseconds = 0, ...args): numb
8496
timeoutCallbacksCb[id] = callback;
8597
}
8698

87-
timeoutHandler.postDelayed(runnable, long(nextCallMs()));
88-
99+
handler.postDelayed(runnable, long(milliseconds));
89100
return id;
90101
}
91102

0 commit comments

Comments
 (0)