liriliri / eruda

Console for mobile browsers
https://eruda.liriliri.io
MIT License
18.07k stars 1.16k forks source link

Enhanced loader for Eruda #327

Open MasterInQuestion opened 1 year ago

MasterInQuestion commented 1 year ago

    Enhanced loader for Eruda, in bookmarklet form.     Attempt to workaround Eruda not loading due to site's CSP (Content Security Policy) configuration.

    When remote loading prevented by CSP, fallback attempts to retrieve Eruda's content from a local file.     2 approaches initializing the script are tried:     |1| Text in "<script>" element, inject and load. [1]     |2| (if didn't work) Directly execute the script's text. [1] Probably not much performance difference. Mostly for demo.

[[ javascript: (function () { var x0, x1, body = document.getElementsByTagName( "body" )[0]; body.appendChild( x0 = document.createElement( "script" ) ); x0.src = "https://cdn.jsdelivr.net/npm/eruda"; x0.onload = function () { eruda.init(); }; x0.onerror = function () { this.parentNode.removeChild( this ); body.appendChild( x0 = document.createElement( "input" ) ); x0.type = "file"; x0.onchange = function () { this.parentNode.removeChild( this ); x1 = new FileReader(); x1.onload = function () { x1 = x1.result + "\neruda.init();"; body.appendChild( x0 = document.createElement( "script" ) ); x0.text = x1; if ( "eruda" in window === false ) { x0.parentNode.removeChild( x0 ); Function( x1 )(); }; }; x1.readAsText( this.files[0] ); }; x0.style = "z-index: 2147483647; position: fixed; bottom: 0"; x0.click(); }; })(); ]]

    Unrolled and commented: [[

    (function () {
// ---- BEGIN (0)
    var x0, x1,
    body = document.getElementsByTagName( "body" )[0];

    body.appendChild( x0 = document.createElement( "script" ) );
    x0.src = "https://cdn.jsdelivr.net/npm/eruda";
    x0.onload = function () { eruda.init(); };
    x0.onerror = function () {
// ---- BEGIN (1)
    this.parentNode.removeChild( this );
// Choose downloaded [ https://cdn.jsdelivr.net/npm/eruda ] for the file input.
    body.appendChild( x0 = document.createElement( "input" ) );
    x0.type = "file";
    x0.onchange = function () {
// ---- BEGIN (2)
    this.parentNode.removeChild( this );
    x1 = new FileReader();

    x1.onload = function () {
// ---- BEGIN (3)
    x1 = x1.result + "\neruda.init();";
// More readable form: `x1 = ( x1.result + "\n" + "eruda.init();" );`
    body.appendChild( x0 = document.createElement( "script" ) );
    x0.text = x1;

// "error" event does not trigger, so:
    if ( "eruda" in window === false ) {
// Guessed condition.
    x0.parentNode.removeChild( x0 );
    Function( x1 )(); // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#never_use_direct_eval!
    };
// ---- END (3)
    };

    x1.readAsText( this.files[0] );
// ---- END (2)
    };

    x0.style = "z-index: 2147483647; position: fixed; bottom: 0";
    x0.click(); // May not work for certain browsers; attempted anyway.
// ---- END (1)
    };
// ---- END (0)
    })();

]]

    All `${Node}.parentNode.removeChild( ${Node} );` parts are not really necessary: merely included for saner DOM tree.     See also: https://github.com/liriliri/eruda/discussions/326