luciopaiva / witchcraft

Inject Javascript and CSS right from your file system. Think GreaseMonkey for more advanced users.
https://luciopaiva.com/witchcraft
MIT License
254 stars 18 forks source link

How to get a reference to the page level global scope? #50

Open gillyspy opened 2 years ago

gillyspy commented 2 years ago

I would like to get a reference to the true global scope.

window.load , etc, etc all provide a reference to window that is limited to content scripts.

I see that in the content script that you are using Function to immediately run the script.

What if there was an option to load the content into a script tag. Similar to what you are doing with css (and style tags).

in this way the script should load as if it was a local script and thus have global scope, etc.

maybe there could be a new declaration of

//@mode=X

X===1 means to behave as proposed below @mode missing or undefined, etc means to behave as you already have it (using Function(scriptContents)())

chrome.runtime.onMessage.addListener(({scriptType, scriptContents}) => {
    if (scriptType === "js") {
        const scriptEl = document.createElement('script');
         scriptEl.type = 'text/javscript';
        scriptEl.appendChild(document.createTextNode(scriptContents));
        scriptEl.setAttribute("data-witchcraft", "");  // to make it easy finding the element if we want to
        document.body.appendChild(scriptEl);
    } else if (scriptType === "css") {
        const style = document.createElement('style');
        style.type = 'text/css';
        style.appendChild(document.createTextNode(scriptContents));
        style.setAttribute("data-witchcraft", "");  // to make it easy finding the element if we want to
        document.head.appendChild(style);
    }
});
gillyspy commented 2 years ago

these changes i made here bd6b0dd3c2956f8193730a17e66c0bb0697df403 work for me

Note that mode 0 and 1 are the meaningful ones. The user can do 2 and 3 simply by adding event listener wrappers on their own scripts in combination with mode 1.

 if ( scriptMode === 0 ){
      Function(scriptContents)();
    }

    if ( scriptMode === 1 ){
      createScriptEl({ node : 'head', scriptContents })
    }

    if ( scriptMode === 2 ){
      window.addEventListener('load', (ev) => {
        createScriptEl({ node : 'body', scriptContents });
      })
    }

    if ( scriptMode === 3 ){
      document.addEventListener('DOMContentLoaded', (ev) => {
        createScriptEl({ node : 'body', scriptContents });
      });