diff --git a/ide.js b/ide.js index 3b7f7e4..1506ba2 100644 --- a/ide.js +++ b/ide.js @@ -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); + }; +})(); diff --git a/jdk.js b/jdk.js index e94249b..11ec439 100755 --- a/jdk.js +++ b/jdk.js @@ -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; } } diff --git a/jdk/java/io/File.js b/jdk/java/io/File.js index 5966bb2..6649417 100755 --- a/jdk/java/io/File.js +++ b/jdk/java/io/File.js @@ -1,4 +1,4 @@ -jdk.imports['java.io.File'].load = () => { +jdk.imports['java.io.File'].load = async () => { class File { constructor(file) { this.absPath = file; diff --git a/jdk/java/io/InputStream.js b/jdk/java/io/InputStream.js index cc1984e..143e7a9 100755 --- a/jdk/java/io/InputStream.js +++ b/jdk/java/io/InputStream.js @@ -1,4 +1,4 @@ -jdk.imports['java.io.InputStream'].load = () => { +jdk.imports['java.io.InputStream'].load = async () => { class InputStream { constructor() { this.reset(); diff --git a/jdk/java/io/PrintStream.js b/jdk/java/io/PrintStream.js index 46e4cb7..7c8054e 100755 --- a/jdk/java/io/PrintStream.js +++ b/jdk/java/io/PrintStream.js @@ -1,4 +1,4 @@ -jdk.imports['java.io.PrintStream'].load = () => { +jdk.imports['java.io.PrintStream'].load = async () => { class PrintStream { constructor() { this.log = ''; diff --git a/jdk/java/lang/Character.js b/jdk/java/lang/Character.js index 1abfd39..afe0490 100755 --- a/jdk/java/lang/Character.js +++ b/jdk/java/lang/Character.js @@ -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); diff --git a/jdk/java/lang/Double.js b/jdk/java/lang/Double.js index 2318c42..c4924f8 100755 --- a/jdk/java/lang/Double.js +++ b/jdk/java/lang/Double.js @@ -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'; diff --git a/jdk/java/lang/Float.js b/jdk/java/lang/Float.js index 5aadc48..dd9a071 100755 --- a/jdk/java/lang/Float.js +++ b/jdk/java/lang/Float.js @@ -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); diff --git a/jdk/java/lang/Integer.js b/jdk/java/lang/Integer.js index 5145dae..02a6253 100755 --- a/jdk/java/lang/Integer.js +++ b/jdk/java/lang/Integer.js @@ -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); diff --git a/jdk/java/lang/Long.js b/jdk/java/lang/Long.js index af8f225..90f05ed 100755 --- a/jdk/java/lang/Long.js +++ b/jdk/java/lang/Long.js @@ -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); diff --git a/jdk/java/lang/Short.js b/jdk/java/lang/Short.js index 1977bd0..d28792a 100755 --- a/jdk/java/lang/Short.js +++ b/jdk/java/lang/Short.js @@ -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); diff --git a/jdk/java/lang/String.js b/jdk/java/lang/String.js index e70782d..0d90454 100755 --- a/jdk/java/lang/String.js +++ b/jdk/java/lang/String.js @@ -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; diff --git a/jdk/java/lang/StringBuilder.js b/jdk/java/lang/StringBuilder.js index 0bd927f..637f3b5 100755 --- a/jdk/java/lang/StringBuilder.js +++ b/jdk/java/lang/StringBuilder.js @@ -1,4 +1,4 @@ -jdk.imports['java.lang.StringBuilder'].load = () => { +jdk.imports['java.lang.StringBuilder'].load = async () => { class StringBuilder { constructor() { this._str = ''; diff --git a/jdk/java/lang/System.js b/jdk/java/lang/System.js index df23b08..d7d4426 100755 --- a/jdk/java/lang/System.js +++ b/jdk/java/lang/System.js @@ -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 {} diff --git a/jdk/java/lang/Thread.js b/jdk/java/lang/Thread.js index 31c0ba2..88bcbaa 100755 --- a/jdk/java/lang/Thread.js +++ b/jdk/java/lang/Thread.js @@ -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); diff --git a/jdk/java/util/AbstractList.js b/jdk/java/util/AbstractList.js index 386a363..84c37d8 100755 --- a/jdk/java/util/AbstractList.js +++ b/jdk/java/util/AbstractList.js @@ -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() { diff --git a/jdk/java/util/ArrayList.js b/jdk/java/util/ArrayList.js index c9108a0..ef39cf8 100755 --- a/jdk/java/util/ArrayList.js +++ b/jdk/java/util/ArrayList.js @@ -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) { diff --git a/jdk/java/util/Arrays.js b/jdk/java/util/Arrays.js index bc48677..17b5bf8 100755 --- a/jdk/java/util/Arrays.js +++ b/jdk/java/util/Arrays.js @@ -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; diff --git a/jdk/java/util/Collections.js b/jdk/java/util/Collections.js index f7a6760..1a75d89 100755 --- a/jdk/java/util/Collections.js +++ b/jdk/java/util/Collections.js @@ -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; diff --git a/jdk/java/util/Formatter.js b/jdk/java/util/Formatter.js index 20737a7..3c2e631 100755 --- a/jdk/java/util/Formatter.js +++ b/jdk/java/util/Formatter.js @@ -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) { diff --git a/jdk/java/util/HashMap.js b/jdk/java/util/HashMap.js index e1f3692..b042b46 100755 --- a/jdk/java/util/HashMap.js +++ b/jdk/java/util/HashMap.js @@ -1,4 +1,4 @@ -jdk.imports['java.util.HashMap'].load = () => { +jdk.imports['java.util.HashMap'].load = async () => { class HashMap { constructor() { this.content = {}; diff --git a/jdk/java/util/HashSet.js b/jdk/java/util/HashSet.js index ff5be68..90870d5 100755 --- a/jdk/java/util/HashSet.js +++ b/jdk/java/util/HashSet.js @@ -1,4 +1,4 @@ -jdk.imports['java.util.HashSet'].load = () => { +jdk.imports['java.util.HashSet'].load = async () => { class HashSet { constructor() { this.content = {}; diff --git a/jdk/java/util/IllegalFormatException.js b/jdk/java/util/IllegalFormatException.js index 5d2a113..dc7dcdf 100755 --- a/jdk/java/util/IllegalFormatException.js +++ b/jdk/java/util/IllegalFormatException.js @@ -1,4 +1,4 @@ -jdk.imports['java.util.IllegalFormatException'].load = () => { +jdk.imports['java.util.IllegalFormatException'].load = async () => { // TODO import and extend exception class IllegalFormatException { diff --git a/jdk/java/util/Itr.js b/jdk/java/util/Itr.js index da21599..eca88b0 100755 --- a/jdk/java/util/Itr.js +++ b/jdk/java/util/Itr.js @@ -1,4 +1,4 @@ -jdk.imports['java.util.Itr'].load = () => { +jdk.imports['java.util.Itr'].load = async () => { class Itr { constructor(list) { this.cursor = 0; diff --git a/jdk/java/util/LinkedList.js b/jdk/java/util/LinkedList.js index 1a17fcd..fa414f2 100755 --- a/jdk/java/util/LinkedList.js +++ b/jdk/java/util/LinkedList.js @@ -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) { diff --git a/jdk/java/util/Random.js b/jdk/java/util/Random.js index 0289804..38e1212 100755 --- a/jdk/java/util/Random.js +++ b/jdk/java/util/Random.js @@ -1,4 +1,4 @@ -jdk.imports['java.util.Random'].load = () => { +jdk.imports['java.util.Random'].load = async () => { class Random { constructor() { this.seed = undefined; diff --git a/jdk/java/util/Scanner.js b/jdk/java/util/Scanner.js index 5c975ee..9f510aa 100755 --- a/jdk/java/util/Scanner.js +++ b/jdk/java/util/Scanner.js @@ -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) { diff --git a/jdk/java/util/Stack.js b/jdk/java/util/Stack.js index d15203e..b30a90f 100755 --- a/jdk/java/util/Stack.js +++ b/jdk/java/util/Stack.js @@ -1,4 +1,4 @@ -jdk.imports['java.util.Stack'].load = () => { +jdk.imports['java.util.Stack'].load = async () => { class Stack { constructor() { this.content = new Array(); diff --git a/package.json b/package.json index 45edd61..c008d43 100644 --- a/package.json +++ b/package.json @@ -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": {