-
Notifications
You must be signed in to change notification settings - Fork 14
Description
Consider the following example where requestIdleCallback is requested in two different windows:
requestIdleCallbackIsCalled = false;
const iframe = document.createElement('iframe');
const logs = [];
iframe.onload = () => {
requestIdleCallback(() => {
requestIdleCallbackIsCalled = true;
logs.push('1.A1');
});
iframe.contentWindow.requestIdleCallback(() => {
requestIdleCallbackIsCalled = true;
logs.push('2.B1');
});
iframe.contentWindow.requestIdleCallback(() => {
requestIdleCallbackIsCalled = true;
logs.push('3.B2');
});
requestIdleCallback(() => {
requestIdleCallbackIsCalled = true;
logs.push('4.A2');
});
}
document.body.appendChild(iframe);This would result in the log being 1.A1, 2.B1, 3.B2, 4.A2 in Chrome and sometimes in Firefox but my faithful implementation of the specification as well as Firefox would sometimes order them as 1.A1, 2.B1, 4.A2, 3.B2.
My statement assumes that step 3 in the start an idle period algorithm, which states "optionally, if the user agent determines the idle period should be delayed, return from this algorithm", doesn't allow UA to ignore the idle period for one window but not for the other.
My reading of the specification goes as follows:
- Adds a callback 1.A1 to the top-level window's idle request callbacks, then schedules a new task to start an idle period algorithm (SIPA-A1). Currently scheduled tasks are: [SIPA-A1].
- Adds a callback 2.B1 to iframe's content window's idle request callbacks, then schedules a new task to start an idle period algorithm (SIPA-B1). Now we have scheduled tasks: [SIPA-A1, SIPA-B1].
- Adds a callback 3.B2 to iframe's idle request callbacks. No new tasks scheduled.
- Adds a callback 4.A2 to iframe's idle request callbacks. No new tasks scheduled.
- SIPA-A1 runs. Callbacks 1.A1 and 4.A2 move from the list of idle request callbacks to the list of runnable idle callbacks.
A new task to invoke idle callbacks (IIC-A1) is scheduled. Currently scheduled tasks are: [SIPA-B1, IIC-A1]. - SIPA-B1 runs. Callbacks 2.B1 and 3.B2 move from the list of idle request callbacks to the list of runnable idle callbacks.
A new task to invoke idle callbacks (IIC-B1) is scheduled. Currently scheduled tasks are: [IIC-A1, IIC-B1]. - IIC-A1 runs. The callback 1.A1 is executed. A new task to invoke idle callbacks (IIC-A2) is scheduled.
Currently scheduled tasks are: [IIC-B1, IIC-A2]. - IIC-B1 runs. The callback 2.B1 is executed. A new task to invoke idle callbacks (IIC-B2) is scheduled.
Currently scheduled tasks are: [IIC-A2, IIC-B2]. - IIC-A2 runs. The callback 4.A2 is executed.
- IIC-B2 runs. The callback 3.B2 is executed.
What am I missing here? What allows Chrome and (sometimes) Firefox to execute callbacks in other orders? Perhaps step 3 in the start an idle period algorithm? If so, then 2.B1 should be the first to execute.
Perhaps step 1 in the invoke idle callbacks algorithm, which states, "if the user-agent believes it should end the idle period early due to newly scheduled high-priority work, skip to step 4." If this were to always happen at the beginning of (9) perhaps the observed order would make sense.
But then it seems problematic that the ordering of idle callbacks change across content windows. I understand the need to let UA delay work by arbitrary amount but the order of callbacks being completely dependent on UAs isn't ideal to say the least.