This does not reduce the number of threads we end up using in these
cases, but simplifies the complex implementation substantially by
relying on the idle thread lifetime management logic from nsThreadPool.
The nsISerialEventTarget implementation is maintained by wrapping the
nsThreadPool with a TaskQueue.
As a result of using these more reliable backing implementations, the
type is now also safe to use from any thread, rather than requiring
dispatches to all occur from the creator thread.
Unfortunately, this required some changes to the
UntrustedModulesProcessor, which was relying on the ability to fetch the
PRThread* (and from that the HANDLE) from the lazy thread in order to
perform priority changes on it. This was fixed by using a
nsIThreadPoolListener to watch the thread being created and destroyed,
and manually record a HANDLE to the thread which can be used for these
priority changes.
Differential Revision: https://phabricator.services.mozilla.com/D168017