Otherwise, though, Safari still supports MV2. Everyone seems to think webRequestBlocking is the only relevant change in MV3, but it's not. Equally important IMO is arbitrary JavaScript injection into web pages, which MV2 allows but MV3 does not.
MV3 is so locked down that you can't even use String.replace() with a constructed JavaScript function. It's really a nightmare.
Google's excuse is that all JavaScript needs to be statically declared in the extension so that the Chrome Web Store can review it. But then the Chrome Web Store allows a bunch of malware to be published anyway!
In Chrome 135, which is very recent—the public is currently on Chrome 138—Google added an execute() method to run an individual script. However, the API is not available from the extension content script, so if it needs to be triggered from the content script, you have to make an async call to the background script (or more accurately, the background service worker, which is a whole other nightmare of MV3). Moreover, the API accepts only a string for JS code or a filename; you still can't use a Function() constructor for example.
In Chrome 138, the current version, Google switched from developer mode to a dedicated userscripts permission toggle in the extension details, which is disabled by default. I think Google is still working on but has not finished a permissions request API. Remember this is almost SEVEN YEARS after Google first announced Manifest V3. The entire time, Google has been stalling, foot dragging, practically getting dragged kicking and screaming into doing the least possible work here.
Surprisingly this async serialize/deserialize nature of the API (https://github.com/Tampermonkey/tampermonkey/blob/cdfc253c07... ?) somehow still manages to inject and execute scripts fast enough to make them act like content scripts at document_start. The only problem is no arbitration between extensions, cant force Tampermonkey inject before uBO (tons of adblock filters disable functions required for Tampermonkey and effectively kill Tampermonkey in the process).