186 строки
5.7 KiB
JavaScript
186 строки
5.7 KiB
JavaScript
mergeInto(LibraryManager.library, {
|
|
$EmJVM: {
|
|
debug: false,
|
|
|
|
nextId: 0,
|
|
objects: {},
|
|
classNames: {}, // class name => singleton object
|
|
|
|
addObject: function(o) {
|
|
var ret = EmJVM.nextId++;
|
|
EmJVM.objects[ret] = o;
|
|
o.id = ret;
|
|
o.refs = 1;
|
|
o.nextMethodId = 0;
|
|
// XXX Module.print('add object ' + JSON.stringify(o).substr(0, 80) + (ret > 5285 ? new Error().stack : ''));
|
|
return ret;
|
|
},
|
|
|
|
addSingletonObject: function(o) {
|
|
EmJVM.classNames[o.name] = o;
|
|
return EmJVM.addObject(o);
|
|
},
|
|
|
|
createString: function(data) {
|
|
return EmJVM.addObject({ name: 'string', value: data });
|
|
},
|
|
|
|
createByteArray: function(data) {
|
|
return EmJVM.addObject({ name: 'byteArray', value: data });
|
|
},
|
|
|
|
// utils
|
|
|
|
widecharToString: function(ptr, len) {
|
|
var nullTerminated = typeof(len) == "undefined";
|
|
var ret = "";
|
|
var i = 0;
|
|
var t;
|
|
while (1) {
|
|
t = getValue(ptr + 2 * i, 'i16');
|
|
if (nullTerminated && t == 0) break;
|
|
if (t != 0) {
|
|
ret += String.fromCharCode(t);
|
|
}
|
|
++i;
|
|
if (!nullTerminated && i == len) break;
|
|
};
|
|
return ret;
|
|
},
|
|
},
|
|
|
|
emjvm_newString__deps: ['$EmJVM'],
|
|
emjvm_newString: function(chars, len) {
|
|
return EmJVM.createString(EmJVM.widecharToString(chars, len));
|
|
},
|
|
|
|
emjvm_getStringUTFChars: function(jniEnv, string, isCopy) {
|
|
var obj = EmJVM.objects[string];
|
|
assert(obj.name == 'string');
|
|
if (isCopy) setValue(isCopy, 'i8', 1);
|
|
var buffer = _malloc(obj.value.length+1);
|
|
writeStringToMemory(obj.value, buffer);
|
|
return buffer;
|
|
},
|
|
|
|
emjvm_getStringUTFLength: function(jniEnv, string) {
|
|
var obj = EmJVM.objects[string];
|
|
if (obj.value) {
|
|
return obj.value.length;
|
|
}
|
|
return 0;
|
|
},
|
|
|
|
emjvm_releaseStringUTFChars: function(jniEnv, string, utf) {
|
|
},
|
|
|
|
emjvm_getObjectClass__deps: ['$EmJVM'],
|
|
emjvm_getObjectClass: function(env, jobject) {
|
|
if (EmJVM.debug) {
|
|
console.log('EMJVM_GetObjectClass+AddLocalRef: ' + [jobject]);
|
|
}
|
|
var obj = EmJVM.objects[jobject];
|
|
obj.refs++;
|
|
return jobject;
|
|
},
|
|
|
|
emjvm_getMethodID: function(jclass, name, sig) {
|
|
if (EmJVM.debug) {
|
|
console.log('EMJVM_GetMethodID: ' + [jclass, Pointer_stringify(name), Pointer_stringify(sig)]);
|
|
console.log('EMJVM_GetMethodID: ' + [EmJVM.objects[jclass].name]);
|
|
}
|
|
// assumes class <--> object, just called on singletons
|
|
name = Pointer_stringify(name);
|
|
var obj = EmJVM.objects[jclass];
|
|
if (!obj[name]) {
|
|
throw 'missing implementation for ' + obj.name + '::' + name + ' : ' + new Error().stack;
|
|
}
|
|
if (!obj[name + '__methodId']) {
|
|
var methodId = obj.nextMethodId++;
|
|
obj[name + '__methodId'] = methodId;
|
|
obj['method__' + methodId] = obj[name];
|
|
obj['methodName__' + methodId] = name;
|
|
}
|
|
return obj[name + '__methodId'];
|
|
},
|
|
|
|
emjvm_getStaticMethodID: function(jniEnv, jclass, name, sig) {
|
|
// Pretend this to be the same as looking up a non-static method
|
|
return _emjvm_getMethodID(jclass, name, sig);
|
|
},
|
|
|
|
emjvm_callObjectMethod: function(jniEnv, jobject, methodId, varargs) {
|
|
if (EmJVM.debug) {
|
|
console.log('EMJVM_CallObjectMethod: ' + [jobject, EmJVM.objects[jobject].name, methodId, EmJVM.objects[jobject]['methodName__' + methodId]]);
|
|
}
|
|
return EmJVM.objects[jobject]['method__' + methodId](varargs);
|
|
},
|
|
|
|
emjvm_callStaticObjectMethod: function(jniEnv, jclass, methodId, varargs) {
|
|
// Pretend this to be the same as calling a non-static method
|
|
return _emjvm_callObjectMethod(jniEnv, jclass, methodId, varargs);
|
|
},
|
|
|
|
emjvm_callStaticBooleanMethod: function(jniEnv, jclass, methodId, varargs) {
|
|
// Only differs in return type
|
|
return _emjvm_callStaticObjectMethod(jniEnv, jclass, methodId, varargs);
|
|
},
|
|
|
|
emjvm_callBooleanMethod: function(jniEnv, jobject, methodId, varargs) {
|
|
// Pretend this to be the same as calling a non-static method
|
|
return _emjvm_callStaticBooleanMethod(jniEnv, jobject, methodId, varargs);
|
|
},
|
|
|
|
emjvm_callVoidMethod: function(jniEnv, jobject, methodId, varargs) {
|
|
_emjvm_callObjectMethod(jniEnv, jobject, methodId, varargs);
|
|
},
|
|
|
|
emjvm_callIntMethod: function(jniEnv, jobject, methodId, varargs) {
|
|
return _emjvm_callObjectMethod(jniEnv, jobject, methodId, varargs);
|
|
},
|
|
|
|
emjvm_deleteLocalRef: function(jniEnv, jobject) {
|
|
if (EmJVM.debug) {
|
|
console.log('EMJVM_DeleteLocalRef: ' + [jobject]);
|
|
}
|
|
var obj = EmJVM.objects[jobject];
|
|
obj.refs--;
|
|
if (obj.refs == 0) {
|
|
if (EmJVM.debug) {
|
|
console.log('EMJVM_DeleteLocalRef: remove ' + obj.name);
|
|
}
|
|
delete EmJVM.objects[jobject];
|
|
}
|
|
},
|
|
|
|
emjvm_getArrayLength: function(jniEnv, jobject) {
|
|
var obj = EmJVM.objects[jobject];
|
|
assert(obj.name == 'byteArray');
|
|
return obj.value.length;
|
|
},
|
|
|
|
emjvm_getByteArrayRegion: function(jniEnv, jobject, start, len, buf) {
|
|
var obj = EmJVM.objects[jobject];
|
|
assert(obj.name == 'byteArray');
|
|
assert(obj.value); // we set this to null below and assume we are never called again
|
|
if (EmJVM.debug) {
|
|
console.log('emjvm_getByteArrayRegion: ' + [jobject, obj.value.length, start, len, buf]);
|
|
}
|
|
assert(start + len <= obj.value.length);
|
|
assert(len == obj.value.length); // we assume users read it all, and we can now copy it all with set() and then free it
|
|
HEAPU8.set(obj.value, buf);
|
|
obj.value = null; // XXX assume byte arrays are one-shot
|
|
},
|
|
|
|
emjvm_findClass: function(env, name) {
|
|
name = Pointer_stringify(name);
|
|
if (EmJVM.debug) {
|
|
console.log('emjvm_findClass: ' + [name]);
|
|
}
|
|
var obj = EmJVM.classNames[name];
|
|
assert(obj);
|
|
return obj.id;
|
|
},
|
|
});
|
|
|