| /* |
| * 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.lang; |
| |
| import com.google.gwt.core.client.JavaScriptObject; |
| |
| // CHECKSTYLE_NAMING_OFF: Uses legacy conventions of underscore prefixes. |
| |
| /** |
| * This is a magic class the compiler uses to perform any cast operations that |
| * require code. |
| */ |
| final class Cast { |
| |
| static native boolean canCast(Object src, int dstId) /*-{ |
| return src.@java.lang.Object::castableTypeMap && |
| !!src.@java.lang.Object::castableTypeMap[dstId]; |
| }-*/; |
| |
| /** |
| * Danger: value not coerced to boolean; use the result only in a boolean |
| * context. |
| */ |
| static native boolean canCastUnsafe(Object src, int dstId) /*-{ |
| return src.@java.lang.Object::castableTypeMap && |
| src.@java.lang.Object::castableTypeMap[dstId]; |
| }-*/; |
| |
| static native String charToString(char x) /*-{ |
| return String.fromCharCode(x); |
| }-*/; |
| |
| static Object dynamicCast(Object src, int dstId) { |
| if (src != null && !canCastUnsafe(src, dstId)) { |
| throw new ClassCastException(); |
| } |
| return src; |
| } |
| |
| /** |
| * Allow a dynamic cast to an object, always succeeding if it's a JSO. |
| */ |
| static Object dynamicCastAllowJso(Object src, int dstId) { |
| if (src != null && !isJavaScriptObject(src) && |
| !canCastUnsafe(src, dstId)) { |
| throw new ClassCastException(); |
| } |
| return src; |
| } |
| |
| /** |
| * Allow a cast to JSO only if there's no type ID. |
| */ |
| static Object dynamicCastJso(Object src) { |
| if (src != null && isJavaObject(src)) { |
| throw new ClassCastException(); |
| } |
| return src; |
| } |
| |
| static boolean instanceOf(Object src, int dstId) { |
| return (src != null) && canCast(src, dstId); |
| } |
| |
| static boolean instanceOfJso(Object src) { |
| return (src != null) && isJavaScriptObject(src); |
| } |
| |
| /** |
| * Returns true if the object is a Java object and can be cast, or if it's a |
| * non-null JSO. |
| */ |
| static boolean instanceOfOrJso(Object src, int dstId) { |
| return (src != null) && |
| (isJavaScriptObject(src) || canCast(src, dstId)); |
| } |
| |
| static boolean isJavaObject(Object src) { |
| return isNonStringJavaObject(src) || isJavaString(src); |
| } |
| |
| static boolean isJavaScriptObject(Object src) { |
| return !isNonStringJavaObject(src) && !isJavaString(src); |
| } |
| |
| static boolean isJavaScriptObjectOrString(Object src) { |
| return !isNonStringJavaObject(src); |
| } |
| |
| /** |
| * Uses the not operator to perform a null-check; do NOT use on anything that |
| * could be a String. |
| */ |
| static native boolean isNotNull(Object src) /*-{ |
| // Coerce to boolean. |
| return !!src; |
| }-*/; |
| |
| /** |
| * Uses the not operator to perform a null-check; do NOT use on anything that |
| * could be a String. |
| */ |
| static native boolean isNull(Object src) /*-{ |
| return !src; |
| }-*/; |
| |
| static native boolean jsEquals(Object a, Object b) /*-{ |
| return a == b; |
| }-*/; |
| |
| static native boolean jsNotEquals(Object a, Object b) /*-{ |
| return a != b; |
| }-*/; |
| |
| static native Object maskUndefined(Object src) /*-{ |
| return (src == null) ? null : src; |
| }-*/; |
| |
| /** |
| * See JLS 5.1.3. |
| */ |
| static native byte narrow_byte(double x) /*-{ |
| return x << 24 >> 24; |
| }-*/; |
| |
| /** |
| * See JLS 5.1.3. |
| */ |
| static native char narrow_char(double x) /*-{ |
| return x & 0xFFFF; |
| }-*/; |
| |
| /** |
| * See JLS 5.1.3. |
| */ |
| static native int narrow_int(double x) /*-{ |
| return ~~x; |
| }-*/; |
| |
| /** |
| * See JLS 5.1.3. |
| */ |
| static native short narrow_short(double x) /*-{ |
| return x << 16 >> 16; |
| }-*/; |
| |
| /** |
| * See JLS 5.1.3 for why we do a two-step cast. First we round to int, then |
| * narrow to byte. |
| */ |
| static byte round_byte(double x) { |
| return narrow_byte(round_int(x)); |
| } |
| |
| /** |
| * See JLS 5.1.3 for why we do a two-step cast. First we round to int, then |
| * narrow to char. |
| */ |
| static char round_char(double x) { |
| return narrow_char(round_int(x)); |
| } |
| |
| /** |
| * See JLS 5.1.3. |
| */ |
| static native int round_int(double x) /*-{ |
| // TODO: reference java.lang.Integer::MAX_VALUE when we get clinits fixed |
| return ~~Math.max(Math.min(x, 2147483647), -2147483648); |
| }-*/; |
| |
| /** |
| * See JLS 5.1.3 for why we do a two-step cast. First we rount to int, then |
| * narrow to short. |
| */ |
| static short round_short(double x) { |
| return narrow_short(round_int(x)); |
| } |
| |
| /** |
| * Check a statically false cast, which can succeed if the argument is null. |
| * Called by compiler-generated code based on static type information. |
| */ |
| static Object throwClassCastExceptionUnlessNull(Object o) |
| throws ClassCastException { |
| if (o != null) { |
| throw new ClassCastException(); |
| } |
| return o; |
| } |
| |
| private static native JavaScriptObject getNullMethod() /*-{ |
| return @null::nullMethod(); |
| }-*/; |
| |
| /** |
| * Returns whether the Object is a Java String. |
| * |
| * Depends on the requirement that queryId = 1 is reserved for String, |
| * and that the trivial cast String to String is explicitly added to the |
| * castableTypeMap for String, and String cannot be the target of a cast from |
| * anything else (except for the trivial cast from Object), since |
| * java.lang.String is a final class. |
| * (See the constructor for the CastNormalizer.AssignTypeCastabilityVisitor). |
| * |
| * Since java Strings are translated as JavaScript strings, Strings need to be |
| * interchangeable between GWT modules, unlike other Java Objects. |
| */ |
| private static boolean isJavaString(Object src) { |
| return canCast(src, 1); |
| } |
| |
| /** |
| * Returns whether the Object is a Java Object but not a String. |
| * |
| * Depends on all Java Objects (except for String) having the typeMarker field |
| * generated, and set to the nullMethod for the current GWT module. Note this |
| * test essentially tests whether an Object is a java object for the current |
| * GWT module. Java Objects from external GWT modules are not recognizable as |
| * Java Objects in this context. |
| */ |
| private static boolean isNonStringJavaObject(Object src) { |
| return Util.getTypeMarker(src) == getNullMethod(); |
| } |
| } |
| |
| // CHECKSTYLE_NAMING_ON |