Sync with upstream, part 2

This is a second attempt of #7, which was blocked by #8.