Package com.google.gwt.core.client

Source Code of com.google.gwt.core.client.JavaScriptExceptionTest

/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.core.client;

import com.google.gwt.junit.DoNotRunWith;
import com.google.gwt.junit.Platform;
import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.useragent.client.UserAgent;

/**
* Any JavaScript exceptions occurring within JSNI methods are wrapped as this
* class when caught in Java code. The wrapping does not occur until the
* exception passes out of JSNI into Java. Before that, the thrown object
* remains a native JavaScript exception object, and can be caught in JSNI as
* normal.
*/
public class JavaScriptExceptionTest extends GWTTestCase {

  private static native JavaScriptObject makeJSO() /*-{
    return {
      toString:function() {
        return "jso";
      },
      name: "myName",
      message: "myDescription",
      extraField: "extraData"
    };
  }-*/;

  private static Object makeJavaObject() {
    Object o = new Object() {
      @Override public String toString() {
        return "myLameObject";
      }
    };
    return o;
  }

  private static native void throwNative(Object e) /*-{
    throw e;
  }-*/;

  private static native void throwTypeError() /*-{
    "dummy".notExistsWillThrowTypeError();
  }-*/;

  private static native void throwSvgError() /*-{
    // In Firefox, this throws an object (not Error):
    $doc.createElementNS("http://www.w3.org/2000/svg", "text").getBBox();

    // For other browsers, make sure an exception is thrown to keep the test simple
    throw new Error;
  }-*/;

  private static void throwSandwichJava(Object e) {
    throwNative(e);
  }

  private static Throwable catchJava(Runnable runnable) {
    try {
      runnable.run();
    } catch (Throwable e) {
      return e;
    }
    return null;
  }

  private static native Object catchNative(Runnable runnable) /*-{
    try {
      runnable.@java.lang.Runnable::run()();
    } catch(e) {
      return e;
    }
  }-*/;

  private static Runnable createThrowRunnable(final Throwable e) {
    return new Runnable() {
      @Override public void run() {
        throw sneakyThrow(e);
      }

      @SuppressWarnings("unchecked")
      <T extends RuntimeException> T sneakyThrow(Throwable e) {
        return (T) e;
      }
    };
  }

  private static Runnable createThrowNativeRunnable(final Object e) {
    return new Runnable() {
      @Override public void run() {
        throwNative(e);
      }
    };
  }

  private static void assertJavaScriptException(Object expected, Throwable exception) {
    assertTrue(exception instanceof JavaScriptException);
    assertEquals(expected, ((JavaScriptException) exception).getThrown());
  }

  /**
   * This test doesn't work in Development Mode yet; we'd need a way to throw
   * true native objects as exceptions. Windows/IE is the deal killer right now
   * on really making this work since there's no way to raise an exception of a
   * true JS value. We could use JS lambdas around Java calls to get around this
   * restriction.
   */
  public native void disabledTestJsExceptionSandwich() /*-{
    var e = { };
    try {
      @com.google.gwt.core.client.JavaScriptExceptionTest::throwSandwichJava(Ljava/lang/Object;)(e);
    } catch (t) {
      @junit.framework.Assert::assertSame(Ljava/lang/Object;Ljava/lang/Object;)(e, t);
    }
  }-*/;

  @Override
  public String getModuleName() {
    return "com.google.gwt.core.Core";
  }

  public void testCatch() {
    RuntimeException e = new RuntimeException();
    assertSame(e, catchJava(createThrowRunnable(e)));

    JavaScriptObject jso = makeJSO();
    e = new JavaScriptException(jso);
    assertJavaScriptException(jso, catchJava(createThrowRunnable(e)));
  }

  // java throw -> jsni catch -> jsni throw -> java catch
  public void testJavaNativeJavaSandwichCatch() {
    RuntimeException e = new RuntimeException();
    assertSame(e, javaNativeJavaSandwich(e));

    JavaScriptObject jso = makeJSO();
    e = new JavaScriptException(jso);
    assertJavaScriptException(jso, javaNativeJavaSandwich(e));
  }

  private Throwable javaNativeJavaSandwich(RuntimeException e) {
    return catchJava(createThrowNativeRunnable(catchJava(createThrowRunnable(e))));
  }

  public void testCatchThrowNative() {
    Object e;

    e = makeJSO();
    assertJavaScriptException(e, catchJava(createThrowNativeRunnable(e)));

    e = "testing";
    assertJavaScriptException(e, catchJava(createThrowNativeRunnable(e)));

    e = null;
    assertJavaScriptException(e, catchJava(createThrowNativeRunnable(e)));

    e = makeJavaObject();
    assertJavaScriptException(e, catchJava(createThrowNativeRunnable(e)));

    e = new RuntimeException();
    assertSame(e, catchJava(createThrowNativeRunnable(e)));

    e = new JavaScriptException("exception message"); // Thrown is not set
    assertSame(e, catchJava(createThrowNativeRunnable(e)));

    e = new JavaScriptException(makeJSO());
    assertSame(e, catchJava(createThrowNativeRunnable(e)));
  }

