mirror of
https://github.com/quinton-ashley/java2js
synced 2024-12-29 10:11:54 +01:00
1.0.4
This commit is contained in:
parent
e2ed130148
commit
159919e856
20
ide.js
20
ide.js
@ -1,9 +1,13 @@
|
|||||||
window.ide = {};
|
(async () => {
|
||||||
ide.log = document.getElementById('javaConsole');
|
window.ide = {};
|
||||||
ide.file0 = document.getElementById('javaFile');
|
ide.log = document.getElementById('javaConsole');
|
||||||
|
ide.file0 = document.getElementById('javaFile');
|
||||||
|
|
||||||
ide.file0.onchange = () => {
|
await jdk.init();
|
||||||
ide.log.value = '';
|
|
||||||
let file = ide.file0.value;
|
ide.file0.onchange = () => {
|
||||||
jdk.run(file);
|
ide.log.value = '';
|
||||||
};
|
let file = ide.file0.value;
|
||||||
|
jdk.run(file);
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
122
jdk.js
122
jdk.js
@ -45,7 +45,9 @@
|
|||||||
|
|
||||||
/* JDK implementation in modern JavaScript */
|
/* JDK implementation in modern JavaScript */
|
||||||
class JDK {
|
class JDK {
|
||||||
constructor() {
|
constructor() {}
|
||||||
|
|
||||||
|
async init() {
|
||||||
this.java = {};
|
this.java = {};
|
||||||
let pkgs = ['com', 'lang', 'org', 'io', 'util'];
|
let pkgs = ['com', 'lang', 'org', 'io', 'util'];
|
||||||
for (let pkg of pkgs) {
|
for (let pkg of pkgs) {
|
||||||
@ -76,50 +78,23 @@
|
|||||||
for (let name of names) {
|
for (let name of names) {
|
||||||
lang.push('java.lang.' + name);
|
lang.push('java.lang.' + name);
|
||||||
}
|
}
|
||||||
this.import(lang);
|
await this.import(lang);
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
|
|
||||||
// stub main for now
|
// stub main for now
|
||||||
this.main = () => {};
|
this.main = () => {};
|
||||||
|
|
||||||
this.load();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
load() {
|
// async load() {
|
||||||
let ready = 0;
|
// // load all imported classes
|
||||||
// load all imported classes
|
// for (let className in this.imports) {
|
||||||
for (let className in this.imports) {
|
// let imp = this.imports[className];
|
||||||
let imp = this.imports[className];
|
// imp.classPath ??= className.split('.');
|
||||||
if (imp.classPath) {
|
// await imp.load();
|
||||||
imp.classPath = className.split('.');
|
// }
|
||||||
}
|
|
||||||
if (imp.ready) {
|
// this.launch();
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
launch() {
|
launch() {
|
||||||
// make java.lang classes global
|
// make java.lang classes global
|
||||||
@ -144,15 +119,15 @@
|
|||||||
return _class;
|
return _class;
|
||||||
}
|
}
|
||||||
|
|
||||||
import(classNames) {
|
async import(classNames) {
|
||||||
if (!classNames) return;
|
if (!classNames) return;
|
||||||
if (typeof classNames == 'string') {
|
if (typeof classNames == 'string') {
|
||||||
classNames = [classNames];
|
classNames = [classNames];
|
||||||
}
|
}
|
||||||
|
|
||||||
let ready = 0;
|
let classes = [];
|
||||||
|
|
||||||
for (let className of classNames) {
|
for (let className of classNames) {
|
||||||
|
log('importing ' + className);
|
||||||
let imp = this.imports[className];
|
let imp = this.imports[className];
|
||||||
if (imp) {
|
if (imp) {
|
||||||
// class is ready for use
|
// class is ready for use
|
||||||
@ -170,34 +145,29 @@
|
|||||||
}
|
}
|
||||||
src += '.js';
|
src += '.js';
|
||||||
|
|
||||||
const getJS = new Promise((resolve, reject) => {
|
const loadJS = () => {
|
||||||
const script = document.createElement('script');
|
return new Promise((resolve, reject) => {
|
||||||
document.body.appendChild(script);
|
const script = document.createElement('script');
|
||||||
script.onload = resolve;
|
document.body.appendChild(script);
|
||||||
script.onerror = reject;
|
script.onload = resolve;
|
||||||
script.async = true;
|
script.onerror = reject;
|
||||||
script.src = src;
|
script.async = true;
|
||||||
});
|
script.src = src;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
getJS.then(() => {});
|
await loadJS();
|
||||||
}
|
|
||||||
|
|
||||||
if (ready != classNames.length) {
|
await imp.load();
|
||||||
throw 'loading java classes';
|
|
||||||
}
|
|
||||||
|
|
||||||
let classes = [];
|
|
||||||
for (let className of classNames) {
|
|
||||||
let imp = this.imports[className];
|
|
||||||
classes.push(this.getClass(imp.classPath));
|
classes.push(this.getClass(imp.classPath));
|
||||||
}
|
}
|
||||||
if (classNames.length == 1) {
|
|
||||||
classes = classes[0];
|
if (classNames.length == 1) classes = classes[0];
|
||||||
}
|
|
||||||
return classes;
|
return classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
run(file) {
|
async run(file) {
|
||||||
let classLine = file.indexOf('public class');
|
let classLine = file.indexOf('public class');
|
||||||
let imports = file.slice(0, classLine);
|
let imports = file.slice(0, classLine);
|
||||||
imports = imports.match(/(?<=^import )[^;]*/gm) || [];
|
imports = imports.match(/(?<=^import )[^;]*/gm) || [];
|
||||||
@ -205,17 +175,6 @@
|
|||||||
let userName = window?.QuintOS?.userName || 'quinton-ashley';
|
let userName = window?.QuintOS?.userName || 'quinton-ashley';
|
||||||
let className = file.slice(classLine + 13, file.indexOf(' {', classLine + 13));
|
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
|
// hacky support for Java 15 triple quotes
|
||||||
file = file.replaceAll(/"""([^"]*)"""/g, (match, str) => {
|
file = file.replaceAll(/"""([^"]*)"""/g, (match, str) => {
|
||||||
str = str.replaceAll(/(.*)(\n|$)/g, '"$1\\n"+').slice(0, -1);
|
str = str.replaceAll(/(.*)(\n|$)/g, '"$1\\n"+').slice(0, -1);
|
||||||
@ -234,8 +193,6 @@
|
|||||||
|
|
||||||
// log(file);
|
// log(file);
|
||||||
|
|
||||||
let suffix = `\njdk.main = ${className}.main;\n}`;
|
|
||||||
|
|
||||||
window.file0 = file;
|
window.file0 = file;
|
||||||
|
|
||||||
let trans = java_to_javascript(file);
|
let trans = java_to_javascript(file);
|
||||||
@ -245,14 +202,27 @@
|
|||||||
trans = trans.replace(/(\([^\)]*\) =>)/gm, 'async $1');
|
trans = trans.replace(/(\([^\)]*\) =>)/gm, 'async $1');
|
||||||
trans = trans.replace(/([\w_\$]+\.next(Int|Float|Double|Line|Short|Long)*\(\))/gm, 'await $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;
|
trans = prefix + trans + suffix;
|
||||||
|
|
||||||
log(trans);
|
log(trans);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
eval(trans);
|
eval(trans);
|
||||||
this.load();
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
if (window?.ide) ide.log.value += e;
|
if (window?.ide) ide.log.value += e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
jdk.imports['java.io.File'].load = () => {
|
jdk.imports['java.io.File'].load = async () => {
|
||||||
class File {
|
class File {
|
||||||
constructor(file) {
|
constructor(file) {
|
||||||
this.absPath = file;
|
this.absPath = file;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
jdk.imports['java.io.InputStream'].load = () => {
|
jdk.imports['java.io.InputStream'].load = async () => {
|
||||||
class InputStream {
|
class InputStream {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.reset();
|
this.reset();
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
jdk.imports['java.io.PrintStream'].load = () => {
|
jdk.imports['java.io.PrintStream'].load = async () => {
|
||||||
class PrintStream {
|
class PrintStream {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.log = '';
|
this.log = '';
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
jdk.imports['java.lang.Character'].load = () => {
|
jdk.imports['java.lang.Character'].load = async () => {
|
||||||
class Character {}
|
class Character {}
|
||||||
Character.isDigit = (c) => {
|
Character.isDigit = (c) => {
|
||||||
c = c.charCodeAt(0);
|
c = c.charCodeAt(0);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
jdk.imports['java.lang.Double'].load = () => {
|
jdk.imports['java.lang.Double'].load = async () => {
|
||||||
class Double {
|
class Double {
|
||||||
constructor() {
|
constructor() {
|
||||||
throw 'new Double() not supported';
|
throw 'new Double() not supported';
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
jdk.imports['java.lang.Float'].load = () => {
|
jdk.imports['java.lang.Float'].load = async () => {
|
||||||
class Float {}
|
class Float {}
|
||||||
Float.parseFloat = (d) => {
|
Float.parseFloat = (d) => {
|
||||||
return parseFloat(d);
|
return parseFloat(d);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
jdk.imports['java.lang.Integer'].load = () => {
|
jdk.imports['java.lang.Integer'].load = async () => {
|
||||||
class Integer {}
|
class Integer {}
|
||||||
Integer.parseInt = (d) => {
|
Integer.parseInt = (d) => {
|
||||||
return parseInt(d);
|
return parseInt(d);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
jdk.imports['java.lang.Long'].load = () => {
|
jdk.imports['java.lang.Long'].load = async () => {
|
||||||
class Long {}
|
class Long {}
|
||||||
Long.parseLong = (d) => {
|
Long.parseLong = (d) => {
|
||||||
return parseInt(d);
|
return parseInt(d);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
jdk.imports['java.lang.Short'].load = () => {
|
jdk.imports['java.lang.Short'].load = async () => {
|
||||||
class Short {}
|
class Short {}
|
||||||
Short.parseShort = (d) => {
|
Short.parseShort = (d) => {
|
||||||
return parseInt(d);
|
return parseInt(d);
|
||||||
|
@ -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 is special, I just extended js String prototype
|
||||||
String.prototype.hashCode = () => {
|
String.prototype.hashCode = () => {
|
||||||
let h = this._hashCode;
|
let h = this._hashCode;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
jdk.imports['java.lang.StringBuilder'].load = () => {
|
jdk.imports['java.lang.StringBuilder'].load = async () => {
|
||||||
class StringBuilder {
|
class StringBuilder {
|
||||||
constructor() {
|
constructor() {
|
||||||
this._str = '';
|
this._str = '';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
jdk.imports['java.lang.System'].load = () => {
|
jdk.imports['java.lang.System'].load = async () => {
|
||||||
const Formatter = jdk.import('java.util.Formatter');
|
const Formatter = await jdk.import('java.util.Formatter');
|
||||||
const InputStream = jdk.import('java.io.InputStream');
|
const InputStream = await jdk.import('java.io.InputStream');
|
||||||
const PrintStream = jdk.import('java.io.PrintStream');
|
const PrintStream = await jdk.import('java.io.PrintStream');
|
||||||
|
|
||||||
class System {}
|
class System {}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
jdk.imports['java.lang.Thread'].load = () => {
|
jdk.imports['java.lang.Thread'].load = async () => {
|
||||||
class Thread {
|
class Thread {
|
||||||
async sleep(millis) {
|
async sleep(millis) {
|
||||||
await setTimeout(millis);
|
await setTimeout(millis);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
jdk.imports['java.util.AbstractList'].load = () => {
|
jdk.imports['java.util.AbstractList'].load = async () => {
|
||||||
const Itr = jdk.import('java.util.Itr');
|
const Itr = await jdk.import('java.util.Itr');
|
||||||
|
|
||||||
class AbstractList {
|
class AbstractList {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
jdk.imports['java.util.ArrayList'].load = () => {
|
jdk.imports['java.util.ArrayList'].load = async () => {
|
||||||
let AbstractList = jdk.import('java.util.AbstractList');
|
let AbstractList = await jdk.import('java.util.AbstractList');
|
||||||
|
|
||||||
class ArrayList extends AbstractList {
|
class ArrayList extends AbstractList {
|
||||||
constructor(...args) {
|
constructor(...args) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
jdk.imports['java.util.Arrays'].load = () => {
|
jdk.imports['java.util.Arrays'].load = async () => {
|
||||||
class Arrays {
|
class Arrays {
|
||||||
fill(data, begin, nbElem, param) {
|
fill(data, begin, nbElem, param) {
|
||||||
const max = begin + nbElem;
|
const max = begin + nbElem;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
jdk.imports['java.util.Collections'].load = () => {
|
jdk.imports['java.util.Collections'].load = async () => {
|
||||||
class Collections {
|
class Collections {
|
||||||
sort(list) {
|
sort(list) {
|
||||||
if (!list.size()) return;
|
if (!list.size()) return;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
jdk.imports['java.util.Formatter'].load = () => {
|
jdk.imports['java.util.Formatter'].load = async () => {
|
||||||
const IllegalFormatException = jdk.import('java.util.IllegalFormatException');
|
const IllegalFormatException = await jdk.import('java.util.IllegalFormatException');
|
||||||
|
|
||||||
class Formatter {
|
class Formatter {
|
||||||
format(format, ...args) {
|
format(format, ...args) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
jdk.imports['java.util.HashMap'].load = () => {
|
jdk.imports['java.util.HashMap'].load = async () => {
|
||||||
class HashMap {
|
class HashMap {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.content = {};
|
this.content = {};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
jdk.imports['java.util.HashSet'].load = () => {
|
jdk.imports['java.util.HashSet'].load = async () => {
|
||||||
class HashSet {
|
class HashSet {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.content = {};
|
this.content = {};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
jdk.imports['java.util.IllegalFormatException'].load = () => {
|
jdk.imports['java.util.IllegalFormatException'].load = async () => {
|
||||||
// TODO import and extend exception
|
// TODO import and extend exception
|
||||||
|
|
||||||
class IllegalFormatException {
|
class IllegalFormatException {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
jdk.imports['java.util.Itr'].load = () => {
|
jdk.imports['java.util.Itr'].load = async () => {
|
||||||
class Itr {
|
class Itr {
|
||||||
constructor(list) {
|
constructor(list) {
|
||||||
this.cursor = 0;
|
this.cursor = 0;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
jdk.imports['java.util.LinkedList'].load = () => {
|
jdk.imports['java.util.LinkedList'].load = async () => {
|
||||||
let AbstractList = jdk.import('java.util.AbstractList');
|
let AbstractList = await jdk.import('java.util.AbstractList');
|
||||||
|
|
||||||
class LinkedList extends AbstractList {
|
class LinkedList extends AbstractList {
|
||||||
constructor(...args) {
|
constructor(...args) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
jdk.imports['java.util.Random'].load = () => {
|
jdk.imports['java.util.Random'].load = async () => {
|
||||||
class Random {
|
class Random {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.seed = undefined;
|
this.seed = undefined;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
jdk.imports['java.util.Scanner'].load = () => {
|
jdk.imports['java.util.Scanner'].load = async () => {
|
||||||
const File = jdk.import('java.io.File');
|
const File = await jdk.import('java.io.File');
|
||||||
|
|
||||||
class Scanner {
|
class Scanner {
|
||||||
constructor(input) {
|
constructor(input) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
jdk.imports['java.util.Stack'].load = () => {
|
jdk.imports['java.util.Stack'].load = async () => {
|
||||||
class Stack {
|
class Stack {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.content = new Array();
|
this.content = new Array();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "java2js",
|
"name": "java2js",
|
||||||
"version": "1.0.3",
|
"version": "1.0.4",
|
||||||
"description": "Converts Java to JavaScript with support for p5.js and QuintOS.",
|
"description": "Converts Java to JavaScript with support for p5.js and QuintOS.",
|
||||||
"main": "java2js.js",
|
"main": "java2js.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user