diff --git a/Makefile b/Makefile index 91c5ecf5..e4782090 100644 --- a/Makefile +++ b/Makefile @@ -64,7 +64,7 @@ build/program.jar.js: program.jar build/jsc.js aot-methods.txt js build/jsc.js -cp java/classes.jar program.jar -d -jf program.jar -mff aot-methods.txt > build/program.jar.js closure: build/classes.jar.js build/j2me.js - java -jar tools/closure.jar --language_in ECMASCRIPT5 -O SHUMWAY_OPTIMIZATIONS build/j2me.js > build/j2me.cc.js \ + java -jar tools/closure.jar --language_in ECMASCRIPT5 -O J2ME_OPTIMIZATIONS build/j2me.js > build/j2me.cc.js \ && mv build/j2me.cc.js build/j2me.js java -jar tools/closure.jar --language_in ECMASCRIPT5 -O SIMPLE build/classes.jar.js > build/classes.jar.cc.js \ && mv build/classes.jar.cc.js build/classes.jar.js diff --git a/README.md b/README.md index 9af221ac..596748c2 100644 --- a/README.md +++ b/README.md @@ -205,8 +205,8 @@ To use it, first install a recent version of the `make closure` compiles some JavaScript code with the Closure compiler. -To use it, first download Shumway's version of the compiler to tools/closure.jar: +To use it, first download this custom version of the compiler to tools/closure.jar: ``` -wget https://github.com/mozilla/shumway/raw/master/utils/closure.jar -P tools/ +wget https://github.com/mykmelez/closure-compiler/releases/download/v0.1/closure.jar -P tools/ ``` diff --git a/jit/analyze.ts b/jit/analyze.ts index 4ad1e9b6..3125e7a9 100644 --- a/jit/analyze.ts +++ b/jit/analyze.ts @@ -32,10 +32,7 @@ module J2ME { "com/sun/midp/util/isolate/InterIsolateMutex.lock0.(I)V": YieldReason.Root, "com/sun/midp/events/NativeEventMonitor.waitForNativeEvent.(Lcom/sun/midp/events/NativeEvent;)I": YieldReason.Root, "com/sun/midp/io/j2me/push/ConnectionRegistry.poll0.(J)I": YieldReason.Root, - "com/sun/midp/rms/RecordStoreUtil.exists.(Ljava/lang/String;Ljava/lang/String;I)Z": YieldReason.Root, "com/sun/midp/rms/RecordStoreFile.openRecordStoreFile.(Ljava/lang/String;Ljava/lang/String;I)I": YieldReason.Root, - "com/sun/midp/rms/RecordStoreFile.commitWrite.(I)V": YieldReason.Root, - "com/sun/midp/rms/RecordStoreFile.closeFile.(I)V": YieldReason.Root, "com/ibm/oti/connection/file/Connection.truncateImpl.([BJ)V": YieldReason.Root, "com/ibm/oti/connection/file/FCInputStream.openImpl.([B)I": YieldReason.Root, "com/ibm/oti/connection/file/FCOutputStream.openImpl.([B)I": YieldReason.Root, diff --git a/libs/fs.js b/libs/fs.js index 676b45ec..021c26a4 100644 --- a/libs/fs.js +++ b/libs/fs.js @@ -383,7 +383,7 @@ var fs = (function() { } } - var newArray = new Uint8Array(newBufferSize); + var newArray = new Int8Array(newBufferSize); newArray.set(this.array); this.array = newArray; @@ -463,7 +463,7 @@ var fs = (function() { var fd = openedFiles.push({ dirty: false, path: path, - buffer: new FileBuffer(new Uint8Array(reader.result)), + buffer: new FileBuffer(new Int8Array(reader.result)), mtime: record.mtime, size: record.size, position: 0, diff --git a/midp/codec.js b/midp/codec.js index 4228e51b..735ff70e 100644 --- a/midp/codec.js +++ b/midp/codec.js @@ -66,7 +66,7 @@ DataEncoder.prototype.getData = function() { } var DataDecoder = function(data, offset, length) { - this.data = JSON.parse(util.decodeUtf8(new Uint8Array(data.buffer, offset, length))); + this.data = JSON.parse(util.decodeUtf8(new Int8Array(data.buffer, offset, length))); this.current = []; } diff --git a/midp/crypto.js b/midp/crypto.js index 11f8e0cc..95916e18 100644 --- a/midp/crypto.js +++ b/midp/crypto.js @@ -99,7 +99,7 @@ Native["com/sun/midp/crypto/SHA.nativeFinal.([BII[BI[I[I[I[I)V"] = function(inBu } var hash = hasher.digest(); - outBuf.set(new Uint8Array(hash.buffer), outOff); + outBuf.set(new Int8Array(hash.buffer), outOff); // XXX Call the reset method instead to completely reset the object. data.set(MIDP.emptyDataArray); @@ -120,7 +120,7 @@ Native["com/sun/midp/crypto/SHA.nativeClone.([I)V"] = function(data) { }; Native["com/sun/midp/crypto/MD5.nativeUpdate.([BII[I[I[I[I)V"] = function(inBuf, inOff, inLen, state, num, count, data) { - MIDP.getMD5Hasher(data).update(MIDP.bin2String(new Uint8Array(inBuf.subarray(inOff, inOff + inLen)))); + MIDP.getMD5Hasher(data).update(MIDP.bin2String(new Int8Array(inBuf.subarray(inOff, inOff + inLen)))); }; Native["com/sun/midp/crypto/MD5.nativeFinal.([BII[BI[I[I[I[I)V"] = function(inBuf, inOff, inLen, outBuf, outOff, state, num, count, data) { diff --git a/midp/fs.js b/midp/fs.js index 8845ccee..26191b1b 100644 --- a/midp/fs.js +++ b/midp/fs.js @@ -38,11 +38,8 @@ Native["com/sun/midp/midletsuite/MIDletSuiteStorage.getSecureFilenameBase.(I)Lja Native["com/sun/midp/rms/RecordStoreUtil.exists.(Ljava/lang/String;Ljava/lang/String;I)Z"] = function(filenameBase, name, ext) { - asyncImpl("Z", new Promise(function(resolve, reject) { - var path = RECORD_STORE_BASE + "/" + util.fromJavaString(filenameBase) + "/" + util.fromJavaString(name) + "." + ext; - // return fs.exists(path) ? 1 : 0; - resolve(fs.exists(path) ? 1 : 0); - })); + var path = RECORD_STORE_BASE + "/" + util.fromJavaString(filenameBase) + "/" + util.fromJavaString(name) + "." + ext; + return fs.exists(path) ? 1 : 0; }; Native["com/sun/midp/rms/RecordStoreUtil.deleteFile.(Ljava/lang/String;Ljava/lang/String;I)V"] = @@ -134,17 +131,11 @@ Native["com/sun/midp/rms/RecordStoreFile.writeBytes.(I[BII)V"] = function(handle }; Native["com/sun/midp/rms/RecordStoreFile.commitWrite.(I)V"] = function(handle) { - asyncImpl("V", new Promise(function(resolve, reject) { - fs.flush(handle); - resolve(); - })); + fs.flush(handle); }; Native["com/sun/midp/rms/RecordStoreFile.closeFile.(I)V"] = function(handle) { - asyncImpl("V", new Promise(function(resolve, reject) { - fs.close(handle); - resolve(); - })); + fs.close(handle); }; Native["com/sun/midp/rms/RecordStoreFile.truncateFile.(II)V"] = function(handle, size) { @@ -493,7 +484,7 @@ Native["com/ibm/oti/connection/file/FCInputStream.readByteImpl.(I)I"] = function var data = fs.read(fd, curpos, curpos+1); - return (data.byteLength > 0) ? data[0] : -1; + return (data.byteLength > 0) ? (data[0] & 0xFF) : -1; }; Native["com/ibm/oti/connection/file/FCInputStream.closeImpl.(I)V"] = function(fd) { @@ -551,7 +542,7 @@ Native["com/ibm/oti/connection/file/FCOutputStream.syncImpl.(I)V"] = function(fd }; Native["com/ibm/oti/connection/file/FCOutputStream.writeByteImpl.(II)V"] = function(val, fd) { - var buf = new Uint8Array(1); + var buf = new Int8Array(1); buf[0] = val; fs.write(fd, buf); }; diff --git a/midp/localmsg.js b/midp/localmsg.js index 0733a11c..37aba1ea 100644 --- a/midp/localmsg.js +++ b/midp/localmsg.js @@ -174,7 +174,7 @@ NokiaMessagingLocalMsgConnection.prototype.sendMessageToServer = function(messag default: console.error("(nokia.messaging) event " + name + " not implemented " + - util.decodeUtf8(new Uint8Array(message.data.buffer, message.offset, message.length))); + util.decodeUtf8(new Int8Array(message.data.buffer, message.offset, message.length))); return; } @@ -381,7 +381,7 @@ NokiaPhoneStatusLocalMsgConnection.prototype.sendMessageToServer = function(mess default: console.error("(nokia.phone-status) Query " + decoder.getName() + " not implemented " + - util.decodeUtf8(new Uint8Array(message.data.buffer, message.offset, message.length))); + util.decodeUtf8(new Int8Array(message.data.buffer, message.offset, message.length))); break; } } else if (queryKind === "Disable") { @@ -407,7 +407,7 @@ NokiaPhoneStatusLocalMsgConnection.prototype.sendMessageToServer = function(mess default: console.error("(nokia.phone-status) event " + name + " not implemented " + - util.decodeUtf8(new Uint8Array(message.data.buffer, message.offset, message.length))); + util.decodeUtf8(new Int8Array(message.data.buffer, message.offset, message.length))); return; } }; @@ -526,7 +526,7 @@ NokiaContactsLocalMsgConnection.prototype.sendMessageToServer = function(message var numEntries = decoder.getValue(DataType.ULONG); if (numEntries !== 1) { console.error("(nokia.contacts) event getFirst with numEntries != 1 not implemented " + - util.decodeUtf8(new Uint8Array(message.data.buffer, message.offset, message.length))); + util.decodeUtf8(new Int8Array(message.data.buffer, message.offset, message.length))); } this.getFirstOrNext(trans_id, "getFirst"); @@ -542,12 +542,12 @@ NokiaContactsLocalMsgConnection.prototype.sendMessageToServer = function(message var includeStartEntry = decoder.getValue(DataType.BOOLEAN); if (includeStartEntry == 1) { console.error("(nokia.contacts) event getNext with includeStartEntry == true not implemented " + - util.decodeUtf8(new Uint8Array(message.data.buffer, message.offset, message.length))); + util.decodeUtf8(new Int8Array(message.data.buffer, message.offset, message.length))); } var numEntries = decoder.getValue(DataType.ULONG); if (numEntries !== 1) { console.error("(nokia.contacts) event getNext with numEntries != 1 not implemented " + - util.decodeUtf8(new Uint8Array(message.data.buffer, message.offset, message.length))); + util.decodeUtf8(new Int8Array(message.data.buffer, message.offset, message.length))); } this.getFirstOrNext(trans_id, "getNext"); @@ -555,7 +555,7 @@ NokiaContactsLocalMsgConnection.prototype.sendMessageToServer = function(message default: console.error("(nokia.contacts) event " + name + " not implemented " + - util.decodeUtf8(new Uint8Array(message.data.buffer, message.offset, message.length))); + util.decodeUtf8(new Int8Array(message.data.buffer, message.offset, message.length))); return; } } @@ -684,7 +684,7 @@ NokiaFileUILocalMsgConnection.prototype.sendMessageToServer = function(message) default: console.error("(nokia.file-ui) event " + name + " not implemented " + - util.decodeUtf8(new Uint8Array(message.data.buffer, message.offset, message.length))); + util.decodeUtf8(new Int8Array(message.data.buffer, message.offset, message.length))); return; } }; @@ -756,7 +756,7 @@ NokiaImageProcessingLocalMsgConnection.prototype.sendMessageToServer = function( if (aspect != "FullImage" && aspect != "LockToPartialView") { console.error("(nokia.image-processing) event " + name + " with aspect != 'FullImage' or 'LockToPartialView' not implemented " + - util.decodeUtf8(new Uint8Array(message.data.buffer, message.offset, message.length))); + util.decodeUtf8(new Int8Array(message.data.buffer, message.offset, message.length))); return; } @@ -859,7 +859,7 @@ NokiaImageProcessingLocalMsgConnection.prototype.sendMessageToServer = function( default: console.error("(nokia.image-processing) event " + name + " not implemented " + - util.decodeUtf8(new Uint8Array(message.data.buffer, message.offset, message.length))); + util.decodeUtf8(new Int8Array(message.data.buffer, message.offset, message.length))); return; } }; @@ -913,7 +913,7 @@ NokiaProductInfoLocalMsgConnection.prototype.sendMessageToServer = function(mess break; default: console.error("(nokia.status-info) event " + name + " not implemented " + - util.decodeUtf8(new Uint8Array(message.data.buffer, message.offset, message.length))); + util.decodeUtf8(new Int8Array(message.data.buffer, message.offset, message.length))); return; } }; @@ -1038,7 +1038,7 @@ NokiaActiveStandbyLocalMsgConnection.prototype.sendMessageToServer = function(me default: console.error("(nokia.active-standby) event " + name + " not implemented " + - util.decodeUtf8(new Uint8Array(message.data.buffer, message.offset, message.length))); + util.decodeUtf8(new Int8Array(message.data.buffer, message.offset, message.length))); return; } } @@ -1124,7 +1124,7 @@ Native["org/mozilla/io/LocalMsgConnection.sendData.([BII)V"] = function(data, of this.connection.sendMessageToClient(message); } else { if (MIDP.FakeLocalMsgServers.indexOf(this.protocolName) != -1) { - console.warn("sendData (" + util.decodeUtf8(new Uint8Array(data.buffer, offset, length)) + ") to an unimplemented localmsg server (" + this.protocolName + ")"); + console.warn("sendData (" + util.decodeUtf8(new Int8Array(data.buffer, offset, length)) + ") to an unimplemented localmsg server (" + this.protocolName + ")"); } this.connection.sendMessageToServer(message); diff --git a/midp/media.js b/midp/media.js index 91e858ea..aba269d1 100644 --- a/midp/media.js +++ b/midp/media.js @@ -714,7 +714,7 @@ PlayerContainer.prototype.getRecordedSize = function() { PlayerContainer.prototype.getRecordedData = function(offset, size, buffer) { var toRead = (size < this.audioRecorder.data.length) ? size : this.audioRecorder.data.byteLength; buffer.set(this.audioRecorder.data.subarray(0, toRead), offset); - this.audioRecorder.data = new Uint8Array(this.audioRecorder.data.buffer.slice(toRead)); + this.audioRecorder.data = new Int8Array(this.audioRecorder.data.buffer.slice(toRead)); }; PlayerContainer.prototype.startSnapshot = function(imageType) { @@ -732,7 +732,7 @@ PlayerContainer.prototype.getDuration = function() { var AudioRecorder = function(aMimeType) { this.mimeType = aMimeType || "audio/3gpp"; this.eventListeners = {}; - this.data = new Uint8Array(); + this.data = new Int8Array(); this.sender = DumbPipe.open("audiorecorder", { mimeType: this.mimeType }, this.recipient.bind(this)); @@ -816,7 +816,7 @@ AudioRecorder.prototype.stop = function() { // The audio data we received are encoded with a proper format, it doesn't // make sense to concatenate them like the socket, so let just override // the buffered data here. - var data = new Uint8Array(message.data); + var data = new Int8Array(message.data); if (this.getContentType() === "audio/amr") { data = Media.convert3gpToAmr(data); } @@ -854,7 +854,7 @@ AudioRecorder.prototype.pause = function() { // The audio data we received are encoded with a proper format, it doesn't // make sense to concatenate them like the socket, so let just override // the buffered data here. - this.data = new Uint8Array(message.data); + this.data = new Int8Array(message.data); resolve(1); }.bind(this); diff --git a/midp/midp.js b/midp/midp.js index a9f93f10..8b73e555 100644 --- a/midp/midp.js +++ b/midp/midp.js @@ -97,7 +97,7 @@ Native["com/sun/midp/jarutil/JarReader.readJarEntry0.(Ljava/lang/String;Ljava/la if (!bytes) throw $.newIOException(); var length = bytes.byteLength; - var data = new Uint8Array(bytes); + var data = new Int8Array(bytes); var array = J2ME.newByteArray(length); for (var n = 0; n < length; ++n) array[n] = data[n]; @@ -535,7 +535,7 @@ Native["com/sun/midp/util/ResourceHandler.loadRomizedResource0.(Ljava/lang/Strin } var len = data.byteLength; var bytes = J2ME.newByteArray(len); - var src = new Uint8Array(data); + var src = new Int8Array(data); for (var n = 0; n < bytes.byteLength; ++n) bytes[n] = src[n]; return bytes; @@ -862,33 +862,29 @@ Native["com/sun/midp/util/isolate/InterIsolateMutex.getID0.(Ljava/lang/String;)I Native["com/sun/midp/util/isolate/InterIsolateMutex.lock0.(I)V"] = function(id) { var ctx = $.ctx; + var mutex; + for (var i = 0; i < MIDP.InterIsolateMutexes.length; i++) { + if (MIDP.InterIsolateMutexes[i].id == id) { + mutex = MIDP.InterIsolateMutexes[i]; + break; + } + } + + if (!mutex) { + throw $.newIllegalStateException("Invalid mutex ID"); + } + + if (!mutex.locked) { + mutex.locked = true; + mutex.holder = ctx.runtime.isolate.id; + return; + } + + if (mutex.holder == ctx.runtime.isolate.id) { + throw $.newRuntimeException("Attempting to lock mutex twice within the same Isolate"); + } + asyncImpl("V", new Promise(function(resolve, reject) { - ctx.setAsCurrentContext(); - var mutex; - for (var i = 0; i < MIDP.InterIsolateMutexes.length; i++) { - if (MIDP.InterIsolateMutexes[i].id == id) { - mutex = MIDP.InterIsolateMutexes[i]; - break; - } - } - - if (!mutex) { - reject($.newIllegalStateException("Invalid mutex ID")); - return; - } - - if (!mutex.locked) { - mutex.locked = true; - mutex.holder = ctx.runtime.isolate.id; - resolve(); - return; - } - - if (mutex.holder == ctx.runtime.isolate.id) { - reject($.newRuntimeException("Attempting to lock mutex twice within the same Isolate")); - return; - } - mutex.waiting.push(function() { mutex.locked = true; mutex.holder = ctx.runtime.isolate.id; diff --git a/midp/socket.js b/midp/socket.js index d558e8b0..60196c9f 100644 --- a/midp/socket.js +++ b/midp/socket.js @@ -65,7 +65,7 @@ Native["com/sun/midp/io/j2me/socket/Protocol.open0.([BI)V"] = function(ipBytes, this.options[SOCKET_OPT.RCVBUF] = 8192; this.options[SOCKET_OPT.SNDBUF] = 8192; - this.data = new Uint8Array(); + this.data = new Int8Array(); this.waitingData = null; this.socket.onopen = function() { @@ -88,11 +88,11 @@ Native["com/sun/midp/io/j2me/socket/Protocol.open0.([BI)V"] = function(ipBytes, this.socket.ondata = (function(message) { // console.log("this.socket.ondata: " + JSON.stringify(message)); if (this.data.byteLength === 0) { - this.data = new Uint8Array(message.data); + this.data = new Int8Array(message.data); } else { - var newArray = new Uint8Array(this.data.byteLength + message.data.byteLength); + var newArray = new Int8Array(this.data.byteLength + message.data.byteLength); newArray.set(this.data); - newArray.set(new Uint8Array(message.data), this.data.byteLength); + newArray.set(new Int8Array(message.data), this.data.byteLength); this.data = newArray; } diff --git a/native.js b/native.js index e96a4685..ba59af19 100644 --- a/native.js +++ b/native.js @@ -280,13 +280,6 @@ Native["java/lang/Object.getClass.()Ljava/lang/Class;"] = function() { return J2ME.getRuntimeKlass($.ctx.runtime, this.klass).classObject; }; -Native["java/lang/Object.hashCode.()I"] = function() { - var hashCode = this.hashCode; - while (!hashCode) - hashCode = this.hashCode = util.id(); - return hashCode; -}; - Native["java/lang/Object.wait.(J)V"] = function(timeout) { $.ctx.wait(this, timeout.toNumber()); }; @@ -797,7 +790,7 @@ Native["com/sun/cldc/i18n/j2me/UTF_8_Reader.readNative.([CII)I"] = function(cbuf }; Native["java/io/DataInputStream.bytesToUTF.([B)Ljava/lang/String;"] = function(bytearr) { - var array = new Uint8Array(bytearr.buffer); + var array = new Int8Array(bytearr.buffer); try { return J2ME.newString(util.decodeUtf8Array(array)); } catch(e) { @@ -860,7 +853,7 @@ Native["com/sun/cldc/i18n/j2me/UTF_8_Writer.encodeUTF8.([CII)[B"] = function(cbu var count = 0; while (count < len) { - var outputByte = new Uint8Array(4); // Never more than 4 encoded bytes + var outputByte = new Int8Array(4); // Never more than 4 encoded bytes inputChar = 0xffff & cbuf[off + count]; if (0 != pendingSurrogate) { if (0xdc00 <= inputChar && inputChar <= 0xdfff) { diff --git a/tests/automation.js b/tests/automation.js index e82570ab..b3def76e 100644 --- a/tests/automation.js +++ b/tests/automation.js @@ -70,7 +70,7 @@ var gfxTests = [ ]; var expectedUnitTestResults = [ - { name: "pass", number: 71575 }, + { name: "pass", number: 71574 }, { name: "fail", number: 0 }, { name: "known fail", number: 215 }, { name: "unknown pass", number: 0 } diff --git a/tests/com/sun/midp/publickeystore/TestInputOutputStorage.java b/tests/com/sun/midp/publickeystore/TestInputOutputStorage.java index 8ea00257..f408e209 100644 --- a/tests/com/sun/midp/publickeystore/TestInputOutputStorage.java +++ b/tests/com/sun/midp/publickeystore/TestInputOutputStorage.java @@ -33,7 +33,9 @@ public class TestInputOutputStorage implements Testlet { public void test(TestHarness th) { try { FileConnection file = (FileConnection)Connector.open("file:////prova"); - th.check(!file.exists()); + if (file.exists()) { + file.delete(); + } file.create(); RandomAccessStream ras = new RandomAccessStream(); diff --git a/tests/com/sun/midp/util/isolate/TestInterIsolateMutex.java b/tests/com/sun/midp/util/isolate/TestInterIsolateMutex.java index 579520fd..5d127c2b 100644 --- a/tests/com/sun/midp/util/isolate/TestInterIsolateMutex.java +++ b/tests/com/sun/midp/util/isolate/TestInterIsolateMutex.java @@ -49,6 +49,20 @@ class LockerIsolate2 { } } +class LockerThread extends Thread { + public void run() { + SecurityToken t = SecurityTokenProvider.getToken(); + InterIsolateMutex m = InterIsolateMutex.getInstance(t, "mutex"); + + m.lock(); + try { + // Give the test some time to test waiting for the lock + Thread.sleep(1000); + } catch (Exception e) {} + m.unlock(); + } +} + public class TestInterIsolateMutex implements Testlet { public void test(TestHarness th) { SecurityToken t = SecurityTokenProvider.getToken(); @@ -128,5 +142,59 @@ public class TestInterIsolateMutex implements Testlet { } catch (Exception e) { th.fail("Unexpected exception: " + e); } + + m.unlock(); + + try { + Isolate iso1 = new Isolate("com.sun.midp.util.isolate.LockerIsolate1", new String[] {}); + Isolate iso2 = new Isolate("com.sun.midp.util.isolate.LockerIsolate2", new String[] {}); + + iso2.start(); + iso1.start(); + + m.lock(); + m.unlock(); + + iso2.waitForExit(); + iso1.waitForExit(); + } catch (Exception e) { + th.fail("Unexpected exception: " + e); + } + + try { + Isolate iso = new Isolate("com.sun.midp.util.isolate.LockerIsolate2", new String[] {}); + LockerThread lockerThread = new LockerThread(); + + lockerThread.start(); + + try { + Thread.yield(); + } catch (Exception e) {} + + iso.start(); + + iso.waitForExit(); + lockerThread.join(); + } catch (Exception e) { + th.fail("Unexpected exception: " + e); + } + + try { + Isolate iso = new Isolate("com.sun.midp.util.isolate.LockerIsolate2", new String[] {}); + LockerThread lockerThread = new LockerThread(); + + iso.start(); + + try { + Thread.yield(); + } catch (Exception e) {} + + lockerThread.start(); + + iso.waitForExit(); + lockerThread.join(); + } catch (Exception e) { + th.fail("Unexpected exception: " + e); + } } }