rebased from upstream