merged with upstream manually after too many changes