1

TLDR; Is it possible to load an ES6 module into the sandboxed DOM of GreaseMonkey in a way that is similar to doing a @require?

Going a little nuts here. I've been writing a GM script in Firefox to "enhance" a certain website with custom functionality, backed by my GM script interacting with a database on my local server to store and retrieve the data that I generate when using my enhancements.

For this particular website (sorry for being vague, but these sites aren't... Let's called it, safe for work), my hands were pretty free as to how to structure and run my code, as the site doesn't restrict anything via CORS or CSP. In other words, I could simply add script tags to the site's DOM via GM, and then it'd run fine.

However, I'm now extending my GM script's scope to an additional site - "Site B" - which is indeed very restrictive about what I'm allowed to do there. For instance, while I can add a script tag and load my code that way, I cannot access my database from that code (via PouchDB), as it tries to XHR to my local server's domain which is prohibited by that site's CSP.

I can still modify and read Site B's page from the GM sandbox while having full access to my own resources on the server, as the code then runs from within that sandboxed environment, which doesn't restrict XHR or anything like that, and the regular interface that GM provides is sufficient for my needs.

So, I thought I'd rewrite again, and that I'd try to use ES6 modules this time because my code is already very spaghetti bolognese, and it's about time to clean it up a bit anyway.

Thing is, to load a javascript as a module, you need to use type=module on the script tag, and I'm no longer injecting script tags (due to CORS and CSP). And the way @require works it assumes a regular script, not a module.

I've tried to search for ways to access the sandboxed DOM (if it even has one?), to see if I might programatically load a script as a module inside the sandbox (something like document.append(createdScriptTagThatHasAttribueTypeSetToModule)), but everything I find is about how to load stuff into, and mess with, the page DOM, never the GM DOM. I've looked at the GM documentation about unsafeWindow and GM.* methods, but everything is more aimed at how someone gains more access to the browser page's DOM, and not how one gets more access to fiddle with the sandboxed DOM.

Basically, I just really want to be able to load my external script as a module, so that I can start working with a less spaghetti-esque structure to my rapidly increasing code base.

Thanks in advance for any tips :)

DanielSmedegaardBuus
  • 977
  • 1
  • 10
  • 18
  • How about an `import(...)` expression? – user3840170 Mar 25 '23 at 11:58
  • That expression is only valid in a script loaded as a `module` which brings me back to square one :) – DanielSmedegaardBuus Mar 25 '23 at 12:28
  • Really? For me, `` displays an error due to the module not being found, but otherwise runs fine. – user3840170 Mar 25 '23 at 12:35
  • Well, I **think** so... I get `TypeError: error loading dynamically imported module` when I do that in the sandbox, which as far my current Google-fu leads me to understand is because the script with the `import` (which would be the GM script in this case) isn't loaded as a module, but a regular script? Perhaps the default for literal ` – DanielSmedegaardBuus Mar 25 '23 at 12:43
  • 1
    I just tried a statement, `import('https://mini.local/greasemonkey/test/index.js').then(console.log).catch(console.error);` from the Developer Tools console in FF, and it worked - `console.log` printed out `Promise { : "pending" }` and then logging output from code inside `index.js`. A simple GM script on the same page with the same statement yields, `TypeError: error loading dynamically imported module`, so even if I'm incorrectly assuming the problem, there's something-something I need to do differently, if possible, when trying to load in GM :'( – DanielSmedegaardBuus Mar 25 '23 at 12:58

2 Answers2

0

Greasemonkey currently injects userscripts into contentScripts context.
Tampermonkey & Violentmonkey also inject userscript into contentScripts context (and page context under conditions).

At the moment, Content scripts modules are not supported in Firefox & Chrome. However, you can use dynamic import() (MV3 support under-development).

See Also

erosman
  • 7,094
  • 7
  • 27
  • 46
0

the principle of @require is that use the code as a string to stitch in order

so generally only umd/iife module work in Tampermonkey/Violentmonkey/Greasemonkey

but you can use the build tools like webpack/vite/rollup/esbuild to build your esm code to iife format

if you want do this by build tools, you can use my plugin vite-plugin-monkey

lisonge
  • 429
  • 4
  • 9