Skip to content

Commit

Permalink
Workaround HtmlUnit bug when calling window.onerror
Browse files Browse the repository at this point in the history
See https://sourceforge.net/p/htmlunit/bugs/1924/

Change-Id: I79ec9a0e5984c3179b3f82a7b48f91413e7b62ac
  • Loading branch information
tbroyer committed Oct 12, 2017
1 parent 6df7caf commit cb112c0
Showing 1 changed file with 87 additions and 1 deletion.
88 changes: 87 additions & 1 deletion user/src/com/google/gwt/junit/RunStyleHtmlUnit.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package com.google.gwt.junit;

import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.JS_WINDOW_ONERROR_COLUMN_ERROR_ARGUMENT;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.dev.shell.HostedModePluginObject;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet;
Expand All @@ -36,8 +38,14 @@
import com.gargoylesoftware.htmlunit.javascript.host.Window;
import com.gargoylesoftware.htmlunit.util.WebClientUtils;

import net.sourceforge.htmlunit.corejs.javascript.Context;
import net.sourceforge.htmlunit.corejs.javascript.Function;
import net.sourceforge.htmlunit.corejs.javascript.JavaScriptException;
import net.sourceforge.htmlunit.corejs.javascript.ScriptableObject;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
Expand Down Expand Up @@ -162,6 +170,9 @@ protected void setupWebClient(WebClient webClient) {
JavaScriptEngine hostedEngine = new HostedJavaScriptEngine(webClient,
treeLogger);
webClient.setJavaScriptEngine(hostedEngine);
} else {
JavaScriptEngine webEngine = new WebJavaScriptEngine(webClient);
webClient.setJavaScriptEngine(webEngine);
}
if (System.getProperty("gwt.htmlunit.debug") != null) {
WebClientUtils.attachVisualDebugger(webClient);
Expand All @@ -188,12 +199,87 @@ public HostedJavaScriptEngine(WebClient webClient, TreeLogger logger) {
public void initialize(WebWindow webWindow) {
// Hook in the hosted-mode plugin after initializing the JS engine.
super.initialize(webWindow);
Window window = (Window) webWindow.getScriptObject();
Window window = (Window) webWindow.getScriptableObject();
window.defineProperty("__gwt_HostedModePlugin",
new HostedModePluginObject(this, logger), ScriptableObject.READONLY);
}
}

/**
* JavaScriptEngine subclass that fixes a bug when calling {@code window.onerror}.
* Make sure to remove when updating HtmlUnit.
*
* @see <a href="https://sourceforge.net/p/htmlunit/bugs/1924/">HtmlUnit bug #1924</a>
*/
private static class WebJavaScriptEngine extends JavaScriptEngine {
private static final Log LOG = LogFactory.getLog(JavaScriptEngine.class);

public WebJavaScriptEngine(WebClient webClient) {
super(webClient);
}

@Override
protected void handleJavaScriptException(ScriptException scriptException,
boolean triggerOnError) {
// XXX(tbroyer): copied from JavaScriptEngine to call below triggerOnError
// instead of Window's triggerOnError.

// Trigger window.onerror, if it has been set.
final InteractivePage page = scriptException.getPage();
if (triggerOnError && page != null) {
final WebWindow window = page.getEnclosingWindow();
if (window != null) {
final Window w = (Window) window.getScriptableObject();
if (w != null) {
try {
triggerOnError(w, scriptException);
} catch (final Exception e) {
handleJavaScriptException(new ScriptException(page, e, null), false);
}
}
}
}
final JavaScriptErrorListener javaScriptErrorListener =
getWebClient().getJavaScriptErrorListener();
if (javaScriptErrorListener != null) {
javaScriptErrorListener.scriptException(page, scriptException);
}
// Throw a Java exception if the user wants us to.
if (getWebClient().getOptions().isThrowExceptionOnScriptError()) {
throw scriptException;
}
// Log the error; ScriptException instances provide good debug info.
LOG.info("Caught script exception", scriptException);
}

private void triggerOnError(Window w, ScriptException e) {
// XXX(tbroyer): copied from HtmlUnit's javascript.host.Window
// with fix unwrapping the JS exception before passing it back to JS.
final Object o = w.getOnerror();
if (o instanceof Function) {
final Function f = (Function) o;
final String msg = e.getMessage();
final String url = e.getPage().getUrl().toExternalForm();
final int line = e.getFailingLineNumber();

Object[] args;
if (w.getBrowserVersion().hasFeature(JS_WINDOW_ONERROR_COLUMN_ERROR_ARGUMENT)) {
final int column = e.getFailingColumnNumber();

Object jsError = null;
if (e.getCause() instanceof JavaScriptException) {
jsError = ((JavaScriptException) e.getCause()).getValue();
}

args = new Object[] {msg, url, Integer.valueOf(line), Integer.valueOf(column), jsError};
} else {
args = new Object[] {msg, url, Integer.valueOf(line)};
}
f.call(Context.getCurrentContext(), w, w, args);
}
}
}

private static final Map<String, BrowserVersion> BROWSER_MAP = Maps.newHashMap();
private static final Map<BrowserVersion, String> USER_AGENT_MAP = Maps.newHashMap();

Expand Down

0 comments on commit cb112c0

Please sign in to comment.