summaryrefslogtreecommitdiffstats
path: root/mobile/android/modules/JNI.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/modules/JNI.jsm')
-rw-r--r--mobile/android/modules/JNI.jsm1167
1 files changed, 1167 insertions, 0 deletions
diff --git a/mobile/android/modules/JNI.jsm b/mobile/android/modules/JNI.jsm
new file mode 100644
index 000000000..1e10b9cfb
--- /dev/null
+++ b/mobile/android/modules/JNI.jsm
@@ -0,0 +1,1167 @@
+// JavaScript to Java bridge via the Java Native Interface
+// Allows calling into Android SDK from JavaScript in Firefox Add-On.
+// Released into the public domain.
+// C. Scott Ananian <cscott@laptop.org> (http://cscott.net)
+
+// NOTE: All changes to this file should first be pushed to the repo at:
+// https://github.com/cscott/skeleton-addon-fxandroid/tree/jni
+
+var EXPORTED_SYMBOLS = ["JNI","android_log"];
+
+Components.utils.import("resource://gre/modules/ctypes.jsm")
+
+var liblog = ctypes.open('liblog.so');
+var android_log = liblog.declare("__android_log_write",
+ ctypes.default_abi,
+ ctypes.int32_t,
+ ctypes.int32_t,
+ ctypes.char.ptr,
+ ctypes.char.ptr);
+
+var libxul = ctypes.open('libxul.so');
+
+var jenvptr = ctypes.voidptr_t;
+var jclass = ctypes.voidptr_t;
+var jobject = ctypes.voidptr_t;
+var jvalue = ctypes.voidptr_t;
+var jmethodid = ctypes.voidptr_t;
+var jfieldid = ctypes.voidptr_t;
+
+var jboolean = ctypes.uint8_t;
+var jbyte = ctypes.int8_t;
+var jchar = ctypes.uint16_t;
+var jshort = ctypes.int16_t;
+var jint = ctypes.int32_t;
+var jlong = ctypes.int64_t;
+var jfloat = ctypes.float32_t;
+var jdouble = ctypes.float64_t;
+
+var jsize = jint;
+var jstring = jobject;
+var jarray = jobject;
+var jthrowable = jobject;
+
+var JNINativeInterface = new ctypes.StructType(
+ "JNINativeInterface",
+ [{reserved0: ctypes.voidptr_t},
+ {reserved1: ctypes.voidptr_t},
+ {reserved2: ctypes.voidptr_t},
+ {reserved3: ctypes.voidptr_t},
+ {GetVersion: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.int32_t,
+ [ctypes.voidptr_t]).ptr},
+ {DefineClass: new ctypes.FunctionType(ctypes.default_abi,
+ jclass,
+ [jenvptr, ctypes.char.ptr, jobject,
+ jbyte.array(), jsize]).ptr},
+ {FindClass: new ctypes.FunctionType(ctypes.default_abi,
+ jclass,
+ [jenvptr,
+ ctypes.char.ptr]).ptr},
+ {FromReflectedMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jmethodid,
+ [jenvptr, jobject]).ptr},
+ {FromReflectedField: new ctypes.FunctionType(ctypes.default_abi,
+ jfieldid,
+ [jenvptr, jobject]).ptr},
+ {ToReflectedMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jobject,
+ [jenvptr, jclass,
+ jmethodid]).ptr},
+ {GetSuperclass: new ctypes.FunctionType(ctypes.default_abi,
+ jclass, [jenvptr, jclass]).ptr},
+ {IsAssignableFrom: new ctypes.FunctionType(ctypes.default_abi,
+ jboolean,
+ [jenvptr, jclass, jclass]).ptr},
+ {ToReflectedField: new ctypes.FunctionType(ctypes.default_abi,
+ jobject,
+ [jenvptr, jclass,
+ jfieldid]).ptr},
+ {Throw: new ctypes.FunctionType(ctypes.default_abi,
+ jint, [jenvptr, jthrowable]).ptr},
+ {ThrowNew: new ctypes.FunctionType(ctypes.default_abi,
+ jint, [jenvptr, jclass,
+ ctypes.char.ptr]).ptr},
+ {ExceptionOccurred: new ctypes.FunctionType(ctypes.default_abi,
+ jthrowable, [jenvptr]).ptr},
+ {ExceptionDescribe: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t, [jenvptr]).ptr},
+ {ExceptionClear: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t, [jenvptr]).ptr},
+ {FatalError: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr,
+ ctypes.char.ptr]).ptr},
+ {PushLocalFrame: new ctypes.FunctionType(ctypes.default_abi,
+ jint,
+ [jenvptr, jint]).ptr},
+ {PopLocalFrame: new ctypes.FunctionType(ctypes.default_abi,
+ jobject,
+ [jenvptr, jobject]).ptr},
+ {NewGlobalRef: new ctypes.FunctionType(ctypes.default_abi,
+ jobject, [jenvptr, jobject]).ptr},
+ {DeleteGlobalRef: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr,
+ jobject]).ptr},
+ {DeleteLocalRef: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr,
+ jobject]).ptr},
+ {IsSameObject: new ctypes.FunctionType(ctypes.default_abi,
+ jboolean,
+ [jenvptr, jobject, jobject]).ptr},
+ {NewLocalRef: new ctypes.FunctionType(ctypes.default_abi,
+ jobject, [jenvptr, jobject]).ptr},
+ {EnsureLocalCapacity: new ctypes.FunctionType(ctypes.default_abi,
+ jint, [jenvptr, jint]).ptr},
+ {AllocObject: new ctypes.FunctionType(ctypes.default_abi,
+ jobject, [jenvptr, jclass]).ptr},
+ {NewObject: new ctypes.FunctionType(ctypes.default_abi,
+ jobject,
+ [jenvptr,
+ jclass,
+ jmethodid,
+ "..."]).ptr},
+ {NewObjectV: ctypes.voidptr_t},
+ {NewObjectA: ctypes.voidptr_t},
+ {GetObjectClass: new ctypes.FunctionType(ctypes.default_abi,
+ jclass,
+ [jenvptr, jobject]).ptr},
+ {IsInstanceOf: new ctypes.FunctionType(ctypes.default_abi,
+ jboolean,
+ [jenvptr, jobject, jclass]).ptr},
+ {GetMethodID: new ctypes.FunctionType(ctypes.default_abi,
+ jmethodid,
+ [jenvptr,
+ jclass,
+ ctypes.char.ptr,
+ ctypes.char.ptr]).ptr},
+ {CallObjectMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jobject,
+ [jenvptr, jobject, jmethodid,
+ "..."]).ptr},
+ {CallObjectMethodV: ctypes.voidptr_t},
+ {CallObjectMethodA: ctypes.voidptr_t},
+ {CallBooleanMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jboolean,
+ [jenvptr,
+ jobject,
+ jmethodid,
+ "..."]).ptr},
+ {CallBooleanMethodV: ctypes.voidptr_t},
+ {CallBooleanMethodA: ctypes.voidptr_t},
+ {CallByteMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jbyte,
+ [jenvptr,
+ jobject,
+ jmethodid,
+ "..."]).ptr},
+ {CallByteMethodV: ctypes.voidptr_t},
+ {CallByteMethodA: ctypes.voidptr_t},
+ {CallCharMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jchar,
+ [jenvptr,
+ jobject,
+ jmethodid,
+ "..."]).ptr},
+ {CallCharMethodV: ctypes.voidptr_t},
+ {CallCharMethodA: ctypes.voidptr_t},
+ {CallShortMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jshort,
+ [jenvptr,
+ jobject,
+ jmethodid,
+ "..."]).ptr},
+ {CallShortMethodV: ctypes.voidptr_t},
+ {CallShortMethodA: ctypes.voidptr_t},
+ {CallIntMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jint,
+ [jenvptr,
+ jobject,
+ jmethodid,
+ "..."]).ptr},
+ {CallIntMethodV: ctypes.voidptr_t},
+ {CallIntMethodA: ctypes.voidptr_t},
+ {CallLongMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jlong,
+ [jenvptr,
+ jobject,
+ jmethodid,
+ "..."]).ptr},
+ {CallLongMethodV: ctypes.voidptr_t},
+ {CallLongMethodA: ctypes.voidptr_t},
+ {CallFloatMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jfloat,
+ [jenvptr,
+ jobject,
+ jmethodid,
+ "..."]).ptr},
+ {CallFloatMethodV: ctypes.voidptr_t},
+ {CallFloatMethodA: ctypes.voidptr_t},
+ {CallDoubleMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jdouble,
+ [jenvptr,
+ jobject,
+ jmethodid,
+ "..."]).ptr},
+ {CallDoubleMethodV: ctypes.voidptr_t},
+ {CallDoubleMethodA: ctypes.voidptr_t},
+ {CallVoidMethod: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr,
+ jobject,
+ jmethodid,
+ "..."]).ptr},
+ {CallVoidMethodV: ctypes.voidptr_t},
+ {CallVoidMethodA: ctypes.voidptr_t},
+ {CallNonvirtualObjectMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jobject,
+ [jenvptr, jobject,
+ jclass, jmethodid,
+ "..."]).ptr},
+ {CallNonvirtualObjectMethodV: ctypes.voidptr_t},
+ {CallNonvirtualObjectMethodA: ctypes.voidptr_t},
+ {CallNonvirtualBooleanMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jboolean,
+ [jenvptr, jobject,
+ jclass, jmethodid,
+ "..."]).ptr},
+ {CallNonvirtualBooleanMethodV: ctypes.voidptr_t},
+ {CallNonvirtualBooleanMethodA: ctypes.voidptr_t},
+ {CallNonvirtualByteMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jbyte,
+ [jenvptr, jobject,
+ jclass, jmethodid,
+ "..."]).ptr},
+ {CallNonvirtualByteMethodV: ctypes.voidptr_t},
+ {CallNonvirtualByteMethodA: ctypes.voidptr_t},
+ {CallNonvirtualCharMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jchar,
+ [jenvptr, jobject,
+ jclass, jmethodid,
+ "..."]).ptr},
+ {CallNonvirtualCharMethodV: ctypes.voidptr_t},
+ {CallNonvirtualCharMethodA: ctypes.voidptr_t},
+ {CallNonvirtualShortMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jshort,
+ [jenvptr, jobject,
+ jclass, jmethodid,
+ "..."]).ptr},
+ {CallNonvirtualShortMethodV: ctypes.voidptr_t},
+ {CallNonvirtualShortMethodA: ctypes.voidptr_t},
+ {CallNonvirtualIntMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jint,
+ [jenvptr, jobject,
+ jclass, jmethodid,
+ "..."]).ptr},
+ {CallNonvirtualIntMethodV: ctypes.voidptr_t},
+ {CallNonvirtualIntMethodA: ctypes.voidptr_t},
+ {CallNonvirtualLongMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jlong,
+ [jenvptr, jobject,
+ jclass, jmethodid,
+ "..."]).ptr},
+ {CallNonvirtualLongMethodV: ctypes.voidptr_t},
+ {CallNonvirtualLongMethodA: ctypes.voidptr_t},
+ {CallNonvirtualFloatMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jfloat,
+ [jenvptr, jobject,
+ jclass, jmethodid,
+ "..."]).ptr},
+ {CallNonvirtualFloatMethodV: ctypes.voidptr_t},
+ {CallNonvirtualFloatMethodA: ctypes.voidptr_t},
+ {CallNonvirtualDoubleMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jdouble,
+ [jenvptr, jobject,
+ jclass, jmethodid,
+ "..."]).ptr},
+ {CallNonvirtualDoubleMethodV: ctypes.voidptr_t},
+ {CallNonvirtualDoubleMethodA: ctypes.voidptr_t},
+ {CallNonvirtualVoidMethod: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jobject,
+ jclass, jmethodid,
+ "..."]).ptr},
+ {CallNonvirtualVoidMethodV: ctypes.voidptr_t},
+ {CallNonvirtualVoidMethodA: ctypes.voidptr_t},
+ {GetFieldID: new ctypes.FunctionType(ctypes.default_abi,
+ jfieldid,
+ [jenvptr, jclass,
+ ctypes.char.ptr,
+ ctypes.char.ptr]).ptr},
+ {GetObjectField: new ctypes.FunctionType(ctypes.default_abi,
+ jobject,
+ [jenvptr, jobject,
+ jfieldid]).ptr},
+ {GetBooleanField: new ctypes.FunctionType(ctypes.default_abi,
+ jboolean,
+ [jenvptr, jobject,
+ jfieldid]).ptr},
+ {GetByteField: new ctypes.FunctionType(ctypes.default_abi,
+ jbyte,
+ [jenvptr, jobject,
+ jfieldid]).ptr},
+ {GetCharField: new ctypes.FunctionType(ctypes.default_abi,
+ jchar,
+ [jenvptr, jobject,
+ jfieldid]).ptr},
+ {GetShortField: new ctypes.FunctionType(ctypes.default_abi,
+ jshort,
+ [jenvptr, jobject,
+ jfieldid]).ptr},
+ {GetIntField: new ctypes.FunctionType(ctypes.default_abi,
+ jint,
+ [jenvptr, jobject,
+ jfieldid]).ptr},
+ {GetLongField: new ctypes.FunctionType(ctypes.default_abi,
+ jlong,
+ [jenvptr, jobject,
+ jfieldid]).ptr},
+ {GetFloatField: new ctypes.FunctionType(ctypes.default_abi,
+ jfloat,
+ [jenvptr, jobject,
+ jfieldid]).ptr},
+ {GetDoubleField: new ctypes.FunctionType(ctypes.default_abi,
+ jdouble,
+ [jenvptr, jobject,
+ jfieldid]).ptr},
+ {SetObjectField: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jobject,
+ jfieldid, jobject]).ptr},
+ {SetBooleanField: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jobject,
+ jfieldid, jboolean]).ptr},
+ {SetByteField: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jobject,
+ jfieldid, jbyte]).ptr},
+ {SetCharField: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jobject,
+ jfieldid, jchar]).ptr},
+ {SetShortField: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jobject,
+ jfieldid, jshort]).ptr},
+ {SetIntField: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jobject,
+ jfieldid, jint]).ptr},
+ {SetLongField: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jobject,
+ jfieldid, jlong]).ptr},
+ {SetFloatField: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jobject,
+ jfieldid, jfloat]).ptr},
+ {SetDoubleField: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jobject,
+ jfieldid, jdouble]).ptr},
+ {GetStaticMethodID: new ctypes.FunctionType(ctypes.default_abi,
+ jmethodid,
+ [jenvptr,
+ jclass,
+ ctypes.char.ptr,
+ ctypes.char.ptr]).ptr},
+ {CallStaticObjectMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jobject,
+ [jenvptr, jclass,
+ jmethodid,
+ "..."]).ptr},
+ {CallStaticObjectMethodV: ctypes.voidptr_t},
+ {CallStaticObjectMethodA: ctypes.voidptr_t},
+ {CallStaticBooleanMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jboolean,
+ [jenvptr, jclass,
+ jmethodid,
+ "..."]).ptr},
+ {CallStaticBooleanMethodV: ctypes.voidptr_t},
+ {CallStaticBooleanMethodA: ctypes.voidptr_t},
+ {CallStaticByteMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jbyte,
+ [jenvptr, jclass,
+ jmethodid,
+ "..."]).ptr},
+ {CallStaticByteMethodV: ctypes.voidptr_t},
+ {CallStaticByteMethodA: ctypes.voidptr_t},
+ {CallStaticCharMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jchar,
+ [jenvptr, jclass,
+ jmethodid,
+ "..."]).ptr},
+ {CallStaticCharMethodV: ctypes.voidptr_t},
+ {CallStaticCharMethodA: ctypes.voidptr_t},
+ {CallStaticShortMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jshort,
+ [jenvptr, jclass,
+ jmethodid,
+ "..."]).ptr},
+ {CallStaticShortMethodV: ctypes.voidptr_t},
+ {CallStaticShortMethodA: ctypes.voidptr_t},
+ {CallStaticIntMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jint,
+ [jenvptr, jclass,
+ jmethodid,
+ "..."]).ptr},
+ {CallStaticIntMethodV: ctypes.voidptr_t},
+ {CallStaticIntMethodA: ctypes.voidptr_t},
+ {CallStaticLongMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jlong,
+ [jenvptr, jclass,
+ jmethodid,
+ "..."]).ptr},
+ {CallStaticLongMethodV: ctypes.voidptr_t},
+ {CallStaticLongMethodA: ctypes.voidptr_t},
+ {CallStaticFloatMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jfloat,
+ [jenvptr, jclass,
+ jmethodid,
+ "..."]).ptr},
+ {CallStaticFloatMethodV: ctypes.voidptr_t},
+ {CallStaticFloatMethodA: ctypes.voidptr_t},
+ {CallStaticDoubleMethod: new ctypes.FunctionType(ctypes.default_abi,
+ jdouble,
+ [jenvptr, jclass,
+ jmethodid,
+ "..."]).ptr},
+ {CallStaticDoubleMethodV: ctypes.voidptr_t},
+ {CallStaticDoubleMethodA: ctypes.voidptr_t},
+ {CallStaticVoidMethod: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jclass,
+ jmethodid,
+ "..."]).ptr},
+ {CallStaticVoidMethodV: ctypes.voidptr_t},
+ {CallStaticVoidMethodA: ctypes.voidptr_t},
+ {GetStaticFieldID: new ctypes.FunctionType(ctypes.default_abi,
+ jfieldid,
+ [jenvptr, jclass,
+ ctypes.char.ptr,
+ ctypes.char.ptr]).ptr},
+ {GetStaticObjectField: new ctypes.FunctionType(ctypes.default_abi,
+ jobject,
+ [jenvptr, jclass,
+ jfieldid]).ptr},
+ {GetStaticBooleanField: new ctypes.FunctionType(ctypes.default_abi,
+ jboolean,
+ [jenvptr, jclass,
+ jfieldid]).ptr},
+ {GetStaticByteField: new ctypes.FunctionType(ctypes.default_abi,
+ jbyte,
+ [jenvptr, jclass,
+ jfieldid]).ptr},
+ {GetStaticCharField: new ctypes.FunctionType(ctypes.default_abi,
+ jchar,
+ [jenvptr, jclass,
+ jfieldid]).ptr},
+ {GetStaticShortField: new ctypes.FunctionType(ctypes.default_abi,
+ jshort,
+ [jenvptr, jclass,
+ jfieldid]).ptr},
+ {GetStaticIntField: new ctypes.FunctionType(ctypes.default_abi,
+ jint,
+ [jenvptr, jclass,
+ jfieldid]).ptr},
+ {GetStaticLongField: new ctypes.FunctionType(ctypes.default_abi,
+ jlong,
+ [jenvptr, jclass,
+ jfieldid]).ptr},
+ {GetStaticFloatField: new ctypes.FunctionType(ctypes.default_abi,
+ jfloat,
+ [jenvptr, jclass,
+ jfieldid]).ptr},
+ {GetStaticDoubleField: new ctypes.FunctionType(ctypes.default_abi,
+ jdouble,
+ [jenvptr, jclass,
+ jfieldid]).ptr},
+ {SetStaticObjectField: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jclass,
+ jfieldid, jobject]).ptr},
+ {SetStaticBooleanField: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jclass,
+ jfieldid, jboolean]).ptr},
+ {SetStaticByteField: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jclass,
+ jfieldid, jbyte]).ptr},
+ {SetStaticCharField: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jclass,
+ jfieldid, jchar]).ptr},
+ {SetStaticShortField: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jclass,
+ jfieldid, jshort]).ptr},
+ {SetStaticIntField: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jclass,
+ jfieldid, jint]).ptr},
+ {SetStaticLongField: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jclass,
+ jfieldid, jlong]).ptr},
+ {SetStaticFloatField: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jclass,
+ jfieldid, jfloat]).ptr},
+ {SetStaticDoubleField: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jclass,
+ jfieldid, jdouble]).ptr},
+
+ {NewString: new ctypes.FunctionType(ctypes.default_abi,
+ jstring,
+ [jenvptr, jchar.ptr, jsize]).ptr},
+ {GetStringLength: new ctypes.FunctionType(ctypes.default_abi,
+ jsize,
+ [jenvptr, jstring]).ptr},
+ {GetStringChars: new ctypes.FunctionType(ctypes.default_abi,
+ jchar.ptr,
+ [jenvptr, jstring,
+ jboolean.ptr]).ptr},
+ {ReleaseStringChars: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jstring,
+ jchar.ptr]).ptr},
+
+ {NewStringUTF: new ctypes.FunctionType(ctypes.default_abi,
+ jstring,
+ [jenvptr,
+ ctypes.char.ptr]).ptr},
+ {GetStringUTFLength: new ctypes.FunctionType(ctypes.default_abi,
+ jsize,
+ [jenvptr, jstring]).ptr},
+ {GetStringUTFChars: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.char.ptr,
+ [jenvptr, jstring,
+ jboolean.ptr]).ptr},
+ {ReleaseStringUTFChars: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jstring,
+ ctypes.char.ptr]).ptr},
+ {GetArrayLength: new ctypes.FunctionType(ctypes.default_abi,
+ jsize,
+ [jenvptr, jarray]).ptr},
+ {NewObjectArray: new ctypes.FunctionType(ctypes.default_abi,
+ jarray,
+ [jenvptr, jsize,
+ jclass, jobject]).ptr},
+ {GetObjectArrayElement: new ctypes.FunctionType(ctypes.default_abi,
+ jobject,
+ [jenvptr, jarray,
+ jsize]).ptr},
+ {SetObjectArrayElement: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jarray,
+ jsize, jobject]).ptr},
+ {NewBooleanArray: new ctypes.FunctionType(ctypes.default_abi,
+ jarray,
+ [jenvptr, jsize]).ptr},
+ {NewByteArray: new ctypes.FunctionType(ctypes.default_abi,
+ jarray,
+ [jenvptr, jsize]).ptr},
+ {NewCharArray: new ctypes.FunctionType(ctypes.default_abi,
+ jarray,
+ [jenvptr, jsize]).ptr},
+ {NewShortArray: new ctypes.FunctionType(ctypes.default_abi,
+ jarray,
+ [jenvptr, jsize]).ptr},
+ {NewIntArray: new ctypes.FunctionType(ctypes.default_abi,
+ jarray,
+ [jenvptr, jsize]).ptr},
+ {NewLongArray: new ctypes.FunctionType(ctypes.default_abi,
+ jarray,
+ [jenvptr, jsize]).ptr},
+ {NewFloatArray: new ctypes.FunctionType(ctypes.default_abi,
+ jarray,
+ [jenvptr, jsize]).ptr},
+ {NewDoubleArray: new ctypes.FunctionType(ctypes.default_abi,
+ jarray,
+ [jenvptr, jsize]).ptr},
+ {GetBooleanArrayElements: new ctypes.FunctionType(ctypes.default_abi,
+ jboolean.ptr,
+ [jenvptr, jarray,
+ jboolean.ptr]).ptr},
+ {GetByteArrayElements: new ctypes.FunctionType(ctypes.default_abi,
+ jbyte.ptr,
+ [jenvptr, jarray,
+ jboolean.ptr]).ptr},
+ {GetCharArrayElements: new ctypes.FunctionType(ctypes.default_abi,
+ jchar.ptr,
+ [jenvptr, jarray,
+ jboolean.ptr]).ptr},
+ {GetShortArrayElements: new ctypes.FunctionType(ctypes.default_abi,
+ jshort.ptr,
+ [jenvptr, jarray,
+ jboolean.ptr]).ptr},
+ {GetIntArrayElements: new ctypes.FunctionType(ctypes.default_abi,
+ jint.ptr,
+ [jenvptr, jarray,
+ jboolean.ptr]).ptr},
+ {GetLongArrayElements: new ctypes.FunctionType(ctypes.default_abi,
+ jlong.ptr,
+ [jenvptr, jarray,
+ jboolean.ptr]).ptr},
+ {GetFloatArrayElements: new ctypes.FunctionType(ctypes.default_abi,
+ jfloat.ptr,
+ [jenvptr, jarray,
+ jboolean.ptr]).ptr},
+ {GetDoubleArrayElements: new ctypes.FunctionType(ctypes.default_abi,
+ jdouble.ptr,
+ [jenvptr, jarray,
+ jboolean.ptr]).ptr},
+ {ReleaseBooleanArrayElements: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jarray,
+ jboolean.ptr,
+ jint]).ptr},
+ {ReleaseByteArrayElements: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jarray,
+ jbyte.ptr,
+ jint]).ptr},
+ {ReleaseCharArrayElements: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jarray,
+ jchar.ptr,
+ jint]).ptr},
+ {ReleaseShortArrayElements: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jarray,
+ jshort.ptr,
+ jint]).ptr},
+ {ReleaseIntArrayElements: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jarray,
+ jint.ptr,
+ jint]).ptr},
+ {ReleaseLongArrayElements: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jarray,
+ jlong.ptr,
+ jint]).ptr},
+ {ReleaseFloatArrayElements: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jarray,
+ jfloat.ptr,
+ jint]).ptr},
+ {ReleaseDoubleArrayElements: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jarray,
+ jdouble.ptr,
+ jint]).ptr},
+ {GetBooleanArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jarray,
+ jsize, jsize,
+ jboolean.array()]).ptr},
+ {GetByteArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jarray,
+ jsize, jsize,
+ jbyte.array()]).ptr},
+ {GetCharArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jarray,
+ jsize, jsize,
+ jchar.array()]).ptr},
+ {GetShortArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jarray,
+ jsize, jsize,
+ jshort.array()]).ptr},
+ {GetIntArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jarray,
+ jsize, jsize,
+ jint.array()]).ptr},
+ {GetLongArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jarray,
+ jsize, jsize,
+ jlong.array()]).ptr},
+ {GetFloatArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jarray,
+ jsize, jsize,
+ jfloat.array()]).ptr},
+ {GetDoubleArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jarray,
+ jsize, jsize,
+ jdouble.array()]).ptr},
+ {SetBooleanArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jarray,
+ jsize, jsize,
+ jboolean.array()]).ptr},
+ {SetByteArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jarray,
+ jsize, jsize,
+ jbyte.array()]).ptr},
+ {SetCharArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jarray,
+ jsize, jsize,
+ jchar.array()]).ptr},
+ {SetShortArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jarray,
+ jsize, jsize,
+ jshort.array()]).ptr},
+ {SetIntArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jarray,
+ jsize, jsize,
+ jint.array()]).ptr},
+ {SetLongArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jarray,
+ jsize, jsize,
+ jlong.array()]).ptr},
+ {SetFloatArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jarray,
+ jsize, jsize,
+ jfloat.array()]).ptr},
+ {SetDoubleArrayRegion: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jarray,
+ jsize, jsize,
+ jdouble.array()]).ptr},
+ {RegisterNatives: ctypes.voidptr_t},
+ {UnregisterNatives: ctypes.voidptr_t},
+ {MonitorEnter: new ctypes.FunctionType(ctypes.default_abi,
+ jint, [jenvptr, jobject]).ptr},
+ {MonitorExit: new ctypes.FunctionType(ctypes.default_abi,
+ jint, [jenvptr, jobject]).ptr},
+ {GetJavaVM: ctypes.voidptr_t},
+ {GetStringRegion: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jstring,
+ jsize, jsize,
+ jchar.array()]).ptr},
+ {GetStringUTFRegion: new ctypes.FunctionType(ctypes.default_abi,
+ ctypes.void_t,
+ [jenvptr, jstring,
+ jsize, jsize,
+ ctypes.char.array()]).ptr},
+ {GetPrimitiveArrayCritical: ctypes.voidptr_t},
+ {ReleasePrimitiveArrayCritical: ctypes.voidptr_t},
+ {GetStringCritical: ctypes.voidptr_t},
+ {ReleaseStringCritical: ctypes.voidptr_t},
+ {NewWeakGlobalRef: ctypes.voidptr_t},
+ {DeleteWeakGlobalRef: ctypes.voidptr_t},
+ {ExceptionCheck: new ctypes.FunctionType(ctypes.default_abi,
+ jboolean, [jenvptr]).ptr},
+ {NewDirectByteBuffer: ctypes.voidptr_t},
+ {GetDirectBufferAddress: ctypes.voidptr_t},
+ {GetDirectBufferCapacity: ctypes.voidptr_t},
+ {GetObjectRefType: ctypes.voidptr_t}]
+);
+
+var GetJNIForThread = libxul.declare("GetJNIForThread",
+ ctypes.default_abi,
+ JNINativeInterface.ptr.ptr);
+
+var registry = Object.create(null);
+var classes = Object.create(null);
+
+function JNIUnloadClasses(jenv) {
+ Object.getOwnPropertyNames(registry).forEach(function(classname) {
+ var jcls = unwrap(registry[classname]);
+ jenv.contents.contents.DeleteGlobalRef(jenv, jcls);
+
+ // Purge the registry, so we don't try to reuse stale global references
+ // in JNI calls and we garbage-collect the JS global reference objects.
+ delete registry[classname];
+ });
+
+ // The refs also get added to the 'classes' object, so we should purge it too.
+ // That object is a hierarchical data structure organized by class path parts,
+ // but deleting its own properties should be sufficient to break its refs.
+ Object.getOwnPropertyNames(classes).forEach(function(topLevelPart) {
+ delete classes[topLevelPart];
+ });
+}
+
+var PREFIX = 'js#';
+// this regex matches one component of a type signature:
+// any number of array modifiers, followed by either a
+// primitive type character or L<classname>;
+var sigRegex = () => /\[*([VZBCSIJFD]|L([^.\/;]+(\/[^.\/;]+)*);)/g;
+var ensureSig = function(classname_or_signature) {
+ // convert a classname into a signature,
+ // leaving unchanged signatures. We assume that
+ // anything not a valid signature is a classname.
+ var m = sigRegex().exec(classname_or_signature);
+ return (m && m[0] === classname_or_signature) ? classname_or_signature :
+ 'L' + classname_or_signature.replace(/\./g, '/') + ';';
+};
+var wrap = function(obj, classSig) {
+ if (!classSig) { return obj; }
+ // don't wrap primitive types.
+ if (classSig.charAt(0)!=='L' &&
+ classSig.charAt(0)!=='[') { return obj; }
+ var proto = registry[classSig][PREFIX+'proto'];
+ return new proto(obj);
+};
+var unwrap = function(obj, opt_jenv, opt_ctype) {
+ if (obj && typeof(obj)==='object' && (PREFIX+'obj') in obj) {
+ return obj[PREFIX+'obj'];
+ } else if (opt_jenv && opt_ctype) {
+ if (opt_ctype !== jobject)
+ return opt_ctype(obj); // cast to given primitive ctype
+ if (typeof(obj)==='string')
+ return unwrap(JNINewString(opt_jenv, obj)); // create Java String
+ }
+ return obj;
+};
+var ensureLoaded = function(jenv, classSig) {
+ if (!Object.hasOwnProperty.call(registry, classSig)) {
+ JNILoadClass(jenv, classSig);
+ }
+ return registry[classSig];
+};
+
+function JNINewString(jenv, value) {
+ var s = jenv.contents.contents.NewStringUTF(jenv, ctypes.char.array()(value));
+ ensureLoaded(jenv, "Ljava/lang/String;");
+ return wrap(s, "Ljava/lang/String;");
+}
+
+function JNIReadString(jenv, jstring_value) {
+ var val = unwrap(jstring_value);
+ if ((!val) || val.isNull()) { return null; }
+ var chars = jenv.contents.contents.GetStringUTFChars(jenv, val, null);
+ var result = chars.readString();
+ jenv.contents.contents.ReleaseStringUTFChars(jenv, val, chars);
+ return result;
+}
+
+var sigInfo = {
+ 'V': { name: 'Void', longName: 'Void', ctype: ctypes.void_t },
+ 'Z': { name: 'Boolean', longName: 'Boolean', ctype: jboolean },
+ 'B': { name: 'Byte', longName: 'Byte', ctype: jbyte },
+ 'C': { name: 'Char', longName: 'Char', ctype: jchar },
+ 'S': { name: 'Short', longName: 'Short', ctype: jshort },
+ 'I': { name: 'Int', longName: 'Integer', ctype: jint },
+ 'J': { name: 'Long', longName: 'Long', ctype: jlong },
+ 'F': { name: 'Float', longName: 'Float', ctype: jfloat },
+ 'D': { name: 'Double', longName: 'Double', ctype: jdouble },
+ 'L': { name: 'Object', longName: 'Object', ctype: jobject },
+ '[': { name: 'Object', longName: 'Object', ctype: jarray }
+};
+
+var sig2type = function(sig) { return sigInfo[sig.charAt(0)].name; };
+var sig2ctype = function(sig) { return sigInfo[sig.charAt(0)].ctype; };
+var sig2prim = function(sig) { return sigInfo[sig.charAt(0)].longName; };
+
+// return the class object for a signature string.
+// allocates 1 or 2 local refs
+function JNIClassObj(jenv, classSig) {
+ var jenvpp = function() { return jenv.contents.contents; };
+ // Deal with funny calling convention of JNI FindClass method.
+ // Classes get the leading & trailing chars stripped; primitives
+ // have to be looked up via their wrapper type.
+ var prim = function(ty) {
+ var jcls = jenvpp().FindClass(jenv, "java/lang/"+ty);
+ var jfld = jenvpp().GetStaticFieldID(jenv, jcls, "TYPE",
+ "Ljava/lang/Class;");
+ return jenvpp().GetStaticObjectField(jenv, jcls, jfld);
+ };
+ switch (classSig.charAt(0)) {
+ case '[':
+ return jenvpp().FindClass(jenv, classSig);
+ case 'L':
+ classSig = classSig.substring(1, classSig.indexOf(';'));
+ return jenvpp().FindClass(jenv, classSig);
+ default:
+ return prim(sig2prim(classSig));
+ }
+}
+
+// return the signature string for a Class object.
+// allocates 2 local refs
+function JNIClassSig(jenv, jcls) {
+ var jenvpp = function() { return jenv.contents.contents; };
+ var jclscls = jenvpp().FindClass(jenv, "java/lang/Class");
+ var jmtd = jenvpp().GetMethodID(jenv, jclscls,
+ "getName", "()Ljava/lang/String;");
+ var name = jenvpp().CallObjectMethod(jenv, jcls, jmtd);
+ name = JNIReadString(jenv, name);
+ // API is weird. Make sure we're using slashes not dots
+ name = name.replace(/\./g, '/');
+ // special case primitives, arrays
+ if (name.charAt(0)==='[') return name;
+ switch(name) {
+ case 'void': return 'V';
+ case 'boolean': return 'Z';
+ case 'byte': return 'B';
+ case 'char': return 'C';
+ case 'short': return 'S';
+ case 'int': return 'I';
+ case 'long': return 'J';
+ case 'float': return 'F';
+ case 'double': return 'D';
+ default:
+ return 'L' + name + ';';
+ }
+}
+
+// create dispatch method
+// we resolve overloaded methods only by # of arguments. If you need
+// further resolution, use the 'long form' of the method name, ie:
+// obj['toString()Ljava/lang/String'].call(obj);
+var overloadFunc = function(basename) {
+ return function() {
+ return this[basename+'('+arguments.length+')'].apply(this, arguments);
+ };
+};
+
+// Create appropriate wrapper fields/methods for a Java class.
+function JNILoadClass(jenv, classSig, opt_props) {
+ var jenvpp = function() { return jenv.contents.contents; };
+ var props = opt_props || {};
+
+ // allocate a local reference frame with enough space
+ // this class (1 or 2 local refs) plus superclass (3 refs)
+ // plus array element class (1 or 2 local refs)
+ var numLocals = 7;
+ jenvpp().PushLocalFrame(jenv, numLocals);
+
+ var jcls;
+ if (Object.hasOwnProperty.call(registry, classSig)) {
+ jcls = unwrap(registry[classSig]);
+ } else {
+ jcls = jenvpp().NewGlobalRef(jenv, JNIClassObj(jenv, classSig));
+
+ // get name of superclass
+ var jsuper = jenvpp().GetSuperclass(jenv, jcls);
+ if (jsuper.isNull()) {
+ jsuper = null;
+ } else {
+ jsuper = JNIClassSig(jenv, jsuper);
+ }
+
+ registry[classSig] = Object.create(jsuper?ensureLoaded(jenv, jsuper):null);
+ registry[classSig][PREFIX+'obj'] = jcls; // global ref, persistent.
+ registry[classSig][PREFIX+'proto'] =
+ function(o) { this[PREFIX+'obj'] = o; };
+ registry[classSig][PREFIX+'proto'].prototype =
+ Object.create(jsuper ?
+ ensureLoaded(jenv, jsuper)[PREFIX+'proto'].prototype :
+ null);
+ // Add a __cast__ method to the wrapper corresponding to the class
+ registry[classSig].__cast__ = function(obj) {
+ return wrap(unwrap(obj), classSig);
+ };
+
+ // make wrapper accessible via the classes object.
+ var path = sig2type(classSig).toLowerCase();
+ if (classSig.charAt(0)==='L') {
+ path = classSig.substring(1, classSig.length-1);
+ }
+ if (classSig.charAt(0)!=='[') {
+ var root = classes, i;
+ var parts = path.split('/');
+ for (i = 0; i < parts.length-1; i++) {
+ if (!Object.hasOwnProperty.call(root, parts[i])) {
+ root[parts[i]] = Object.create(null);
+ }
+ root = root[parts[i]];
+ }
+ root[parts[parts.length-1]] = registry[classSig];
+ }
+ }
+
+ var r = registry[classSig];
+ var rpp = r[PREFIX+'proto'].prototype;
+
+ if (classSig.charAt(0)==='[') {
+ // add 'length' field for arrays
+ Object.defineProperty(rpp, 'length', {
+ get: function() {
+ return jenvpp().GetArrayLength(jenv, unwrap(this));
+ }
+ });
+ // add 'get' and 'set' methods, 'new' constructor
+ var elemSig = classSig.substring(1);
+ ensureLoaded(jenv, elemSig);
+
+ registry[elemSig].__array__ = r;
+ if (!Object.hasOwnProperty.call(registry[elemSig], 'array'))
+ registry[elemSig].array = r;
+
+ if (elemSig.charAt(0)==='L' || elemSig.charAt(0)==='[') {
+ var elemClass = unwrap(registry[elemSig]);
+
+ rpp.get = function(idx) {
+ return wrap(jenvpp().GetObjectArrayElement(jenv, unwrap(this), idx),
+ elemSig);
+ };
+ rpp.set = function(idx, value) {
+ jenvpp().SetObjectArrayElement(jenv, unwrap(this), idx,
+ unwrap(value, jenv, jobject));
+ };
+ rpp.getElements = function(start, len) {
+ var i, r=[];
+ for (i=0; i<len; i++) { r.push(this.get(start+i)); }
+ return r;
+ };
+ rpp.setElements = function(start, vals) {
+ vals.forEach(function(v, i) { this.set(start+i, v); }.bind(this));
+ };
+ r['new'] = function(length) {
+ return wrap(jenvpp().NewObjectArray(jenv, length, elemClass, null),
+ classSig);
+ };
+ } else {
+ var ty = sig2type(elemSig), ctype = sig2ctype(elemSig);
+ var constructor = "New"+ty+"Array";
+ var getter = "Get"+ty+"ArrayRegion";
+ var setter = "Set"+ty+"ArrayRegion";
+ rpp.get = function(idx) { return this.getElements(idx, 1)[0]; };
+ rpp.set = function(idx, val) { this.setElements(idx, [val]); };
+ rpp.getElements = function(start, len) {
+ var j = jenvpp();
+ var buf = new (ctype.array())(len);
+ j[getter].call(j, jenv, unwrap(this), start, len, buf);
+ return buf;
+ };
+ rpp.setElements = function(start, vals) {
+ var j = jenvpp();
+ j[setter].call(j, jenv, unwrap(this), start, vals.length,
+ ctype.array()(vals));
+ };
+ r['new'] = function(length) {
+ var j = jenvpp();
+ return wrap(j[constructor].call(j, jenv, length), classSig);
+ };
+ }
+ }
+
+ (props.static_fields || []).forEach(function(fld) {
+ var jfld = jenvpp().GetStaticFieldID(jenv, jcls, fld.name, fld.sig);
+ var ty = sig2type(fld.sig), nm = fld.sig;
+ var getter = "GetStatic"+ty+"Field", setter = "SetStatic"+ty+"Field";
+ ensureLoaded(jenv, nm);
+ var props = {
+ get: function() {
+ var j = jenvpp();
+ return wrap(j[getter].call(j, jenv, jcls, jfld), nm);
+ },
+ set: function(newValue) {
+ var j = jenvpp();
+ j[setter].call(j, jenv, jcls, jfld, unwrap(newValue));
+ }
+ };
+ Object.defineProperty(r, fld.name, props);
+ // add static fields to object instances, too.
+ Object.defineProperty(rpp, fld.name, props);
+ });
+ (props.static_methods || []).forEach(function(mtd) {
+ var jmtd = jenvpp().GetStaticMethodID(jenv, jcls, mtd.name, mtd.sig);
+ var argctypes = mtd.sig.match(sigRegex()).map(s => sig2ctype(s));
+ var returnSig = mtd.sig.substring(mtd.sig.indexOf(')')+1);
+ var ty = sig2type(returnSig), nm = returnSig;
+ var call = "CallStatic"+ty+"Method";
+ ensureLoaded(jenv, nm);
+ r[mtd.name] = rpp[mtd.name] = overloadFunc(mtd.name);
+ r[mtd.name + mtd.sig] = r[mtd.name+'('+(argctypes.length-1)+')'] =
+ // add static methods to object instances, too.
+ rpp[mtd.name + mtd.sig] = rpp[mtd.name+'('+(argctypes.length-1)+')'] = function() {
+ var i, j = jenvpp();
+ var args = [jenv, jcls, jmtd];
+ for (i=0; i<arguments.length; i++) {
+ args.push(unwrap(arguments[i], jenv, argctypes[i]));
+ }
+ return wrap(j[call].apply(j, args), nm);
+ };
+ });
+ (props.constructors || []).forEach(function(mtd) {
+ mtd.name = "<init>";
+ var jmtd = jenvpp().GetMethodID(jenv, jcls, mtd.name, mtd.sig);
+ var argctypes = mtd.sig.match(sigRegex()).map(s => sig2ctype(s));
+ var returnSig = mtd.sig.substring(mtd.sig.indexOf(')')+1);
+
+ r['new'] = overloadFunc('new');
+ r['new'+mtd.sig] = r['new('+(argctypes.length-1)+')'] = function() {
+ var i, j = jenvpp();
+ var args = [jenv, jcls, jmtd];
+ for (i=0; i<arguments.length; i++) {
+ args.push(unwrap(arguments[i], jenv, argctypes[i]));
+ }
+ return wrap(j.NewObject.apply(j, args), classSig);
+ };
+ });
+ (props.fields || []).forEach(function(fld) {
+ var jfld = jenvpp().GetFieldID(jenv, jcls, fld.name, fld.sig);
+ var ty = sig2type(fld.sig), nm = fld.sig;
+ var getter = "Get"+ty+"Field", setter = "Set"+ty+"Field";
+ ensureLoaded(jenv, nm);
+ Object.defineProperty(rpp, fld.name, {
+ get: function() {
+ var j = jenvpp();
+ return wrap(j[getter].call(j, jenv, unwrap(this), jfld), nm);
+ },
+ set: function(newValue) {
+ var j = jenvpp();
+ j[setter].call(j, jenv, unwrap(this), jfld, unwrap(newValue));
+ }
+ });
+ });
+ (props.methods || []).forEach(function(mtd) {
+ var jmtd = jenvpp().GetMethodID(jenv, jcls, mtd.name, mtd.sig);
+ var argctypes = mtd.sig.match(sigRegex()).map(s => sig2ctype(s));
+ var returnSig = mtd.sig.substring(mtd.sig.indexOf(')')+1);
+ var ty = sig2type(returnSig), nm = returnSig;
+ var call = "Call"+ty+"Method";
+ ensureLoaded(jenv, nm);
+ rpp[mtd.name] = overloadFunc(mtd.name);
+ rpp[mtd.name + mtd.sig] = rpp[mtd.name+'('+(argctypes.length-1)+')'] = function() {
+ var i, j = jenvpp();
+ var args = [jenv, unwrap(this), jmtd];
+ for (i=0; i<arguments.length; i++) {
+ args.push(unwrap(arguments[i], jenv, argctypes[i]));
+ }
+ return wrap(j[call].apply(j, args), nm);
+ };
+ });
+ jenvpp().PopLocalFrame(jenv, null);
+ return r;
+}
+
+// exported object
+var JNI = {
+ // primitive types
+ jboolean: jboolean,
+ jbyte: jbyte,
+ jchar: jchar,
+ jshort: jshort,
+ jint: jint,
+ jlong: jlong,
+ jfloat: jfloat,
+ jdouble: jdouble,
+ jsize: jsize,
+
+ // class registry
+ classes: classes,
+
+ // methods
+ GetForThread: GetJNIForThread,
+ NewString: JNINewString,
+ ReadString: JNIReadString,
+ LoadClass: function(jenv, classname_or_signature, props) {
+ return JNILoadClass(jenv, ensureSig(classname_or_signature), props);
+ },
+ UnloadClasses: JNIUnloadClasses
+};