It's built on unsound foundations that causes an endless stream of this kind of bugs. They make compromises regarding security engineering and then do indeed put a fair amount of engineering resources to mitigate the resulting security problems.
This can be said to be good or bad engineering depending on your viewpoint, the alternatives might for example have performance tradeoffs and it can be valid engineering to make tradeoffs that favour other things at expense of security. But also we certainly do know practical and proven ways to eliminate this class of memory safety bugs in JS implementations, so it's definitely an engineering choice.