pluotsorbet/native.js.in

800 строки
27 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
2015-05-16 21:08:48 +03:00
var asyncImpl = J2ME.asyncImplOld;
2015-03-24 01:56:38 +03:00
function preemptingImpl(returnKind, returnValue) {
if (J2ME.Scheduler.shouldPreempt()) {
asyncImpl(returnKind, Promise.resolve(returnValue));
return;
}
return returnValue;
}
var Override = {};
2014-07-15 10:47:20 +04:00
Native["java/lang/System.arraycopy.(Ljava/lang/Object;ILjava/lang/Object;II)V"] =
function(addr, srcAddr, srcOffset, dstAddr, dstOffset, length) {
2015-07-07 20:12:03 +03:00
if (srcAddr === J2ME.Constants.NULL || dstAddr === J2ME.Constants.NULL) {
throw $.newNullPointerException("Cannot copy to/from a null array.");
}
var src = getHandle(srcAddr);
var dst = getHandle(dstAddr);
2015-07-22 01:49:33 +03:00
var srcClassInfo = src.classInfo;
var dstClassInfo = dst.classInfo;
2015-07-22 01:49:33 +03:00
if (!(srcClassInfo instanceof J2ME.ArrayClassInfo) || !(dstClassInfo instanceof J2ME.ArrayClassInfo)) {
throw $.newArrayStoreException("Can only copy to/from array types.");
}
if (srcOffset < 0 || (srcOffset+length) > src.length || dstOffset < 0 || (dstOffset+length) > dst.length || length < 0) {
throw $.newArrayIndexOutOfBoundsException("Invalid index.");
}
2015-07-22 01:49:33 +03:00
var srcIsPrimitive = srcClassInfo instanceof J2ME.PrimitiveArrayClassInfo;
var dstIsPrimitive = dstClassInfo instanceof J2ME.PrimitiveArrayClassInfo;
if ((srcIsPrimitive && dstIsPrimitive && srcClassInfo !== dstClassInfo) ||
(srcIsPrimitive && !dstIsPrimitive) ||
(!srcIsPrimitive && dstIsPrimitive)) {
2015-07-22 01:49:33 +03:00
throw $.newArrayStoreException("Incompatible component types: " + srcClassInfo + " -> " + dstClassInfo);
}
if (!dstIsPrimitive) {
2015-07-22 01:49:33 +03:00
if (srcClassInfo !== dstClassInfo && !J2ME.isAssignableTo(srcClassInfo.elementClass, dstClassInfo.elementClass)) {
2014-09-05 22:36:46 +04:00
var copy = function(to, from) {
var addr = src[from];
var obj = getHandle(addr);
2015-07-22 01:49:33 +03:00
if (obj && !J2ME.isAssignableTo(obj.classInfo, dstClassInfo.elementClass)) {
throw $.newArrayStoreException("Incompatible component types.");
}
dst[to] = addr;
};
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;
}
}
2015-07-22 01:49:33 +03:00
if (srcAddr !== dstAddr || dstOffset < srcOffset) {
2014-07-13 20:03:11 +04:00
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-12-19 00:03:59 +03:00
};
2014-07-15 09:13:01 +04:00
var stubProperties = {
"com.nokia.multisim.slots": "1",
"com.nokia.mid.imsi": "000000000000000",
"com.nokia.mid.imei": "",
};
Native["java/lang/System.getProperty0.(Ljava/lang/String;)Ljava/lang/String;"] = function(addr, keyAddr) {
var key = J2ME.fromStringAddr(keyAddr);
var value;
switch (key) {
2014-07-15 09:13:01 +04:00
case "microedition.encoding":
2014-12-05 05:33:42 +03:00
// The value of this property is different than the value on a real Nokia Asha 503 phone.
// On the phone, it is: ISO8859_1.
// If we changed this, we would need to remove the optimizations for UTF_8_Reader and
// UTF_8_Writer and optimize the ISO8859_1 alternatives.
value = "UTF-8";
break;
case "microedition.io.file.FileConnection.version":
value = "1.0";
break;
case "microedition.locale":
value = navigator.language;
break;
2014-08-02 06:37:12 +04:00
case "microedition.platform":
value = config.platform ? config.platform : "Nokia503/14.0.4/java_runtime_version=Nokia_Asha_1_2";
2014-08-02 06:37:12 +04:00
break;
2014-08-08 07:35:02 +04:00
case "microedition.platformimpl":
value = null;
2014-08-08 07:35:02 +04:00
break;
case "microedition.profiles":
2014-12-05 05:33:42 +03:00
value = "MIDP-2.1"
break;
case "microedition.pim.version":
value = "1.0";
break;
2014-11-15 00:57:46 +03:00
case "microedition.amms.version":
value = "1.1";
break;
2014-11-19 05:55:19 +03:00
case "microedition.media.version":
value = '1.2';
break;
2014-11-15 00:58:48 +03:00
case "mmapi-configuration":
value = null;
break;
2014-08-02 07:25:58 +04:00
case "fileconn.dir.memorycard":
value = "file:///MemoryCard/";
break;
// The names here should be localized.
case "fileconn.dir.memorycard.name":
value = "Memory card";
2014-08-02 07:25:58 +04:00
break;
case "fileconn.dir.private":
value = "file:///Private/";
break;
case "fileconn.dir.private.name":
value = "Private";
2014-08-05 08:51:46 +04:00
break;
2014-09-04 06:03:11 +04:00
case "fileconn.dir.applications.bookmarks":
value = null;
2014-09-04 06:03:11 +04:00
break;
case "fileconn.dir.received":
value = "file:///Phone/_my_downloads/";
2014-10-31 13:31:02 +03:00
break;
case "fileconn.dir.received.name":
value = "Downloads";
2014-09-20 04:17:47 +04:00
break;
case "fileconn.dir.photos":
value = "file:///Phone/_my_pictures/";
2014-09-20 04:26:56 +04:00
break;
case "fileconn.dir.photos.name":
value = "Photos";
break;
case "fileconn.dir.videos":
value = "file:///Phone/_my_videos/";
break;
2014-09-20 04:26:56 +04:00
case "fileconn.dir.videos.name":
value = "Videos";
break;
case "fileconn.dir.recordings":
value = "file:///Phone/_my_recordings/";
break;
2014-09-20 04:26:56 +04:00
case "fileconn.dir.recordings.name":
value = "Recordings";
2014-09-20 04:17:47 +04:00
break;
case "fileconn.dir.roots.names":
value = MIDP.fsRootNames.join(";");
break;
case "fileconn.dir.roots.external":
value = MIDP.fsRoots.map(function(v) { return "file:///" + v }).join("\n");
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;
case "com.nokia.mid.batterylevel":
// http://developer.nokia.com/community/wiki/Checking_battery_level_in_Java_ME
value = Math.floor(navigator.battery.level * 100).toString();
break;
2014-08-08 07:35:02 +04:00
case "com.nokia.mid.ui.version":
2014-12-05 05:33:42 +03:00
value = "1.7";
2014-08-08 07:35:02 +04:00
break;
case "com.nokia.mid.mnc":
2015-01-27 03:51:23 +03:00
if (mobileInfo.icc.mcc && mobileInfo.icc.mnc) {
// The concatenation of the MCC and MNC for the ICC (i.e. SIM card).
value = util.pad(mobileInfo.icc.mcc, 3) + util.pad(mobileInfo.icc.mnc, 3);
} else {
value = null;
}
break;
case "com.nokia.mid.networkID":
2015-01-27 03:51:23 +03:00
if (mobileInfo.network.mcc && mobileInfo.network.mnc) {
// The concatenation of MCC and MNC for the network.
value = util.pad(mobileInfo.network.mcc, 3) + util.pad(mobileInfo.network.mnc, 3);
} else {
value = null;
}
break;
case "com.nokia.mid.ui.customfontsize":
2014-12-05 05:33:42 +03:00
value = "true";
break;
case "classpathext":
2014-08-08 20:41:58 +04:00
value = null;
break;
2014-11-19 05:55:19 +03:00
case "supports.audio.capture":
value = "true";
break;
2014-12-05 05:33:42 +03:00
case "supports.video.capture":
value = "true";
break;
2014-11-19 05:55:19 +03:00
case "supports.recording":
value = "true";
break;
case "audio.encodings":
value = "encoding=audio/amr";
2014-11-19 05:55:19 +03:00
break;
case "video.snapshot.encodings":
// FIXME Some MIDlets pass a string that contains lots of constraints
// as the `imageType` which is not yet handled in DirectVideo.jpp, let's
// just put the whole string here as a workaround and fix this in issue #688.
value = "encoding=jpeg&quality=80&progressive=true&type=jfif&width=400&height=400";
break;
default:
if (MIDP.additionalProperties[key]) {
value = MIDP.additionalProperties[key];
} else if (typeof stubProperties[key] !== "undefined") {
value = stubProperties[key];
} else {
console.warn("UNKNOWN PROPERTY (java/lang/System): " + key);
stubProperties[key] = value = null;
}
break;
}
2014-12-19 00:03:59 +03:00
return J2ME.newString(value);
};
2014-07-15 10:19:26 +04:00
Native["java/lang/System.currentTimeMillis.()J"] = function(addr) {
2015-05-20 03:49:48 +03:00
return J2ME.returnLongValue(Date.now());
2014-12-19 00:03:59 +03:00
};
Native["com/sun/cldchi/jvm/JVM.unchecked_char_arraycopy.([CI[CII)V"] =
function(addr, srcAddr, srcOffset, dstAddr, dstOffset, length) {
var src = (srcAddr + J2ME.Constants.ARRAY_HDR_SIZE >> 1) + srcOffset;
var dst = (dstAddr + J2ME.Constants.ARRAY_HDR_SIZE >> 1) + dstOffset;
i16.set(i16.subarray(src, src + length), dst);
2014-12-19 00:03:59 +03:00
};
Native["com/sun/cldchi/jvm/JVM.unchecked_int_arraycopy.([II[III)V"] =
function(addr, srcAddr, srcOffset, dstAddr, dstOffset, length) {
var src = (srcAddr + J2ME.Constants.ARRAY_HDR_SIZE >> 2) + srcOffset;
var dst = (dstAddr + J2ME.Constants.ARRAY_HDR_SIZE >> 2) + dstOffset;
i32.set(i32.subarray(src, src + length), dst);
2014-12-19 00:03:59 +03:00
};
Native["com/sun/cldchi/jvm/JVM.unchecked_obj_arraycopy.([Ljava/lang/Object;I[Ljava/lang/Object;II)V"] =
function(addr, srcAddr, srcOffset, dstAddr, dstOffset, length) {
var src = (srcAddr + J2ME.Constants.ARRAY_HDR_SIZE >> 2) + srcOffset;
var dst = (dstAddr + J2ME.Constants.ARRAY_HDR_SIZE >> 2) + dstOffset;
2015-07-22 01:49:33 +03:00
if (srcAddr !== dstAddr || dstOffset < srcOffset) {
for (var n = 0; n < length; ++n) {
i32[dst++] = i32[src++];
}
2014-07-15 10:19:26 +04:00
} else {
dst += length;
src += length;
2014-07-15 10:19:26 +04:00
for (var n = 0; n < length; ++n)
i32[--dst] = src[--src];
2014-07-15 10:19:26 +04:00
}
2014-12-19 00:03:59 +03:00
};
2014-07-15 10:37:33 +04:00
Native["com/sun/cldchi/jvm/JVM.monotonicTimeMillis.()J"] = function(addr) {
2015-05-20 03:49:48 +03:00
return J2ME.returnLongValue(performance.now());
2014-12-19 00:03:59 +03:00
};
Native["java/lang/Object.getClass.()Ljava/lang/Class;"] = function(addr) {
return $.getClassObjectAddress(J2ME.getClassInfo(addr));
2014-12-19 00:03:59 +03:00
};
2014-07-18 10:02:28 +04:00
Native["java/lang/Class.getSuperclass.()Ljava/lang/Class;"] = function(addr) {
var superClassInfo = J2ME.getClassInfo(addr).superClass;
2015-07-22 01:49:33 +03:00
if (!superClassInfo) {
return J2ME.Constants.NULL;
}
2015-07-22 01:49:33 +03:00
return $.getClassObjectAddress(superClassInfo);
};
Native["java/lang/Class.invoke_clinit.()V"] = function(addr) {
var self = getHandle(addr);
2015-07-22 01:49:33 +03:00
var classInfo = J2ME.classIdToClassInfoMap[self.vmClass];
var className = classInfo.getClassNameSlow();
2015-03-10 04:18:43 +03:00
var clinit = classInfo.staticInitializer;
J2ME.preemptionLockLevel++;
if (clinit && clinit.classInfo.getClassNameSlow() === className) {
2015-05-05 05:46:26 +03:00
$.ctx.executeMethod(clinit);
}
2014-12-19 00:03:59 +03:00
};
2014-07-26 22:42:02 +04:00
Native["java/lang/Class.invoke_verify.()V"] = function(addr) {
// There is currently no verification.
};
Native["java/lang/Class.init9.()V"] = function(addr) {
var self = getHandle(addr);
2015-07-22 01:49:33 +03:00
release || J2ME.Debug.assert(self.vmClass in J2ME.classIdToClassInfoMap, "Class must be linked.");
$.setClassInitialized(self.vmClass);
J2ME.preemptionLockLevel--;
2014-12-19 00:03:59 +03:00
};
2014-07-26 22:42:02 +04:00
Native["java/lang/Class.getName.()Ljava/lang/String;"] = function(addr) {
var self = getHandle(addr);
2015-07-22 01:49:33 +03:00
var classInfo = J2ME.classIdToClassInfoMap[self.vmClass];
return J2ME.newString(classInfo.getClassNameSlow().replace(/\//g, "."));
2014-12-19 00:03:59 +03:00
};
2014-07-18 10:02:28 +04:00
Native["java/lang/Class.forName0.(Ljava/lang/String;)V"] = function(addr, nameAddr) {
var classInfo = null;
try {
2015-07-07 20:12:03 +03:00
if (nameAddr === J2ME.Constants.NULL) {
throw new J2ME.ClassNotFoundException();
2015-07-07 20:12:03 +03:00
}
var className = J2ME.fromStringAddr(nameAddr).replace(/\./g, "/");
classInfo = CLASSES.getClass(className);
} catch (e) {
2015-07-07 20:12:52 +03:00
if (e instanceof (J2ME.ClassNotFoundException)) {
throw $.newClassNotFoundException("'" + e.message + "' not found.");
2015-07-07 20:12:52 +03:00
}
throw e;
}
// The following can trigger an unwind.
J2ME.classInitCheck(classInfo);
};
Native["java/lang/Class.forName1.(Ljava/lang/String;)Ljava/lang/Class;"] = function(addr, nameAddr) {
var className = J2ME.fromStringAddr(nameAddr).replace(/\./g, "/");
var classInfo = CLASSES.getClass(className);
2015-07-22 01:49:33 +03:00
return $.getClassObjectAddress(classInfo);
2014-12-19 00:03:59 +03:00
};
2014-07-15 10:47:20 +04:00
Native["java/lang/Class.newInstance0.()Ljava/lang/Object;"] = function(addr) {
var self = getHandle(addr);
2015-07-22 01:49:33 +03:00
var classInfo = J2ME.classIdToClassInfoMap[self.vmClass];
if (classInfo.isInterface ||
classInfo.isAbstract) {
throw $.newInstantiationException("Can't instantiate interfaces or abstract classes");
}
2015-07-22 01:49:33 +03:00
if (classInfo instanceof J2ME.ArrayClassInfo) {
throw $.newInstantiationException("Can't instantiate array classes");
}
2015-07-22 01:49:33 +03:00
return J2ME.allocObject(classInfo);
2015-02-26 03:01:07 +03:00
};
Native["java/lang/Class.newInstance1.(Ljava/lang/Object;)V"] = function(addr, oAddr) {
var classInfo = J2ME.getClassInfo(oAddr);
2015-02-26 03:01:07 +03:00
// The following can trigger an unwind.
var methodInfo = classInfo.getLocalMethodByNameString("<init>", "()V", false);
if (!methodInfo) {
throw $.newInstantiationException("Can't instantiate classes without a nullary constructor");
}
2015-07-08 00:55:54 +03:00
J2ME.getLinkedMethod(methodInfo)(oAddr);
2014-12-19 00:03:59 +03:00
};
Native["java/lang/Class.isInterface.()Z"] = function(addr) {
var self = getHandle(addr);
2015-07-22 01:49:33 +03:00
var classInfo = J2ME.classIdToClassInfoMap[self.vmClass];
return classInfo.isInterface ? 1 : 0;
2014-12-19 00:03:59 +03:00
};
2014-07-19 04:55:09 +04:00
Native["java/lang/Class.isArray.()Z"] = function(addr) {
var self = getHandle(addr);
2015-07-22 01:49:33 +03:00
var classInfo = J2ME.classIdToClassInfoMap[self.vmClass];
return classInfo instanceof J2ME.ArrayClassInfo ? 1 : 0;
2014-12-19 00:03:59 +03:00
};
2014-07-19 04:55:09 +04:00
Native["java/lang/Class.isAssignableFrom.(Ljava/lang/Class;)Z"] = function(addr, fromClassAddr) {
var self = getHandle(addr);
2015-07-22 01:49:33 +03:00
var selfClassInfo = J2ME.classIdToClassInfoMap[self.vmClass];
if (fromClassAddr === J2ME.Constants.NULL) {
throw $.newNullPointerException();
2015-07-22 01:49:33 +03:00
}
var fromClass = getHandle(fromClassAddr);
var fromClassInfo = J2ME.classIdToClassInfoMap[fromClass.vmClass];
return J2ME.isAssignableTo(fromClassInfo, selfClassInfo) ? 1 : 0;
2014-12-19 00:03:59 +03:00
};
2014-07-19 04:55:09 +04:00
Native["java/lang/Class.isInstance.(Ljava/lang/Object;)Z"] = function(addr, objAddr) {
if (objAddr === J2ME.Constants.NULL) {
return 0;
}
var self = getHandle(addr);
2015-07-22 01:49:33 +03:00
var classInfo = J2ME.classIdToClassInfoMap[self.vmClass];
var objClassInfo = J2ME.getClassInfo(objAddr);
return J2ME.isAssignableTo(objClassInfo, classInfo) ? 1 : 0;
2014-12-19 00:03:59 +03:00
};
2014-07-19 04:55:09 +04:00
Native["java/lang/Float.floatToIntBits.(F)I"] = function(addr, f) {
2015-05-10 04:32:02 +03:00
return aliasedF32[0] = f, aliasedI32[0];
}
Native["java/lang/Float.intBitsToFloat.(I)F"] = function(addr, i) {
2015-05-10 04:32:02 +03:00
return aliasedI32[0] = i, aliasedF32[0];
}
Native["java/lang/Double.doubleToLongBits.(D)J"] = function(addr, d) {
aliasedF64[0] = d;
return J2ME.returnLong(aliasedI32[0], aliasedI32[1]);
}
Native["java/lang/Double.longBitsToDouble.(J)D"] = function(addr, l, h) {
2015-05-10 04:32:02 +03:00
aliasedI32[0] = l;
aliasedI32[1] = h;
return aliasedF64[0];
}
Native["java/lang/Throwable.fillInStackTrace.()V"] = function(addr) {
2015-05-09 07:14:44 +03:00
J2ME.traceWriter && J2ME.traceWriter.writeLn("REDUX");
//var stackTrace = [];
//setNative(addr, stackTrace);
2015-05-09 07:14:44 +03:00
//$.ctx.frames.forEach(function(frame) {
// if (!frame.methodInfo)
// return;
// var methodInfo = frame.methodInfo;
// var methodName = methodInfo.name;
// if (!methodName)
// return;
// var classInfo = methodInfo.classInfo;
// var className = classInfo.getClassNameSlow();
// stackTrace.unshift({ className: className, methodName: methodName, methodSignature: methodInfo.signature, offset: frame.bci });
//});
2014-12-19 00:03:59 +03:00
};
2014-07-18 10:02:28 +04:00
Native["java/lang/Throwable.obtainBackTrace.()Ljava/lang/Object;"] = function(addr) {
2015-06-30 23:30:03 +03:00
var resultAddr = J2ME.Constants.NULL;
// XXX: Untested.
var stackTrace = NativeMap.get(addr);
if (stackTrace) {
var depth = stackTrace.length;
var classNamesAddr = J2ME.newStringArray(depth);
var classNames = J2ME.getArrayFromAddr(classNamesAddr);
var methodNamesAddr = J2ME.newStringArray(depth);
var methodNames = J2ME.getArrayFromAddr(methodNamesAddr);
var methodSignaturesAddr = J2ME.newStringArray(depth);
var methodSignatures = J2ME.getArrayFromAddr(methodSignaturesAddr);
var offsetsAddr = J2ME.newIntArray(depth);
var offsets = J2ME.getArrayFromAddr(offsetsAddr);
stackTrace.forEach(function(e, n) {
2015-03-18 02:48:06 +03:00
classNames[n] = J2ME.newString(e.className);
methodNames[n] = J2ME.newString(e.methodName);
methodSignatures[n] = J2ME.newString(e.methodSignature);
2014-07-31 02:49:58 +04:00
offsets[n] = e.offset;
});
resultAddr = J2ME.newObjectArray(3);
var result = J2ME.getArrayFromAddr(resultAddr);
result[0] = classNamesAddr;
result[1] = methodNamesAddr;
result[2] = methodSignaturesAddr;
result[3] = offsetsAddr;
2014-07-31 02:49:58 +04:00
}
return resultAddr;
2014-12-19 00:03:59 +03:00
};
2014-07-19 04:55:09 +04:00
Native["java/lang/Runtime.freeMemory.()J"] = function(addr) {
2015-07-25 03:38:55 +03:00
return J2ME.returnLongValue(@ASMJS_TOTAL_MEMORY@ - ASM._getUsedHeapSize());
2014-12-19 00:03:59 +03:00
};
2014-07-19 20:23:14 +04:00
Native["java/lang/Runtime.totalMemory.()J"] = function(addr) {
2015-07-25 03:38:55 +03:00
return J2ME.returnLongValue(@ASMJS_TOTAL_MEMORY@);
2014-12-19 00:03:59 +03:00
};
2014-07-19 20:23:14 +04:00
Native["java/lang/Runtime.gc.()V"] = function(addr) {
2015-07-20 01:22:42 +03:00
ASM._forceCollection();
2014-12-19 00:03:59 +03:00
};
2014-07-19 20:23:14 +04:00
Native["java/lang/Math.floor.(D)D"] = function(addr, val) {
return Math.floor(val);
2014-12-19 00:03:59 +03:00
};
2014-07-27 02:00:19 +04:00
Native["java/lang/Math.asin.(D)D"] = function(addr, val) {
return Math.asin(val);
2014-12-19 00:03:59 +03:00
};
2014-07-27 02:00:19 +04:00
Native["java/lang/Math.acos.(D)D"] = function(addr, val) {
return Math.acos(val);
2014-12-19 00:03:59 +03:00
};
2014-07-27 02:00:19 +04:00
Native["java/lang/Math.atan.(D)D"] = function(addr, val) {
return Math.atan(val);
2014-12-19 00:03:59 +03:00
};
2014-07-27 02:00:19 +04:00
Native["java/lang/Math.atan2.(DD)D"] = function(addr, x, y) {
return Math.atan2(x, y);
2014-12-19 00:03:59 +03:00
};
2014-07-27 02:00:19 +04:00
Native["java/lang/Math.sin.(D)D"] = function(addr, val) {
return Math.sin(val);
2014-12-19 00:03:59 +03:00
};
2014-07-27 02:00:19 +04:00
Native["java/lang/Math.cos.(D)D"] = function(addr, val) {
return Math.cos(val);
2014-12-19 00:03:59 +03:00
};
2014-07-27 02:00:19 +04:00
Native["java/lang/Math.tan.(D)D"] = function(addr, val) {
return Math.tan(val);
2014-12-19 00:03:59 +03:00
};
2014-07-27 02:00:19 +04:00
Native["java/lang/Math.sqrt.(D)D"] = function(addr, val) {
return Math.sqrt(val);
2014-12-19 00:03:59 +03:00
};
2014-07-27 02:00:19 +04:00
Native["java/lang/Math.ceil.(D)D"] = function(addr, val) {
return Math.ceil(val);
2014-12-19 00:03:59 +03:00
};
2014-07-27 02:00:19 +04:00
Native["java/lang/Math.floor.(D)D"] = function(addr, val) {
return Math.floor(val);
2014-12-19 00:03:59 +03:00
};
Native["java/lang/Thread.currentThread.()Ljava/lang/Thread;"] = function(addr) {
return $.ctx.threadAddress;
2014-12-19 00:03:59 +03:00
};
2014-07-20 11:35:00 +04:00
Native["java/lang/Thread.setPriority0.(II)V"] = function(addr, oldPriority, newPriority) {
2014-12-19 00:03:59 +03:00
};
2014-07-20 11:35:00 +04:00
Native["java/lang/Thread.start0.()V"] = function(addr) {
var self = getHandle(addr);
// The main thread starts during bootstrap and don't allow calling start()
// on already running threads.
if (addr === $.ctx.runtime.mainThread || self.nativeAlive)
throw $.newIllegalThreadStateException();
self.nativeAlive = 1;
// XXX self.pid seems to be unused, so remove it.
self.pid = util.id();
2014-07-28 10:39:41 +04:00
// Create a context for the thread and start it.
2014-12-19 00:03:59 +03:00
var newCtx = new Context($.ctx.runtime);
newCtx.threadAddress = addr;
2014-12-12 03:04:44 +03:00
var classInfo = CLASSES.getClass("org/mozilla/internal/Sys");
2015-03-11 23:05:03 +03:00
var run = classInfo.getMethodByNameString("runThread", "(Ljava/lang/Thread;)V", true);
2015-05-15 04:09:45 +03:00
newCtx.nativeThread.pushFrame(null);
newCtx.nativeThread.pushFrame(run);
newCtx.nativeThread.frame.setParameter(J2ME.Kind.Reference, 0, addr);
2015-05-15 04:09:45 +03:00
newCtx.start();
2015-03-07 02:38:15 +03:00
}
2014-07-20 11:35:00 +04:00
Native["java/lang/Thread.activeCount.()I"] = function(addr) {
2014-12-19 00:03:59 +03:00
return $.ctx.runtime.threadCount;
};
var consoleBuffer = "";
function flushConsoleBuffer() {
if (consoleBuffer.length) {
var temp = consoleBuffer;
consoleBuffer = "";
2015-04-01 21:13:27 +03:00
console.info(temp);
}
}
console.print = function(ch) {
if (ch === 10) {
flushConsoleBuffer();
} else {
consoleBuffer += String.fromCharCode(ch);
}
};
Native["com/sun/cldchi/io/ConsoleOutputStream.write.(I)V"] = function(addr, ch) {
console.print(ch);
2014-12-19 00:03:59 +03:00
};
2014-07-19 04:55:09 +04:00
Native["com/sun/cldc/io/ResourceInputStream.open.(Ljava/lang/String;)Ljava/lang/Object;"] = function(addr, nameAddr) {
var fileName = J2ME.fromStringAddr(nameAddr);
var data = JARStore.loadFile(fileName);
var objAddr = J2ME.Constants.NULL;
if (data) {
2015-07-22 01:49:33 +03:00
objAddr = J2ME.allocObject(CLASSES.java_lang_Object);
setNative(objAddr, {
data: data,
pos: 0,
});
}
2015-07-17 13:54:39 +03:00
return objAddr;
2014-12-19 00:03:59 +03:00
};
2014-07-19 04:55:09 +04:00
Native["com/sun/cldc/io/ResourceInputStream.clone.(Ljava/lang/Object;)Ljava/lang/Object;"] = function(addr, sourceAddr) {
2015-07-22 01:49:33 +03:00
var objAddr = J2ME.allocObject(CLASSES.java_lang_Object);
var sourceDecoder = NativeMap.get(sourceAddr);
setNative(objAddr, {
data: new Uint8Array(sourceDecoder.data),
pos: sourceDecoder.pos,
});
2015-07-17 13:54:39 +03:00
return objAddr;
2014-12-19 00:03:59 +03:00
};
Native["com/sun/cldc/io/ResourceInputStream.bytesRemain.(Ljava/lang/Object;)I"] = function(addr, fileDecoderAddr) {
var handle = NativeMap.get(fileDecoderAddr);
2014-10-15 00:18:50 +04:00
return handle.data.length - handle.pos;
2014-12-19 00:03:59 +03:00
};
2014-07-19 04:55:09 +04:00
Native["com/sun/cldc/io/ResourceInputStream.readByte.(Ljava/lang/Object;)I"] = function(addr, fileDecoderAddr) {
var handle = NativeMap.get(fileDecoderAddr);
2014-10-15 00:18:50 +04:00
return (handle.data.length - handle.pos > 0) ? handle.data[handle.pos++] : -1;
2014-12-19 00:03:59 +03:00
};
2014-07-19 04:55:09 +04:00
Native["com/sun/cldc/io/ResourceInputStream.readBytes.(Ljava/lang/Object;[BII)I"] =
function(addr, fileDecoderAddr, bAddr, off, len) {
var b = J2ME.getArrayFromAddr(bAddr);
var handle = NativeMap.get(fileDecoderAddr);
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;
2014-10-15 00:18:50 +04:00
return (len > 0) ? len : -1;
2014-12-19 00:03:59 +03:00
};
2014-07-19 05:23:49 +04:00
Native["com/sun/cldc/isolate/Isolate.registerNewIsolate.()V"] = function(addr) {
var self = getHandle(addr);
self._id = util.id();
2014-12-19 00:03:59 +03:00
};
2014-08-07 09:43:05 +04:00
Native["com/sun/cldc/isolate/Isolate.getStatus.()I"] = function(addr) {
var runtime = NativeMap.get(addr);
return runtime ? runtime.status : J2ME.RuntimeStatus.New;
2014-12-19 00:03:59 +03:00
};
2014-08-07 10:57:44 +04:00
Native["com/sun/cldc/isolate/Isolate.nativeStart.()V"] = function(addr) {
$.ctx.runtime.jvm.startIsolate(addr);
2014-12-19 00:03:59 +03:00
};
2014-08-07 22:46:11 +04:00
Native["com/sun/cldc/isolate/Isolate.waitStatus.(I)V"] = function(addr, status) {
var runtime = NativeMap.get(addr);
asyncImpl("V", new Promise(function(resolve, reject) {
if (runtime.status >= status) {
2014-10-17 07:08:51 +04:00
resolve();
2014-08-07 23:12:57 +04:00
return;
2014-08-07 22:46:11 +04:00
}
2014-10-17 07:08:51 +04:00
function waitForStatus() {
if (runtime.status >= status) {
resolve();
return;
}
runtime.waitStatus(waitForStatus);
}
waitForStatus();
}));
2014-12-19 00:03:59 +03:00
};
2014-08-08 09:29:16 +04:00
Native["com/sun/cldc/isolate/Isolate.currentIsolate0.()Lcom/sun/cldc/isolate/Isolate;"] = function(addr) {
return $.ctx.runtime.isolateAddress;
2014-12-19 00:03:59 +03:00
};
2014-08-09 00:04:40 +04:00
Native["com/sun/cldc/isolate/Isolate.getIsolates0.()[Lcom/sun/cldc/isolate/Isolate;"] = function(addr) {
var isolatesAddr = J2ME.newObjectArray(Runtime.all.size);
var isolates = J2ME.getArrayFromAddr(isolatesAddr);
2014-08-09 00:04:40 +04:00
var n = 0;
Runtime.all.forEach(function(runtime) {
isolates[n++] = runtime.isolateAddress;
2014-08-09 00:04:40 +04:00
});
return isolatesAddr;
2014-12-19 00:03:59 +03:00
};
Native["com/sun/cldc/isolate/Isolate.setPriority0.(I)V"] = function(addr, newPriority) {
// XXX Figure out if there's anything to do here. If not, say so.
2014-12-19 00:03:59 +03:00
};
2014-08-12 04:16:18 +04:00
Native["com/sun/j2me/content/AppProxy.midletIsAdded.(ILjava/lang/String;)V"] = function(addr, suiteId, classNameAddr) {
2015-01-14 22:32:43 +03:00
console.warn("com/sun/j2me/content/AppProxy.midletIsAdded.(ILjava/lang/String;)V not implemented");
2014-12-19 00:03:59 +03:00
};
2014-12-18 02:25:34 +03:00
Native["com/nokia/mid/impl/jms/core/Launcher.handleContent.(Ljava/lang/String;)V"] = function(addr, contentAddr) {
var fileName = J2ME.fromStringAddr(contentAddr);
var ext = fileName.split('.').pop().toLowerCase();
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#Supported_image_formats
if (["jpg", "jpeg", "gif", "apng", "png", "bmp", "ico"].indexOf(ext) == -1) {
console.error("File not supported: " + fileName);
throw $.newException("File not supported: " + fileName);
}
// `fileName` is supposed to be a full path, but we don't support
// partition, e.g. `C:` or `E:` etc, so the `fileName` we got here
// is something like: `Photos/sampleImage.jpg`, we need to prepend
// the root dir to make sure it's valid.
var imgData = fs.getBlob("/" + fileName);
if (!imgData) {
console.error("File not found: " + fileName);
throw $.newException("File not found: " + fileName);
}
var maskId = "image-launcher";
var mask = document.getElementById(maskId);
function _revokeImageURL() {
URL.revokeObjectURL(/url\((.+)\)/ig.exec(mask.style.backgroundImage)[1]);
}
if (mask) {
_revokeImageURL();
} else {
mask = document.createElement("div");
mask.id = maskId;
mask.onclick = mask.ontouchstart = function() {
_revokeImageURL();
mask.parentNode.removeChild(mask);
};
document.getElementById("main").appendChild(mask);
}
mask.style.backgroundImage = "url(" +
URL.createObjectURL(imgData) + ")";
2014-12-19 00:03:59 +03:00
};
function addUnimplementedNative(signature, returnValue) {
var doNotWarn;
if (typeof returnValue === "function") {
doNotWarn = returnValue;
} else {
doNotWarn = function() { return returnValue };
}
var warnOnce = function() {
console.warn(signature + " not implemented");
warnOnce = doNotWarn;
return doNotWarn();
};
Native[signature] = function(addr) { return warnOnce() };
}
Native["org/mozilla/internal/Sys.eval.(Ljava/lang/String;)V"] = function(addr, srcAddr) {
if (!release) {
eval(J2ME.fromStringAddr(srcAddr));
}
};
2015-03-26 01:35:27 +03:00
Native["java/lang/String.intern.()Ljava/lang/String;"] = function(addr) {
var self = getHandle(addr);
var value = J2ME.getArrayFromAddr(self.value);
var internedStringAddr = J2ME.internedStrings.getByRange(value, self.offset, self.count);
if (internedStringAddr !== null) {
return internedStringAddr;
2015-03-26 01:35:27 +03:00
}
J2ME.internedStrings.put(value.subarray(self.offset, self.offset + self.count), addr);
return addr;
2015-03-26 01:35:27 +03:00
};
var profileStarted = false;
Native["org/mozilla/internal/Sys.startProfile.()V"] = function(addr) {
if (profile === 4) {
if (!profileStarted) {
profileStarted = true;
console.log("Start profile at: " + performance.now());
startTimeline();
}
}
};
var profileSaved = false;
Native["org/mozilla/internal/Sys.stopProfile.()V"] = function(addr) {
if (profile === 4) {
if (!profileSaved) {
profileSaved = true;
console.log("Stop profile at: " + performance.now());
setZeroTimeout(function() {
stopAndSaveTimeline();
});
}
}
};