Surprisingly I can not find the answer to this question anywhere on the web.
In the documentation it is stated that setTimeout and setInterval share the same pool of ids, as well as that an id will never repeat. If that is the case then they must eventually run out because there is a maximum number the computer can handle? What happens then, you can't use timeouts anymore?
TL;DR;
It depends on the browser's engine.
In Blink and Webkit:
Official specification
From the W3C docs:
Also:
Note: while the W3C mentions two lists, the WHATWG spec establishes that
setTimeout
andsetInterval
share a common list of active timers. That means that you can useclearInterval()
to remove a timer created bysetTimeout()
and vice versa.Basically, each user agent has freedom to implement the handle Id as they please, with the only requirement to be an integer unique for each object; you can get as many answers as browser implementations.
Let's see, for example, what Blink is doing.
Blink implementation
Previous note: It's not such an easy task to find the actual source code of Blink. It belongs to the Chromium codebase which is mirrored in GitHub. I will link GitHub (its current latest tag:
72.0.3598.1
) because its better tools to navigate the code. Three years ago, they were pushing commits to chromium/blink/. Nowadays, active development is on chromium/third_party/WebKit but there is a discussion going on about a new migration.In Blink (and in WebKit, which obviously has a very similar codebase), the responsible of maintaining the aforementioned list of active timers is the
DOMTimerCoordinator
belonging to eachExecutionContext
.The
DOMTimerCoordinator
stores the timers in theblink::HeapHashMap
(aliasTimeoutMap
) collectiontimers_
which key is (meeting the specs)int
type:That answer your first question (in the contex of Blink): the maximum number of active timers for each context is 231-1; much lower than the JavaScript
MAX_SAFE_INTEGER
(253-1) that you mentioned but still more than enough for normal use cases.For your second question, "What happens then, you can't use timeouts anymore?", I have so far just a partial answer.
New timers are created by
DOMTimerCoordinator::InstallNewTimeout()
. It calls the private member functionNextID()
to retrieve an available integer key andDOMTimer::Create
for the actual creation of the timer object. Then, it inserts the new timer and the corresponding key intotimers_
.NextID()
gets the next id in a circular sequence from 1 to 231-1:It increments in 1 the value of
circular_sequential_id_
or set it to 1 if it goes beyond the upper limit (althoughINT_MAX
+1 invokes UB, most C implementations returnINT_MIN
).So, when the
DOMTimerCoordinator
runs out of IDs, tries again from 1 up until it finds one free.But, what happen if they are all in use? What does prevent
NextID()
from entering in a endless loop? It seems that nothing. Likely, Blink developers codedNextID()
under the assumption that there will never be 231-1 timers concurrently. It makes sense; for every byte returned byDOMTimer::Create()
you will need a GB of RAM to storetimers_
if it is full. It can add up to TB if you store long callbacks. Let alone the time needed to create them.Anyway, it looks surprising that no guard against an endless loop has been implemented, so I have contacted Blink developers, but so far I have no response. I will update my answer if they reply.