also including some refactoring:
- add `// @ts-check`
- use Map to completely avoid prototype pollution
- assign random id to each iframe for reduce chance to brute-force attack, and leak of iframe counts
- check iframe.contentWindow and MessageEvent.source to validate message is coming from correct iframe (it works on latest Chrome/Firefox/Safari but I'm not sure this is allowed by spec)
follow-up of #17420fix#18299