SeleniumHQ / htmlunit-driver

WebDriver compatible driver for HtmlUnit headless browser.
Apache License 2.0
255 stars 86 forks source link

Rhino not compiling any JavaScript when ScriptException encountered #144

Closed sandeep-dfe closed 7 months ago

sandeep-dfe commented 9 months ago

eg if javascript is pulled from a file such as

then htmlunit driver does not find the javascript function referenced on the html page, ie I get error such as :

"org.htmlunit.ScriptException: ReferenceError: "updateNumberOfSchemes" is not defined. "

Even though "webClient.getOptions().setJavaScriptEnabled(true)"

rbri commented 9 months ago

@sandeep-dfe Hmm, sounds strange - maybe there is another reason for that. Do you have a (public) website where i can try to reproduce that?

sandeep-dfe commented 9 months ago

Hi @rbri

try driver.get("https://find-employer-schemes.education.gov.uk/");

this gives

eg [pool-1-thread-1] [ERROR] o.h.j.DefaultJavaScriptErrorListener Error during JavaScript execution org.htmlunit.ScriptException: ReferenceError: "sortSchemes" is not defined.

Chromedriver does not have this problem

rbri commented 7 months ago

sorry but i can't reproduce this. Can you please make a complete sample class.

sandeep-dfe commented 7 months ago

htmlunit-js-error.zip

Hi @rbri Please review javascriptIssueDemo in the attachment, thanks.

rbri commented 7 months ago

@sandeep-dfe OK, another limitation of the rhino (core-js) engine.

at the beginning of the log output you will see the reason:

org.htmlunit.ScriptException: TypeError: redeclaration of var i. (https://find-employer-schemes.education.gov.uk/js/site.js?v=rG3nlLugPDi7jE4PNwDK7S4obbQ#1)

Because of this error the whole js code not compile and therefore you miss the function.

At the moment you can only patch the js code on the fly.

Please implement your own ScriptPreProcessor (see https://github.com/HtmlUnit/htmlunit/blob/master/src/main/java/org/htmlunit/javascript/preprocessor/HtmxOneNineTenScriptPreProcessor.java as sample).

the important part should look like

@Override
public String preProcess(final HtmlPage htmlPage, final String sourceCode, final String sourceName,
        final int lineNumber, final HtmlElement htmlElement) {

    String patchedSourceCode = sourceCode;

    if (sourceName.contains("/site.js") && !sourceName.contains("/site.js#")) {
        patchedSourceCode = StringUtils.replace(
                sourceCode,
                "var t=this,i=t.getAttribute(\"data-menu-section\");const n=document.querySelector('.govuk-header__navigation-item[data-menu-section=\"'+i+'\"]');",
                "var t=this,ix=t.getAttribute(\"data-menu-section\");const n=document.querySelector('.govuk-header__navigation-item[data-menu-section=\"'+ix+'\"]');");
    }

    if (nextScriptPreProcessor_ != null) {
        return nextScriptPreProcessor_.preProcess(htmlPage, patchedSourceCode, sourceName, lineNumber, htmlElement);
    }

    return patchedSourceCode;
}

This replaces the declaration of var i at one place - to avoid the re declaration error.

Attach the preprocessor to your client and your code should run.

            webClient.setScriptPreProcessor(new ...ScriptPreProcessor());
sandeep-dfe commented 7 months ago

Thanks for the guidance @rbri

sandeep-dfe commented 7 months ago

@rbri I've closed this issue however as the suggestion is more of a workaround, it it be better if the issue remained open until a fix found?