mirror of
https://github.com/quinton-ashley/java2js
synced 2024-12-29 10:11:54 +01:00
1.1.9
This commit is contained in:
parent
ba69a3c8b0
commit
8de0c299bb
31
README.md
31
README.md
@ -1,8 +1,10 @@
|
||||
# Java to Javascript
|
||||
# Java to JavaScript (java2js)
|
||||
|
||||
I've built on top of the [java-to-javascript](https://github.com/wyattades/java-to-javascript) transpiler by @wyattades and got inspiration from the barebones JDK (Java Development Kit) implementation in [java2javascript](https://github.com/java2script/java2script) by @BobHanson, @zhourenjian, @abego, and others.
|
||||
`java2js` can translate simple Java programs to JavaScript and runs them using a JavaScript based JDK.
|
||||
|
||||
I created this project so intro level computer science students could write Java code but still use my [QuintOS](https://github.com/quinton-ashley/quintos) retro game engine library, which is web based. Yes, I went to all this trouble just so my students don't have to run their programs in a boring Java console! To achieve this I've been working on a JDK implementation in modern Javascript.
|
||||
I made significant improvements to the [java-to-javascript](https://github.com/wyattades/java-to-javascript) transpiler by @wyattades. I also did a modern JS implementation of the fundamental classes in the JDK (Java Development Kit), inspired by [java2javascript](https://github.com/java2script/java2script) by @BobHanson, @zhourenjian, @abego, and others.
|
||||
|
||||
I created this project so intro level computer science students could write Java code but still use my [QuintOS](https://github.com/quinton-ashley/quintos) retro game engine library, which is web based.
|
||||
|
||||
## Java Classes Included in the JS JDK
|
||||
|
||||
@ -37,13 +39,13 @@ I created this project so intro level computer science students could write Java
|
||||
|
||||
## API
|
||||
|
||||
### jdk.init(root)
|
||||
### await jdk.init(root)
|
||||
|
||||
- root (optional) can be a local path or url to the parent folder of the JS `jdk` folder, by default it links to 'https://unpkg.com/java2js' (this package) so you don't need to change it
|
||||
- root (optional) path to the parent folder of the JS `jdk` folder, by default it is `./` you could also link to this package online 'https://unpkg.com/java2js'
|
||||
|
||||
This function imports much of the standard Java lang classes into the global scope. You must use it before translating or running files.
|
||||
|
||||
### jdk.translate(javaFile)
|
||||
### await jdk.translate(javaFile)
|
||||
|
||||
- javaFile is a string with contents of a Java file
|
||||
|
||||
@ -59,9 +61,22 @@ Loads the JS class file but doesn't run the main method.
|
||||
|
||||
Runs the main method with optional JVM arguments.
|
||||
|
||||
## Features
|
||||
|
||||
- imports
|
||||
- static classes
|
||||
- static methods
|
||||
- array literals
|
||||
- arrays with initial size
|
||||
- two dimensional arrays
|
||||
- lambda arrow functions
|
||||
- triple quotes
|
||||
|
||||
## Known limitations
|
||||
|
||||
- casting to int truncation workaround requires parenthesis around the number being cast `int x = (int) (Math.random() * 100);`
|
||||
- not very good error reporting
|
||||
|
||||
- casting to int (truncation) requires parenthesis around the number being cast `int x = (int) (Math.random() * 100);`
|
||||
|
||||
- no support for method overloading, though a workaround might be possible by making a function with the og name route to each of the variations of the overloaded function
|
||||
|
||||
@ -71,7 +86,7 @@ Runs the main method with optional JVM arguments.
|
||||
|
||||
- no third level static classes
|
||||
|
||||
- not much error checking
|
||||
- no method can be named `.length()` because it will be replaced with `.length` for getting the length of Strings in JS
|
||||
|
||||
## Contribute
|
||||
|
||||
|
7
ide.js
7
ide.js
@ -3,8 +3,11 @@
|
||||
await jdk.init();
|
||||
|
||||
let file0 = document.getElementById('javaFile');
|
||||
file0.onchange = () => {
|
||||
file0.onchange = async () => {
|
||||
jdk.log.value = '';
|
||||
jdk.run(file0.value);
|
||||
let translation = await jdk.translate(file0.value);
|
||||
console.log(translation);
|
||||
jdk.load(translation);
|
||||
jdk.run();
|
||||
};
|
||||
})();
|
||||
|
52
jdk.js
52
jdk.js
@ -48,7 +48,7 @@
|
||||
constructor() {}
|
||||
|
||||
async init(root) {
|
||||
this.root = root || 'https://unpkg.com/java2js';
|
||||
this.root = root || './';
|
||||
this.java = {};
|
||||
let pkgs = ['com', 'io', 'lang', 'org', 'security', 'time', 'util'];
|
||||
for (let pkg of pkgs) {
|
||||
@ -98,17 +98,6 @@
|
||||
this.main = () => {};
|
||||
}
|
||||
|
||||
// async load() {
|
||||
// // load all imported classes
|
||||
// for (let className in this.imports) {
|
||||
// let imp = this.imports[className];
|
||||
// imp.classPath ??= className.split('.');
|
||||
// await imp.load();
|
||||
// }
|
||||
|
||||
// this.launch();
|
||||
// }
|
||||
|
||||
run(jvmArgs) {
|
||||
this.main(jvmArgs);
|
||||
}
|
||||
@ -148,9 +137,9 @@
|
||||
return new Promise((resolve, reject) => {
|
||||
const script = document.createElement('script');
|
||||
document.body.appendChild(script);
|
||||
script.async = true;
|
||||
script.onload = resolve;
|
||||
script.onerror = reject;
|
||||
script.async = true;
|
||||
script.src = src;
|
||||
});
|
||||
};
|
||||
@ -172,11 +161,14 @@
|
||||
// bodge fix to avoid getting the index of a commented out class
|
||||
// (only works with normal comments)
|
||||
let classLine = file.indexOf('\npublic class');
|
||||
if (classLine < 0) classLine = file.indexOf('public class');
|
||||
if (classLine < 0) {
|
||||
classLine = file.indexOf('public class');
|
||||
} else {
|
||||
classLine += 1;
|
||||
}
|
||||
let imports = file.slice(0, classLine);
|
||||
imports = imports.match(/(?<=^import )[^;]*/gm) || [];
|
||||
|
||||
let userName = window?.QuintOS?.userName || 'quinton-ashley';
|
||||
let className = file.slice(classLine + 13, file.indexOf(' {', classLine + 13));
|
||||
|
||||
// workaround hack for converting triple quotes to a normal string
|
||||
@ -229,7 +221,6 @@
|
||||
|
||||
// cast to int, truncates the number (just removes decimal value)
|
||||
file = file.replace(/\(int\)\s*/gm, 'Math.floor');
|
||||
file = file.replace(/\(int\)\s*\-/gm, 'Math.ceil');
|
||||
|
||||
let trans = await java_to_javascript(file);
|
||||
|
||||
@ -269,21 +260,9 @@
|
||||
}
|
||||
|
||||
load(trans) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
const script = document.createElement('script');
|
||||
script.async = false;
|
||||
script.onload = function () {
|
||||
// log('loaded: ' + src);
|
||||
resolve();
|
||||
};
|
||||
script.onerror = (e) => {
|
||||
reject(e);
|
||||
};
|
||||
|
||||
script.innerHTML = trans;
|
||||
|
||||
document.body.appendChild(script);
|
||||
});
|
||||
const script = document.createElement('script');
|
||||
script.innerHTML = trans;
|
||||
document.body.appendChild(script);
|
||||
}
|
||||
}
|
||||
window.jdk = new JDK();
|
||||
@ -19131,9 +19110,13 @@
|
||||
|
||||
let asyncMethods = [];
|
||||
if (typeof QuintOS != 'undefined') {
|
||||
// asyncMethods = {
|
||||
// Sprite: ['move']
|
||||
// };
|
||||
asyncMethods = [
|
||||
'alert',
|
||||
'delay',
|
||||
'erase',
|
||||
'eraseRect',
|
||||
'frame',
|
||||
'move',
|
||||
@ -19212,7 +19195,7 @@
|
||||
return `${parseExpr(expr.leftOperand)} ${op} ${parseExpr(expr.rightOperand)}`;
|
||||
case 'MethodInvocation':
|
||||
let str = '';
|
||||
if (asyncMethods.includes(expr.name.identifier)) {
|
||||
if (asyncMethods.includes(expr.name.identifier) && !expr.isInConstructor) {
|
||||
str += 'await ';
|
||||
}
|
||||
if (expr.expression) {
|
||||
@ -19354,10 +19337,13 @@
|
||||
const statements = [];
|
||||
|
||||
for (const stat of block.statements) {
|
||||
if (method && stat.node == 'ExpressionStatement') {
|
||||
stat.expression.isInConstructor = method.constructor;
|
||||
}
|
||||
const str = parseStatement(stat);
|
||||
const arr = Array.isArray(str) ? str : [str];
|
||||
statements.push(...arr.map(semicolon));
|
||||
if (method && !method.isAsync && statements.join('').includes('await')) {
|
||||
if (method && !method.isAsync && !method.constructor && statements.join('').includes('await')) {
|
||||
asyncMethods.push(method.name.identifier);
|
||||
method.isAsync = true;
|
||||
}
|
||||
|
@ -43,10 +43,10 @@ jdk.imports['java.io.PrintStream'].load = async () => {
|
||||
}
|
||||
if (ln) str += '\n';
|
||||
this.log += str;
|
||||
if (window?.ide) {
|
||||
ide.log.value += str;
|
||||
this._onPrint(str.length);
|
||||
if (jdk.log) {
|
||||
jdk.log.value += str;
|
||||
}
|
||||
this._onPrint(str.length);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "java2js",
|
||||
"version": "1.1.8",
|
||||
"version": "1.1.9",
|
||||
"description": "Converts Java to JavaScript with support for p5.js and QuintOS.",
|
||||
"main": "jdk.js",
|
||||
"scripts": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user