Introduce raiseExceptionAndYield function and use it when needed

This commit is contained in:
Marco Castelluccio 2014-08-26 09:47:51 -07:00
Родитель 88e2782e55
Коммит c3fbae4470
3 изменённых файлов: 68 добавлений и 94 удалений

Просмотреть файл

@ -103,8 +103,13 @@ Context.prototype.raiseException = function(className, message) {
throw VM.Yield; throw VM.Yield;
} }
Context.prototype.raiseExceptionAndYield = function(className, message) {
this.raiseException(className, message);
throw VM.Yield;
}
Context.prototype.raiseRuntimeException = function(message) { Context.prototype.raiseRuntimeException = function(message) {
this.raiseException("java/lang/RuntimeException", message); this.raiseExceptionAndYield("java/lang/RuntimeException", message);
} }
Context.prototype.execute = function(stopFrame) { Context.prototype.execute = function(stopFrame) {
@ -204,7 +209,7 @@ Context.prototype.monitorEnter = function(obj) {
Context.prototype.monitorExit = function(obj) { Context.prototype.monitorExit = function(obj) {
var lock = obj.lock; var lock = obj.lock;
if (lock.thread !== this.thread) if (lock.thread !== this.thread)
this.raiseException("java/lang/IllegalMonitorStateException"); this.raiseExceptionAndYield("java/lang/IllegalMonitorStateException");
if (--lock.level > 0) { if (--lock.level > 0) {
return; return;
} }
@ -217,9 +222,9 @@ Context.prototype.monitorExit = function(obj) {
Context.prototype.wait = function(obj, timeout) { Context.prototype.wait = function(obj, timeout) {
var lock = obj.lock; var lock = obj.lock;
if (!lock || lock.thread !== this.thread) if (!lock || lock.thread !== this.thread)
this.raiseException("java/lang/IllegalMonitorStateException"); this.raiseExceptionAndYield("java/lang/IllegalMonitorStateException");
if (timeout < 0) if (timeout < 0)
this.raiseException("java/lang/IllegalArgumentException"); this.raiseExceptionAndYield("java/lang/IllegalArgumentException");
var lockLevel = lock.level; var lockLevel = lock.level;
while (lock.level > 0) while (lock.level > 0)
this.monitorExit(obj); this.monitorExit(obj);
@ -241,7 +246,7 @@ Context.prototype.wait = function(obj, timeout) {
Context.prototype.notify = function(obj, notifyAll) { Context.prototype.notify = function(obj, notifyAll) {
if (!obj.lock || obj.lock.thread !== this.thread) if (!obj.lock || obj.lock.thread !== this.thread)
this.raiseException("java/lang/IllegalMonitorStateException"); this.raiseExceptionAndYield("java/lang/IllegalMonitorStateException");
this.unblock(obj, "waiting", notifyAll, function(ctx) { this.unblock(obj, "waiting", notifyAll, function(ctx) {
ctx.wakeup(obj); ctx.wakeup(obj);
}); });

Просмотреть файл

@ -15,7 +15,7 @@ Native["com/sun/midp/jarutil/JarReader.readJarEntry0.(Ljava/lang/String;Ljava/la
var entryName = util.fromJavaString(stack.pop()), jar = util.fromJavaString(stack.pop()); var entryName = util.fromJavaString(stack.pop()), jar = util.fromJavaString(stack.pop());
var bytes = CLASSES.loadFileFromJar(jar, entryName); var bytes = CLASSES.loadFileFromJar(jar, entryName);
if (!bytes) if (!bytes)
ctx.raiseException("java/io/IOException"); ctx.raiseExceptionAndYield("java/io/IOException");
var length = bytes.byteLength; var length = bytes.byteLength;
var data = new Uint8Array(bytes); var data = new Uint8Array(bytes);
var array = ctx.newPrimitiveArray("B", length); var array = ctx.newPrimitiveArray("B", length);
@ -414,7 +414,7 @@ Native["com/sun/midp/chameleon/skins/resources/LoadedSkinData.beginReadingSkinFi
var fileName = util.fromJavaString(stack.pop()); var fileName = util.fromJavaString(stack.pop());
var data = CLASSES.loadFile(fileName); var data = CLASSES.loadFile(fileName);
if (!data) if (!data)
ctx.raiseException("java/io/IOException"); ctx.raiseExceptionAndYield("java/io/IOException");
MIDP.skinFileData = new DataView(data); MIDP.skinFileData = new DataView(data);
MIDP.skinFilePos = 0; MIDP.skinFilePos = 0;
} }
@ -422,7 +422,7 @@ Native["com/sun/midp/chameleon/skins/resources/LoadedSkinData.beginReadingSkinFi
Native["com/sun/midp/chameleon/skins/resources/LoadedSkinData.readByteArray.(I)[B"] = function(ctx, stack) { Native["com/sun/midp/chameleon/skins/resources/LoadedSkinData.readByteArray.(I)[B"] = function(ctx, stack) {
var len = stack.pop(); var len = stack.pop();
if (!MIDP.skinFileData || (MIDP.skinFilePos + len) > MIDP.skinFileData.byteLength) if (!MIDP.skinFileData || (MIDP.skinFilePos + len) > MIDP.skinFileData.byteLength)
ctx.raiseException("java/lang/IllegalStateException"); ctx.raiseExceptionAndYield("java/lang/IllegalStateException");
var bytes = ctx.newPrimitiveArray("B", len); var bytes = ctx.newPrimitiveArray("B", len);
for (var n = 0; n < len; ++n) { for (var n = 0; n < len; ++n) {
bytes[n] = MIDP.skinFileData.getUint8(MIDP.skinFilePos++); bytes[n] = MIDP.skinFileData.getUint8(MIDP.skinFilePos++);
@ -432,13 +432,13 @@ Native["com/sun/midp/chameleon/skins/resources/LoadedSkinData.readByteArray.(I)[
Native["com/sun/midp/chameleon/skins/resources/LoadedSkinData.readIntArray.()[I"] = function(ctx, stack) { Native["com/sun/midp/chameleon/skins/resources/LoadedSkinData.readIntArray.()[I"] = function(ctx, stack) {
if (!MIDP.skinFileData || (MIDP.skinFilePos + 4) > MIDP.skinFileData.byteLength) if (!MIDP.skinFileData || (MIDP.skinFilePos + 4) > MIDP.skinFileData.byteLength)
ctx.raiseException("java/lang/IllegalStateException"); ctx.raiseExceptionAndYield("java/lang/IllegalStateException");
var len = MIDP.skinFileData.getInt32(MIDP.skinFilePos, true); var len = MIDP.skinFileData.getInt32(MIDP.skinFilePos, true);
MIDP.skinFilePos += 4; MIDP.skinFilePos += 4;
var ints = ctx.newPrimitiveArray("I", len); var ints = ctx.newPrimitiveArray("I", len);
for (var n = 0; n < len; ++n) { for (var n = 0; n < len; ++n) {
if ((MIDP.skinFilePos + 4) > MIDP.skinFileData.byteLength) if ((MIDP.skinFilePos + 4) > MIDP.skinFileData.byteLength)
ctx.raiseException("java/lang/IllegalStateException"); ctx.raiseExceptionAndYield("java/lang/IllegalStateException");
ints[n] = MIDP.skinFileData.getInt32(MIDP.skinFilePos, true); ints[n] = MIDP.skinFileData.getInt32(MIDP.skinFilePos, true);
MIDP.skinFilePos += 4; MIDP.skinFilePos += 4;
} }
@ -450,17 +450,17 @@ MIDP.STRING_ENCODING_UTF8 = 1;
Native["com/sun/midp/chameleon/skins/resources/LoadedSkinData.readStringArray.()[Ljava/lang/String;"] = function(ctx, stack) { Native["com/sun/midp/chameleon/skins/resources/LoadedSkinData.readStringArray.()[Ljava/lang/String;"] = function(ctx, stack) {
if (!MIDP.skinFileData || (MIDP.skinFilePos + 4) > MIDP.skinFileData.byteLength) if (!MIDP.skinFileData || (MIDP.skinFilePos + 4) > MIDP.skinFileData.byteLength)
ctx.raiseException("java/lang/IllegalStateException"); ctx.raiseExceptionAndYield("java/lang/IllegalStateException");
var len = MIDP.skinFileData.getInt32(MIDP.skinFilePos, true); var len = MIDP.skinFileData.getInt32(MIDP.skinFilePos, true);
MIDP.skinFilePos += 4; MIDP.skinFilePos += 4;
var strings = ctx.newArray("[Ljava/lang/String;", len); var strings = ctx.newArray("[Ljava/lang/String;", len);
for (var n = 0; n < len; ++n) { for (var n = 0; n < len; ++n) {
if ((MIDP.skinFilePos + 2) > MIDP.skinFileData.byteLength) if ((MIDP.skinFilePos + 2) > MIDP.skinFileData.byteLength)
ctx.raiseException("java/lang/IllegalStateException"); ctx.raiseExceptionAndYield("java/lang/IllegalStateException");
var strLen = MIDP.skinFileData.getUint8(MIDP.skinFilePos++); var strLen = MIDP.skinFileData.getUint8(MIDP.skinFilePos++);
var strEnc = MIDP.skinFileData.getUint8(MIDP.skinFilePos++); var strEnc = MIDP.skinFileData.getUint8(MIDP.skinFilePos++);
if ((MIDP.skinFilePos + strLen) > MIDP.skinFileData.byteLength) if ((MIDP.skinFilePos + strLen) > MIDP.skinFileData.byteLength)
ctx.raiseException("java/lang/IllegalStateException"); ctx.raiseExceptionAndYield("java/lang/IllegalStateException");
var bytes = MIDP.skinFileData.buffer.slice(MIDP.skinFilePos, MIDP.skinFilePos + strLen); var bytes = MIDP.skinFileData.buffer.slice(MIDP.skinFilePos, MIDP.skinFilePos + strLen);
MIDP.skinFilePos += strLen; MIDP.skinFilePos += strLen;
var str; var str;
@ -472,7 +472,7 @@ Native["com/sun/midp/chameleon/skins/resources/LoadedSkinData.readStringArray.()
} else if (strEnc === MIDP.STRING_ENCODING_UTF8) { } else if (strEnc === MIDP.STRING_ENCODING_UTF8) {
str = util.decodeUtf8(bytes); str = util.decodeUtf8(bytes);
} else { } else {
ctx.raiseException("java/lang/IllegalStateException"); ctx.raiseExceptionAndYield("java/lang/IllegalStateException");
} }
strings[n] = ctx.newString(str); strings[n] = ctx.newString(str);
} }
@ -512,8 +512,8 @@ Native["com/sun/midp/util/ResourceHandler.loadRomizedResource0.(Ljava/lang/Strin
var fileName = "assets/0/" + util.fromJavaString(stack.pop()).replace("_", ".").replace("_png", ".png"); var fileName = "assets/0/" + util.fromJavaString(stack.pop()).replace("_", ".").replace("_png", ".png");
var data = CLASSES.loadFile(fileName); var data = CLASSES.loadFile(fileName);
if (!data) { if (!data) {
console.log(fileName); console.log("ResourceHandler::loadRomizedResource0: " + fileName);
ctx.raiseException("java/io/IOException"); ctx.raiseExceptionAndYield("java/io/IOException");
} }
var len = data.byteLength; var len = data.byteLength;
var bytes = ctx.newPrimitiveArray("B", len); var bytes = ctx.newPrimitiveArray("B", len);
@ -658,12 +658,7 @@ Native["com/sun/midp/rms/RecordStoreFile.openRecordStoreFile.(Ljava/lang/String;
function openCallback(fd) { function openCallback(fd) {
if (fd == -1) { if (fd == -1) {
try { ctx.raiseException("java/io/IOException", "openRecordStoreFile: open failed");
ctx.raiseException("java/io/IOException", "openRecordStoreFile: open failed");
} catch(ex) {
// Catch and ignore the VM.Yield exception that Context.raiseException
// throws so we reach ctx.resume() to resume the thread.
}
} else { } else {
stack.push(fd); // handle stack.push(fd); // handle
} }
@ -683,22 +678,12 @@ Native["com/sun/midp/rms/RecordStoreFile.openRecordStoreFile.(Ljava/lang/String;
fs.open(path, openCallback); fs.open(path, openCallback);
} }
else { else {
try { ctx.raiseException("java/io/IOException", "openRecordStoreFile: create failed");
ctx.raiseException("java/io/IOException", "openRecordStoreFile: create failed");
} catch(ex) {
// Catch and ignore the VM.Yield exception that Context.raiseException
// throws so we reach ctx.resume() to resume the thread.
}
ctx.resume(); ctx.resume();
} }
}); });
} else { } else {
try { ctx.raiseException("java/io/IOException", "openRecordStoreFile: mkdirp failed");
ctx.raiseException("java/io/IOException", "openRecordStoreFile: mkdirp failed");
} catch(ex) {
// Catch and ignore the VM.Yield exception that Context.raiseException
// throws so we reach ctx.resume() to resume the thread.
}
ctx.resume(); ctx.resume();
} }
}); });
@ -720,15 +705,16 @@ Native["com/sun/midp/rms/RecordStoreFile.readBytes.(I[BII)I"] = function(ctx, st
var from = fs.getpos(handle); var from = fs.getpos(handle);
var to = from + numBytes; var to = from + numBytes;
var readBytes = fs.read(handle, from, to); var readBytes = fs.read(handle, from, to);
if (readBytes.byteLength > 0) {
var subBuffer = buf.subarray(offset, offset + readBytes.byteLength); if (readBytes.byteLength <= 0) {
for (var i = 0; i < readBytes.byteLength; i++) { ctx.raiseExceptionAndYield("java/io/IOException", "handle invalid or segment indices out of bounds");
subBuffer[i] = readBytes[i];
}
stack.push(readBytes.byteLength);
} else {
ctx.raiseException("java/io/IOException", "handle invalid or segment indices out of bounds");
} }
var subBuffer = buf.subarray(offset, offset + readBytes.byteLength);
for (var i = 0; i < readBytes.byteLength; i++) {
subBuffer[i] = readBytes[i];
}
stack.push(readBytes.byteLength);
} }
Native["com/sun/midp/rms/RecordStoreFile.writeBytes.(I[BII)V"] = function(ctx, stack) { Native["com/sun/midp/rms/RecordStoreFile.writeBytes.(I[BII)V"] = function(ctx, stack) {
@ -797,11 +783,11 @@ Native["com/sun/midp/rms/RecordStoreSharedDBHeader.shareCachedData0.(I[BI)I"] =
var sharedHeader = MIDP.RecordStoreCache[lookupId]; var sharedHeader = MIDP.RecordStoreCache[lookupId];
if (!sharedHeader) { if (!sharedHeader) {
ctx.raiseException("java/lang/IllegalStateException", "invalid header lookup ID"); ctx.raiseExceptionAndYield("java/lang/IllegalStateException", "invalid header lookup ID");
} }
if (!headerData) { if (!headerData) {
ctx.raiseException("java/lang/IllegalArgumentException", "header data is null"); ctx.raiseExceptionAndYield("java/lang/IllegalArgumentException", "header data is null");
} }
var size = headerDataSize; var size = headerDataSize;
@ -819,11 +805,11 @@ Native["com/sun/midp/rms/RecordStoreSharedDBHeader.updateCachedData0.(I[BII)I"]
var sharedHeader = MIDP.RecordStoreCache[lookupId]; var sharedHeader = MIDP.RecordStoreCache[lookupId];
if (!sharedHeader) { if (!sharedHeader) {
ctx.raiseException("java/lang/IllegalStateException", "invalid header lookup ID"); ctx.raiseExceptionAndYield("java/lang/IllegalStateException", "invalid header lookup ID");
} }
if (!headerData) { if (!headerData) {
ctx.raiseException("java/lang/IllegalArgumentException", "header data is null"); ctx.raiseExceptionAndYield("java/lang/IllegalArgumentException", "header data is null");
} }
if (sharedHeader.headerVersion > headerVersion && sharedHeader.headerData) { if (sharedHeader.headerVersion > headerVersion && sharedHeader.headerData) {
@ -845,7 +831,7 @@ Native["com/sun/midp/rms/RecordStoreSharedDBHeader.getHeaderRefCount0.(I)I"] = f
var sharedHeader = MIDP.RecordStoreCache[lookupId]; var sharedHeader = MIDP.RecordStoreCache[lookupId];
if (!sharedHeader) { if (!sharedHeader) {
ctx.raiseException("java/lang/IllegalStateException", "invalid header lookup ID"); ctx.raiseExceptionAndYield("java/lang/IllegalStateException", "invalid header lookup ID");
} }
stack.push(sharedHeader.refCount); stack.push(sharedHeader.refCount);
@ -1069,7 +1055,7 @@ Native["com/sun/midp/l10n/LocalizedStringsBase.getContent.(I)Ljava/lang/String;"
}); });
var data = CLASSES.loadFile("assets/0/en-US.xml"); var data = CLASSES.loadFile("assets/0/en-US.xml");
if (!data || !key) if (!data || !key)
ctx.raiseException("java/io/IOException"); ctx.raiseExceptionAndYield("java/io/IOException");
var text = util.decodeUtf8(data); var text = util.decodeUtf8(data);
var xml = new window.DOMParser().parseFromString(text, "text/xml"); var xml = new window.DOMParser().parseFromString(text, "text/xml");
var entries = xml.getElementsByTagName("localized_string"); var entries = xml.getElementsByTagName("localized_string");
@ -1080,7 +1066,7 @@ Native["com/sun/midp/l10n/LocalizedStringsBase.getContent.(I)Ljava/lang/String;"
return; return;
} }
} }
ctx.raiseException("java/lang/IllegalStateException"); ctx.raiseExceptionAndYield("java/lang/IllegalStateException");
} }
Native["javax/microedition/lcdui/Graphics.getPixel.(IIZ)I"] = function(ctx, stack) { Native["javax/microedition/lcdui/Graphics.getPixel.(IIZ)I"] = function(ctx, stack) {
@ -1506,12 +1492,7 @@ Native["com/ibm/oti/connection/file/Connection.truncateImpl.([BJ)V"] = function(
fs.open(path, function(fd) { fs.open(path, function(fd) {
if (fd == -1) { if (fd == -1) {
try { ctx.raiseException("java/io/IOException", "truncate failed");
ctx.raiseException("java/io/IOException", "truncate failed");
} catch(ex) {
// Catch and ignore the VM.Yield exception that Context.raiseException
// throws so we reach ctx.resume() to resume the thread.
}
ctx.resume(); ctx.resume();
} else { } else {
var data = fs.read(fd); var data = fs.read(fd);
@ -1519,12 +1500,7 @@ Native["com/ibm/oti/connection/file/Connection.truncateImpl.([BJ)V"] = function(
if (truncated) { if (truncated) {
fs.write(fd, data.subarray(0, newLength)); fs.write(fd, data.subarray(0, newLength));
} else { } else {
try { ctx.raiseException("java/io/IOException", "truncate failed");
ctx.raiseException("java/io/IOException", "truncate failed");
} catch(ex) {
// Catch and ignore the VM.Yield exception that Context.raiseException
// throws so we reach ctx.resume() to resume the thread.
}
} }
ctx.resume(); ctx.resume();
}); });
@ -1676,13 +1652,8 @@ Native["com/sun/midp/io/j2me/storage/RandomAccessStream.open.(Ljava/lang/String;
function open() { function open() {
fs.open(path, function(fd) { fs.open(path, function(fd) {
if (fd == -1) { if (fd == -1) {
try { ctx.raiseException("java/io/IOException",
ctx.raiseException("java/io/IOException", "RandomAccessStream::open(" + fileName + ") failed opening the file");
"RandomAccessStream::open(" + fileName + ") failed opening the file");
} catch(ex) {
// Catch and ignore the VM.Yield exception that Context.raiseException
// throws so we reach ctx.resume() to resume the thread.
}
} else { } else {
stack.push(fd); stack.push(fd);
} }
@ -1700,13 +1671,8 @@ Native["com/sun/midp/io/j2me/storage/RandomAccessStream.open.(Ljava/lang/String;
if (created) { if (created) {
open(); open();
} else { } else {
try { ctx.raiseException("java/io/IOException",
ctx.raiseException("java/io/IOException", "RandomAccessStream::open(" + fileName + ") failed creating the file");
"RandomAccessStream::open(" + fileName + ") failed creating the file");
} catch(ex) {
// Catch and ignore the VM.Yield exception that Context.raiseException
// throws so we reach ctx.resume() to resume the thread.
}
ctx.resume(); ctx.resume();
} }
}); });
@ -1723,15 +1689,17 @@ Native["com/sun/midp/io/j2me/storage/RandomAccessStream.read.(I[BII)I"] = functi
var from = fs.getpos(handle); var from = fs.getpos(handle);
var to = from + length; var to = from + length;
var readBytes = fs.read(handle, from, to); var readBytes = fs.read(handle, from, to);
if (readBytes.byteLength > 0) {
var subBuffer = buffer.subarray(offset, offset + readBytes.byteLength); if (readBytes.byteLength <= 0) {
for (var i = 0; i < readBytes.byteLength; i++) {
subBuffer[i] = readBytes[i];
}
stack.push(readBytes.byteLength);
} else {
stack.push(-1); stack.push(-1);
return;
} }
var subBuffer = buffer.subarray(offset, offset + readBytes.byteLength);
for (var i = 0; i < readBytes.byteLength; i++) {
subBuffer[i] = readBytes[i];
}
stack.push(readBytes.byteLength);
} }
Native["com/sun/midp/io/j2me/storage/RandomAccessStream.write.(I[BII)V"] = function(ctx, stack) { Native["com/sun/midp/io/j2me/storage/RandomAccessStream.write.(I[BII)V"] = function(ctx, stack) {
@ -1758,11 +1726,12 @@ Native["com/sun/midp/io/j2me/storage/RandomAccessStream.sizeOf.(I)I"] = function
var handle = stack.pop(); var handle = stack.pop();
var size = fs.getsize(handle); var size = fs.getsize(handle);
if (size == -1) { if (size == -1) {
ctx.raiseException("java/io/IOException", "RandomAccessStream::sizeOf(" + handle + ") failed"); ctx.raiseExceptionAndYield("java/io/IOException", "RandomAccessStream::sizeOf(" + handle + ") failed");
} else {
stack.push(size);
} }
stack.push(size);
} }
Native["com/sun/midp/io/j2me/storage/RandomAccessStream.close.(I)V"] = function(ctx, stack) { Native["com/sun/midp/io/j2me/storage/RandomAccessStream.close.(I)V"] = function(ctx, stack) {

Просмотреть файл

@ -11,7 +11,7 @@ Native.invoke = function(ctx, methodInfo) {
methodInfo.native = Native[key]; methodInfo.native = Native[key];
if (!methodInfo.native) { if (!methodInfo.native) {
console.log("Missing native: " + key); console.log("Missing native: " + key);
ctx.raiseException("java/lang/RuntimeException", key + " not found"); ctx.raiseExceptionAndYield("java/lang/RuntimeException", key + " not found");
} }
} }
methodInfo.native.call(null, ctx, ctx.current().stack); methodInfo.native.call(null, ctx, ctx.current().stack);
@ -20,23 +20,23 @@ Native.invoke = function(ctx, methodInfo) {
Native["java/lang/System.arraycopy.(Ljava/lang/Object;ILjava/lang/Object;II)V"] = function(ctx, stack) { 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(); var length = stack.pop(), dstOffset = stack.pop(), dst = stack.pop(), srcOffset = stack.pop(), src = stack.pop();
if (!src || !dst) if (!src || !dst)
ctx.raiseException("java/lang/NullPointerException", "Cannot copy to/from a null array."); ctx.raiseExceptionAndYield("java/lang/NullPointerException", "Cannot copy to/from a null array.");
var srcClass = src.class; var srcClass = src.class;
var dstClass = dst.class; var dstClass = dst.class;
if (!srcClass.isArrayClass || !dstClass.isArrayClass) if (!srcClass.isArrayClass || !dstClass.isArrayClass)
ctx.raiseException("java/lang/ArrayStoreException", "Can only copy to/from array types."); 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) if (srcOffset < 0 || (srcOffset+length) > src.length || dstOffset < 0 || (dstOffset+length) > dst.length || length < 0)
ctx.raiseException("java/lang/ArrayIndexOutOfBoundsException", "Invalid index."); ctx.raiseExceptionAndYield("java/lang/ArrayIndexOutOfBoundsException", "Invalid index.");
if ((!!srcClass.elementClass != !!dstClass.elementClass) || if ((!!srcClass.elementClass != !!dstClass.elementClass) ||
(!srcClass.elementClass && srcClass != dstClass)) { (!srcClass.elementClass && srcClass != dstClass)) {
ctx.raiseException("java/lang/ArrayStoreException", "Incompatible component types."); ctx.raiseExceptionAndYield("java/lang/ArrayStoreException", "Incompatible component types.");
} }
if (dstClass.elementClass) { if (dstClass.elementClass) {
if (srcClass != dstClass && !srcClass.elementClass.isAssignableTo(dstClass.elementClass)) { if (srcClass != dstClass && !srcClass.elementClass.isAssignableTo(dstClass.elementClass)) {
function copy(to, from) { function copy(to, from) {
var obj = src[from]; var obj = src[from];
if (obj && !obj.class.isAssignableTo(dstClass.elementClass)) if (obj && !obj.class.isAssignableTo(dstClass.elementClass))
ctx.raiseException("java/lang/ArrayStoreException", "Incompatible component types."); ctx.raiseExceptionAndYield("java/lang/ArrayStoreException", "Incompatible component types.");
dst[to] = obj; dst[to] = obj;
} }
if (dst !== src || dstOffset < srcOffset) { if (dst !== src || dstOffset < srcOffset) {
@ -225,7 +225,7 @@ Native["java/lang/Class.forName.(Ljava/lang/String;)Ljava/lang/Class;"] = functi
classInfo = CLASSES.getClass(className); classInfo = CLASSES.getClass(className);
} catch (e) { } catch (e) {
if (e instanceof (Classes.ClassNotFoundException)) if (e instanceof (Classes.ClassNotFoundException))
ctx.raiseException("java/lang/ClassNotFoundException", "'" + className + "' not found."); ctx.raiseExceptionAndYield("java/lang/ClassNotFoundException", "'" + className + "' not found.");
throw e; throw e;
} }
stack.push(classInfo.getClassObject(ctx)); stack.push(classInfo.getClassObject(ctx));
@ -272,7 +272,7 @@ Native["java/lang/Class.isArray.()Z"] = function(ctx, stack) {
Native["java/lang/Class.isAssignableFrom.(Ljava/lang/Class;)Z"] = function(ctx, stack) { Native["java/lang/Class.isAssignableFrom.(Ljava/lang/Class;)Z"] = function(ctx, stack) {
var fromClass = stack.pop(), classObject = stack.pop(); var fromClass = stack.pop(), classObject = stack.pop();
if (!fromClass) if (!fromClass)
ctx.raiseException("java/lang/NullPointerException"); ctx.raiseExceptionAndYield("java/lang/NullPointerException");
stack.push(fromClass.vmClass.isAssignableTo(classObject.vmClass) ? 1 : 0); stack.push(fromClass.vmClass.isAssignableTo(classObject.vmClass) ? 1 : 0);
} }
@ -428,7 +428,7 @@ Native["java/lang/Thread.start0.()V"] = function(ctx, stack) {
// The main thread starts during bootstrap and don't allow calling start() // The main thread starts during bootstrap and don't allow calling start()
// on already running threads. // on already running threads.
if (thread === ctx.runtime.mainThread || thread.alive) if (thread === ctx.runtime.mainThread || thread.alive)
ctx.raiseException("java/lang/IllegalThreadStateException"); ctx.raiseExceptionAndYield("java/lang/IllegalThreadStateException");
thread.alive = true; thread.alive = true;
thread.pid = util.id(); thread.pid = util.id();
var run = CLASSES.getMethod(thread.class, "run", "()V", false, true); var run = CLASSES.getMethod(thread.class, "run", "()V", false, true);