mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
1168 lines
61 KiB
JavaScript
1168 lines
61 KiB
JavaScript
// 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
|
|
};
|