Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clear return value of vapi.js content script #3721

Merged
merged 1 commit into from
May 1, 2018

Conversation

Rob--W
Copy link
Contributor

@Rob--W Rob--W commented May 1, 2018

Upon start-up, uBlock runs all content scripts in manifest.json using chrome.tabs.executeScript. When this API is used, the value of the last expression is automatically cloned and transferred to the callback of chrome.tabs.executeScript. This is convenient if needed, and a performance burden otherwise (the latter is the case for uBlock).

There are three content scripts that need to be checked:

  • vapi.js
    The last expression is often the vAPI object, and it is relatively expensive to clone this object. This commit sets the value of the last expression to void 0 to solve this inefficiency.

    vAPI = window.vAPI = vAPI instanceof Object && vAPI.uBO === true
    ? vAPI
    : { uBO: true };
    }
    /******************************************************************************/

  • vapi-client.js
    No action needed yet; The last expression is vAPI.shutdown.add(...), which has a void return value.

    vAPI.shutdown = {
    jobs: [],
    add: function(job) {
    this.jobs.push(job);
    },

    vAPI.shutdown.add(function() {
    vAPI.messaging.shutdown();
    window.vAPI = undefined;
    });
    // https://www.youtube.com/watch?v=rT5zCHn0tsg
    // https://www.youtube.com/watch?v=E-jS4e3zacI
    /******************************************************************************/
    /******************************************************************************/
    } // <<<<<<<< end of HUGE-IF-BLOCK

  • contentscript.js
    No action needed yet; The last expression is an immediately-invoked function expression without return value.

    uBlock/src/js/contentscript.js

    Lines 1267 to 1417 in 820ec69

    (function bootstrap() {
    var bootstrapPhase2 = function(ev) {
    // This can happen on Firefox. For instance:
    // https://github.com/gorhill/uBlock/issues/1893
    if ( window.location === null ) { return; }
    if ( ev ) {
    document.removeEventListener('DOMContentLoaded', bootstrapPhase2);
    }
    if ( vAPI instanceof Object === false ) {
    return;
    }
    if ( vAPI.domWatcher instanceof Object ) {
    vAPI.domWatcher.start();
    }
    // Element picker works only in top window for now.
    if (
    window !== window.top ||
    vAPI.domFilterer instanceof Object === false
    ) {
    return;
    }
    // To send mouse coordinates to main process, as the chrome API fails
    // to provide the mouse position to context menu listeners.
    // https://github.com/chrisaljoudi/uBlock/issues/1143
    // Also, find a link under the mouse, to try to avoid confusing new tabs
    // as nuisance popups.
    // Ref.: https://developer.mozilla.org/en-US/docs/Web/Events/contextmenu
    var onMouseClick = function(ev) {
    var elem = ev.target;
    while ( elem !== null && elem.localName !== 'a' ) {
    elem = elem.parentElement;
    }
    vAPI.messaging.send(
    'contentscript',
    {
    what: 'mouseClick',
    x: ev.clientX,
    y: ev.clientY,
    url: elem !== null && ev.isTrusted !== false ? elem.href : ''
    }
    );
    };
    document.addEventListener('mousedown', onMouseClick, true);
    // https://github.com/gorhill/uMatrix/issues/144
    vAPI.shutdown.add(function() {
    document.removeEventListener('mousedown', onMouseClick, true);
    });
    };
    var bootstrapPhase1 = function(response) {
    // cosmetic filtering engine aka 'cfe'
    var cfeDetails = response && response.specificCosmeticFilters;
    if ( !cfeDetails || !cfeDetails.ready ) {
    vAPI.domWatcher = vAPI.domCollapser = vAPI.domFilterer =
    vAPI.domSurveyor = vAPI.domIsLoaded = null;
    return;
    }
    if ( response.noCosmeticFiltering ) {
    vAPI.domFilterer = null;
    vAPI.domSurveyor = null;
    } else {
    var domFilterer = vAPI.domFilterer;
    if ( response.noGenericCosmeticFiltering || cfeDetails.noDOMSurveying ) {
    vAPI.domSurveyor = null;
    }
    domFilterer.exceptions = cfeDetails.exceptionFilters;
    domFilterer.hideNodeAttr = cfeDetails.hideNodeAttr;
    domFilterer.hideNodeStyleSheetInjected =
    cfeDetails.hideNodeStyleSheetInjected === true;
    domFilterer.addCSSRule(
    cfeDetails.declarativeFilters,
    'display:none!important;'
    );
    domFilterer.addCSSRule(
    cfeDetails.highGenericHideSimple,
    'display:none!important;',
    { type: 'simple', lazy: true }
    );
    domFilterer.addCSSRule(
    cfeDetails.highGenericHideComplex,
    'display:none!important;',
    { type: 'complex', lazy: true }
    );
    domFilterer.addCSSRule(
    cfeDetails.injectedHideFilters,
    'display:none!important;',
    { injected: true }
    );
    domFilterer.addProceduralSelectors(cfeDetails.proceduralFilters);
    }
    if ( cfeDetails.networkFilters.length !== 0 ) {
    vAPI.userStylesheet.add(
    cfeDetails.networkFilters + '\n{display:none!important;}');
    }
    vAPI.userStylesheet.apply();
    // Library of resources is located at:
    // https://github.com/gorhill/uBlock/blob/master/assets/ublock/resources.txt
    if ( response.scriptlets ) {
    vAPI.injectScriptlet(document, response.scriptlets);
    vAPI.injectedScripts = response.scriptlets;
    }
    if ( vAPI.domSurveyor instanceof Object ) {
    vAPI.domSurveyor.start(cfeDetails);
    }
    // https://github.com/chrisaljoudi/uBlock/issues/587
    // If no filters were found, maybe the script was injected before
    // uBlock's process was fully initialized. When this happens, pages
    // won't be cleaned right after browser launch.
    if (
    typeof document.readyState === 'string' &&
    document.readyState !== 'loading'
    ) {
    bootstrapPhase2();
    } else {
    document.addEventListener('DOMContentLoaded', bootstrapPhase2);
    }
    };
    // This starts bootstrap process.
    vAPI.messaging.send(
    'contentscript',
    {
    what: 'retrieveContentScriptParameters',
    url: window.location.href,
    isRootFrame: window === window.top,
    charset: document.characterSet
    },
    bootstrapPhase1
    );
    })();
    /******************************************************************************/
    /******************************************************************************/
    /******************************************************************************/
    } // <<<<<<<< end of HUGE-IF-BLOCK

Upon start-up, uBlock runs all content scripts in manifest.json using
`chrome.tabs.executeScript`. When this API is used, the value of the
last expression is automatically cloned and transferred to the
callback of `chrome.tabs.executeScript`. This is convenient if needed,
and a performance burden otherwise (the latter is the case for uBlock).

There are three content scripts that need to be checked:

- vapi.js
  The last expression is often the vAPI object, and it is relatively
  expensive to clone this object. This commit sets the value of the
  last expression to `void 0` to solve this inefficiency.

- vapi-client.js
  No action needed yet; The last expression is `vAPI.shutdown.add(...)`,
  which has a void return value.

- contentscript.js
  No action needed yet; The last expression is an immediately-invoked
  function expression without return value.
@gorhill gorhill merged commit b27f23d into gorhill:master May 1, 2018
@gorhill
Copy link
Owner

gorhill commented May 1, 2018

Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants