Revision: 8668
Author: [email protected]
Date: Mon Aug 30 07:43:31 2010
Log: Removed Object.typeId from generated class prototypes, and from the
compilation and linkage phases. Type cast checking depends only on the
castableTypeMaps and queryIds now.
Fixed a bug in deRPC for preserving meta data in transmitted Arrays for
proper element assignment type checking.
Review at http://gwt-code-reviews.appspot.com/751803
http://code.google.com/p/google-web-toolkit/source/detail?r=8668
Modified:
/trunk/dev/core/src/com/google/gwt/core/ext/linker/SymbolData.java
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardSymbolData.java
/trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
/trunk/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java
/trunk/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java
/trunk/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
/trunk/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Array.java
/trunk/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Cast.java
/trunk/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Util.java
/trunk/user/src/com/google/gwt/rpc/linker/ClientOracleLinker.java
/trunk/user/src/com/google/gwt/rpc/server/ClientOracle.java
/trunk/user/src/com/google/gwt/rpc/server/DelegatingClientOracle.java
/trunk/user/src/com/google/gwt/rpc/server/HostedModeClientOracle.java
/trunk/user/src/com/google/gwt/rpc/server/WebModeClientOracle.java
/trunk/user/src/com/google/gwt/rpc/server/WebModePayloadSink.java
/trunk/user/super/com/google/gwt/emul/java/lang/Object.java
/trunk/user/test/com/google/gwt/dev/jjs/test/ClassCastTest.java
/trunk/user/test/com/google/gwt/emultest/java/lang/ObjectTest.java
/trunk/user/test/com/google/gwt/user/client/rpc/CollectionsTest.java
/trunk/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java
=======================================
--- /trunk/dev/core/src/com/google/gwt/core/ext/linker/SymbolData.java Mon
Aug 16 17:56:17 2010
+++ /trunk/dev/core/src/com/google/gwt/core/ext/linker/SymbolData.java Mon
Aug 30 07:43:31 2010
@@ -102,6 +102,11 @@
*/
String getMemberName();
+ /**
+ * Returns the queryId for castability comparisons.
+ */
+ int getQueryId();
+
/**
* Returns the line number on which the symbol was originally declared or
* <code>-1</code> if the line number is unknown.
@@ -120,11 +125,6 @@
*/
String getSymbolName();
- /**
- * Returns the typeId or <code>0</code> if the type does not have a
typeId.
- */
- int getTypeId();
-
/**
* Returns <code>true</code> if the symbol represents a class.
*/
=======================================
---
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardSymbolData.java
Mon Aug 16 17:56:17 2010
+++
/trunk/dev/core/src/com/google/gwt/core/ext/linker/impl/StandardSymbolData.java
Mon Aug 30 07:43:31 2010
@@ -32,9 +32,9 @@
public class StandardSymbolData implements SymbolData {
public static StandardSymbolData forClass(String className, String
uriString,
- int lineNumber, int typeId, CastableTypeMap castableTypeMap) {
+ int lineNumber, int queryId, CastableTypeMap castableTypeMap) {
return new StandardSymbolData(className, null, null, uriString,
lineNumber,
- typeId, castableTypeMap);
+ queryId, castableTypeMap);
}
public static StandardSymbolData forMember(String className,
@@ -62,11 +62,11 @@
private int sourceLine;
private String sourceUri;
private String symbolName;
- private int typeId;
+ private int queryId;
private CastableTypeMap castableTypeMap;
private StandardSymbolData(String className, String memberName,
- String methodSig, String sourceUri, int sourceLine, int typeId,
+ String methodSig, String sourceUri, int sourceLine, int queryId,
CastableTypeMap castableTypeMap) {
assert className != null && className.length() > 0 : "className";
assert memberName != null || methodSig == null : "methodSig without
memberName";
@@ -77,7 +77,7 @@
this.methodSig = methodSig;
this.sourceUri = sourceUri;
this.sourceLine = sourceLine;
- this.typeId = typeId;
+ this.queryId = queryId;
this.castableTypeMap = castableTypeMap;
}
@@ -102,6 +102,10 @@
public String getMemberName() {
return memberName;
}
+
+ public int getQueryId() {
+ return queryId;
+ }
public int getSourceLine() {
return sourceLine;
@@ -114,10 +118,6 @@
public String getSymbolName() {
return symbolName;
}
-
- public int getTypeId() {
- return typeId;
- }
public boolean isClass() {
return memberName == null;
@@ -159,7 +159,7 @@
sourceLine = in.readInt();
sourceUri = (String) in.readObject();
symbolName = in.readUTF();
- typeId = in.readInt();
+ queryId = in.readInt();
castableTypeMap = (CastableTypeMap) in.readObject();
}
@@ -187,7 +187,7 @@
out.writeInt(sourceLine);
out.writeObject(sourceUri);
out.writeUTF(symbolName);
- out.writeInt(typeId);
+ out.writeInt(queryId);
out.writeObject(castableTypeMap);
}
}
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java Thu Aug 19
13:25:39 2010
+++ /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java Mon Aug 30
04:31:11 2010
@@ -318,7 +318,7 @@
*/
private final SourceInfo intrinsic;
- private List<JsonObject> jsonCastableTypeMaps;
+ private IdentityHashMap<JReferenceType, JsonObject> castableTypeMaps;
private Map<JReferenceType, JNonNullType> nonNullTypes = new
IdentityHashMap<JReferenceType, JNonNullType>();
@@ -348,8 +348,6 @@
private JClassType typeClass;
- private Map<JReferenceType, Integer> typeIdMap = new
HashMap<JReferenceType, Integer>();
-
private JInterfaceType typeJavaIoSerializable;
private JInterfaceType typeJavaLangCloneable;
@@ -766,18 +764,23 @@
return allEntryMethods;
}
- public JsonObject getCastableTypeMap(int typeId) {
+ public JsonObject getCastableTypeMap(JReferenceType referenceType) {
+
// ensure jsonCastableTypeMaps has been initialized
// it might not have been if the CastNormalizer has not been run
- if (jsonCastableTypeMaps == null) {
- jsonCastableTypeMaps = new ArrayList<JsonObject>();
- // ensure the always-false (typeId == 0) entry is present
- jsonCastableTypeMaps.add(new JsonObject(createSourceInfoSynthetic(
- JProgram.class, "always-false typeinfo entry"),
- getJavaScriptObject()));
+ if (castableTypeMaps == null) {
+ initTypeInfo(null);
}
- return jsonCastableTypeMaps.get(typeId);
+ JsonObject returnMap = castableTypeMaps.get(referenceType);
+ if (returnMap == null) {
+ // add a new empty map
+ returnMap = new JsonObject(createSourceInfoSynthetic(JProgram.class,
+ "empty map"),
getJavaScriptObject());
+ castableTypeMaps.put(referenceType, returnMap);
+ }
+
+ return returnMap;
}
public CorrelationFactory getCorrelator() {
@@ -1099,16 +1102,6 @@
return getTypeArray(type, dim);
}
}
-
- public int getTypeId(JReferenceType referenceType) {
- assert (referenceType == getRunTimeType(referenceType));
- Integer integer = typeIdMap.get(referenceType);
- if (integer == null) {
- return 0;
- }
-
- return integer.intValue();
- }
public JClassType getTypeJavaLangClass() {
return typeClass;
@@ -1165,13 +1158,15 @@
public JPrimitiveType getTypeVoid() {
return JPrimitiveType.VOID;
}
-
- public void initTypeInfo(List<JReferenceType> types,
- List<JsonObject> jsonObjects) {
- for (int i = 0, c = types.size(); i < c; ++i) {
- typeIdMap.put(types.get(i), Integer.valueOf(i));
- }
- this.jsonCastableTypeMaps = jsonObjects;
+
+ public void initTypeInfo(
+ IdentityHashMap<JReferenceType,JsonObject>
instantiatedTypeCastableTypeMaps) {
+
+ castableTypeMaps = instantiatedTypeCastableTypeMaps;
+
+ if (castableTypeMaps == null || castableTypeMaps.size() == 0) {
+ castableTypeMaps = new IdentityHashMap<JReferenceType, JsonObject>();
+ }
}
public boolean isJavaLangString(JType type) {
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java
Mon Aug 16 17:56:17 2010
+++ /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java
Mon Aug 30 04:31:11 2010
@@ -124,15 +124,11 @@
JMethodCall call = new JMethodCall(x.getSourceInfo(), null, initDim,
arrayType);
JLiteral classLit = x.getClassLiteral();
-
- int typeId = program.getTypeId(arrayType);
- JLiteral typeIdLit = program.getLiteralInt(typeId);
- JsonObject castableTypeMap = program.getCastableTypeMap(typeId);
-
+ JsonObject castableTypeMap = program.getCastableTypeMap(arrayType);
JLiteral queryIdLit =
program.getLiteralInt(tryGetQueryId(arrayType));
JExpression dim = x.dims.get(0);
JType elementType = arrayType.getElementType();
- call.addArgs(classLit, typeIdLit, castableTypeMap, queryIdLit, dim,
+ call.addArgs(classLit, castableTypeMap, queryIdLit, dim,
getSeedTypeLiteralFor(elementType));
ctx.replaceMe(call);
}
@@ -145,8 +141,6 @@
JMethodCall call = new JMethodCall(sourceInfo, null, initDims,
arrayType);
JsonArray classLitList = new JsonArray(sourceInfo,
program.getJavaScriptObject());
- JsonArray typeIdList = new JsonArray(sourceInfo,
- program.getJavaScriptObject());
JsonArray castableTypeMapList = new JsonArray(sourceInfo,
program.getJavaScriptObject());
JsonArray queryIdList = new JsonArray(sourceInfo,
@@ -160,12 +154,8 @@
JLiteral classLit = x.getClassLiterals().get(i);
classLitList.exprs.add(classLit);
-
- int typeId = program.getTypeId(curArrayType);
- JLiteral typeIdLit = program.getLiteralInt(typeId);
- typeIdList.exprs.add(typeIdLit);
-
- JsonObject castableTypeMap = program.getCastableTypeMap(typeId);
+
+ JsonObject castableTypeMap =
program.getCastableTypeMap(curArrayType);
castableTypeMapList.exprs.add(castableTypeMap);
JLiteral queryIdLit =
program.getLiteralInt(tryGetQueryId(curArrayType));
@@ -174,7 +164,7 @@
dimList.exprs.add(x.dims.get(i));
cur = curArrayType.getElementType();
}
- call.addArgs(classLitList, typeIdList, castableTypeMapList,
queryIdList,
+ call.addArgs(classLitList, castableTypeMapList, queryIdList,
dimList, program.getLiteralInt(dims),
getSeedTypeLiteralFor(cur));
ctx.replaceMe(call);
}
@@ -187,28 +177,24 @@
JMethodCall call = new JMethodCall(sourceInfo, null, initValues,
arrayType);
JLiteral classLit = x.getClassLiteral();
-
- int typeId = program.getTypeId(arrayType);
- JLiteral typeIdLit = program.getLiteralInt(typeId);
- JsonObject castableTypeMap = program.getCastableTypeMap(typeId);
-
+ JsonObject castableTypeMap = program.getCastableTypeMap(arrayType);
JLiteral queryIdLit =
program.getLiteralInt(tryGetQueryId(arrayType));
JsonArray initList = new JsonArray(sourceInfo,
program.getJavaScriptObject());
for (int i = 0; i < x.initializers.size(); ++i) {
initList.exprs.add(x.initializers.get(i));
}
- call.addArgs(classLit, typeIdLit, castableTypeMap, queryIdLit,
initList);
+ call.addArgs(classLit, castableTypeMap, queryIdLit, initList);
ctx.replaceMe(call);
}
private int tryGetQueryId(JArrayType type) {
JType elementType = type.getElementType();
- int leafTypeId = -1;
+ int leafQueryId = -1;
if (elementType instanceof JReferenceType) {
- leafTypeId =
program.getQueryId(program.getRunTimeType((JReferenceType) elementType));
- }
- return leafTypeId;
+ leafQueryId =
program.getQueryId(program.getRunTimeType((JReferenceType) elementType));
+ }
+ return leafQueryId;
}
}
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java Wed
Mar 10 15:24:26 2010
+++ /trunk/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java Mon
Aug 30 04:31:11 2010
@@ -53,11 +53,6 @@
* on {...@link CatchBlockNormalizer}, {...@link CompoundAssignmentNormalizer},
* {...@link JsoDevirtualizer}, and {...@link LongCastNormalizer} having already
run.
*
- * <p>
- * Object and String always get a typeId of 1 and 2, respectively. 0 is
reserved
- * as the typeId for any classes that can never be instance type of a
successful
- * dynamic cast.
- * </p>
* <p>
* Object and String always get a queryId of 0 and 1, respectively. The 0
* queryId always means "always succeeds". In practice, we never generate
an
@@ -65,20 +60,21 @@
* where the 0 queryId means that anything can be stored into an Object[].
* </p>
* <p>
- * JavaScriptObject and subclasses have no typeId at all. JavaScriptObject
has a
- * queryId of -1, which again is only used for array store checking, to
ensure
- * that a non-JSO is not stored into a JavaScriptObject[].
+ * JavaScriptObject has a queryId of -1, which again is only used for
array store
+ * checking, to ensure that a non-JSO is not stored into a
JavaScriptObject[].
* </p>
*/
public class CastNormalizer {
- private class AssignTypeIdsVisitor extends JVisitor {
+ private class AssignTypeCastabilityVisitor extends JVisitor {
Set<JReferenceType> alreadyRan = new HashSet<JReferenceType>();
- private List<JReferenceType> instantiableTypes = new
ArrayList<JReferenceType>();
- private final List<JArrayType> instantiatedArrayTypes = new
ArrayList<JArrayType>();
- private List<JsonObject> jsonObjects = new ArrayList<JsonObject>();
+ private IdentityHashMap<JReferenceType, JsonObject>
+ castableTypeMaps = new IdentityHashMap<JReferenceType,
JsonObject>();
+ private final List<JArrayType> instantiatedArrayTypes =
+ new ArrayList<JArrayType>();
private int nextQueryId = 0;
- private Map<JReferenceType, Set<JReferenceType>> queriedTypes = new
IdentityHashMap<JReferenceType, Set<JReferenceType>>();
+ private Map<JReferenceType, Set<JReferenceType>> queriedTypes =
+ new IdentityHashMap<JReferenceType, Set<JReferenceType>>();
{
JTypeOracle typeOracle = program.typeOracle;
@@ -93,26 +89,17 @@
program.getTypeJavaLangObject());
// Reserve query id 1 for java.lang.String to facilitate the mashup
case.
+ // Also, facilitates detecting an object as a Java String (see
Cast.java)
// Multiple GWT modules need to modify String's prototype the same
way.
recordCastInternal(program.getTypeJavaLangString(),
program.getTypeJavaLangObject());
}
- public void computeTypeIds() {
-
- // the 0th entry is the "always false" entry
- instantiableTypes.add(null);
- jsonObjects.add(new JsonObject(program.createSourceInfoSynthetic(
- AssignTypeIdsVisitor.class, "always-false typeinfo entry"),
- program.getJavaScriptObject()));
-
- /*
- * Do String first to reserve typeIds 1 and 2 for Object and String,
- * respectively. This ensures consistent modification of String's
- * prototype.
- */
+ public void computeTypeCastabilityMaps() {
+
+ // do String first (which will pull in Object also, it's superclass).
computeSourceType(program.getTypeJavaLangString());
- assert (instantiableTypes.size() == 3);
+ assert (castableTypeMaps.size() == 3);
/*
* Compute the list of classes than can successfully satisfy cast
@@ -130,9 +117,9 @@
}
// pass our info to JProgram
- program.initTypeInfo(instantiableTypes, jsonObjects);
-
- // JSO's maker queryId is -1 (used for array stores).
+ program.initTypeInfo(castableTypeMaps);
+
+ // JSO's marker queryId is -1 (used for array stores).
JClassType jsoType = program.getJavaScriptObject();
if (jsoType != null) {
queryIds.put(jsoType, -1);
@@ -156,7 +143,6 @@
// will generate a null pointer exception instead
return;
}
- JArrayType lhsArrayType = lhsArrayRef.getArrayType();
// primitives are statically correct
if (!(elementType instanceof JReferenceType)) {
@@ -177,6 +163,7 @@
JType rhsType = x.getRhs().getType();
assert (rhsType instanceof JReferenceType);
+ JArrayType lhsArrayType = lhsArrayRef.getArrayType();
for (JArrayType arrayType : instantiatedArrayTypes) {
if (typeOracle.canTheoreticallyCast(arrayType, lhsArrayType)) {
JType itElementType = arrayType.getElementType();
@@ -257,7 +244,7 @@
// Create a sparse lookup object.
SourceInfo sourceInfo = program.createSourceInfoSynthetic(
- AssignTypeIdsVisitor.class, "typeinfo lookup");
+ AssignTypeCastabilityVisitor.class, "typeinfo lookup");
JsonObject jsonObject = new JsonObject(sourceInfo,
program.getJavaScriptObject());
// Start at 1; 0 is Object and always true.
@@ -272,7 +259,7 @@
/*
* Don't add an entry for empty answer sets, except for Object and
String
- * which require typeIds.
+ * which require entries.
*/
if (jsonObject.propInits.isEmpty()
&& type != program.getTypeJavaLangObject()
@@ -281,8 +268,7 @@
}
// add an entry for me
- instantiableTypes.add(type);
- jsonObjects.add(jsonObject);
+ castableTypeMaps.put(type,jsonObject);
}
private void recordCast(JType targetType, JExpression rhs) {
@@ -604,9 +590,9 @@
visitor.accept(program);
}
{
- AssignTypeIdsVisitor assigner = new AssignTypeIdsVisitor();
+ AssignTypeCastabilityVisitor assigner = new
AssignTypeCastabilityVisitor();
assigner.accept(program);
- assigner.computeTypeIds();
+ assigner.computeTypeCastabilityMaps();
}
{
ReplaceTypeChecksVisitor replacer = new ReplaceTypeChecksVisitor();
=======================================
---
/trunk/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
Mon Aug 16 17:56:17 2010
+++
/trunk/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
Mon Aug 30 04:31:11 2010
@@ -118,7 +118,6 @@
import com.google.gwt.dev.js.ast.JsNameRef;
import com.google.gwt.dev.js.ast.JsNew;
import com.google.gwt.dev.js.ast.JsNode;
-import com.google.gwt.dev.js.ast.JsNumberLiteral;
import com.google.gwt.dev.js.ast.JsObjectLiteral;
import com.google.gwt.dev.js.ast.JsParameter;
import com.google.gwt.dev.js.ast.JsPostfixOperation;
@@ -445,14 +444,13 @@
}
private void recordSymbol(JReferenceType x, JsName jsName) {
- int typeId = program.getTypeId(x);
-
- JsonObject castableTypeMapObj = program.getCastableTypeMap(typeId);
+ int queryId = program.getQueryId(x);
+ JsonObject castableTypeMapObj = program.getCastableTypeMap(x);
CastableTypeMap castableTypeMap = new
StandardCastableTypeMap(castableTypeMapObj.toString());
StandardSymbolData symbolData =
StandardSymbolData.forClass(x.getName(),
x.getSourceInfo().getFileName(),
x.getSourceInfo().getStartLine(),
- typeId, castableTypeMap);
+ queryId, castableTypeMap);
assert !symbolTable.containsKey(symbolData);
symbolTable.put(symbolData, jsName);
}
@@ -1500,9 +1498,9 @@
lhs, rhs);
}
- private void generateCastableTypeIds(JClassType x, List<JsStatement>
globalStmts) {
- int typeId = program.getTypeId(x);
- if (typeId >= 0) {
+ private void generateCastableTypeMap(JClassType x, List<JsStatement>
globalStmts) {
+ JsonObject castableTypeMap = program.getCastableTypeMap(x);
+ if (castableTypeMap != null) {
JField castableTypeMapField =
program.getIndexedField("Object.castableTypeMap");
JsName castableTypeMapName = names.get(castableTypeMapField);
if (castableTypeMapName == null) {
@@ -1513,8 +1511,7 @@
SourceInfo sourceInfo = jsProgram.createSourceInfoSynthetic(
GenerateJavaScriptAST.class, "Castable type map");
- JsonObject jsonObject = program.getCastableTypeMap(typeId);
- accept(jsonObject);
+ accept(castableTypeMap);
JsExpression objExpr = pop();
// Generate castableTypeMap for each type prototype
@@ -1564,8 +1561,7 @@
generateTypeMarker(globalStmts);
}
- generateTypeId(x, globalStmts);
- generateCastableTypeIds(x, globalStmts);
+ generateCastableTypeMap(x, globalStmts);
}
private void generateGwtOnLoad(List<JsFunction> entryFuncs,
@@ -1787,27 +1783,6 @@
typeForStatMap.put(stmt, program.getTypeJavaLangObject());
}
}
-
- private void generateTypeId(JClassType x, List<JsStatement>
globalStmts) {
- int typeId = program.getTypeId(x);
- if (typeId >= 0) {
- JField typeIdField = program.getIndexedField("Object.typeId");
- JsName typeIdName = names.get(typeIdField);
- if (typeIdName == null) {
- // Was pruned; this compilation must have no dynamic casts.
- return;
- }
- SourceInfo sourceInfo = x.getSourceInfo().makeChild(
- GenerateJavaScriptVisitor.class, "Type id assignment");
- JsNameRef fieldRef = typeIdName.makeRef(sourceInfo);
- fieldRef.setQualifier(globalTemp.makeRef(sourceInfo));
- JsNumberLiteral typeIdLit = jsProgram.getNumberLiteral(typeId);
- JsExpression asg = createAssignment(fieldRef, typeIdLit);
- JsExprStmt asgStmt = asg.makeStmt();
- globalStmts.add(asgStmt);
- typeForStatMap.put(asgStmt, x);
- }
- }
private void generateTypeMarker(List<JsStatement> globalStmts) {
JField typeMarkerField =
program.getIndexedField("Object.typeMarker");
@@ -2156,7 +2131,6 @@
// Object fields
specialObfuscatedIdents.put("expando", "eX");
- specialObfuscatedIdents.put("typeId", "tI");
specialObfuscatedIdents.put("typeMarker", "tM");
specialObfuscatedIdents.put("castableTypeMap", "cM");
=======================================
---
/trunk/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Array.java
Mon Aug 16 17:56:17 2010
+++
/trunk/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Array.java
Mon Aug 30 04:31:11 2010
@@ -97,8 +97,7 @@
public static <T> T[] cloneSubrange(T[] array, int fromIndex, int
toIndex) {
Array a = asArrayType(array);
Array result = arraySlice(a, fromIndex, toIndex);
- initValues(a.getClass(), Util.getTypeId(a),
- Util.getCastableTypeMap(a), a.queryId, result);
+ initValues(a.getClass(), Util.getCastableTypeMap(a), a.queryId,
result);
// implicit type arg not inferred (as of JDK 1.5.0_07)
return Array.<T> asArray(result);
}
@@ -117,8 +116,7 @@
public static <T> T[] createFrom(T[] array, int length) {
Array a = asArrayType(array);
Array result = createFromSeed(NULL_SEED_TYPE, length);
- initValues(a.getClass(), Util.getTypeId(a),
- Util.getCastableTypeMap(a), a.queryId, result);
+ initValues(a.getClass(), Util.getCastableTypeMap(a), a.queryId,
result);
// implicit type arg not inferred (as of JDK 1.5.0_07)
return Array.<T> asArray(result);
}
@@ -128,18 +126,17 @@
* array, [a, b, c].
*
* @param arrayClass the class of the array
- * @param typeId the typeId of the array
* @param castableTypeMap the map of types to which this array can be
casted,
* in the form of a JSON map object
* @param queryId the queryId of the array
* @param length the length of the array
- * @param seedType the primitive type of the array; 0: null; 1: zero; 2:
false
+ * @param seedType the primitive type of the array; 0: null; 1: zero; 2:
false; 3: long
* @return the new array
*/
- public static Array initDim(Class<?> arrayClass, int typeId,
+ public static Array initDim(Class<?> arrayClass,
JavaScriptObject castableTypeMap, int queryId, int length, int
seedType) {
Array result = createFromSeed(seedType, length);
- initValues(arrayClass, typeId, castableTypeMap, queryId, result);
+ initValues(arrayClass, castableTypeMap, queryId, result);
return result;
}
@@ -148,18 +145,17 @@
* array, [a, b, c].
*
* @param arrayClasses the class of each dimension of the array
- * @param typeIdExprs the typeId of each dimension, from highest to
lowest
* @param castableTypeMapExprs the JSON castableTypeMap of each
dimension,
* from highest to lowest
* @param queryIdExprs the queryId of each dimension, from highest to
lowest
* @param dimExprs the length of each dimension, from highest to lower
- * @param seedType the primitive type of the array; 0: null; 1: zero; 2:
false
+ * @param seedType the primitive type of the array; 0: null; 1: zero; 2:
false; 3: long
* @return the new array
*/
- public static Array initDims(Class<?> arrayClasses[], int[] typeIdExprs,
- JavaScriptObject[] castableTypeMapExprs, int[] queryIdExprs, int[]
dimExprs,
- int count, int seedType) {
- return initDims(arrayClasses, typeIdExprs, castableTypeMapExprs,
queryIdExprs,
+ public static Array initDims(Class<?> arrayClasses[],
+ JavaScriptObject[] castableTypeMapExprs, int[] queryIdExprs,
+ int[] dimExprs, int count, int seedType) {
+ return initDims(arrayClasses, castableTypeMapExprs, queryIdExprs,
dimExprs, 0, count, seedType);
}
@@ -168,18 +164,16 @@
* array, [a, b, c, d].
*
* @param arrayClass the class of the array
- * @param typeId the typeId of the array
* @param castableTypeMap the map of types to which this array can be
casted,
* in the form of a JSON map object
* @param queryId the queryId of the array
* @param array the JSON array that will be transformed into a GWT array
* @return values; having wrapped it for GWT
*/
- public static Array initValues(Class<?> arrayClass, int typeId,
+ public static Array initValues(Class<?> arrayClass,
JavaScriptObject castableTypeMap, int queryId, Array array) {
ExpandoWrapper.wrapArray(array);
array.arrayClass = arrayClass;
- Util.setTypeId(array, typeId);
Util.setCastableTypeMap(array, castableTypeMap);
array.queryId = queryId;
return array;
@@ -227,6 +221,7 @@
* @see #NULL_SEED_TYPE
* @see #ZERO_SEED_TYPE
* @see #FALSE_SEED_TYPE
+ * @see #LONG_SEED_TYPE
* @return the new JSON array
*/
private static native Array createFromSeed(int seedType, int length) /*-{
@@ -247,22 +242,21 @@
return array;
}-*/;
- private static Array initDims(Class<?> arrayClasses[], int[] typeIdExprs,
+ private static Array initDims(Class<?> arrayClasses[],
JavaScriptObject[] castableTypeMapExprs, int[] queryIdExprs, int[]
dimExprs,
int index, int count, int seedType) {
-
int length = dimExprs[index];
boolean isLastDim = (index == (count - 1));
Array result = createFromSeed(isLastDim ? seedType : NULL_SEED_TYPE,
length);
- initValues(arrayClasses[index], typeIdExprs[index],
- castableTypeMapExprs[index], queryIdExprs[index], result);
+ initValues(arrayClasses[index], castableTypeMapExprs[index],
+ queryIdExprs[index], result);
if (!isLastDim) {
// Recurse to next dimension.
++index;
for (int i = 0; i < length; ++i) {
- set(result, i, initDims(arrayClasses, typeIdExprs,
castableTypeMapExprs,
+ set(result, i, initDims(arrayClasses, castableTypeMapExprs,
queryIdExprs, dimExprs, index, count, seedType));
}
}
=======================================
---
/trunk/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Cast.java
Mon Aug 16 17:56:17 2010
+++
/trunk/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Cast.java
Mon Aug 30 04:31:11 2010
@@ -26,7 +26,7 @@
final class Cast {
static native boolean canCast(Object src, int dstId) /*-{
- return [email protected]::typeId &&
+ return [email protected]::castableTypeMap &&
[email protected]::castableTypeMap[dstId];
}-*/;
@@ -35,7 +35,7 @@
* context.
*/
static native boolean canCastUnsafe(Object src, int dstId) /*-{
- return [email protected]::typeId &&
+ return [email protected]::castableTypeMap &&
[email protected]::castableTypeMap[dstId];
}-*/;
@@ -75,9 +75,6 @@
return (src != null) && canCast(src, dstId);
}
- /**
- * Instance of JSO only if there's no type ID.
- */
static boolean instanceOfJso(Object src) {
return (src != null) && isJavaScriptObject(src);
}
@@ -92,15 +89,15 @@
}
static boolean isJavaObject(Object src) {
- return Util.getTypeMarker(src) == getNullMethod() ||
Util.getTypeId(src) == 2;
+ return isNonStringJavaObject(src) || isJavaString(src);
}
static boolean isJavaScriptObject(Object src) {
- return Util.getTypeMarker(src) != getNullMethod() &&
Util.getTypeId(src) != 2;
+ return !isNonStringJavaObject(src) && !isJavaString(src);
}
static boolean isJavaScriptObjectOrString(Object src) {
- return Util.getTypeMarker(src) != getNullMethod();
+ return !isNonStringJavaObject(src);
}
/**
@@ -208,6 +205,35 @@
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
=======================================
---
/trunk/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Util.java
Mon Aug 16 17:56:17 2010
+++
/trunk/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Util.java
Mon Aug 30 04:31:11 2010
@@ -18,29 +18,21 @@
import com.google.gwt.core.client.JavaScriptObject;
/**
- * This class is used to access the private, GWT-specific typeId and
typeMarker
- * fields.
+ * This class is used to access the private, GWT-specific
+ * castableTypeMap and typeMarker fields.
*/
final class Util {
-
+
static native JavaScriptObject getCastableTypeMap(Object o) /*-{
return [email protected]::castableTypeMap;
}-*/;
- static native int getTypeId(Object o) /*-{
- return [email protected]::typeId;
- }-*/;
-
static native JavaScriptObject getTypeMarker(Object o) /*-{
return [email protected]::typeMarker;
}-*/;
-
+
static native void setCastableTypeMap(Object o, JavaScriptObject
castableTypeMap) /*-{
[email protected]::castableTypeMap = castableTypeMap;
}-*/;
- static native void setTypeId(Object o, int typeId) /*-{
- [email protected]::typeId = typeId;
- }-*/;
-
-}
+}
=======================================
--- /trunk/user/src/com/google/gwt/rpc/linker/ClientOracleLinker.java Mon
Aug 16 17:56:17 2010
+++ /trunk/user/src/com/google/gwt/rpc/linker/ClientOracleLinker.java Mon
Aug 30 04:31:11 2010
@@ -71,7 +71,7 @@
for (SymbolData symbolData : result.getSymbolMap()) {
builder.add(symbolData.getSymbolName(),
symbolData.getJsniIdent(),
symbolData.getClassName(), symbolData.getMemberName(),
- symbolData.getTypeId(),
+ symbolData.getQueryId(),
new CastableTypeDataImpl(symbolData.getCastableTypeMap()));
}
=======================================
--- /trunk/user/src/com/google/gwt/rpc/server/ClientOracle.java Mon Aug 16
17:56:17 2010
+++ /trunk/user/src/com/google/gwt/rpc/server/ClientOracle.java Mon Aug 30
04:31:11 2010
@@ -105,15 +105,15 @@
public abstract Field[] getOperableFields(Class<?> clazz);
/**
- * Returns the name of the top-level function that is used as the seed
- * function for a given type.
+ * Returns the assigned castability queryId of a given type.
*/
- public abstract String getSeedName(Class<?> clazz);
+ public abstract int getQueryId(Class<?> clazz);
/**
- * Returns the assigned typeId of a given type or 0.
+ * Returns the name of the top-level function that is used as the seed
+ * function for a given type.
*/
- public abstract int getTypeId(Class<?> clazz);
+ public abstract String getSeedName(Class<?> clazz);
/**
* Returns the deobfuscated name of a type based on the name of the
type's
=======================================
--- /trunk/user/src/com/google/gwt/rpc/server/DelegatingClientOracle.java
Mon Aug 16 17:56:17 2010
+++ /trunk/user/src/com/google/gwt/rpc/server/DelegatingClientOracle.java
Mon Aug 30 04:31:11 2010
@@ -85,13 +85,13 @@
}
@Override
- public String getSeedName(Class<?> clazz) {
- return delegate.getSeedName(clazz);
+ public int getQueryId(Class<?> clazz) {
+ return delegate.getQueryId(clazz);
}
@Override
- public int getTypeId(Class<?> clazz) {
- return delegate.getTypeId(clazz);
+ public String getSeedName(Class<?> clazz) {
+ return delegate.getSeedName(clazz);
}
@Override
=======================================
--- /trunk/user/src/com/google/gwt/rpc/server/HostedModeClientOracle.java
Mon Aug 16 17:56:17 2010
+++ /trunk/user/src/com/google/gwt/rpc/server/HostedModeClientOracle.java
Mon Aug 30 04:31:11 2010
@@ -132,16 +132,16 @@
* Unimplemented.
*/
@Override
- public String getSeedName(Class<?> clazz) {
- return unimplemented();
+ public int getQueryId(Class<?> clazz) {
+ return this.<Integer> unimplemented();
}
/**
* Unimplemented.
*/
@Override
- public int getTypeId(Class<?> clazz) {
- return this.<Integer> unimplemented();
+ public String getSeedName(Class<?> clazz) {
+ return unimplemented();
}
/**
=======================================
--- /trunk/user/src/com/google/gwt/rpc/server/WebModeClientOracle.java Mon
Aug 16 17:56:17 2010
+++ /trunk/user/src/com/google/gwt/rpc/server/WebModeClientOracle.java Mon
Aug 30 04:31:11 2010
@@ -52,11 +52,23 @@
private WebModeClientOracle oracle = new WebModeClientOracle();
public void add(String jsIdent, String jsniIdent, String className,
- String memberName, int typeId, CastableTypeData castableTypeData) {
+ String memberName, int queryId, CastableTypeData castableTypeData)
{
+
oracle.idents.add(jsIdent);
ClassData data = oracle.getClassData(className);
- data.typeId = typeId;
- data.castableTypeData = castableTypeData;
+
+ /*
+ * Don't overwrite castableTypeData and queryId if already set.
+ * There are many versions of symbols for a given className,
+ * corresponding to the type of member fields, etc.,
+ * which don't have the queryId or castableTypeData initialized.
Only
+ * the symbol data for the class itself has this info.
+ */
+ if (data.castableTypeData == null) {
+ data.queryId = queryId;
+ data.castableTypeData = castableTypeData;
+ }
+
if (jsniIdent == null || jsniIdent.length() == 0) {
data.typeName = className;
data.seedName = jsIdent;
@@ -109,15 +121,15 @@
}
private static class ClassData implements Serializable {
- private static final long serialVersionUID = 4L;
+ private static final long serialVersionUID = 5L;
public CastableTypeData castableTypeData;
public final Map<String, String> fieldIdentsToNames = new
HashMap<String, String>();
public final Map<String, String> fieldNamesToIdents = new
HashMap<String, String>();
public final Map<String, String> methodJsniNamesToIdents = new
HashMap<String, String>();
+ public int queryId;
public String seedName;
public List<String> serializableFields = Collections.emptyList();
- public int typeId;
public String typeName;
}
@@ -345,15 +357,9 @@
}
@Override
- public String getSeedName(Class<?> clazz) {
- ClassData data = getClassData(clazz.getName());
- return data.seedName;
- }
-
- @Override
- public int getTypeId(Class<?> clazz) {
+ public int getQueryId(Class<?> clazz) {
while (clazz != null) {
- int toReturn = getTypeId(canonicalName(clazz));
+ int toReturn = getQueryId(canonicalName(clazz));
if (toReturn != 0) {
return toReturn;
}
@@ -361,6 +367,12 @@
}
return 0;
}
+
+ @Override
+ public String getSeedName(Class<?> clazz) {
+ ClassData data = getClassData(clazz.getName());
+ return data.seedName;
+ }
@Override
public String getTypeName(String seedName) {
@@ -437,9 +449,9 @@
return getMethodId(className, methodName, jsniArgTypes);
}
- private int getTypeId(String className) {
+ private int getQueryId(String className) {
ClassData data = getClassData(className);
- return data.typeId;
+ return data.queryId;
}
/**
=======================================
--- /trunk/user/src/com/google/gwt/rpc/server/WebModePayloadSink.java Mon
Aug 16 17:56:17 2010
+++ /trunk/user/src/com/google/gwt/rpc/server/WebModePayloadSink.java Mon
Aug 30 04:31:11 2010
@@ -532,7 +532,7 @@
}
String initValuesId = clientOracle.getMethodId(
- "com.google.gwt.lang.Array", "initValues", "Ljava/lang/Class;", "I",
+ "com.google.gwt.lang.Array", "initValues", "Ljava/lang/Class;",
"Lcom/google/gwt/core/client/JavaScriptObject;", "I",
"Lcom/google/gwt/lang/Array;");
assert initValuesId != null : "Could not find initValues";
@@ -547,26 +547,22 @@
constructorFunctions.put(targetClass, functionName);
/*
- * Set the typeIds, castableTypeData, and queryIds to exact values,
+ * Set the castableTypeData and queryIds to exact values,
* or fall back to acting like a plain Object[] array.
*/
- CastableTypeData castableTypeData;
- int typeId = clientOracle.getTypeId(targetClass);
- if (typeId != 0) {
- castableTypeData = clientOracle.getCastableTypeData(targetClass);
- } else {
- typeId = clientOracle.getTypeId(Object[].class);
+ CastableTypeData castableTypeData =
clientOracle.getCastableTypeData(targetClass);
+ if (castableTypeData == null) {
castableTypeData =
clientOracle.getCastableTypeData(Object[].class);
}
- int queryId = clientOracle.getTypeId(x.getComponentType());
+ int queryId = clientOracle.getQueryId(x.getComponentType());
if (queryId == 0) {
- queryId = clientOracle.getTypeId(Object.class);
+ queryId = clientOracle.getQueryId(Object.class);
}
byte[] ident = getBytes("_0");
- // function foo(_0) {return initValues(classLid, typeId, queryId,
_0)}
+ // function foo(_0) {return initValues(classLid, castableTypeData,
queryId, _0)}
function();
push(functionName);
lparen();
@@ -578,8 +574,6 @@
lparen();
push(classLitId);
comma();
- push(String.valueOf(typeId));
- comma();
push(castableTypeData.toJs());
comma();
push(String.valueOf(queryId));
=======================================
--- /trunk/user/super/com/google/gwt/emul/java/lang/Object.java Mon Aug 16
17:56:17 2010
+++ /trunk/user/super/com/google/gwt/emul/java/lang/Object.java Mon Aug 30
04:31:11 2010
@@ -34,14 +34,6 @@
@SuppressWarnings("unused")
private transient JavaScriptObject expando;
- /**
- * magic magic magic.
- *
- * @skip
- */
- @SuppressWarnings("unused")
- private transient int typeId;
-
/**
* A JavaScript Json map for looking up castability between types.
*
=======================================
--- /trunk/user/test/com/google/gwt/dev/jjs/test/ClassCastTest.java Mon Dec
21 10:20:58 2009
+++ /trunk/user/test/com/google/gwt/dev/jjs/test/ClassCastTest.java Mon Aug
30 04:31:11 2010
@@ -34,11 +34,16 @@
static abstract class Food {
}
+
+ static class Drink {
+ }
private volatile Object arrayOfInt = new int[3];
private volatile Object arrayOfWidget = new Widget[4];
+ private volatile Object arrayOfApple = new Apple[5];
private volatile Food foodItem = new Apple();
private volatile CanEatRaw rawFoodItem = new Apple();
+ private volatile Object drinkItem = new Drink();
@Override
public String getModuleName() {
@@ -55,15 +60,20 @@
assertFalse(arrayOfInt instanceof Food);
assertFalse(arrayOfWidget instanceof Food);
}
-
+
public void testBaseToInterface() {
- Apple apple = (Apple) foodItem;
- }
-
+ CanEatRaw canEatRaw = (CanEatRaw) foodItem;
+ }
+
+ public void testBaseToInterfaceArrayElement() {
+ CanEatRaw[] canEatRawArray = new CanEatRaw[3];
+ canEatRawArray[1] = (CanEatRaw) foodItem;
+ }
+
public void testBaseToInterfaceMethod() {
- Apple apple = (Apple) getFoodItem();
- }
-
+ CanEatRaw canEatRaw = (CanEatRaw) getFoodItem();
+ }
+
@SuppressWarnings("cast")
public void testBaseToInterfaceToConcreteCrazyInline() {
Apple apple = (Apple) (CanEatRaw) (Food) new Apple();
@@ -85,6 +95,21 @@
Apple apple = (Apple) foodItem;
}
+ public void testDownCastToArrayElement() {
+ Apple[] appleArray = new Apple[3];
+ appleArray[2] = (Apple) foodItem;
+ }
+
+ public void testDownCastToArrayArrayElement() {
+ Apple[][] appleArrayArray = new Apple[3][4];
+ appleArrayArray[2][2] = (Apple) foodItem;
+ }
+
+ public void testArrayToArrayArrayElement() {
+ Apple[][] appleArrayArray = new Apple[3][5];
+ appleArrayArray[2] = (Apple[]) arrayOfApple;
+ }
+
public void testDownCastClassMethod() {
Apple apple = (Apple) getFoodItem();
}
@@ -93,6 +118,11 @@
Apple apple = (Apple) rawFoodItem;
}
+ public void testDownCastInterfaceToArrayElement() {
+ Apple[] appleArray = new Apple[3];
+ appleArray[2] = (Apple) rawFoodItem;
+ }
+
public void testDownCastInterfaceMethod() {
Apple apple = (Apple) getRawFoodItem();
}
@@ -108,7 +138,92 @@
public void testInterfaceToBaseToConcreteMethod() {
Apple apple = (Apple) getRawFoodAsFoodMethod();
}
-
+
+ public void testClassCastExceptionObjectToConcrete() {
+ try {
+ Apple apple = (Apple) drinkItem;
+ fail("Expected ClassCastException");
+ } catch (ClassCastException e) {
+ // expected
+ }
+ }
+
+ public void testClassCastExceptionToBase() {
+ try {
+ Food food = (Food) drinkItem;
+ fail("Expected ClassCastException");
+ } catch (ClassCastException e) {
+ // expected
+ }
+ }
+
+ public void testClassCastExceptionToInterface() {
+ try {
+ CanEatRaw canEatRaw = (CanEatRaw) drinkItem;
+ fail("Expected ClassCastException");
+ } catch (ClassCastException e) {
+ // expected
+ }
+ }
+
+ public void testClassCastExceptionArrayToConcrete() {
+ try {
+ Apple apple = (Apple) arrayOfWidget;
+ fail("Expected ClassCastException");
+ } catch (ClassCastException e) {
+ // expected
+ }
+ }
+
+ public void testClassCastExceptionObjectToArray() {
+ try {
+ Apple[] appleArray = (Apple[]) drinkItem;
+ fail("Expected ClassCastException");
+ } catch (ClassCastException e) {
+ // expected
+ }
+ }
+
+ public void testClassCastExceptionObjectToConcreteArrayElement() {
+ try {
+ Apple[] appleArray = new Apple[3];
+ appleArray[0] = (Apple) drinkItem;
+ fail("Expected ClassCastException");
+ } catch (ClassCastException e) {
+ // expected
+ }
+ }
+
+ public void testArrayStoreExceptionObjectToConcreteArrayElement() {
+ try {
+ Object[] appleArray = new Apple[3];
+ appleArray[0] = drinkItem;
+ fail("Expected ArrayStoreException");
+ } catch (ArrayStoreException e) {
+ // expected
+ }
+ }
+
+ public void testClassCastExceptionArrayToArrayArrayElement() {
+ try {
+ Apple[][] appleArrayArray = new Apple[3][4];
+ appleArrayArray[2] = (Apple[]) arrayOfWidget;
+ fail("Expected ClassCastException");
+ } catch (ClassCastException e) {
+ // expected
+ }
+ }
+
+ public void testArrayStoreExceptionArrayToArrayArrayElement() {
+ try {
+ Object[][] appleArrayArray = new Apple[3][4];
+ appleArrayArray[2] = (Object[]) arrayOfWidget;
+ fail("Expected ArrayStoreException");
+ } catch (ArrayStoreException e) {
+ // expected
+ }
+ }
+
private CanEatRaw getFoodAsRawFoodField() {
return (CanEatRaw) foodItem;
}
=======================================
--- /trunk/user/test/com/google/gwt/emultest/java/lang/ObjectTest.java Fri
Jun 13 17:45:25 2008
+++ /trunk/user/test/com/google/gwt/emultest/java/lang/ObjectTest.java Mon
Aug 30 04:31:11 2010
@@ -15,6 +15,7 @@
*/
package com.google.gwt.emultest.java.lang;
+import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.junit.client.GWTTestCase;
/**
@@ -37,26 +38,26 @@
}
/**
- * Tests that 'java.lang.Object.typeId' does not shadow a local field.
+ * Tests that 'java.lang.Object.castableTypeMap' does not shadow a local
field.
*/
- public void testTypeIdShadow() {
- // arbitrary number
- final int typeId = -824107554;
- Object obj = new Object() {
- public int hashCode() {
- return typeId;
- }
- };
- assertEquals(typeId, obj.hashCode());
+ public void testCastableTypeMapShadow() {
+ final JavaScriptObject castableTypeMap =
JavaScriptObject.createObject();
+ class TestClass {
+ public JavaScriptObject getCastableTypeMap() {
+ return castableTypeMap;
+ }
+ }
+ TestClass test = new TestClass();
+ assertEquals(castableTypeMap, test.getCastableTypeMap());
}
/**
* Tests that 'java.lang.Object.typeMarker' does not shadow a local
field.
*/
public void testTypeMarkerShadow() {
- final Object typeMarker = new Object();
+ final JavaScriptObject typeMarker = JavaScriptObject.createObject();
class TestClass {
- public Object getTypeMarker() {
+ public JavaScriptObject getTypeMarker() {
return typeMarker;
}
}
=======================================
--- /trunk/user/test/com/google/gwt/user/client/rpc/CollectionsTest.java
Fri Jul 23 07:41:23 2010
+++ /trunk/user/test/com/google/gwt/user/client/rpc/CollectionsTest.java
Mon Aug 30 04:31:11 2010
@@ -48,26 +48,6 @@
public class CollectionsTest extends RpcTestBase {
private CollectionsTestServiceAsync collectionsTestService;
-
- /**
- * TODO: Why is this disabled???
- */
- public void disabledTestDateArray() {
- CollectionsTestServiceAsync service = getServiceAsync();
- final Date[] expected = TestSetFactory.createDateArray();
- delayTestFinishForRpc();
- service.echo(expected, new AsyncCallback<Date[]>() {
- public void onFailure(Throwable caught) {
- TestSetValidator.rethrowException(caught);
- }
-
- public void onSuccess(Date[] result) {
- assertNotNull(result);
- assertTrue(TestSetValidator.equals(expected, result));
- finishTest();
- }
- });
- }
/**
* This tests sending payloads that must be segmented to avoid problems
with
@@ -156,6 +136,11 @@
public void onSuccess(Boolean[] result) {
assertNotNull(result);
assertTrue(TestSetValidator.equals(expected, result));
+
+ // ensure result preserves meta-data for array store type checking
+ assertTrue(TestSetValidator.checkObjectArrayElementAssignment(
+ result, 0, new Boolean(false)));
+
finishTest();
}
});
@@ -173,6 +158,11 @@
public void onSuccess(Byte[] result) {
assertNotNull(result);
assertTrue(TestSetValidator.equals(expected, result));
+
+ // ensure result preserves meta-data for array store type checking
+ assertTrue(TestSetValidator.checkObjectArrayElementAssignment(
+ result, 0, new Byte((byte) 0)));
+
finishTest();
}
});
@@ -190,11 +180,38 @@
public void onSuccess(Character[] result) {
assertNotNull(result);
assertTrue(TestSetValidator.equals(expected, result));
+
+ // ensure result preserves meta-data for array store type checking
+ assertTrue(TestSetValidator.checkObjectArrayElementAssignment(
+ result, 0, new Character('0')));
+
finishTest();
}
});
}
-
+
+ public void testDateArray() {
+ CollectionsTestServiceAsync service = getServiceAsync();
+ final Date[] expected = TestSetFactory.createDateArray();
+ delayTestFinishForRpc();
+ service.echo(expected, new AsyncCallback<Date[]>() {
+ public void onFailure(Throwable caught) {
+ TestSetValidator.rethrowException(caught);
+ }
+
+ public void onSuccess(Date[] result) {
+ assertNotNull(result);
+ assertTrue(TestSetValidator.equals(expected, result));
+
+ // ensure result preserves meta-data for array store type checking
+ assertTrue(TestSetValidator.checkObjectArrayElementAssignment(
+ result, 0, new Date()));
+
+ finishTest();
+ }
+ });
+ }
+
public void testDoubleArray() {
CollectionsTestServiceAsync service = getServiceAsync();
final Double[] expected = TestSetFactory.createDoubleArray();
@@ -207,6 +224,11 @@
public void onSuccess(Double[] result) {
assertNotNull(result);
assertTrue(TestSetValidator.equals(expected, result));
+
+ // ensure result preserves meta-data for array store type checking
+ assertTrue(TestSetValidator.checkObjectArrayElementAssignment(
+ result, 0, new Double(0.0)));
+
finishTest();
}
});
@@ -275,6 +297,11 @@
public void onSuccess(Enum<?>[] result) {
assertNotNull(result);
assertTrue(TestSetValidator.equals(expected, result));
+
+ // ensure result preserves meta-data for array store type checking
+ assertTrue(TestSetValidator.checkObjectArrayElementAssignment(
+ result, 0, TestSetFactory.MarkerTypeEnum.C));
+
finishTest();
}
});
@@ -292,6 +319,11 @@
public void onSuccess(Float[] result) {
assertNotNull(result);
assertTrue(TestSetValidator.equals(expected, result));
+
+ // ensure result preserves meta-data for array store type checking
+ assertTrue(TestSetValidator.checkObjectArrayElementAssignment(
+ result, 0, new Float(0.0)));
+
finishTest();
}
});
@@ -344,6 +376,11 @@
public void onSuccess(Integer[] result) {
assertNotNull(result);
assertTrue(TestSetValidator.equals(expected, result));
+
+ // ensure result preserves meta-data for array store type checking
+ assertTrue(TestSetValidator.checkObjectArrayElementAssignment(
+ result, 0, new Integer(0)));
+
finishTest();
}
});
@@ -409,6 +446,11 @@
public void onSuccess(Long[] result) {
assertNotNull(result);
assertTrue(TestSetValidator.equals(expected, result));
+
+ // ensure result preserves meta-data for array store type checking
+ assertTrue(TestSetValidator.checkObjectArrayElementAssignment(
+ result, 0, new Long(0L)));
+
finishTest();
}
});
@@ -560,6 +602,11 @@
public void onSuccess(Short[] result) {
assertNotNull(result);
assertTrue(TestSetValidator.equals(expected, result));
+
+ // ensure result preserves meta-data for array store type checking
+ assertTrue(TestSetValidator.checkObjectArrayElementAssignment(
+ result, 0, new Short((short) 0)));
+
finishTest();
}
});
@@ -594,6 +641,11 @@
public void onSuccess(java.sql.Date[] result) {
assertNotNull(result);
assertTrue(TestSetValidator.equals(expected, result));
+
+ // ensure result preserves meta-data for array store type checking
+ assertTrue(TestSetValidator.checkObjectArrayElementAssignment(
+ result, 0, new java.sql.Date(0L)));
+
finishTest();
}
});
@@ -611,6 +663,11 @@
public void onSuccess(Time[] result) {
assertNotNull(result);
assertTrue(TestSetValidator.equals(expected, result));
+
+ // ensure result preserves meta-data for array store type checking
+ assertTrue(TestSetValidator.checkObjectArrayElementAssignment(
+ result, 0, new Time(0L)));
+
finishTest();
}
});
@@ -628,6 +685,11 @@
public void onSuccess(Timestamp[] result) {
assertNotNull(result);
assertTrue(TestSetValidator.equals(expected, result));
+
+ // ensure result preserves meta-data for array store type checking
+ assertTrue(TestSetValidator.checkObjectArrayElementAssignment(
+ result, 0, new Timestamp(0L)));
+
finishTest();
}
});
@@ -645,6 +707,11 @@
public void onSuccess(String[] result) {
assertNotNull(result);
assertTrue(TestSetValidator.equals(expected, result));
+
+ // ensure result preserves meta-data for array store type checking
+ assertTrue(TestSetValidator.checkObjectArrayElementAssignment(
+ result, 0, new String("")));
+
finishTest();
}
});
@@ -662,6 +729,11 @@
public void onSuccess(String[][] result) {
assertNotNull(result);
+
+ // ensure result preserves meta-data for array store type checking
+ assertTrue(TestSetValidator.checkObjectArrayElementAssignment(
+ result, 0, new String[4]));
+
finishTest();
}
});
=======================================
--- /trunk/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java
Fri Jul 23 07:41:23 2010
+++ /trunk/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java
Mon Aug 30 04:31:11 2010
@@ -50,7 +50,33 @@
* TODO: could add generics to require args to be of the same type
*/
public class TestSetValidator {
-
+
+ private static class UnassignableObject {
+ }
+
+ /**
+ * Check that an Object array has it's meta-data preserved (e.g.
Array.queryId),
+ * to ensure proper type checking on element assignment.
+ */
+ public static boolean checkObjectArrayElementAssignment(Object[] array,
+ int index, Object value) {
+
+ // first check that the requested assignment succeeds
+ try {
+ array[index] = value;
+ } catch (ArrayStoreException e) {
+ return false;
+ }
+
+ // next check that assignment with a bogus type throws
ArrayStoreException
+ try {
+ array[index] = new UnassignableObject();
+ return false;
+ } catch (ArrayStoreException e) {
+ return true;
+ }
+ }
+
public static boolean equals(boolean[] expected, boolean[] actual) {
if (actual == null) {
return false;
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors