1
0
mirror of https://github.com/quinton-ashley/java2js synced 2024-12-29 10:11:54 +01:00
This commit is contained in:
Quinton Ashley 2021-09-24 00:36:29 -05:00
parent e2ed130148
commit 159919e856
29 changed files with 93 additions and 119 deletions

20
ide.js
View File

@ -1,9 +1,13 @@
window.ide = {};
ide.log = document.getElementById('javaConsole');
ide.file0 = document.getElementById('javaFile');
(async () => {
window.ide = {};
ide.log = document.getElementById('javaConsole');
ide.file0 = document.getElementById('javaFile');
ide.file0.onchange = () => {
ide.log.value = '';
let file = ide.file0.value;
jdk.run(file);
};
await jdk.init();
ide.file0.onchange = () => {
ide.log.value = '';
let file = ide.file0.value;
jdk.run(file);
};
})();

122
jdk.js
View File

@ -45,7 +45,9 @@
/* JDK implementation in modern JavaScript */
class JDK {
constructor() {
constructor() {}
async init() {
this.java = {};
let pkgs = ['com', 'lang', 'org', 'io', 'util'];
for (let pkg of pkgs) {
@ -76,50 +78,23 @@
for (let name of names) {
lang.push('java.lang.' + name);
}
this.import(lang);
await this.import(lang);
} catch (e) {}
// stub main for now
this.main = () => {};
this.load();
}
load() {
let ready = 0;
// load all imported classes
for (let className in this.imports) {
let imp = this.imports[className];
if (imp.classPath) {
imp.classPath = className.split('.');
}
if (imp.ready) {
ready++;
continue;
}
if (imp.load) {
try {
imp.load();
} catch (e) {
console.log(e);
continue;
}
imp.load = null;
imp.ready = true;
ready++;
}
}
// some classes may load slower than others,
// wait for them all before launching the Java program
if (ready != Object.keys(this.imports).length) {
let _this = this;
setTimeout(() => {
_this.load();
}, 100);
} else {
this.launch();
}
}
// 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();
// }
launch() {
// make java.lang classes global
@ -144,15 +119,15 @@
return _class;
}
import(classNames) {
async import(classNames) {
if (!classNames) return;
if (typeof classNames == 'string') {
classNames = [classNames];
}
let ready = 0;
let classes = [];
for (let className of classNames) {
log('importing ' + className);
let imp = this.imports[className];
if (imp) {
// class is ready for use
@ -170,34 +145,29 @@
}
src += '.js';
const getJS = new Promise((resolve, reject) => {
const script = document.createElement('script');
document.body.appendChild(script);
script.onload = resolve;
script.onerror = reject;
script.async = true;
script.src = src;
});
const loadJS = () => {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
document.body.appendChild(script);
script.onload = resolve;
script.onerror = reject;
script.async = true;
script.src = src;
});
};
getJS.then(() => {});
}
await loadJS();
if (ready != classNames.length) {
throw 'loading java classes';
}
await imp.load();
let classes = [];
for (let className of classNames) {
let imp = this.imports[className];
classes.push(this.getClass(imp.classPath));
}
if (classNames.length == 1) {
classes = classes[0];
}
if (classNames.length == 1) classes = classes[0];
return classes;
}
run(file) {
async run(file) {
let classLine = file.indexOf('public class');
let imports = file.slice(0, classLine);
imports = imports.match(/(?<=^import )[^;]*/gm) || [];
@ -205,17 +175,6 @@
let userName = window?.QuintOS?.userName || 'quinton-ashley';
let className = file.slice(classLine + 13, file.indexOf(' {', classLine + 13));
let prefix = `(jdk.imports['com.${userName}.${className}'] = {}).load = () => {\n\n`;
// handle Java class imports
for (let i = 0; i < imports.length; i++) {
let imp = imports[i];
let impPath = imp.split('.');
let impName = impPath[impPath.length - 1];
prefix += `let ${impName} = jdk.import('${imp}');\n`;
}
prefix += '\n';
// hacky support for Java 15 triple quotes
file = file.replaceAll(/"""([^"]*)"""/g, (match, str) => {
str = str.replaceAll(/(.*)(\n|$)/g, '"$1\\n"+').slice(0, -1);
@ -234,8 +193,6 @@
// log(file);
let suffix = `\njdk.main = ${className}.main;\n}`;
window.file0 = file;
let trans = java_to_javascript(file);
@ -245,14 +202,27 @@
trans = trans.replace(/(\([^\)]*\) =>)/gm, 'async $1');
trans = trans.replace(/([\w_\$]+\.next(Int|Float|Double|Line|Short|Long)*\(\))/gm, 'await $1');
let prefix = `((jdk.imports['com.${userName}.${className}'] = {}).load = async () => {\n\n`;
// handle Java class imports
for (let i = 0; i < imports.length; i++) {
let imp = imports[i];
let impPath = imp.split('.');
let impName = impPath[impPath.length - 1];
prefix += `let ${impName} = await jdk.import('${imp}');\n`;
}
prefix += '\n';
let suffix = `\njdk.main = ${className}.main;\njdk.launch();\n})();`;
trans = prefix + trans + suffix;
log(trans);
try {
eval(trans);
this.load();
} catch (e) {
console.error(e);
if (window?.ide) ide.log.value += e;
}
}

View File

@ -1,4 +1,4 @@
jdk.imports['java.io.File'].load = () => {
jdk.imports['java.io.File'].load = async () => {
class File {
constructor(file) {
this.absPath = file;

View File

@ -1,4 +1,4 @@
jdk.imports['java.io.InputStream'].load = () => {
jdk.imports['java.io.InputStream'].load = async () => {
class InputStream {
constructor() {
this.reset();

View File

@ -1,4 +1,4 @@
jdk.imports['java.io.PrintStream'].load = () => {
jdk.imports['java.io.PrintStream'].load = async () => {
class PrintStream {
constructor() {
this.log = '';

View File

@ -1,4 +1,4 @@
jdk.imports['java.lang.Character'].load = () => {
jdk.imports['java.lang.Character'].load = async () => {
class Character {}
Character.isDigit = (c) => {
c = c.charCodeAt(0);

View File

@ -1,4 +1,4 @@
jdk.imports['java.lang.Double'].load = () => {
jdk.imports['java.lang.Double'].load = async () => {
class Double {
constructor() {
throw 'new Double() not supported';

View File

@ -1,4 +1,4 @@
jdk.imports['java.lang.Float'].load = () => {
jdk.imports['java.lang.Float'].load = async () => {
class Float {}
Float.parseFloat = (d) => {
return parseFloat(d);

View File

@ -1,4 +1,4 @@
jdk.imports['java.lang.Integer'].load = () => {
jdk.imports['java.lang.Integer'].load = async () => {
class Integer {}
Integer.parseInt = (d) => {
return parseInt(d);

View File

@ -1,4 +1,4 @@
jdk.imports['java.lang.Long'].load = () => {
jdk.imports['java.lang.Long'].load = async () => {
class Long {}
Long.parseLong = (d) => {
return parseInt(d);

View File

@ -1,4 +1,4 @@
jdk.imports['java.lang.Short'].load = () => {
jdk.imports['java.lang.Short'].load = async () => {
class Short {}
Short.parseShort = (d) => {
return parseInt(d);

View File

@ -1,4 +1,4 @@
jdk.imports['java.lang.String'].load = () => {};
jdk.imports['java.lang.String'].load = async () => {};
// String is special, I just extended js String prototype
String.prototype.hashCode = () => {
let h = this._hashCode;

View File

@ -1,4 +1,4 @@
jdk.imports['java.lang.StringBuilder'].load = () => {
jdk.imports['java.lang.StringBuilder'].load = async () => {
class StringBuilder {
constructor() {
this._str = '';

View File

@ -1,7 +1,7 @@
jdk.imports['java.lang.System'].load = () => {
const Formatter = jdk.import('java.util.Formatter');
const InputStream = jdk.import('java.io.InputStream');
const PrintStream = jdk.import('java.io.PrintStream');
jdk.imports['java.lang.System'].load = async () => {
const Formatter = await jdk.import('java.util.Formatter');
const InputStream = await jdk.import('java.io.InputStream');
const PrintStream = await jdk.import('java.io.PrintStream');
class System {}

View File

@ -1,4 +1,4 @@
jdk.imports['java.lang.Thread'].load = () => {
jdk.imports['java.lang.Thread'].load = async () => {
class Thread {
async sleep(millis) {
await setTimeout(millis);

View File

@ -1,5 +1,5 @@
jdk.imports['java.util.AbstractList'].load = () => {
const Itr = jdk.import('java.util.Itr');
jdk.imports['java.util.AbstractList'].load = async () => {
const Itr = await jdk.import('java.util.Itr');
class AbstractList {
constructor() {

View File

@ -1,5 +1,5 @@
jdk.imports['java.util.ArrayList'].load = () => {
let AbstractList = jdk.import('java.util.AbstractList');
jdk.imports['java.util.ArrayList'].load = async () => {
let AbstractList = await jdk.import('java.util.AbstractList');
class ArrayList extends AbstractList {
constructor(...args) {

View File

@ -1,4 +1,4 @@
jdk.imports['java.util.Arrays'].load = () => {
jdk.imports['java.util.Arrays'].load = async () => {
class Arrays {
fill(data, begin, nbElem, param) {
const max = begin + nbElem;

View File

@ -1,4 +1,4 @@
jdk.imports['java.util.Collections'].load = () => {
jdk.imports['java.util.Collections'].load = async () => {
class Collections {
sort(list) {
if (!list.size()) return;

View File

@ -1,5 +1,5 @@
jdk.imports['java.util.Formatter'].load = () => {
const IllegalFormatException = jdk.import('java.util.IllegalFormatException');
jdk.imports['java.util.Formatter'].load = async () => {
const IllegalFormatException = await jdk.import('java.util.IllegalFormatException');
class Formatter {
format(format, ...args) {

View File

@ -1,4 +1,4 @@
jdk.imports['java.util.HashMap'].load = () => {
jdk.imports['java.util.HashMap'].load = async () => {
class HashMap {
constructor() {
this.content = {};

View File

@ -1,4 +1,4 @@
jdk.imports['java.util.HashSet'].load = () => {
jdk.imports['java.util.HashSet'].load = async () => {
class HashSet {
constructor() {
this.content = {};

View File

@ -1,4 +1,4 @@
jdk.imports['java.util.IllegalFormatException'].load = () => {
jdk.imports['java.util.IllegalFormatException'].load = async () => {
// TODO import and extend exception
class IllegalFormatException {

View File

@ -1,4 +1,4 @@
jdk.imports['java.util.Itr'].load = () => {
jdk.imports['java.util.Itr'].load = async () => {
class Itr {
constructor(list) {
this.cursor = 0;

View File

@ -1,5 +1,5 @@
jdk.imports['java.util.LinkedList'].load = () => {
let AbstractList = jdk.import('java.util.AbstractList');
jdk.imports['java.util.LinkedList'].load = async () => {
let AbstractList = await jdk.import('java.util.AbstractList');
class LinkedList extends AbstractList {
constructor(...args) {

View File

@ -1,4 +1,4 @@
jdk.imports['java.util.Random'].load = () => {
jdk.imports['java.util.Random'].load = async () => {
class Random {
constructor() {
this.seed = undefined;

View File

@ -1,5 +1,5 @@
jdk.imports['java.util.Scanner'].load = () => {
const File = jdk.import('java.io.File');
jdk.imports['java.util.Scanner'].load = async () => {
const File = await jdk.import('java.io.File');
class Scanner {
constructor(input) {

View File

@ -1,4 +1,4 @@
jdk.imports['java.util.Stack'].load = () => {
jdk.imports['java.util.Stack'].load = async () => {
class Stack {
constructor() {
this.content = new Array();

View File

@ -1,6 +1,6 @@
{
"name": "java2js",
"version": "1.0.3",
"version": "1.0.4",
"description": "Converts Java to JavaScript with support for p5.js and QuintOS.",
"main": "java2js.js",
"scripts": {