Source code for node's Timers is here and here.
setTimeout will create a new Timeout object which will get appended to a linkedlist itself added to a timerListMap object, which is just a plain JS Object where keys represent the duration in ms and values are the linkedlists.
Finally, this timerListMap object is queued in the timerListQueue PriorityQueue which once again is just a JS class instance.
Then when the event loop (libuv) will call processTimers(now) with a now value larger than the passed timeout, the callback will get retrieved following the reverse route.
So this all means that, in node, the callbacks to timeouts stay in the JS heap the whole time, the whole Timers logic stays in the JavaScript layer and only the asynchronous peeking is initialized by libuv event loop.