22#include < string.h>
33#include < algorithm>
44#include < sstream>
5+ #include < set>
56#include " javaObject.h"
67#include " java.h"
78
@@ -244,6 +245,67 @@ jobject javaFindField(JNIEnv* env, jclass clazz, std::string& fieldName) {
244245 return result;
245246}
246247
248+ const std::string kObject (" java/lang/Object" );
249+ const std::string kString (" java/lang/String" );
250+ const std::string kInteger (" java/lang/Integer" );
251+ const std::string kNumber (" java/lang/Number" );
252+ const std::string kLong (" java/lang/Long" );
253+ const std::string kDouble (" java/lang/Double" );
254+ const std::string kBoolean (" java/lang/Boolean" );
255+
256+ static std::string getArrayElementType (v8::Local<v8::Array> array, uint32_t arraySize) {
257+ std::set<std::string> types;
258+
259+ if (arraySize == 0 ) {
260+ return kObject ;
261+ }
262+
263+ for (uint32_t i=0 ; i<arraySize; i++) {
264+ v8::Local<v8::Value> arg = array->Get (i);
265+ if (arg->IsArray ()) {
266+ return kObject ; // We can exit as soon as we know java/lang/Object is required.
267+ }
268+ else if (arg->IsString ()) {
269+ types.insert (kString );
270+ }
271+ else if (arg->IsInt32 () || arg->IsUint32 ()) {
272+ types.insert (kInteger );
273+ }
274+ else if (arg->IsNumber ()) {
275+ types.insert (kDouble );
276+ }
277+ else if (arg->IsBoolean ()) {
278+ types.insert (kBoolean );
279+ }
280+ else if (arg->IsObject ()) {
281+ v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast (arg);
282+ v8::Local<v8::Value> isJavaLong = obj->GetHiddenValue (NanNew<v8::String>(V8_HIDDEN_MARKER_JAVA_LONG));
283+ if (!isJavaLong.IsEmpty () && isJavaLong->IsBoolean ()) {
284+ types.insert (kLong );
285+ }
286+ else {
287+ return kObject ; // We can exit as soon as we know java/lang/Object is required.
288+ }
289+ }
290+ }
291+
292+ if (types.size () == 1 ) {
293+ return *(types.begin ());
294+ }
295+
296+ assert (types.size () >= 1 );
297+ assert (types.find (kObject )==types.end ());
298+
299+ // We have an array with two or more types. All types can be converted to Object, but there is one other
300+ // case we support, which is when all the types are numeric types.
301+ // We currently have only two non-numeric types. If neither is present in the set, the rest must be numeric.
302+ if (types.find (kString )==types.end () && types.find (kBoolean )==types.end ()) {
303+ return kNumber ;
304+ }
305+
306+ return kObject ;
307+ }
308+
247309jobject v8ToJava (JNIEnv* env, v8::Local<v8::Value> arg) {
248310 if (arg.IsEmpty () || arg->IsNull () || arg->IsUndefined ()) {
249311 return NULL ;
@@ -252,7 +314,8 @@ jobject v8ToJava(JNIEnv* env, v8::Local<v8::Value> arg) {
252314 if (arg->IsArray ()) {
253315 v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast (arg);
254316 uint32_t arraySize = array->Length ();
255- jclass objectClazz = env->FindClass (" java/lang/Object" );
317+ std::string arrayType = getArrayElementType (array, arraySize);
318+ jclass objectClazz = env->FindClass (arrayType.c_str ());
256319 jobjectArray result = env->NewObjectArray (arraySize, objectClazz, NULL );
257320 for (uint32_t i=0 ; i<arraySize; i++) {
258321 jobject val = v8ToJava (env, array->Get (i));
0 commit comments