If a websocket message is split across continuation frames, it is
possible to get to this inner loop. If the browser is closed in the
middle of the message, the connection is closed, which makes the select
check return true, but then the other check returns false, indicating
eof, but the loop would continue.
We do not close the connection here, it just throws, but that's
consistent with other things for now. It should probably change too.
this is both needed for modern opengl because if you are unlucky with your graphics drivers there it won't render anything when the core context is enabled, but also when rendering custom data and having stray VAOs open that you didn't unbind on the start of the nanovega render calls.
stuff like `glEnableVertexAttribArray` and `glVertexAttribPointer`, which is called below, is only valid with a VAO bound.
The debugger tells me the Invoke method is accessing an invalid, but
non-null pointer. This appears to be a use-after-free delegate context
pointer. This is not easy to reproduce - even with the browser, I'd have
to open and close tons of windows and trigger specific callbacks to get
the behavior. (I found the best one to get it was the status text
changed event out of WebView2, probably because it uses a member
variable without any explicit local.)
I suspect it has to do with the delegate trying to capture both `this`
and other local variables at the same time. I couldn't confirm this, but
the theory is that normally, when a delegate captures a local variable,
the compiler places it in an allocated heap block instead of on the
stack, but perhaps `this` gets different treatment and it is wiped out
or the block is GC'd or something. (The AddRef does GC.addRoot to the
containing class that had the delegate member, so that should have
prevented it from disappearing, but it is possible I did it wrong.)
Nevertheless, I recall having trouble with this in the past as well,
and decided perhaps the best thing to do is to just take control of
which context, exactly, is passed and retained. Hence the conversion to
`function` so I can hold on to it better. This makes things harder to
use - especially since IFTI wouldn't pick up the usage correctly - but
meh, I'm mostly just passing the class handles down so not that bad.
Not 100% sure this actually even fixed the crash; it hasn't happened
again since using it, but that's no guarantee given how difficult it is
to reproduce.