jQuery 3 made $.ready resolve asynchronously and always, which is more correct and changes the timing of code that had been relying on the synchronous path.
// 2.x: fires synchronously if the DOM is already ready
// 3.x: always fires on the next tick
$(document).ready(fn);
// and it is a real promise now
$.ready.then(() => { /* ... */ });
The breakage is subtle: code that called ready() after load and expected the callback to have already run before the next line now finds it has not. It also stopped accepting non-DOM arguments, so $(window).ready() and $('#el').ready() are deprecated — both were always the document handler wearing a disguise.