pluotsorbet/native.js

728 строки
25 KiB
JavaScript
Исходник Обычный вид История

2014-07-13 01:07:11 +04:00
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set shiftwidth=4 tabstop=4 autoindent cindent expandtab: */
2014-09-05 22:36:46 +04:00
'use strict';
2014-07-13 01:07:11 +04:00
2014-07-21 08:32:47 +04:00
var Native = {};
2014-07-15 10:47:20 +04:00
Native.invoke = function(ctx, methodInfo) {
2014-07-21 09:08:08 +04:00
if (!methodInfo.native) {
var key = methodInfo.classInfo.className + "." + methodInfo.name + "." + methodInfo.signature;
2014-07-24 11:21:59 +04:00
methodInfo.native = Native[key];
if (!methodInfo.native) {
console.error("Missing native: " + key);
ctx.raiseExceptionAndYield("java/lang/RuntimeException", key + " not found");
}
2014-07-21 09:08:08 +04:00
}
methodInfo.native.call(null, ctx, ctx.current().stack);
2014-07-13 01:07:11 +04:00
}
Native["java/lang/System.arraycopy.(Ljava/lang/Object;ILjava/lang/Object;II)V"] = function(ctx, stack) {
var length = stack.pop(), dstOffset = stack.pop(), dst = stack.pop(), srcOffset = stack.pop(), src = stack.pop();
if (!src || !dst)
ctx.raiseExceptionAndYield("java/lang/NullPointerException", "Cannot copy to/from a null array.");
var srcClass = src.class;
var dstClass = dst.class;
if (!srcClass.isArrayClass || !dstClass.isArrayClass)
ctx.raiseExceptionAndYield("java/lang/ArrayStoreException", "Can only copy to/from array types.");
if (srcOffset < 0 || (srcOffset+length) > src.length || dstOffset < 0 || (dstOffset+length) > dst.length || length < 0)
ctx.raiseExceptionAndYield("java/lang/ArrayIndexOutOfBoundsException", "Invalid index.");
if ((!!srcClass.elementClass != !!dstClass.elementClass) ||
(!srcClass.elementClass && srcClass != dstClass)) {
ctx.raiseExceptionAndYield("java/lang/ArrayStoreException", "Incompatible component types.");
}
if (dstClass.elementClass) {
if (srcClass != dstClass && !srcClass.elementClass.isAssignableTo(dstClass.elementClass)) {
2014-09-05 22:36:46 +04:00
var copy = function(to, from) {
var obj = src[from];
if (obj && !obj.class.isAssignableTo(dstClass.elementClass))
ctx.raiseExceptionAndYield("java/lang/ArrayStoreException", "Incompatible component types.");
dst[to] = obj;
}
if (dst !== src || dstOffset < srcOffset) {
for (var n = 0; n < length; ++n)
copy(dstOffset++, srcOffset++);
} else {
dstOffset += length;
srcOffset += length;
for (var n = 0; n < length; ++n)
copy(--dstOffset, --srcOffset);
}
return;
}
}
2014-07-13 20:03:11 +04:00
if (dst !== src || dstOffset < srcOffset) {
for (var n = 0; n < length; ++n)
dst[dstOffset++] = src[srcOffset++];
} else {
dstOffset += length;
srcOffset += length;
for (var n = 0; n < length; ++n)
dst[--dstOffset] = src[--srcOffset];
2014-07-13 10:13:53 +04:00
}
}
2014-07-15 09:13:01 +04:00
Native["java/lang/System.getProperty0.(Ljava/lang/String;)Ljava/lang/String;"] = function(ctx, stack) {
var key = stack.pop();
var value;
2014-07-18 09:00:32 +04:00
switch (util.fromJavaString(key)) {
2014-07-15 09:13:01 +04:00
case "microedition.encoding":
value = "UTF-8";
break;
case "microedition.locale":
value = navigator.language;
break;
2014-08-02 06:37:12 +04:00
case "microedition.platform":
value = "NOKIA503/JAVA_RUNTIME_VERSION=NOKIA_ASHA_1_2";
break;
2014-08-08 07:35:02 +04:00
case "microedition.platformimpl":
value = "";
break;
case "microedition.profiles":
value = "MIDP-2.0"
break;
2014-08-02 07:25:58 +04:00
case "fileconn.dir.memorycard":
2014-08-08 00:35:59 +04:00
value = "fcfile:///";
2014-08-02 07:25:58 +04:00
break;
case "fileconn.dir.private":
2014-08-08 00:35:59 +04:00
value = "fcfile:///";
2014-08-05 08:51:46 +04:00
break;
2014-09-04 06:03:11 +04:00
case "fileconn.dir.applications.bookmarks":
value = "fcfile:///";
break;
case "fileconn.dir.received":
value = "fcfile:///";
break;
2014-09-20 04:17:47 +04:00
case "fileconn.dir.roots.names":
2014-09-20 04:18:25 +04:00
// The names here should be localized.
2014-09-20 04:17:47 +04:00
value = "Memory card;Phone memory;Private"
break;
case "fileconn.dir.roots.external":
2014-09-20 04:26:56 +04:00
value = "fcfile:///MemoryCard;fcfile:///;fcfile:///";
break;
case "fileconn.dir.photos.name":
value = "Photos";
break;
case "fileconn.dir.videos.name":
value = "Videos";
break;
case "fileconn.dir.recordings.name":
value = "Recordings";
2014-09-20 04:17:47 +04:00
break;
case "file.separator":
2014-08-05 08:51:46 +04:00
value = "/";
break;
2014-08-05 22:12:49 +04:00
case "com.sun.cldc.util.j2me.TimeZoneImpl.timezone":
// Date.toString() returns something like the following:
// "Wed Sep 17 2014 12:11:23 GMT-0700 (PDT)"
//
// Per http://www.spectrum3847.org/frc2013api/com/sun/cldc/util/j2me/TimeZoneImpl.html,
// timezones can be of the format GMT+0600, which is what this
// regex currently matches. (Those actually in GMT would not
// match the regex, causing the default "GMT" to be returned.)
// If we find this to be a problem, we could alternately return the
// zone name as provided in parenthesis, but that seems locale-specific.
var match = /GMT[+-]\d+/.exec(new Date().toString());
value = (match && match[0]) || "GMT";
2014-08-05 22:12:49 +04:00
break;
case "javax.microedition.io.Connector.protocolpath":
value = "com.sun.midp.io";
break;
case "javax.microedition.io.Connector.protocolpath.fallback":
value = "com.sun.cldc.io";
break;
case "com.nokia.keyboard.type":
value = "None";
break;
2014-08-08 07:35:02 +04:00
case "com.nokia.multisim.slots":
console.warn("Property 'com.nokia.multisim.slots' is a stub");
2014-08-08 07:35:02 +04:00
value = "1";
break;
case "com.nokia.multisim.imsi.sim2":
console.warn("Property 'com.nokia.multisim.imsi.sim2' is a stub");
value = null;
break;
2014-08-08 07:35:02 +04:00
case "com.nokia.mid.imsi":
console.warn("Property 'com.nokia.mid.imsi' is a stub");
2014-08-08 07:35:02 +04:00
value = "000000000000000";
break;
case "com.nokia.mid.ui.version":
console.warn("Property 'com.nokia.mid.ui.version' is a stub");
2014-08-08 07:35:02 +04:00
value = "1.6";
break;
case "com.nokia.mid.mnc":
// The concatenation of the MCC and MNC for the ICC (i.e. SIM card).
2014-09-06 03:06:38 +04:00
value = util.pad(mobileInfo.icc.mcc, 3) + util.pad(mobileInfo.icc.mnc, 3);
break;
case "com.nokia.mid.networkID":
// The concatenation of MCC and MNC for the network.
2014-09-06 03:06:38 +04:00
value = util.pad(mobileInfo.network.mcc, 3) + util.pad(mobileInfo.network.mnc, 3);
break;
case "com.nokia.mid.ui.customfontsize":
console.warn("Property 'com.nokia.mid.ui.customfontsize' is a stub");
value = "false";
break;
case "classpathext":
2014-08-08 20:41:58 +04:00
value = null;
break;
default:
console.warn("UNKNOWN PROPERTY (java/lang/System): " + util.fromJavaString(key));
break;
2014-07-15 09:13:01 +04:00
}
stack.push(value ? ctx.newString(value) : null);
2014-07-15 09:13:01 +04:00
}
2014-07-15 10:19:26 +04:00
Native["java/lang/System.currentTimeMillis.()J"] = function(ctx, stack) {
stack.push2(Long.fromNumber(Date.now()));
}
Native["com/sun/cldchi/jvm/JVM.unchecked_char_arraycopy.([CI[CII)V"] =
Native["com/sun/cldchi/jvm/JVM.unchecked_int_arraycopy.([II[III)V"] = function(ctx, stack) {
var length = stack.pop(), dstOffset = stack.pop(), dst = stack.pop(), srcOffset = stack.pop(), src = stack.pop();
dst.set(src.subarray(srcOffset, srcOffset + length), dstOffset);
}
Native["com/sun/cldchi/jvm/JVM.unchecked_obj_arraycopy.([Ljava/lang/Object;I[Ljava/lang/Object;II)V"] = function(ctx, stack) {
var length = stack.pop(), dstOffset = stack.pop(), dst = stack.pop(), srcOffset = stack.pop(), src = stack.pop();
2014-07-15 10:19:26 +04:00
if (dst !== src || dstOffset < srcOffset) {
for (var n = 0; n < length; ++n)
dst[dstOffset++] = src[srcOffset++];
} else {
dstOffset += length;
srcOffset += length;
for (var n = 0; n < length; ++n)
dst[--dstOffset] = src[--srcOffset];
}
}
2014-07-15 10:37:33 +04:00
Native["com/sun/cldchi/jvm/JVM.monotonicTimeMillis.()J"] = function(ctx, stack) {
stack.push2(Long.fromNumber(performance.now()));
}
Native["java/lang/Object.getClass.()Ljava/lang/Class;"] = function(ctx, stack) {
stack.push(stack.pop().class.getClassObject(ctx));
2014-07-18 10:02:28 +04:00
}
2014-07-28 11:53:37 +04:00
Native["java/lang/Object.hashCode.()I"] = function(ctx, stack) {
var obj = stack.pop();
var hashCode = obj.hashCode;
while (!hashCode)
hashCode = obj.hashCode = util.id();
stack.push(hashCode);
}
Native["java/lang/Object.wait.(J)V"] = function(ctx, stack) {
var timeout = stack.pop2(), obj = stack.pop();
2014-07-29 12:07:15 +04:00
ctx.wait(obj, timeout.toNumber());
2014-07-28 11:53:37 +04:00
}
2014-07-27 05:47:38 +04:00
2014-07-28 23:44:40 +04:00
Native["java/lang/Object.notify.()V"] = function(ctx, stack) {
var obj = stack.pop();
ctx.notify(obj);
}
Native["java/lang/Object.notifyAll.()V"] = function(ctx, stack) {
var obj = stack.pop();
2014-07-29 13:08:04 +04:00
ctx.notify(obj, true);
2014-07-28 23:44:40 +04:00
}
2014-07-26 22:42:02 +04:00
Native["java/lang/Class.invoke_clinit.()V"] = function(ctx, stack) {
var classObject = stack.pop();
var classInfo = classObject.vmClass;
2014-08-07 04:11:27 +04:00
var className = classInfo.className;
var runtime = ctx.runtime;
if (runtime.initialized[className] || runtime.pending[className])
return;
2014-08-07 04:11:27 +04:00
runtime.pending[className] = true;
2014-08-07 09:06:14 +04:00
if (className === "com/sun/cldc/isolate/Isolate") {
// The very first isolate is granted access to the isolate API.
ctx.runtime.setStatic(CLASSES.getField(classInfo, "_API_access_ok", "I", true), 1);
}
var clinit = CLASSES.getMethod(classInfo, "<clinit>.()V", true);
if (clinit)
ctx.pushFrame(clinit, 0);
if (classInfo.superClass)
ctx.pushClassInitFrame(classInfo.superClass);
2014-07-26 22:42:02 +04:00
throw VM.Yield;
}
Native["java/lang/Class.init9.()V"] = function(ctx, stack) {
var classObject = stack.pop();
var classInfo = classObject.vmClass;
2014-08-07 04:11:27 +04:00
var className = classInfo.className;
var runtime = ctx.runtime;
if (runtime.initialized[className])
return;
2014-08-07 04:11:27 +04:00
runtime.pending[className] = false;
runtime.initialized[className] = true;
2014-07-26 22:42:02 +04:00
}
Native["java/lang/Class.getName.()Ljava/lang/String;"] = function(ctx, stack) {
stack.push(ctx.newString(stack.pop().vmClass.className.replace(/\//g, ".")));
2014-07-18 10:02:28 +04:00
}
Native["java/lang/Class.forName.(Ljava/lang/String;)Ljava/lang/Class;"] = function(ctx, stack) {
var name = stack.pop();
2014-07-27 05:20:54 +04:00
try {
2014-08-01 02:01:10 +04:00
if (!name)
throw new Classes.ClassNotFoundException();
2014-08-02 22:27:25 +04:00
var className = util.fromJavaString(name).replace(/\./g, "/");
2014-08-01 02:01:10 +04:00
var classInfo = null;
2014-07-27 05:20:54 +04:00
classInfo = CLASSES.getClass(className);
} catch (e) {
if (e instanceof (Classes.ClassNotFoundException))
ctx.raiseExceptionAndYield("java/lang/ClassNotFoundException", "'" + className + "' not found.");
2014-07-27 05:20:54 +04:00
throw e;
2014-07-15 10:47:20 +04:00
}
stack.push(classInfo.getClassObject(ctx));
2014-07-15 10:47:20 +04:00
}
Native["java/lang/Class.newInstance.()Ljava/lang/Object;"] = function(ctx, stack) {
var classObject = stack.pop();
var className = classObject.vmClass.className;
var syntheticMethod = {
2014-09-22 12:46:49 +04:00
syntheticKey: "ClassNewInstanceSynthetic:" + className,
classInfo: {
constant_pool: [
2014-07-26 00:23:10 +04:00
null,
2014-07-29 15:26:03 +04:00
{ tag: TAGS.CONSTANT_Class, name_index: 2 },
{ bytes: className },
2014-07-29 15:26:03 +04:00
{ tag: TAGS.CONSTANT_Methodref, class_index: 1, name_and_type_index: 4 },
2014-07-26 00:23:10 +04:00
{ name_index: 5, signature_index: 6 },
{ bytes: "<init>" },
{ bytes: "()V" },
]
},
code: [
2014-07-26 00:23:10 +04:00
0xbb, 0x00, 0x01, // new <idx=1>
0x59, // dup
2014-07-26 00:23:10 +04:00
0xb7, 0x00, 0x03, // invokespecial <idx=3>
0xb0 // areturn
],
};
ctx.pushFrame(syntheticMethod, 0);
throw VM.Yield;
};
Native["java/lang/Class.isInterface.()Z"] = function(ctx, stack) {
var classObject = stack.pop();
2014-07-19 04:55:09 +04:00
var classInfo = classObject.vmClass;
stack.push(ACCESS_FLAGS.isInterface(classInfo.access_flags) ? 1 : 0);
2014-07-19 04:55:09 +04:00
}
Native["java/lang/Class.isArray.()Z"] = function(ctx, stack) {
var classObject = stack.pop();
2014-07-19 04:55:09 +04:00
var classInfo = classObject.vmClass;
stack.push(classInfo.isArrayClass ? 1 : 0);
2014-07-19 04:55:09 +04:00
}
Native["java/lang/Class.isAssignableFrom.(Ljava/lang/Class;)Z"] = function(ctx, stack) {
var fromClass = stack.pop(), classObject = stack.pop();
if (!fromClass)
ctx.raiseExceptionAndYield("java/lang/NullPointerException");
stack.push(fromClass.vmClass.isAssignableTo(classObject.vmClass) ? 1 : 0);
2014-07-19 04:55:09 +04:00
}
Native["java/lang/Class.isInstance.(Ljava/lang/Object;)Z"] = function(ctx, stack) {
var obj = stack.pop(), classObject = stack.pop();
stack.push((obj && obj.class.isAssignableTo(classObject.vmClass)) ? 1 : 0);
2014-07-19 04:55:09 +04:00
}
2014-07-26 04:54:34 +04:00
Native["java/lang/Float.floatToIntBits.(F)I"] = (function() {
2014-07-29 06:13:32 +04:00
var fa = new Float32Array(1);
var ia = new Int32Array(fa.buffer);
return function(ctx, stack) {
fa[0] = stack.pop();
stack.push(ia[0]);
2014-07-19 01:44:50 +04:00
}
})();
2014-07-26 00:28:26 +04:00
Native["java/lang/Double.doubleToLongBits.(D)J"] = (function() {
2014-07-29 06:13:32 +04:00
var da = new Float64Array(1);
var ia = new Int32Array(da.buffer);
2014-07-26 00:28:26 +04:00
return function(ctx, stack) {
da[0] = stack.pop2();
stack.push2(Long.fromBits(ia[0], ia[1]));
2014-07-19 01:44:50 +04:00
}
})();
2014-07-26 00:28:26 +04:00
Native["java/lang/Float.intBitsToFloat.(I)F"] = (function() {
2014-07-29 06:13:32 +04:00
var fa = new Float32Array(1);
var ia = new Int32Array(fa.buffer);
2014-07-26 00:28:26 +04:00
return function(ctx, stack) {
ia[0] = stack.pop();
stack.push(fa[0]);
}
})();
2014-07-26 00:28:26 +04:00
Native["java/lang/Double.longBitsToDouble.(J)D"] = (function() {
2014-07-29 06:13:32 +04:00
var da = new Float64Array(1);
var ia = new Int32Array(da.buffer);
2014-07-26 00:28:26 +04:00
return function(ctx, stack) {
var l = stack.pop2();
2014-07-19 05:33:12 +04:00
ia[0] = l.low_;
ia[1] = l.high_;
stack.push2(da[0]);
}
})();
Native["java/lang/Throwable.fillInStackTrace.()V"] = (function(ctx, stack) {
2014-07-31 02:49:58 +04:00
var throwable = stack.pop();
throwable.stackTrace = [];
ctx.frames.forEach(function(frame) {
if (!frame.methodInfo)
return;
var methodInfo = frame.methodInfo;
var methodName = methodInfo.name;
if (!methodName)
return;
2014-07-31 02:49:58 +04:00
var classInfo = methodInfo.classInfo;
var className = classInfo.className;
throwable.stackTrace.unshift({ className: className, methodName: methodName, offset: frame.ip });
});
2014-07-18 10:02:28 +04:00
});
Native["java/lang/Throwable.obtainBackTrace.()Ljava/lang/Object;"] = (function(ctx, stack) {
2014-07-31 02:49:58 +04:00
var obj = stack.pop();
var result = null;
if (obj.stackTrace) {
var depth = obj.stackTrace.length;
2014-08-07 00:52:18 +04:00
var classNames = ctx.newArray("[Ljava/lang/Object;", depth);
var methodNames = ctx.newArray("[Ljava/lang/Object;", depth);
var offsets = ctx.newPrimitiveArray("I", depth);
2014-07-31 02:49:58 +04:00
obj.stackTrace.forEach(function(e, n) {
classNames[n] = ctx.newString(e.className);
methodNames[n] = ctx.newString(e.methodName);
2014-07-31 02:49:58 +04:00
offsets[n] = e.offset;
});
2014-08-07 00:52:18 +04:00
result = ctx.newArray("[Ljava/lang/Object;", 3);
2014-07-31 02:49:58 +04:00
result[0] = classNames;
result[1] = methodNames;
result[2] = offsets;
}
stack.push(result);
2014-07-19 04:55:09 +04:00
});
Native["java/lang/Runtime.freeMemory.()J"] = function(ctx, stack) {
2014-07-26 00:42:44 +04:00
var runtime = stack.pop();
stack.push2(Long.fromInt(0x800000));
2014-07-19 20:23:14 +04:00
}
Native["java/lang/Runtime.totalMemory.()J"] = function(ctx, stack) {
2014-07-26 00:42:44 +04:00
var runtime = stack.pop();
stack.push2(Long.fromInt(0x1000000));
2014-07-19 20:23:14 +04:00
}
Native["java/lang/Runtime.gc.()V"] = function(ctx, stack) {
2014-07-26 00:42:44 +04:00
var runtime = stack.pop();
2014-07-19 20:23:14 +04:00
}
2014-07-27 02:00:19 +04:00
Native["java/lang/Math.floor.(D)D"] = function(ctx, stack) {
stack.push2(Math.floor(stack.pop2()));
}
Native["java/lang/Math.asin.(D)D"] = function(ctx, stack) {
stack.push2(Math.asin(stack.pop2()));
}
Native["java/lang/Math.acos.(D)D"] = function(ctx, stack) {
stack.push2(Math.acos(stack.pop2()));
}
Native["java/lang/Math.atan.(D)D"] = function(ctx, stack) {
stack.push2(Math.atan(stack.pop2()));
}
Native["java/lang/Math.atan2.(DD)D"] = function(ctx, stack) {
var y = stack.pop2(), x = stack.pop2();
stack.push2(Math.atan2(x, y));
}
Native["java/lang/Math.sin.(D)D"] = function(ctx, stack) {
stack.push2(Math.sin(stack.pop2()));
}
Native["java/lang/Math.cos.(D)D"] = function(ctx, stack) {
stack.push2(Math.cos(stack.pop2()));
}
Native["java/lang/Math.tan.(D)D"] = function(ctx, stack) {
stack.push2(Math.tan(stack.pop2()));
}
Native["java/lang/Math.sqrt.(D)D"] = function(ctx, stack) {
stack.push2(Math.sqrt(stack.pop2()));
}
Native["java/lang/Math.ceil.(D)D"] = function(ctx, stack) {
stack.push2(Math.ceil(stack.pop2()));
}
Native["java/lang/Math.floor.(D)D"] = function(ctx, stack) {
stack.push2(Math.floor(stack.pop2()));
}
2014-09-13 00:28:56 +04:00
var internedStrings = new Map();
2014-09-11 03:23:27 +04:00
Native["java/lang/String.intern.()Ljava/lang/String;"] = function(ctx, stack) {
2014-09-13 00:28:56 +04:00
var javaString = stack.pop();
var string = util.fromJavaString(javaString);
var internedString = internedStrings.get(string);
if (internedString) {
stack.push(internedString);
} else {
internedStrings.set(string, javaString);
stack.push(javaString);
}
2014-09-11 03:23:27 +04:00
}
Native["java/lang/Thread.currentThread.()Ljava/lang/Thread;"] = function(ctx, stack) {
stack.push(ctx.thread);
2014-07-20 11:35:00 +04:00
}
Native["java/lang/Thread.setPriority0.(II)V"] = function(ctx, stack) {
var newPriority = stack.pop(), oldPriority = stack.pop(), thread = stack.pop();
2014-07-20 11:35:00 +04:00
}
Native["java/lang/Thread.start0.()V"] = function(ctx, stack) {
var thread = stack.pop();
// The main thread starts during bootstrap and don't allow calling start()
// on already running threads.
2014-08-07 04:05:42 +04:00
if (thread === ctx.runtime.mainThread || thread.alive)
ctx.raiseExceptionAndYield("java/lang/IllegalThreadStateException");
2014-07-29 13:19:10 +04:00
thread.alive = true;
2014-07-28 11:53:37 +04:00
thread.pid = util.id();
2014-09-25 09:38:41 +04:00
var run = CLASSES.getMethod(thread.class, "run.()V", false);
2014-07-28 10:39:41 +04:00
// Create a context for the thread and start it.
2014-08-07 04:04:44 +04:00
var ctx = new Context(ctx.runtime);
2014-07-26 04:54:34 +04:00
ctx.thread = thread;
var caller = new Frame();
ctx.frames.push(caller);
2014-07-28 10:39:41 +04:00
caller.stack.push(thread);
var syntheticMethod = {
2014-09-22 12:46:49 +04:00
syntheticKey: "ThreadStart0Synthetic:" + thread.class.className + "." + run.name + "." + run.signature,
2014-07-28 10:39:41 +04:00
classInfo: {
constant_pool: [
null,
2014-07-29 15:26:03 +04:00
{ tag: TAGS.CONSTANT_Methodref, class_index: 2, name_and_type_index: 4 },
{ tag: TAGS.CONSTANT_Class, name_index: 3 },
2014-07-28 10:39:41 +04:00
{ bytes: "java/lang/Thread" },
2014-07-29 15:26:03 +04:00
{ tag: TAGS.CONSTANT_Methodref, name_index: 5, signature_index: 6 },
2014-07-28 10:39:41 +04:00
{ bytes: "run" },
{ bytes: "()V" },
2014-07-29 15:26:03 +04:00
{ tag: TAGS.CONSTANT_Methodref, class_index: 2, name_and_type_index: 8 },
2014-07-28 10:39:41 +04:00
{ name_index: 9, signature_index: 10 },
{ bytes: "internalExit" },
{ bytes: "()V" },
],
},
code: [
0x2a, // aload_0
0x59, // dup
2014-07-28 11:53:37 +04:00
0xb6, 0x00, 0x01, // invokespecial <idx=1>
2014-07-28 10:39:41 +04:00
0xb7, 0x00, 0x07, // invokespecial <idx=7>
0xb1, // return
],
exception_table: [],
};
ctx.pushFrame(syntheticMethod, 1);
2014-07-26 04:54:34 +04:00
ctx.start(caller);
2014-07-20 11:35:00 +04:00
}
2014-07-28 10:39:41 +04:00
Native["java/lang/Thread.internalExit.()V"] = function(ctx, stack) {
2014-07-29 13:19:10 +04:00
stack.pop().alive = false;
2014-07-28 10:39:41 +04:00
}
Native["java/lang/Thread.isAlive.()Z"] = function(ctx, stack) {
2014-07-29 13:19:10 +04:00
stack.push(stack.pop().alive ? 1 : 0);
2014-07-28 10:39:41 +04:00
}
2014-07-26 04:54:34 +04:00
Native["java/lang/Thread.sleep.(J)V"] = function(ctx, stack) {
var delay = stack.pop2().toNumber();
window.setTimeout(function() {
ctx.resume();
}, delay);
2014-07-29 02:19:07 +04:00
throw VM.Pause;
}
Native["java/lang/Thread.yield.()V"] = function(ctx, stack) {
throw VM.Yield;
2014-07-21 09:24:07 +04:00
}
Native["java/lang/Thread.activeCount.()I"] = function(ctx, stack) {
stack.push(ctx.runtime.threadCount);
}
Native["com/sun/cldchi/io/ConsoleOutputStream.write.(I)V"] = function(ctx, stack) {
var ch = stack.pop(), obj = stack.pop();
console.print(ch);
};
2014-07-19 04:55:09 +04:00
Native["com/sun/cldc/io/ResourceInputStream.open.(Ljava/lang/String;)Ljava/lang/Object;"] = function(ctx, stack) {
var name = stack.pop();
2014-07-19 04:55:09 +04:00
var fileName = util.fromJavaString(name);
var data = CLASSES.loadFile(fileName);
var obj = null;
if (data) {
obj = ctx.newObject(CLASSES.java_lang_Object);
obj.data = new Uint8Array(data);
obj.pos = 0;
}
stack.push(obj);
2014-07-19 04:55:09 +04:00
};
Native["com/sun/cldc/io/ResourceInputStream.bytesRemain.(Ljava/lang/Object;)I"] = function(ctx, stack) {
var handle = stack.pop();
stack.push(handle.data.length - handle.pos);
2014-07-19 04:55:09 +04:00
}
Native["com/sun/cldc/io/ResourceInputStream.readByte.(Ljava/lang/Object;)I"] = function(ctx, stack) {
var handle = stack.pop();
2014-08-06 04:40:13 +04:00
stack.push((handle.data.length - handle.pos > 0) ? handle.data[handle.pos++] : -1);
2014-07-19 04:55:09 +04:00
}
Native["com/sun/cldc/io/ResourceInputStream.readBytes.(Ljava/lang/Object;[BII)I"] = function(ctx, stack) {
var len = stack.pop(), off = stack.pop(), b = stack.pop(), handle = stack.pop();
2014-07-19 04:55:09 +04:00
var data = handle.data;
var remaining = data.length - handle.pos;
if (len > remaining)
2014-07-19 04:55:09 +04:00
len = remaining;
for (var n = 0; n < len; ++n)
b[off+n] = data[handle.pos+n];
2014-07-19 04:55:09 +04:00
handle.pos += len;
stack.push((len > 0) ? len : -1);
2014-07-19 04:55:09 +04:00
}
2014-07-19 05:23:49 +04:00
Native["com/sun/cldc/i18n/uclc/DefaultCaseConverter.toLowerCase.(C)C"] = function(ctx, stack) {
stack.push(String.fromCharCode(stack.pop()).toLowerCase().charCodeAt(0));
}
Native["com/sun/cldc/i18n/uclc/DefaultCaseConverter.toUpperCase.(C)C"] = function(ctx, stack) {
stack.push(String.fromCharCode(stack.pop()).toUpperCase().charCodeAt(0));
2014-07-19 05:23:49 +04:00
}
2014-08-01 09:59:34 +04:00
2014-08-05 20:34:00 +04:00
Native["java/lang/ref/WeakReference.initializeWeakReference.(Ljava/lang/Object;)V"] = function(ctx, stack) {
var target = stack.pop(), _this = stack.pop();
_this.target = target;
}
Native["java/lang/ref/WeakReference.get.()Ljava/lang/Object;"] = function(ctx, stack) {
var _this = stack.pop();
var target = _this.target;
stack.push(target ? target : null);
}
Native["java/lang/ref/WeakReference.clear.()V"] = function(ctx, stack) {
var _this = stack.pop();
_this.target = null;
}
2014-08-07 09:06:14 +04:00
Native["com/sun/cldc/isolate/Isolate.registerNewIsolate.()V"] = function(ctx, stack) {
var _this = stack.pop();
_this.id = util.id();
2014-08-07 09:43:05 +04:00
}
Native["com/sun/cldc/isolate/Isolate.getStatus.()I"] = function(ctx, stack) {
var _this = stack.pop();
stack.push(_this.runtime ? _this.runtime.status : 1); // NEW
2014-08-07 09:06:14 +04:00
}
2014-08-07 10:57:44 +04:00
Native["com/sun/cldc/isolate/Isolate.nativeStart.()V"] = function(ctx, stack) {
var _this = stack.pop();
2014-08-08 10:00:53 +04:00
ctx.runtime.vm.startIsolate(_this);
2014-08-07 22:46:11 +04:00
}
Native["com/sun/cldc/isolate/Isolate.waitStatus.(I)V"] = function(ctx, stack) {
var status = stack.pop(), _this = stack.pop();
var runtime = _this.runtime;
if (runtime.status >= status)
2014-08-07 22:46:11 +04:00
return;
function waitForStatus() {
if (runtime.status >= status) {
2014-08-07 22:46:11 +04:00
ctx.resume();
2014-08-07 23:12:57 +04:00
return;
2014-08-07 22:46:11 +04:00
}
2014-08-07 23:32:43 +04:00
runtime.waitStatus(waitForStatus);
2014-08-07 22:46:11 +04:00
}
2014-08-07 23:12:57 +04:00
waitForStatus();
2014-08-07 22:46:11 +04:00
}
2014-08-08 09:29:16 +04:00
Native["com/sun/cldc/isolate/Isolate.currentIsolate0.()Lcom/sun/cldc/isolate/Isolate;"] = function(ctx, stack) {
2014-08-09 00:41:42 +04:00
stack.push(ctx.runtime.isolate);
2014-08-08 09:29:16 +04:00
}
2014-08-09 00:04:40 +04:00
Native["com/sun/cldc/isolate/Isolate.getIsolates0.()[Lcom/sun/cldc/isolate/Isolate;"] = function(ctx, stack) {
var isolates = ctx.newArray("[Ljava/lang/Object;", Runtime.all.keys().length);
var n = 0;
Runtime.all.forEach(function (runtime) {
2014-08-12 04:13:50 +04:00
isolates[n++] = runtime.isolate;
2014-08-09 00:04:40 +04:00
});
stack.push(isolates);
}
Native["com/sun/cldc/isolate/Isolate.id0.()I"] = function(ctx, stack) {
var _this = stack.pop();
stack.push(_this.id);
}
2014-08-12 04:16:18 +04:00
Native["com/sun/cldc/isolate/Isolate.setPriority0.(I)V"] = function(ctx, stack) {
var _this = stack.pop();
}
2014-08-08 23:56:13 +04:00
var links = {};
var waitingForLinks = {};
Native["com/sun/midp/links/LinkPortal.getLinkCount0.()I"] = function(ctx, stack) {
var isolateId = ctx.runtime.isolate.id;
2014-08-09 00:07:52 +04:00
if (!links[isolateId]) {
2014-08-08 23:56:13 +04:00
waitingForLinks[isolateId] = function() {
2014-08-09 00:07:52 +04:00
stack.push(links[isolateId].length);
ctx.resume();
2014-08-08 23:56:13 +04:00
}
2014-08-09 00:07:52 +04:00
2014-08-08 23:56:13 +04:00
throw VM.Pause;
}
2014-08-09 00:07:52 +04:00
stack.push(links[isolateId].length);
2014-08-08 23:56:13 +04:00
}
Native["com/sun/midp/links/LinkPortal.getLinks0.([Lcom/sun/midp/links/Link;)V"] = function(ctx, stack) {
var linkArray = stack.pop();
2014-08-09 00:07:52 +04:00
2014-08-08 23:56:13 +04:00
var isolateId = ctx.runtime.isolate.id;
for (var i = 0; i < links[isolateId].length; i++) {
var nativePointer = links[isolateId][i].class.getField("nativePointer", "I").get(links[isolateId][i]);
linkArray[i].class.getField("nativePointer", "I").set(linkArray[i], nativePointer);
linkArray[i].sender = links[isolateId][i].sender;
linkArray[i].receiver = links[isolateId][i].receiver;
}
}
Native["com/sun/midp/links/LinkPortal.setLinks0.(I[Lcom/sun/midp/links/Link;)V"] = function(ctx, stack) {
var linkArray = stack.pop(), id = stack.pop();
links[id] = linkArray;
if (waitingForLinks[id]) {
waitingForLinks[id]();
}
}
Native["com/sun/midp/links/Link.init0.(II)V"] = function(ctx, stack) {
var receiver = stack.pop(), sender = stack.pop(), _this = stack.pop();
_this.sender = sender;
_this.receiver = receiver;
_this.class.getField("nativePointer", "I").set(_this, util.id());
}
Native["com/sun/midp/links/Link.receive0.(Lcom/sun/midp/links/LinkMessage;Lcom/sun/midp/links/Link;)V"] = function(ctx, stack) {
var link = stack.pop(), linkMessage = stack.pop(), _this = stack.pop();
// TODO: Implement when something hits send0
console.warn("Called com/sun/midp/links/Link.receive0.(Lcom/sun/midp/links/LinkMessage;Lcom/sun/midp/links/Link;)V");
2014-08-08 23:56:13 +04:00
throw VM.Pause;
}