[FOR DISCUSSION] New, more robust event-dispatching system

(from backlog card [Event Infrastructure Improvements](https://trello.com/c/ogaZoRHJ/1377-events-infrastructure-improvements))

Instead of jQuery, use our own simpler event system for non-DOM objects.

* Includes shim so legacy `$().on()/off()` code still works
* It's easy to make any object into an event dispatcher: just call `EventDispatcher.makeEventDispatcher()` on any object or any class prototype.
* More robust to listeners that throw exceptions -- other listeners will still be called, and `trigger()` will still return control to its caller.  This is important for reducing how frequently core features break due to buggy extensions.
* Events can be marked deprecated, causing `on()` to issue warnings -- this provides much more specific feedback than our current deprecation warnings, at dispatch time.  (In the future, we could also issue warnings when `on()` is called for an event that the object doesn't actually support).
* Easier to debug, since the dispatch code is much simpler.
* Event dispatching is 11x faster (although the overhead was not huge to begin with).
* Uses less memory, since `$(nonDOMObj).on()` leaks memory in jQuery
* The API is a bit simpler, eliminating some pitfalls (e.g. jQuery lets you pass single handler arguments directly, but multiple arguments must be wrapped in an array; here we just use varargs instead).

This initial demonstration converts Document & DocumentManager to use the new system, plus unit tests to verify more of its functionality.

CC @dangoor -- this was the experiment I mentioned back at MAX.
JS code is synchronous, so there can't be any "concurrent" on()/off() calls, right? But a handler that we call could make on()/off() calls. Maybe reword this as: "Use a clone of the list so we're frozen in the face of on()/off() calls made by handlers called here."