-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CORE: prevent unbound growth of suspendedTimeouts and possible NaN values #12059
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,27 @@ | ||
let outOfFocusStart; | ||
let outOfFocusStart = null; // enforce null otherwise it could be undefined and the callback wouldn't execute | ||
let timeOutOfFocus = 0; | ||
let suspendedTimeouts = []; | ||
|
||
document.addEventListener('visibilitychange', () => { | ||
function trackTimeOutOfFocus() { | ||
if (document.hidden) { | ||
outOfFocusStart = Date.now() | ||
} else { | ||
timeOutOfFocus += Date.now() - outOfFocusStart | ||
suspendedTimeouts.forEach(({ callback, startTime, setTimerId }) => setTimerId(setFocusTimeout(callback, timeOutOfFocus - startTime)())) | ||
timeOutOfFocus += Date.now() - (outOfFocusStart ?? 0); // when the page is loaded in hidden state outOfFocusStart is undefined, which results in timeoutOffset being NaN | ||
outOfFocusStart = null; | ||
suspendedTimeouts.forEach(({ callback, startTime, setTimerId }) => setTimerId(setFocusTimeout(callback, timeOutOfFocus - startTime)())); | ||
suspendedTimeouts = []; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. all the suspended timeouts should be dealt with here, I think the list can just be cleared instead of filtering it during the loop There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i agree, i wasn't sure about it, so took the safer route by just filtering on the callback. but prefer this if this is a safe operation |
||
} | ||
}); | ||
} | ||
|
||
document.addEventListener('visibilitychange', trackTimeOutOfFocus); | ||
|
||
export function reset() { | ||
outOfFocusStart = null; | ||
timeOutOfFocus = 0; | ||
suspendedTimeouts = []; | ||
document.removeEventListener('visibilitychange', trackTimeOutOfFocus); | ||
document.addEventListener('visibilitychange', trackTimeOutOfFocus); | ||
} | ||
|
||
/** | ||
* Wraps native setTimeout function in order to count time only when page is focused | ||
|
@@ -19,7 +30,7 @@ document.addEventListener('visibilitychange', () => { | |
* @param {number} [milliseconds] - Minimum duration (in milliseconds) that the callback will be executed after | ||
* @returns {function(*): (number)} - Getter function for current timer id | ||
*/ | ||
export default function setFocusTimeout(callback, milliseconds) { | ||
export function setFocusTimeout(callback, milliseconds) { | ||
const startTime = timeOutOfFocus; | ||
let timerId = setTimeout(() => { | ||
if (timeOutOfFocus === startTime && outOfFocusStart == null) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You had a comment here calling this to be set before looping on suspendedTimeouts - I removed it as I don't think the order matters, it's checked from within a
setTimeout
callback.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes you're right, it shouldn't matter.