  // jsni throw -> java catch -> java throw -> jsni catch
  public void testNativeJavaNativeSandwichCatch() {
    Object e;

    e = makeJSO();
    assertSame(e, nativeJavaNativeSandwich(e));

    e = "testing";
    assertEquals(e, nativeJavaNativeSandwich(e));
    if (GWT.isScript()) { // Devmode will not preserve the same String instance
      assertSame(e, nativeJavaNativeSandwich(e));
    }

    e = null;
    assertSame(e, nativeJavaNativeSandwich(e));

    e = makeJavaObject();
    assertSame(e, nativeJavaNativeSandwich(e));

    e = new RuntimeException();
    assertSame(e, nativeJavaNativeSandwich(e));

    e = new JavaScriptException("exception message"); // Thrown is not set
    assertSame(e, nativeJavaNativeSandwich(e));

    JavaScriptObject jso = makeJSO();
    e = new JavaScriptException(jso);
    assertSame(jso, nativeJavaNativeSandwich(e));
  }

  private Object nativeJavaNativeSandwich(Object e) {
    return catchNative(createThrowRunnable(catchJava(createThrowNativeRunnable(e))));
  }

  public void testJso() {
    JavaScriptObject jso = makeJSO();
    try {
      throwNative(jso);
      fail();
    } catch (JavaScriptException e) {
      assertEquals("myName", e.getName());
      assertDescription(e, "myDescription");
      assertTrue(e.isThrownSet());
      assertSame(jso, e.getThrown());
      assertMessage(e);
    }
  }

  public void testNull() {
    try {
      throwNative(null);
      fail();
    } catch (JavaScriptException e) {
      assertEquals("null", e.getName());
      assertDescription(e, "null");
      assertTrue(e.isThrownSet());
      assertEquals(null, e.getThrown());
      assertMessage(e);
    }
  }

  public void testObject() {
    Object o = makeJavaObject();
    try {
      throwNative(o);
      fail();
    } catch (JavaScriptException e) {
      assertEquals(o.getClass().getName(), e.getName());
      assertDescription(e, "myLameObject");
      assertTrue(e.isThrownSet());
      assertEquals(o, e.getThrown());
      assertMessage(e);
    }
  }

  public void testString() {
    try {
      throwNative("foobarbaz");
      fail();
    } catch (JavaScriptException e) {
      assertEquals("String", e.getName());
      assertDescription(e, "foobarbaz");
      assertTrue(e.isThrownSet());
      assertEquals("foobarbaz", e.getThrown());
      assertMessage(e);
    }
  }

  @DoNotRunWith(Platform.HtmlUnitUnknown)
  public void testTypeError() {
    try {
      throwTypeError();
      fail();
    } catch (JavaScriptException e) {
      assertTypeError(e);
      e = (JavaScriptException) javaNativeJavaSandwich(e);
      assertTypeError(e);
    }
  }

  public void testSvgError() {
    try {
      throwSvgError();
      fail();
    } catch (JavaScriptException e) {
      assertTrue(e.isThrownSet());
      e = (JavaScriptException) javaNativeJavaSandwich(e);
      assertTrue(e.isThrownSet());
    }
  }

  private static void assertTypeError(JavaScriptException e) {
    assertEquals("TypeError", e.getName());
    assertTrue("e.isThrownSet() for a TypeError", e.isThrownSet());
    assertMessage(e);

    if (isIE8()) {
      return;
    }

    String description = e.getDescription();
    // The description depends on the browser.
    // On Chrome 34, the description is: "undefined is not a function".
    if (description.isEmpty()) {
      fail("TypeError description should not be empty");
    }
  }

  private static boolean isIE8() {
    UserAgent userAgent = GWT.create(UserAgent.class);
    return userAgent.getCompileTimeValue().equals("ie8");
  }

  private static void assertDescription(JavaScriptException e, String description) {
    if (!GWT.isScript()) {
      assertTrue("Should start with method name",
          e.getDescription().startsWith(
              "@com.google.gwt.core.client.JavaScriptExceptionTest::"
                  + "throwNative(Ljava/lang/Object;)"));
    }
    assertTrue("Should end with " + e.getDescription(),
        e.getDescription().endsWith(description));
  }

  private static void assertMessage(JavaScriptException e) {
    assertEquals("(" + e.getName() + ") " + e.getDescription(), e.getMessage());
  }
}
TOP

Related Classes of com.google.gwt.core.client.JavaScriptExceptionTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.