- Fixes the incompatible exceptions in JSValueGlue
- Adds toString implementation
- Hacky fix for handling NativeString type
- Removed an unnecessary variable
Patch by: amitmanjhi
Review by: jat (TBR)
git-svn-id: https://google-web-toolkit.googlecode.com/svn/branches/farewellSwt@6146 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/oophm/overlay/com/google/gwt/dev/shell/JsValueGlue.java b/dev/oophm/overlay/com/google/gwt/dev/shell/JsValueGlue.java
index 2d3f953..02e2cdd 100644
--- a/dev/oophm/overlay/com/google/gwt/dev/shell/JsValueGlue.java
+++ b/dev/oophm/overlay/com/google/gwt/dev/shell/JsValueGlue.java
@@ -170,7 +170,12 @@
}
// Just don't know what do to with this.
- throw new HostedModeException(msgPrefix + ": JS value of type "
+ /*
+ * TODO (amitmanjhi): does throwing a HostedModeException here and catching
+ * a RuntimeException in user test
+ * com.google.gwt.dev.jjs.test.HostedTest::testObjectReturns() make sense
+ */
+ throw new IllegalArgumentException(msgPrefix + ": JS value of type "
+ value.getTypeString() + ", expected "
+ TypeInfo.getSourceRepresentation(type));
}
diff --git a/dev/oophm/src/com/google/gwt/dev/shell/HtmlUnitSessionHandler.java b/dev/oophm/src/com/google/gwt/dev/shell/HtmlUnitSessionHandler.java
index 201dafb..e7bb7a7 100644
--- a/dev/oophm/src/com/google/gwt/dev/shell/HtmlUnitSessionHandler.java
+++ b/dev/oophm/src/com/google/gwt/dev/shell/HtmlUnitSessionHandler.java
@@ -46,24 +46,61 @@
*/
public class HtmlUnitSessionHandler extends SessionHandler {
+ private class ToStringMethod extends ScriptableObject implements Function {
+
+ private static final int EXPECTED_NUM_ARGS = 0;
+ private static final long serialVersionUID = 1592865718416163348L;
+
+ public Object call(Context context, Scriptable scope, Scriptable thisObj,
+ Object[] args) {
+ // Allow extra arguments for forward compatibility
+ if (args.length < EXPECTED_NUM_ARGS) {
+ throw Context.reportRuntimeError("Bad number of parameters for function"
+ + " toString: expected "
+ + EXPECTED_NUM_ARGS
+ + ", got "
+ + args.length);
+ }
+ // thisObj is the javaObject.
+ Value thisValue = makeValueFromJsval(context, thisObj);
+ return JavaObject.getReturnValueFromJavaMethod(context,
+ HtmlUnitSessionHandler.this, sessionData.getChannel(),
+ TO_STRING_DISPATCH_ID, thisValue, EMPTY_VALUES);
+ }
+
+ public Scriptable construct(Context cx, Scriptable scope, Object[] args) {
+ throw Context.reportRuntimeError("Function connect can't be used as a "
+ + "constructor");
+ }
+
+ @Override
+ public String getClassName() {
+ return "function toString";
+ }
+ }
+
+ private static final Value EMPTY_VALUES[] = new Value[0];
+ private static final int TO_STRING_DISPATCH_ID = 0;
+
Map<Integer, JavaObject> javaObjectCache;
- int nextId;
/**
* The htmlPage is also used to synchronize calls to Java code.
*/
private HtmlPage htmlPage;
-
private Set<Integer> javaObjectsToFree;
- private JavaScriptEngine jsEngine;
- private IdentityHashMap<Scriptable, Integer> jsObjectToRef;
+ private JavaScriptEngine jsEngine;
+
+ private IdentityHashMap<Scriptable, Integer> jsObjectToRef;
private final PrintWriterTreeLogger logger = new PrintWriterTreeLogger();
private int nextRefId = 1;
private Map<Integer, Scriptable> refToJsObject;
-
private SessionData sessionData;
+
+ private final ToStringMethod toStringMethod = new ToStringMethod();
+
private final Window window;
HtmlUnitSessionHandler(Window window) {
@@ -78,9 +115,8 @@
javaObjectsToFree = new HashSet<Integer>();
nextRefId = 1;
refToJsObject = new HashMap<Integer, Scriptable>();
-
+
// related to JavaObject cache.
- nextId = 1; // skipping zero, reserved.
javaObjectCache = new HashMap<Integer, JavaObject>();
}
@@ -101,7 +137,7 @@
public JavaObject getOrCreateJavaObject(int refId, Context context) {
JavaObject javaObject = javaObjectCache.get(refId);
if (javaObject == null) {
- javaObject = new JavaObject(context, sessionData, nextId++);
+ javaObject = new JavaObject(context, sessionData, refId);
javaObjectCache.put(refId, javaObject);
}
return javaObject;
@@ -114,6 +150,10 @@
"getProperty should not be called on the client-side");
}
+ public Object getToStringTearOff(Context jsContext) {
+ return toStringMethod;
+ }
+
public String getUserAgent() {
return "HtmlUnit-"
+ jsEngine.getWebClient().getBrowserVersion().getUserAgent();
@@ -202,6 +242,17 @@
return returnVal;
}
if (value instanceof Scriptable) {
+ if (value instanceof ScriptableObject) {
+ /*
+ * HACK: check for native types like NativeString. NativeString is
+ * package-protected. What other types do we need to check?
+ */
+ ScriptableObject scriptableValue = (ScriptableObject) value;
+ String className = scriptableValue.getClassName();
+ if (className.equals("String")) {
+ return new Value(scriptableValue.toString());
+ }
+ }
Integer refId = jsObjectToRef.get((Scriptable) value);
if (refId == null) {
refId = nextRefId++;
diff --git a/dev/oophm/src/com/google/gwt/dev/shell/JavaObject.java b/dev/oophm/src/com/google/gwt/dev/shell/JavaObject.java
index c400c28..6f0b585 100644
--- a/dev/oophm/src/com/google/gwt/dev/shell/JavaObject.java
+++ b/dev/oophm/src/com/google/gwt/dev/shell/JavaObject.java
@@ -41,6 +41,32 @@
javaRef.getRefid(), context);
}
+ static Object getReturnValueFromJavaMethod(Context cx,
+ HtmlUnitSessionHandler sessionHandler, BrowserChannel channel,
+ int dispatchId, Value thisValue, Value valueArgs[]) {
+ ReturnMessage returnMessage = null;
+ synchronized (sessionHandler.getHtmlPage()) {
+ try {
+ new InvokeOnServerMessage(channel, dispatchId, thisValue, valueArgs).send();
+ } catch (IOException e) {
+ return Undefined.instance;
+ }
+ try {
+ returnMessage = ((BrowserChannelClient) channel).reactToMessagesWhileWaitingForReturn(sessionHandler);
+ } catch (IOException e) {
+ return Undefined.instance;
+ } catch (BrowserChannelException e) {
+ return Undefined.instance;
+ }
+ }
+ Value returnValue = returnMessage.getReturnValue();
+ if (returnMessage.isException()) {
+ throw new RuntimeException("JavaObject.call failed, returnMessage: "
+ + returnValue.toString());
+ }
+ return sessionHandler.makeJsvalFromValue(cx, returnValue);
+ }
+
static boolean isJavaObject(Context jsContext, ScriptableObject javaObject) {
return javaObject instanceof JavaObject;
}
@@ -87,34 +113,15 @@
args[1]);
int dispatchId = ((Number) args[0]).intValue();
- ReturnMessage returnMessage = null;
- synchronized (sessionData.getSessionHandler().getHtmlPage()) {
- try {
- new InvokeOnServerMessage(sessionData.getChannel(), dispatchId,
- thisValue, valueArgs).send();
- } catch (IOException e) {
- return Undefined.instance;
- }
- try {
- returnMessage = ((BrowserChannelClient) sessionData.getChannel()).reactToMessagesWhileWaitingForReturn(sessionData.getSessionHandler());
- } catch (IOException e) {
- return Undefined.instance;
- } catch (BrowserChannelException e) {
- return Undefined.instance;
- }
- }
- Value returnValue = returnMessage.getReturnValue();
- if (returnMessage.isException()) {
- throw new RuntimeException("JavaObject.call failed, returnMessage: "
- + returnValue.toString());
- }
/*
* Return a object array ret. ret[0] is a boolean indicating whether an
* exception was thrown or not. ret[1] is the exception or the return value.
+ * If there is an exception, a RuntimeException is thrown.
*/
Object ret[] = new Object[2];
ret[0] = Boolean.FALSE;
- ret[1] = sessionData.getSessionHandler().makeJsvalFromValue(cx, returnValue);
+ ret[1] = getReturnValueFromJavaMethod(cx, sessionData.getSessionHandler(),
+ sessionData.getChannel(), dispatchId, thisValue, valueArgs);
return ret;
}
@@ -125,9 +132,17 @@
// ignoring the 'start' argument.
@Override
+ public Object get(int index, Scriptable start) {
+ Value value = ServerMethods.getProperty(sessionData.getChannel(),
+ sessionData.getSessionHandler(), objectRef, index);
+ return sessionData.getSessionHandler().makeJsvalFromValue(jsContext, value);
+ }
+
+ // ignoring the 'start' argument.
+ @Override
public Object get(String name, Scriptable start) {
if ("toString".equals(name)) {
- return sessionData.getToStringTearOff();
+ return sessionData.getSessionHandler().getToStringTearOff(jsContext);
}
if ("id".equals(name)) {
return objectRef;
@@ -139,14 +154,6 @@
return Undefined.instance;
}
- // ignoring the 'start' argument.
- @Override
- public Object get(int index, Scriptable start) {
- Value value = ServerMethods.getProperty(sessionData.getChannel(),
- sessionData.getSessionHandler(), objectRef, index);
- return sessionData.getSessionHandler().makeJsvalFromValue(jsContext, value);
- }
-
@Override
public String getClassName() {
return "Class JavaObject";
diff --git a/dev/oophm/src/com/google/gwt/dev/shell/SessionData.java b/dev/oophm/src/com/google/gwt/dev/shell/SessionData.java
index 25428f2..82281c3 100644
--- a/dev/oophm/src/com/google/gwt/dev/shell/SessionData.java
+++ b/dev/oophm/src/com/google/gwt/dev/shell/SessionData.java
@@ -35,8 +35,4 @@
return sessionHandler;
}
- public Object getToStringTearOff() {
- // TODO Auto-generated method stub
- return null;
- }
}