Initial implementation of issue #2112

This is a first pass at the implementation of issue #2112, posted primarily to get early feedback.  The change is not ready to be merged, though it shouldn't break anything.

TODO:
- [x] Read through the code to sanity check everything in this commit.
- [x] Verify the rerender logic will force an update when the context information changes.
- [x] Add unit tests to test the new functionality.
:( @sebmarkbage I'm going to work on the style automation & linting as much as possible, but let's try to catch things like this (space before open paren, newlines with braces for `if`s). Especially important for new contributors.