Ok wow that's pretty interesting and informative, thx. So after writing my last post I decided to try requesting 999 (as big a number as possible) and then doing my WaitTime (raylib function) call at the start of the game loop. I only wait to try to get as close to my 60hz tick as possible. Then the rest of my game loop is the same as win32: if it's time to do logic, do it, if it's time to render, do it (basically what you wrote). This gets me pretty close in Firefox (~58) and exactly 60 in Chrome. Just deployed that change so I'm curious what your Firefox gets since you've been the big outlier.
raylib WaitTime seems to call nanosleep?? No idea what that's calling in web, I'm not compiling emscripten with ASYNC so I don't think I have access to emscripten_sleep without that compiler switch.