My mistake was trying to create the window on the V8 thread. Instead, uv_thread_create
should be used to call a function that creates the window on a new thread and then proceeds to do its own message pump loop.
The wndproc function then needs to save received messages into a queue in a thread-safe manner and then use uv_async_send
to notify the V8 thread that messages have arrived.
A function on the V8 thread (which was passed to uv_async_init
) is then invoked after messages are enqueued. The function (thread-safely) pops each pending message off the queue and invokes the JS callback.