clearTimeout was not correctly handling the case of clearing a
timeout that is also scheduled to run at the same tick.
This fix adds a deletedKeys array that is checked whilst we are
running the scheduled functions for the current clock tick. If
a function exists in deletedKeys it will not be ran. deletedKeys
is then reset to an empty array.
As described in issue #655, the handler of an interval cannot
successfully clear the same interval that generated it's invocation.
Solve this issue by changing the order in which interval's handlers are
called and then rescheduled to: first reschedule it and then call it.
The actual order (call first then reschedule) produces that, during the
execution of the interval's handler, the handler is not registered as
a function to run after a timeout or interval ("scheduledFunctions"),
because it was previously unregistered. Consequently, if the handler
calls clearInterval, that function wont be able to find the handler and
remove it completely.
All timeouts and intervals set during a tick were being scheduled to run
at delay + end-of-tick, instead of delay + time-of-outer-timeout.
Scheduled run-at times were shifted because currentTime was being
incremented before executing scheduled functions.
Additionally, the execute loop was iterating over a functions-to-run
array, created from scheduledFunctions before starting. Any changes to
scheduledFunctions were being ignored during the tick, and the next tick
would ignore any functions which should have been executed in the past.
The commit is a rewrite of DelayedFunctionScheduler, preserving the
public interface. Execution of scheduled functions updates currentTime
on each iteration, and each time takes the functions with the lowest
runAtMillis from the schedule, if they aren't higher than endTime.
Still not green, but getting close. Summary of Older IE discrepancies:
- Older IE doesn't have apply/call on the timing functions
- Older IE doesn't allow applying falsy arguments
- Older IE doesn't allow setting onclick to undefined values
- Older IE doesn't have text property on dom nodes
If ommited or null, delay for refered methods will default to 0. This
will make setTimeout and setInterval methods to behave as expected by
[HTML5 specs](http://www.w3.org/TR/html51/webappapis.html#timers):
"Let timeout [delay] be the second argument to the method, or zero if the
argument was omitted."
This commit also fixes an issue with tick() being called without arguments,
that causes the scheduler to break and stop working after this call.