js: split runtime into smaller parts

This commit is contained in:
Alexey Andreev 2023-11-07 20:25:55 +01:00
parent 07542499e1
commit 8f8b33c0b1
14 changed files with 982 additions and 831 deletions

View File

@ -53,10 +53,18 @@ public class RuntimeRenderer {
public void prepareAstParts(boolean threadLibraryUsed) { public void prepareAstParts(boolean threadLibraryUsed) {
runtimeAstParts.add(prepareAstPart("runtime.js")); runtimeAstParts.add(prepareAstPart("runtime.js"));
runtimeAstParts.add(prepareAstPart("intern.js")); runtimeAstParts.add(prepareAstPart("primitive.js"));
runtimeAstParts.add(prepareAstPart("numeric.js"));
runtimeAstParts.add(prepareAstPart("long.js")); runtimeAstParts.add(prepareAstPart("long.js"));
runtimeAstParts.add(prepareAstPart("array.js"));
runtimeAstParts.add(prepareAstPart("string.js"));
runtimeAstParts.add(prepareAstPart("reflection.js"));
runtimeAstParts.add(prepareAstPart("exception.js"));
runtimeAstParts.add(prepareAstPart("check.js"));
runtimeAstParts.add(prepareAstPart("console.js"));
runtimeAstParts.add(prepareAstPart("metadata.js"));
runtimeAstParts.add(prepareAstPart(threadLibraryUsed ? "thread.js" : "simpleThread.js")); runtimeAstParts.add(prepareAstPart(threadLibraryUsed ? "thread.js" : "simpleThread.js"));
epilogueAstParts.add(prepareAstPart("array.js")); epilogueAstParts.add(prepareAstPart("types.js"));
} }
public void renderRuntime() { public void renderRuntime() {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2019 Alexey Andreev. * Copyright 2023 Alexey Andreev.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -13,12 +13,271 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
"use strict";
let $rt_booleanArrayCls = $rt_arraycls($rt_booleancls); let $rt_createArray = (cls, sz) => {
let $rt_charArrayCls = $rt_arraycls($rt_charcls); let data = new teavm_globals.Array(sz);
let $rt_byteArrayCls = $rt_arraycls($rt_bytecls); data.fill(null);
let $rt_shortArrayCls = $rt_arraycls($rt_shortcls); return new ($rt_arraycls(cls))(data);
let $rt_intArrayCls = $rt_arraycls($rt_intcls); }
let $rt_longArrayCls = $rt_arraycls($rt_longcls); let $rt_createArrayFromData = (cls, init) => $rt_wrapArray(cls, init);
let $rt_floatArrayCls = $rt_arraycls($rt_floatcls); let $rt_wrapArray = (cls, data) => new ($rt_arraycls(cls))(data);
let $rt_doubleArrayCls = $rt_arraycls($rt_doublecls); let $rt_createUnfilledArray = (cls, sz) => new ($rt_arraycls(cls))(new teavm_globals.Array(sz));
let $rt_createLongArray;
let $rt_createLongArrayFromData;
if (typeof teavm_globals.BigInt64Array !== 'function') {
$rt_createLongArray = sz => {
let data = new teavm_globals.Array(sz);
let arr = new $rt_longArrayCls(data);
data.fill(Long_ZERO);
return arr;
}
$rt_createLongArrayFromData = init => new $rt_longArrayCls(init);
} else {
$rt_createLongArray = sz => new $rt_longArrayCls(new teavm_globals.BigInt64Array(sz));
$rt_createLongArrayFromData = data => {
let buffer = new teavm_globals.BigInt64Array(data.length);
buffer.set(data);
return new $rt_longArrayCls(buffer);
}
}
let $rt_createCharArray = sz => new $rt_charArrayCls(new teavm_globals.Uint16Array(sz));
let $rt_createCharArrayFromData = data => {
let buffer = new teavm_globals.Uint16Array(data.length);
buffer.set(data);
return new $rt_charArrayCls(buffer);
}
let $rt_createByteArray = sz => new $rt_byteArrayCls(new teavm_globals.Int8Array(sz));
let $rt_createByteArrayFromData = data => {
let buffer = new teavm_globals.Int8Array(data.length);
buffer.set(data);
return new $rt_byteArrayCls(buffer);
}
let $rt_createShortArray = sz => new $rt_shortArrayCls(new teavm_globals.Int16Array(sz));
let $rt_createShortArrayFromData = data => {
let buffer = new teavm_globals.Int16Array(data.length);
buffer.set(data);
return new $rt_shortArrayCls(buffer);
}
let $rt_createIntArray = sz => new $rt_intArrayCls(new teavm_globals.Int32Array(sz));
let $rt_createIntArrayFromData = data => {
let buffer = new teavm_globals.Int32Array(data.length);
buffer.set(data);
return new $rt_intArrayCls(buffer);
}
let $rt_createBooleanArray = sz => new $rt_booleanArrayCls(new teavm_globals.Int8Array(sz));
let $rt_createBooleanArrayFromData = data => {
let buffer = new teavm_globals.Int8Array(data.length);
buffer.set(data);
return new $rt_booleanArrayCls(buffer);
}
let $rt_createFloatArray = sz => new $rt_floatArrayCls(new teavm_globals.Float32Array(sz));
let $rt_createFloatArrayFromData = data => {
let buffer = new teavm_globals.Float32Array(data.length);
buffer.set(data);
return new $rt_floatArrayCls(buffer);
}
let $rt_createDoubleArray = sz => new $rt_doubleArrayCls(new teavm_globals.Float64Array(sz));
let $rt_createDoubleArrayFromData = data => {
let buffer = new teavm_globals.Float64Array(data.length);
buffer.set(data);
return new $rt_doubleArrayCls(buffer);
}
let $rt_arraycls = cls => {
let result = cls.$array;
if (result === null) {
function JavaArray(data) {
$rt_objcls().call(this);
this.data = data;
}
JavaArray.prototype = teavm_globals.Object.create($rt_objcls().prototype);
JavaArray.prototype.type = cls;
JavaArray.prototype.constructor = JavaArray;
JavaArray.prototype.toString = function() {
let str = "[";
for (let i = 0; i < this.data.length; ++i) {
if (i > 0) {
str += ", ";
}
str += this.data[i].toString();
}
str += "]";
return str;
};
JavaArray.prototype[teavm_javaVirtualMethod('clone()Ljava/lang/Object;')] = function() {
let dataCopy;
if ('slice' in this.data) {
dataCopy = this.data.slice();
} else {
dataCopy = new this.data.constructor(this.data.length);
for (let i = 0; i < dataCopy.length; ++i) {
dataCopy[i] = this.data[i];
}
}
return new ($rt_arraycls(this.type))(dataCopy);
};
let name = "[" + cls.$meta.binaryName;
JavaArray.$meta = {
item: cls,
supertypes: [$rt_objcls()],
primitive: false,
superclass: $rt_objcls(),
name: name,
binaryName: name,
enum: false,
simpleName: null,
declaringClass: null,
enclosingClass: null
};
JavaArray.classObject = null;
JavaArray.$array = null;
result = JavaArray;
cls.$array = JavaArray;
}
return result;
}
let $rt_createMultiArray = (cls, dimensions) => {
let first = 0;
for (let i = dimensions.length - 1; i >= 0; i = (i - 1) | 0) {
if (dimensions[i] === 0) {
first = i;
break;
}
}
if (first > 0) {
for (let i = 0; i < first; i = (i + 1) | 0) {
cls = $rt_arraycls(cls);
}
if (first === dimensions.length - 1) {
return $rt_createArray(cls, dimensions[first]);
}
}
let arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, first));
let firstDim = dimensions[first] | 0;
for (let i = 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createArray(cls, firstDim);
}
return $rt_createMultiArrayImpl(cls, arrays, dimensions, first);
}
let $rt_createByteMultiArray = dimensions => {
let arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, 0));
if (arrays.length === 0) {
return $rt_createMultiArray($rt_bytecls, dimensions);
}
let firstDim = dimensions[0] | 0;
for (let i = 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createByteArray(firstDim);
}
return $rt_createMultiArrayImpl($rt_bytecls, arrays, dimensions);
}
let $rt_createCharMultiArray = dimensions => {
let arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, 0));
if (arrays.length === 0) {
return $rt_createMultiArray($rt_charcls, dimensions);
}
let firstDim = dimensions[0] | 0;
for (let i = 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createCharArray(firstDim);
}
return $rt_createMultiArrayImpl($rt_charcls, arrays, dimensions, 0);
}
let $rt_createBooleanMultiArray = dimensions => {
let arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, 0));
if (arrays.length === 0) {
return $rt_createMultiArray($rt_booleancls, dimensions);
}
let firstDim = dimensions[0] | 0;
for (let i = 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createBooleanArray(firstDim);
}
return $rt_createMultiArrayImpl($rt_booleancls, arrays, dimensions, 0);
}
let $rt_createShortMultiArray = dimensions => {
let arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, 0));
if (arrays.length === 0) {
return $rt_createMultiArray($rt_shortcls, dimensions);
}
let firstDim = dimensions[0] | 0;
for (let i = 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createShortArray(firstDim);
}
return $rt_createMultiArrayImpl($rt_shortcls, arrays, dimensions, 0);
}
let $rt_createIntMultiArray = dimensions => {
let arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, 0));
if (arrays.length === 0) {
return $rt_createMultiArray($rt_intcls, dimensions);
}
let firstDim = dimensions[0] | 0;
for (let i = 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createIntArray(firstDim);
}
return $rt_createMultiArrayImpl($rt_intcls, arrays, dimensions, 0);
}
let $rt_createLongMultiArray = dimensions => {
let arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, 0));
if (arrays.length === 0) {
return $rt_createMultiArray($rt_longcls, dimensions);
}
let firstDim = dimensions[0] | 0;
for (let i = 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createLongArray(firstDim);
}
return $rt_createMultiArrayImpl($rt_longcls, arrays, dimensions, 0);
}
let $rt_createFloatMultiArray = dimensions => {
let arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, 0));
if (arrays.length === 0) {
return $rt_createMultiArray($rt_floatcls, dimensions);
}
let firstDim = dimensions[0] | 0;
for (let i = 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createFloatArray(firstDim);
}
return $rt_createMultiArrayImpl($rt_floatcls, arrays, dimensions, 0);
}
let $rt_createDoubleMultiArray = dimensions => {
let arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, 0));
if (arrays.length === 0) {
return $rt_createMultiArray($rt_doublecls, dimensions);
}
let firstDim = dimensions[0] | 0;
for (let i = 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createDoubleArray(firstDim);
}
return $rt_createMultiArrayImpl($rt_doublecls, arrays, dimensions, 0);
}
let $rt_primitiveArrayCount = (dimensions, start) => {
let val = dimensions[start + 1] | 0;
for (let i = start + 2; i < dimensions.length; i = (i + 1) | 0) {
val = (val * (dimensions[i] | 0)) | 0;
if (val === 0) {
break;
}
}
return val;
}
let $rt_createMultiArrayImpl = (cls, arrays, dimensions, start) => {
let limit = arrays.length;
for (let i = (start + 1) | 0; i < dimensions.length; i = (i + 1) | 0) {
cls = $rt_arraycls(cls);
let dim = dimensions[i];
let index = 0;
let packedIndex = 0;
while (index < limit) {
let arr = $rt_createUnfilledArray(cls, dim);
for (let j = 0; j < dim; j = (j + 1) | 0) {
arr.data[j] = arrays[index];
index = (index + 1) | 0;
}
arrays[packedIndex] = arr;
packedIndex = (packedIndex + 1) | 0;
}
limit = packedIndex;
}
return arrays[0];
}

View File

@ -0,0 +1,42 @@
/*
* Copyright 2023 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
let $rt_checkBounds = (index, array) => {
if (index < 0 || index >= array.length) {
$rt_throwAIOOBE();
}
return index;
}
let $rt_checkUpperBound = (index, array) => {
if (index >= array.length) {
$rt_throwAIOOBE();
}
return index;
}
let $rt_checkLowerBound = index => {
if (index < 0) {
$rt_throwAIOOBE();
}
return index;
}
let $rt_nullCheck = val => {
if (val === null) {
$rt_throw(teavm_javaConstructor("java.lang.NullPointerException", "()V")());
}
return val;
}

View File

@ -0,0 +1,40 @@
/*
* Copyright 2023 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
let $rt_createOutputFunction = outputFunction => {
let buffer = "";
return msg => {
let index = 0;
while (true) {
let next = msg.indexOf('\n', index);
if (next < 0) {
break;
}
outputFunction(buffer + msg.substring(index, next));
buffer = "";
index = next + 1;
}
buffer += msg.substring(index);
}
}
let $rt_putStdout = typeof teavm_globals.$rt_putStdoutCustom === "function"
? teavm_globals.$rt_putStdoutCustom
: typeof console === "object" ? $rt_createOutputFunction(msg => console.info(msg)) : () => {};
let $rt_putStderr = typeof teavm_globals.$rt_putStderrCustom === "function"
? teavm_globals.$rt_putStderrCustom
: typeof console === "object" ? $rt_createOutputFunction(msg => console.error(msg)) : () => {};

View File

@ -0,0 +1,141 @@
/*
* Copyright 2023 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
let $rt_throw = ex => {
throw $rt_exception(ex)
};
let $rt_javaExceptionProp = teavm_globals.Symbol("javaException")
let $rt_exception = ex => {
let err = ex.$jsException;
if (!err) {
let javaCause = $rt_throwableCause(ex);
let jsCause = javaCause !== null ? javaCause.$jsException : void 0;
let cause = typeof jsCause === "object" ? { cause : jsCause } : void 0;
err = new JavaError("Java exception thrown", cause);
if (typeof teavm_globals.Error.captureStackTrace === "function") {
teavm_globals.Error.captureStackTrace(err);
}
err[$rt_javaExceptionProp] = ex;
ex.$jsException = err;
$rt_fillStack(err, ex);
}
return err;
}
let $rt_fillStack = (err, ex) => {
if (typeof $rt_decodeStack === "function" && err.stack) {
let stack = $rt_decodeStack(err.stack);
let javaStack = $rt_createArray($rt_stecls(), stack.length);
let elem;
let noStack = false;
for (let i = 0; i < stack.length; ++i) {
let element = stack[i];
elem = $rt_createStackElement($rt_str(element.className),
$rt_str(element.methodName), $rt_str(element.fileName), element.lineNumber);
if (elem == null) {
noStack = true;
break;
}
javaStack.data[i] = elem;
}
if (!noStack) {
$rt_setStack(ex, javaStack);
}
}
}
let JavaError;
if (typeof Reflect === 'object') {
let defaultMessage = teavm_globals.Symbol("defaultMessage");
JavaError = function JavaError(message, cause) {
let self = teavm_globals.Reflect.construct(teavm_globals.Error, [void 0, cause], JavaError);
teavm_globals.Object.setPrototypeOf(self, JavaError.prototype);
self[defaultMessage] = message;
return self;
}
JavaError.prototype = teavm_globals.Object.create(teavm_globals.Error.prototype, {
constructor: {
configurable: true,
writable: true,
value: JavaError
},
message: {
get() {
try {
let javaException = this[$rt_javaExceptionProp];
if (typeof javaException === 'object') {
let javaMessage = $rt_throwableMessage(javaException);
if (typeof javaMessage === "object") {
return javaMessage !== null ? javaMessage.toString() : null;
}
}
return this[defaultMessage];
} catch (e) {
return "Exception occurred trying to extract Java exception message: " + e
}
}
}
});
} else {
JavaError = teavm_globals.Error;
}
let $rt_javaException = e => e instanceof teavm_globals.Error && typeof e[$rt_javaExceptionProp] === 'object'
? e[$rt_javaExceptionProp]
: null;
let $rt_jsException = e => typeof e.$jsException === 'object' ? e.$jsException : null;
let $rt_wrapException = err => {
let ex = err[$rt_javaExceptionProp];
if (!ex) {
ex = $rt_createException($rt_str("(JavaScript) " + err.toString()));
err[$rt_javaExceptionProp] = ex;
ex.$jsException = err;
$rt_fillStack(err, ex);
}
return ex;
}
let $rt_createException = message => teavm_javaConstructor("java.lang.RuntimeException",
"(Ljava/lang/String;)V")(message);
let $rt_throwableMessage = t => teavm_javaMethod("java.lang.Throwable", "getMessage()Ljava/lang/String;")(t);
let $rt_throwableCause = t => teavm_javaMethod("java.lang.Throwable", "getCause()Ljava/lang/Throwable;")(t);
let $rt_stecls = () => teavm_javaClassExists("java.lang.StackTraceElement")
? teavm_javaClass("java.lang.StackTraceElement")
: $rt_objcls();
let $rt_throwAIOOBE = () => teavm_javaConstructorExists("java.lang.ArrayIndexOutOfBoundsException", "()V")
? $rt_throw(teavm_javaConstructor("java.lang.ArrayIndexOutOfBoundsException", "()V")())
: $rt_throw($rt_createException($rt_str("")));
let $rt_throwCCE = () => teavm_javaConstructorExists("java.lang.ClassCastException", "()V")
? $rt_throw(teavm_javaConstructor("java.lang.ClassCastException", "()V")())
: $rt_throw($rt_createException($rt_str("")));
let $rt_createStackElement = (className, methodName, fileName, lineNumber) => {
if (teavm_javaConstructorExists("java.lang.StackTraceElement",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V")) {
return teavm_javaConstructor("java.lang.StackTraceElement",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V")(className, methodName, fileName, lineNumber);
} else {
return null;
}
}
let $rt_setStack = (e, stack) => {
if (teavm_javaMethodExists("java.lang.Throwable", "setStackTrace([Ljava/lang/StackTraceElement;)V")) {
teavm_javaMethod("java.lang.Throwable", "setStackTrace([Ljava/lang/StackTraceElement;)V")(e, stack);
}
}

View File

@ -1,56 +0,0 @@
/*
* Copyright 2019 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
let $rt_intern
if (teavm_javaMethodExists("java.lang.String", "intern()Ljava/lang/String;")) {
$rt_intern = function() {
let map = teavm_globals.Object.create(null);
let get;
if (typeof teavm_globals.WeakRef !== 'undefined') {
let registry = new teavm_globals.FinalizationRegistry(value => {
delete map[value];
});
get = str => {
let key = $rt_ustr(str);
let ref = map[key];
let result = typeof ref !== 'undefined' ? ref.deref() : void 0;
if (typeof result !== 'object') {
result = str;
map[key] = new teavm_globals.WeakRef(result);
registry.register(result, key);
}
return result;
}
} else {
get = str => {
let key = $rt_ustr(str);
let result = map[key];
if (typeof result !== 'object') {
result = str;
map[key] = result;
}
return result;
}
}
return get;
}();
} else {
$rt_intern = str => str;
}

View File

@ -15,6 +15,67 @@
*/ */
"use strict"; "use strict";
function Long(lo, hi) {
this.lo = lo | 0;
this.hi = hi | 0;
}
Long.prototype.__teavm_class__ = () => {
return "long";
};
let Long_isPositive = a => (a.hi & 0x80000000) === 0;
let Long_isNegative = a => (a.hi & 0x80000000) !== 0;
let Long_MAX_NORMAL = 1 << 18;
let Long_ZERO;
let Long_create;
let Long_fromInt;
let Long_fromNumber;
let Long_toNumber;
let Long_hi;
let Long_lo;
if (typeof teavm_globals.BigInt !== "function") {
Long.prototype.toString = function() {
let result = [];
let n = this;
let positive = Long_isPositive(n);
if (!positive) {
n = Long_neg(n);
}
let radix = new Long(10, 0);
do {
let divRem = Long_divRem(n, radix);
result.push(teavm_globals.String.fromCharCode(48 + divRem[1].lo));
n = divRem[0];
} while (n.lo !== 0 || n.hi !== 0);
result = result.reverse().join('');
return positive ? result : "-" + result;
};
Long.prototype.valueOf = function() {
return Long_toNumber(this);
};
Long_ZERO = new Long(0, 0);
Long_fromInt = val =>new Long(val, (-(val < 0)) | 0);
Long_fromNumber = val => val >= 0
? new Long(val | 0, (val / 0x100000000) | 0)
: Long_neg(new Long(-val | 0, (-val / 0x100000000) | 0));
Long_create = (lo, hi) => new Long(lo, hi);
Long_toNumber = val => 0x100000000 * val.hi + (val.lo >>> 0);
Long_hi = val => val.hi;
Long_lo = val => val.lo;
} else {
Long_ZERO = teavm_globals.BigInt(0);
Long_create = (lo, hi) => teavm_globals.BigInt.asIntN(64, teavm_globals.BigInt.asUintN(64, teavm_globals.BigInt(lo))
| teavm_globals.BigInt.asUintN(64, (teavm_globals.BigInt(hi) << teavm_globals.BigInt(32))));
Long_fromInt = val => teavm_globals.BigInt.asIntN(64, teavm_globals.BigInt(val | 0));
Long_fromNumber = val => teavm_globals.BigInt.asIntN(64, teavm_globals.BigInt(
val >= 0 ? teavm_globals.Math.floor(val) : teavm_globals.Math.ceil(val)));
Long_toNumber = val => teavm_globals.Number(val);
Long_hi = val => teavm_globals.Number(teavm_globals.BigInt.asIntN(64, val >> teavm_globals.BigInt(32))) | 0;
Long_lo = val => teavm_globals.Number(teavm_globals.BigInt.asIntN(32, val)) | 0;
}
let Long_eq; let Long_eq;
let Long_ne; let Long_ne;
let Long_gt; let Long_gt;

View File

@ -0,0 +1,99 @@
/*
* Copyright 2023 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
let $rt_packageData = null;
let $rt_packages = data => {
let i = 0;
let packages = new teavm_globals.Array(data.length);
for (let j = 0; j < data.length; ++j) {
let prefixIndex = data[i++];
let prefix = prefixIndex >= 0 ? packages[prefixIndex] : "";
packages[j] = prefix + data[i++] + ".";
}
$rt_packageData = packages;
}
let $rt_metadata = data => {
let packages = $rt_packageData;
let i = 0;
while (i < data.length) {
let cls = data[i++];
cls.$meta = {};
let m = cls.$meta;
let className = data[i++];
m.name = className !== 0 ? className : null;
if (m.name !== null) {
let packageIndex = data[i++];
if (packageIndex >= 0) {
m.name = packages[packageIndex] + m.name;
}
}
m.binaryName = "L" + m.name + ";";
let superclass = data[i++];
m.superclass = superclass !== 0 ? superclass : null;
m.supertypes = data[i++];
if (m.superclass) {
m.supertypes.push(m.superclass);
cls.prototype = teavm_globals.Object.create(m.superclass.prototype);
} else {
cls.prototype = {};
}
let flags = data[i++];
m.enum = (flags & 8) !== 0;
m.flags = flags;
m.primitive = false;
m.item = null;
cls.prototype.constructor = cls;
cls.classObject = null;
m.accessLevel = data[i++];
let innerClassInfo = data[i++];
if (innerClassInfo === 0) {
m.simpleName = null;
m.declaringClass = null;
m.enclosingClass = null;
} else {
let enclosingClass = innerClassInfo[0];
m.enclosingClass = enclosingClass !== 0 ? enclosingClass : null;
let declaringClass = innerClassInfo[1];
m.declaringClass = declaringClass !== 0 ? declaringClass : null;
let simpleName = innerClassInfo[2];
m.simpleName = simpleName !== 0 ? simpleName : null;
}
let clinit = data[i++];
cls.$clinit = clinit !== 0 ? clinit : function() {};
let virtualMethods = data[i++];
if (virtualMethods !== 0) {
for (let j = 0; j < virtualMethods.length; j += 2) {
let name = virtualMethods[j];
let func = virtualMethods[j + 1];
if (typeof name === 'string') {
name = [name];
}
for (let k = 0; k < name.length; ++k) {
cls.prototype[name[k]] = func;
}
}
}
cls.$array = null;
}
}

View File

@ -0,0 +1,95 @@
/*
* Copyright 2023 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
let $rt_numberConversionBuffer = new teavm_globals.ArrayBuffer(16);
let $rt_numberConversionView = new teavm_globals.DataView($rt_numberConversionBuffer);
let $rt_numberConversionFloatArray = new teavm_globals.Float32Array($rt_numberConversionBuffer);
let $rt_numberConversionDoubleArray = new teavm_globals.Float64Array($rt_numberConversionBuffer);
let $rt_numberConversionIntArray = new teavm_globals.Int32Array($rt_numberConversionBuffer);
let $rt_doubleToRawLongBits;
let $rt_longBitsToDouble;
if (typeof teavm_globals.BigInt !== 'function') {
$rt_doubleToRawLongBits = n => {
$rt_numberConversionView.setFloat64(0, n, true);
return new Long($rt_numberConversionView.getInt32(0, true), $rt_numberConversionView.getInt32(4, true));
}
$rt_longBitsToDouble = n => {
$rt_numberConversionView.setInt32(0, n.lo, true);
$rt_numberConversionView.setInt32(4, n.hi, true);
return $rt_numberConversionView.getFloat64(0, true);
}
} else if (typeof teavm_globals.BigInt64Array !== 'function') {
$rt_doubleToRawLongBits = n => {
$rt_numberConversionView.setFloat64(0, n, true);
let lo = $rt_numberConversionView.getInt32(0, true);
let hi = $rt_numberConversionView.getInt32(4, true);
return teavm_globals.BigInt.asIntN(64, teavm_globals.BigInt.asUintN(32, teavm_globals.BigInt(lo))
| (teavm_globals.BigInt(hi) << teavm_globals.BigInt(32)));
}
$rt_longBitsToDouble = n => {
$rt_numberConversionView.setFloat64(0, n, true);
let lo = $rt_numberConversionView.getInt32(0, true);
let hi = $rt_numberConversionView.getInt32(4, true);
return teavm_globals.BigInt.asIntN(64, teavm_globals.BigInt.asUintN(32, teavm_globals.BigInt(lo))
| (teavm_globals.BigInt(hi) << teavm_globals.BigInt(32)));
}
} else {
let $rt_numberConversionLongArray = new teavm_globals.BigInt64Array($rt_numberConversionBuffer);
$rt_doubleToRawLongBits = n => {
$rt_numberConversionDoubleArray[0] = n;
return $rt_numberConversionLongArray[0];
}
$rt_longBitsToDouble = n => {
$rt_numberConversionLongArray[0] = n;
return $rt_numberConversionDoubleArray[0];
}
}
let $rt_floatToRawIntBits = n => {
$rt_numberConversionFloatArray[0] = n;
return $rt_numberConversionIntArray[0];
}
let $rt_intBitsToFloat = n => {
$rt_numberConversionIntArray[0] = n;
return $rt_numberConversionFloatArray[0];
}
let $rt_equalDoubles = (a, b) => {
if (a !== a) {
return b !== b;
}
$rt_numberConversionDoubleArray[0] = a;
$rt_numberConversionDoubleArray[1] = b;
return $rt_numberConversionIntArray[0] === $rt_numberConversionIntArray[2]
&& $rt_numberConversionIntArray[1] === $rt_numberConversionIntArray[3];
}
let $rt_compare = (a, b) => a > b ? 1 : a < b ? -1 : a === b ? 0 : 1;
let $rt_imul = teavm_globals.Math.imul || function(a, b) {
let ah = (a >>> 16) & 0xFFFF;
let al = a & 0xFFFF;
let bh = (b >>> 16) & 0xFFFF;
let bl = b & 0xFFFF;
return (al * bl + (((ah * bl + al * bh) << 16) >>> 0)) | 0;
};
let $rt_udiv = (a, b) => ((a >>> 0) / (b >>> 0)) >>> 0;
let $rt_umod = (a, b) => ((a >>> 0) % (b >>> 0)) >>> 0;
let $rt_ucmp = (a, b) => {
a >>>= 0;
b >>>= 0;
return a < b ? -1 : a > b ? 1 : 0;
};

View File

@ -0,0 +1,48 @@
/*
* Copyright 2023 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
let $rt_createcls = () => {
return {
$array : null,
classObject : null,
$meta: {
supertypes : [],
superclass : null
}
};
}
let $rt_createPrimitiveCls = (name, binaryName) => {
let cls = $rt_createcls();
cls.$meta.primitive = true;
cls.$meta.name = name;
cls.$meta.binaryName = binaryName;
cls.$meta.enum = false;
cls.$meta.item = null;
cls.$meta.simpleName = null;
cls.$meta.declaringClass = null;
cls.$meta.enclosingClass = null;
return cls;
}
let $rt_booleancls = $rt_createPrimitiveCls("boolean", "Z");
let $rt_charcls = $rt_createPrimitiveCls("char", "C");
let $rt_bytecls = $rt_createPrimitiveCls("byte", "B");
let $rt_shortcls = $rt_createPrimitiveCls("short", "S");
let $rt_intcls = $rt_createPrimitiveCls("int", "I");
let $rt_longcls = $rt_createPrimitiveCls("long", "J");
let $rt_floatcls = $rt_createPrimitiveCls("float", "F");
let $rt_doublecls = $rt_createPrimitiveCls("double", "D");
let $rt_voidcls = $rt_createPrimitiveCls("void", "V");

View File

@ -0,0 +1,46 @@
/*
* Copyright 2023 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
let $rt_isInstance = (obj, cls) => obj instanceof $rt_objcls() && !!obj.constructor.$meta
&& $rt_isAssignable(obj.constructor, cls);
let $rt_isAssignable = (from, to) => {
if (from === to) {
return true;
}
if (to.$meta.item !== null) {
return from.$meta.item !== null && $rt_isAssignable(from.$meta.item, to.$meta.item);
}
let supertypes = from.$meta.supertypes;
for (let i = 0; i < supertypes.length; i = (i + 1) | 0) {
if ($rt_isAssignable(supertypes[i], to)) {
return true;
}
}
return false;
}
let $rt_castToInterface = (obj, cls) => {
if (obj !== null && !$rt_isInstance(obj, cls)) {
$rt_throwCCE();
}
return obj;
}
let $rt_castToClass = (obj, cls) => {
if (obj !== null && !(obj instanceof cls)) {
$rt_throwCCE();
}
return obj;
}

View File

@ -14,6 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
"use strict"; "use strict";
let $rt_seed = 2463534242; let $rt_seed = 2463534242;
let $rt_nextId = () => { let $rt_nextId = () => {
let x = $rt_seed; let x = $rt_seed;
@ -23,487 +24,7 @@ let $rt_nextId = () => {
$rt_seed = x; $rt_seed = x;
return x; return x;
} }
let $rt_compare = (a, b) => a > b ? 1 : a < b ? -1 : a === b ? 0 : 1;
let $rt_isInstance = (obj, cls) => obj instanceof $rt_objcls() && !!obj.constructor.$meta
&& $rt_isAssignable(obj.constructor, cls);
let $rt_isAssignable = (from, to) => {
if (from === to) {
return true;
}
if (to.$meta.item !== null) {
return from.$meta.item !== null && $rt_isAssignable(from.$meta.item, to.$meta.item);
}
let supertypes = from.$meta.supertypes;
for (let i = 0; i < supertypes.length; i = (i + 1) | 0) {
if ($rt_isAssignable(supertypes[i], to)) {
return true;
}
}
return false;
}
let $rt_castToInterface = (obj, cls) => {
if (obj !== null && !$rt_isInstance(obj, cls)) {
$rt_throwCCE();
}
return obj;
}
let $rt_castToClass = (obj, cls) => {
if (obj !== null && !(obj instanceof cls)) {
$rt_throwCCE();
}
return obj;
}
let $rt_createArray = (cls, sz) => {
let data = new teavm_globals.Array(sz);
data.fill(null);
return new ($rt_arraycls(cls))(data);
}
let $rt_createArrayFromData = (cls, init) => $rt_wrapArray(cls, init);
let $rt_wrapArray = (cls, data) => new ($rt_arraycls(cls))(data);
let $rt_createUnfilledArray = (cls, sz) => new ($rt_arraycls(cls))(new teavm_globals.Array(sz));
let $rt_createLongArray;
let $rt_createLongArrayFromData;
if (typeof teavm_globals.BigInt64Array !== 'function') {
$rt_createLongArray = sz => {
let data = new teavm_globals.Array(sz);
let arr = new $rt_longArrayCls(data);
data.fill(Long_ZERO);
return arr;
}
$rt_createLongArrayFromData = init => new $rt_longArrayCls(init);
} else {
$rt_createLongArray = sz => new $rt_longArrayCls(new teavm_globals.BigInt64Array(sz));
$rt_createLongArrayFromData = data => {
let buffer = new teavm_globals.BigInt64Array(data.length);
buffer.set(data);
return new $rt_longArrayCls(buffer);
}
}
let $rt_createCharArray = sz => new $rt_charArrayCls(new teavm_globals.Uint16Array(sz));
let $rt_createCharArrayFromData = data => {
let buffer = new teavm_globals.Uint16Array(data.length);
buffer.set(data);
return new $rt_charArrayCls(buffer);
}
let $rt_createByteArray = sz => new $rt_byteArrayCls(new teavm_globals.Int8Array(sz));
let $rt_createByteArrayFromData = data => {
let buffer = new teavm_globals.Int8Array(data.length);
buffer.set(data);
return new $rt_byteArrayCls(buffer);
}
let $rt_createShortArray = sz => new $rt_shortArrayCls(new teavm_globals.Int16Array(sz));
let $rt_createShortArrayFromData = data => {
let buffer = new teavm_globals.Int16Array(data.length);
buffer.set(data);
return new $rt_shortArrayCls(buffer);
}
let $rt_createIntArray = sz => new $rt_intArrayCls(new teavm_globals.Int32Array(sz));
let $rt_createIntArrayFromData = data => {
let buffer = new teavm_globals.Int32Array(data.length);
buffer.set(data);
return new $rt_intArrayCls(buffer);
}
let $rt_createBooleanArray = sz => new $rt_booleanArrayCls(new teavm_globals.Int8Array(sz));
let $rt_createBooleanArrayFromData = data => {
let buffer = new teavm_globals.Int8Array(data.length);
buffer.set(data);
return new $rt_booleanArrayCls(buffer);
}
let $rt_createFloatArray = sz => new $rt_floatArrayCls(new teavm_globals.Float32Array(sz));
let $rt_createFloatArrayFromData = data => {
let buffer = new teavm_globals.Float32Array(data.length);
buffer.set(data);
return new $rt_floatArrayCls(buffer);
}
let $rt_createDoubleArray = sz => new $rt_doubleArrayCls(new teavm_globals.Float64Array(sz));
let $rt_createDoubleArrayFromData = data => {
let buffer = new teavm_globals.Float64Array(data.length);
buffer.set(data);
return new $rt_doubleArrayCls(buffer);
}
let $rt_arraycls = cls => {
let result = cls.$array;
if (result === null) {
function JavaArray(data) {
$rt_objcls().call(this);
this.data = data;
}
JavaArray.prototype = teavm_globals.Object.create($rt_objcls().prototype);
JavaArray.prototype.type = cls;
JavaArray.prototype.constructor = JavaArray;
JavaArray.prototype.toString = function() {
let str = "[";
for (let i = 0; i < this.data.length; ++i) {
if (i > 0) {
str += ", ";
}
str += this.data[i].toString();
}
str += "]";
return str;
};
JavaArray.prototype[teavm_javaVirtualMethod('clone()Ljava/lang/Object;')] = function() {
let dataCopy;
if ('slice' in this.data) {
dataCopy = this.data.slice();
} else {
dataCopy = new this.data.constructor(this.data.length);
for (let i = 0; i < dataCopy.length; ++i) {
dataCopy[i] = this.data[i];
}
}
return new ($rt_arraycls(this.type))(dataCopy);
};
let name = "[" + cls.$meta.binaryName;
JavaArray.$meta = {
item: cls,
supertypes: [$rt_objcls()],
primitive: false,
superclass: $rt_objcls(),
name: name,
binaryName: name,
enum: false,
simpleName: null,
declaringClass: null,
enclosingClass: null
};
JavaArray.classObject = null;
JavaArray.$array = null;
result = JavaArray;
cls.$array = JavaArray;
}
return result;
}
let $rt_createcls = () => {
return {
$array : null,
classObject : null,
$meta: {
supertypes : [],
superclass : null
}
};
}
let $rt_createPrimitiveCls = (name, binaryName) => {
let cls = $rt_createcls();
cls.$meta.primitive = true;
cls.$meta.name = name;
cls.$meta.binaryName = binaryName;
cls.$meta.enum = false;
cls.$meta.item = null;
cls.$meta.simpleName = null;
cls.$meta.declaringClass = null;
cls.$meta.enclosingClass = null;
return cls;
}
let $rt_booleancls = $rt_createPrimitiveCls("boolean", "Z");
let $rt_charcls = $rt_createPrimitiveCls("char", "C");
let $rt_bytecls = $rt_createPrimitiveCls("byte", "B");
let $rt_shortcls = $rt_createPrimitiveCls("short", "S");
let $rt_intcls = $rt_createPrimitiveCls("int", "I");
let $rt_longcls = $rt_createPrimitiveCls("long", "J");
let $rt_floatcls = $rt_createPrimitiveCls("float", "F");
let $rt_doublecls = $rt_createPrimitiveCls("double", "D");
let $rt_voidcls = $rt_createPrimitiveCls("void", "V");
let $rt_throw = ex => {
throw $rt_exception(ex)
};
let $rt_javaExceptionProp = teavm_globals.Symbol("javaException")
let $rt_exception = ex => {
let err = ex.$jsException;
if (!err) {
let javaCause = $rt_throwableCause(ex);
let jsCause = javaCause !== null ? javaCause.$jsException : void 0;
let cause = typeof jsCause === "object" ? { cause : jsCause } : void 0;
err = new JavaError("Java exception thrown", cause);
if (typeof teavm_globals.Error.captureStackTrace === "function") {
teavm_globals.Error.captureStackTrace(err);
}
err[$rt_javaExceptionProp] = ex;
ex.$jsException = err;
$rt_fillStack(err, ex);
}
return err;
}
let $rt_fillStack = (err, ex) => {
if (typeof $rt_decodeStack === "function" && err.stack) {
let stack = $rt_decodeStack(err.stack);
let javaStack = $rt_createArray($rt_stecls(), stack.length);
let elem;
let noStack = false;
for (let i = 0; i < stack.length; ++i) {
let element = stack[i];
elem = $rt_createStackElement($rt_str(element.className),
$rt_str(element.methodName), $rt_str(element.fileName), element.lineNumber);
if (elem == null) {
noStack = true;
break;
}
javaStack.data[i] = elem;
}
if (!noStack) {
$rt_setStack(ex, javaStack);
}
}
}
let $rt_createMultiArray = (cls, dimensions) => {
let first = 0;
for (let i = dimensions.length - 1; i >= 0; i = (i - 1) | 0) {
if (dimensions[i] === 0) {
first = i;
break;
}
}
if (first > 0) {
for (let i = 0; i < first; i = (i + 1) | 0) {
cls = $rt_arraycls(cls);
}
if (first === dimensions.length - 1) {
return $rt_createArray(cls, dimensions[first]);
}
}
let arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, first));
let firstDim = dimensions[first] | 0;
for (let i = 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createArray(cls, firstDim);
}
return $rt_createMultiArrayImpl(cls, arrays, dimensions, first);
}
let $rt_createByteMultiArray = dimensions => {
let arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, 0));
if (arrays.length === 0) {
return $rt_createMultiArray($rt_bytecls, dimensions);
}
let firstDim = dimensions[0] | 0;
for (let i = 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createByteArray(firstDim);
}
return $rt_createMultiArrayImpl($rt_bytecls, arrays, dimensions);
}
let $rt_createCharMultiArray = dimensions => {
let arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, 0));
if (arrays.length === 0) {
return $rt_createMultiArray($rt_charcls, dimensions);
}
let firstDim = dimensions[0] | 0;
for (let i = 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createCharArray(firstDim);
}
return $rt_createMultiArrayImpl($rt_charcls, arrays, dimensions, 0);
}
let $rt_createBooleanMultiArray = dimensions => {
let arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, 0));
if (arrays.length === 0) {
return $rt_createMultiArray($rt_booleancls, dimensions);
}
let firstDim = dimensions[0] | 0;
for (let i = 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createBooleanArray(firstDim);
}
return $rt_createMultiArrayImpl($rt_booleancls, arrays, dimensions, 0);
}
let $rt_createShortMultiArray = dimensions => {
let arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, 0));
if (arrays.length === 0) {
return $rt_createMultiArray($rt_shortcls, dimensions);
}
let firstDim = dimensions[0] | 0;
for (let i = 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createShortArray(firstDim);
}
return $rt_createMultiArrayImpl($rt_shortcls, arrays, dimensions, 0);
}
let $rt_createIntMultiArray = dimensions => {
let arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, 0));
if (arrays.length === 0) {
return $rt_createMultiArray($rt_intcls, dimensions);
}
let firstDim = dimensions[0] | 0;
for (let i = 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createIntArray(firstDim);
}
return $rt_createMultiArrayImpl($rt_intcls, arrays, dimensions, 0);
}
let $rt_createLongMultiArray = dimensions => {
let arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, 0));
if (arrays.length === 0) {
return $rt_createMultiArray($rt_longcls, dimensions);
}
let firstDim = dimensions[0] | 0;
for (let i = 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createLongArray(firstDim);
}
return $rt_createMultiArrayImpl($rt_longcls, arrays, dimensions, 0);
}
let $rt_createFloatMultiArray = dimensions => {
let arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, 0));
if (arrays.length === 0) {
return $rt_createMultiArray($rt_floatcls, dimensions);
}
let firstDim = dimensions[0] | 0;
for (let i = 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createFloatArray(firstDim);
}
return $rt_createMultiArrayImpl($rt_floatcls, arrays, dimensions, 0);
}
let $rt_createDoubleMultiArray = dimensions => {
let arrays = new teavm_globals.Array($rt_primitiveArrayCount(dimensions, 0));
if (arrays.length === 0) {
return $rt_createMultiArray($rt_doublecls, dimensions);
}
let firstDim = dimensions[0] | 0;
for (let i = 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createDoubleArray(firstDim);
}
return $rt_createMultiArrayImpl($rt_doublecls, arrays, dimensions, 0);
}
let $rt_primitiveArrayCount = (dimensions, start) => {
let val = dimensions[start + 1] | 0;
for (let i = start + 2; i < dimensions.length; i = (i + 1) | 0) {
val = (val * (dimensions[i] | 0)) | 0;
if (val === 0) {
break;
}
}
return val;
}
let $rt_createMultiArrayImpl = (cls, arrays, dimensions, start) => {
let limit = arrays.length;
for (let i = (start + 1) | 0; i < dimensions.length; i = (i + 1) | 0) {
cls = $rt_arraycls(cls);
let dim = dimensions[i];
let index = 0;
let packedIndex = 0;
while (index < limit) {
let arr = $rt_createUnfilledArray(cls, dim);
for (let j = 0; j < dim; j = (j + 1) | 0) {
arr.data[j] = arrays[index];
index = (index + 1) | 0;
}
arrays[packedIndex] = arr;
packedIndex = (packedIndex + 1) | 0;
}
limit = packedIndex;
}
return arrays[0];
}
let $rt_assertNotNaN = value => {
if (typeof value === 'number' && isNaN(value)) {
throw "NaN";
}
return value;
}
let $rt_createOutputFunction = outputFunction => {
let buffer = "";
return msg => {
let index = 0;
while (true) {
let next = msg.indexOf('\n', index);
if (next < 0) {
break;
}
outputFunction(buffer + msg.substring(index, next));
buffer = "";
index = next + 1;
}
buffer += msg.substring(index);
}
}
let $rt_putStdout = typeof teavm_globals.$rt_putStdoutCustom === "function"
? teavm_globals.$rt_putStdoutCustom
: typeof console === "object" ? $rt_createOutputFunction(msg => console.info(msg)) : () => {};
let $rt_putStderr = typeof teavm_globals.$rt_putStderrCustom === "function"
? teavm_globals.$rt_putStderrCustom
: typeof console === "object" ? $rt_createOutputFunction(msg => console.error(msg)) : () => {};
let $rt_packageData = null;
let $rt_packages = data => {
let i = 0;
let packages = new teavm_globals.Array(data.length);
for (let j = 0; j < data.length; ++j) {
let prefixIndex = data[i++];
let prefix = prefixIndex >= 0 ? packages[prefixIndex] : "";
packages[j] = prefix + data[i++] + ".";
}
$rt_packageData = packages;
}
let $rt_metadata = data => {
let packages = $rt_packageData;
let i = 0;
while (i < data.length) {
let cls = data[i++];
cls.$meta = {};
let m = cls.$meta;
let className = data[i++];
m.name = className !== 0 ? className : null;
if (m.name !== null) {
let packageIndex = data[i++];
if (packageIndex >= 0) {
m.name = packages[packageIndex] + m.name;
}
}
m.binaryName = "L" + m.name + ";";
let superclass = data[i++];
m.superclass = superclass !== 0 ? superclass : null;
m.supertypes = data[i++];
if (m.superclass) {
m.supertypes.push(m.superclass);
cls.prototype = teavm_globals.Object.create(m.superclass.prototype);
} else {
cls.prototype = {};
}
let flags = data[i++];
m.enum = (flags & 8) !== 0;
m.flags = flags;
m.primitive = false;
m.item = null;
cls.prototype.constructor = cls;
cls.classObject = null;
m.accessLevel = data[i++];
let innerClassInfo = data[i++];
if (innerClassInfo === 0) {
m.simpleName = null;
m.declaringClass = null;
m.enclosingClass = null;
} else {
let enclosingClass = innerClassInfo[0];
m.enclosingClass = enclosingClass !== 0 ? enclosingClass : null;
let declaringClass = innerClassInfo[1];
m.declaringClass = declaringClass !== 0 ? declaringClass : null;
let simpleName = innerClassInfo[2];
m.simpleName = simpleName !== 0 ? simpleName : null;
}
let clinit = data[i++];
cls.$clinit = clinit !== 0 ? clinit : function() {};
let virtualMethods = data[i++];
if (virtualMethods !== 0) {
for (let j = 0; j < virtualMethods.length; j += 2) {
let name = virtualMethods[j];
let func = virtualMethods[j + 1];
if (typeof name === 'string') {
name = [name];
}
for (let k = 0; k < name.length; ++k) {
cls.prototype[name[k]] = func;
}
}
}
cls.$array = null;
}
}
let $rt_wrapFunction0 = f => function() { let $rt_wrapFunction0 = f => function() {
return f(this); return f(this);
} }
@ -535,132 +56,9 @@ let $rt_mainStarter = f => (args, callback) => {
} }
$rt_startThread(() => { f.call(null, javaArgs); }, callback); $rt_startThread(() => { f.call(null, javaArgs); }, callback);
} }
let $rt_stringPool_instance;
let $rt_stringPool = strings => {
$rt_stringClassInit();
$rt_stringPool_instance = new teavm_globals.Array(strings.length);
for (let i = 0; i < strings.length; ++i) {
$rt_stringPool_instance[i] = $rt_intern($rt_str(strings[i]));
}
}
let $rt_s = index => $rt_stringPool_instance[index];
let $rt_eraseClinit = target => target.$clinit = () => {}; let $rt_eraseClinit = target => target.$clinit = () => {};
let $rt_numberConversionBuffer = new teavm_globals.ArrayBuffer(16);
let $rt_numberConversionView = new teavm_globals.DataView($rt_numberConversionBuffer);
let $rt_numberConversionFloatArray = new teavm_globals.Float32Array($rt_numberConversionBuffer);
let $rt_numberConversionDoubleArray = new teavm_globals.Float64Array($rt_numberConversionBuffer);
let $rt_numberConversionIntArray = new teavm_globals.Int32Array($rt_numberConversionBuffer);
let $rt_doubleToRawLongBits;
let $rt_longBitsToDouble;
if (typeof teavm_globals.BigInt !== 'function') {
$rt_doubleToRawLongBits = n => {
$rt_numberConversionView.setFloat64(0, n, true);
return new Long($rt_numberConversionView.getInt32(0, true), $rt_numberConversionView.getInt32(4, true));
}
$rt_longBitsToDouble = n => {
$rt_numberConversionView.setInt32(0, n.lo, true);
$rt_numberConversionView.setInt32(4, n.hi, true);
return $rt_numberConversionView.getFloat64(0, true);
}
} else if (typeof teavm_globals.BigInt64Array !== 'function') {
$rt_doubleToRawLongBits = n => {
$rt_numberConversionView.setFloat64(0, n, true);
let lo = $rt_numberConversionView.getInt32(0, true);
let hi = $rt_numberConversionView.getInt32(4, true);
return teavm_globals.BigInt.asIntN(64, teavm_globals.BigInt.asUintN(32, teavm_globals.BigInt(lo))
| (teavm_globals.BigInt(hi) << teavm_globals.BigInt(32)));
}
$rt_longBitsToDouble = n => {
$rt_numberConversionView.setFloat64(0, n, true);
let lo = $rt_numberConversionView.getInt32(0, true);
let hi = $rt_numberConversionView.getInt32(4, true);
return teavm_globals.BigInt.asIntN(64, teavm_globals.BigInt.asUintN(32, teavm_globals.BigInt(lo))
| (teavm_globals.BigInt(hi) << teavm_globals.BigInt(32)));
}
} else {
let $rt_numberConversionLongArray = new teavm_globals.BigInt64Array($rt_numberConversionBuffer);
$rt_doubleToRawLongBits = n => {
$rt_numberConversionDoubleArray[0] = n;
return $rt_numberConversionLongArray[0];
}
$rt_longBitsToDouble = n => {
$rt_numberConversionLongArray[0] = n;
return $rt_numberConversionDoubleArray[0];
}
}
let $rt_floatToRawIntBits = n => {
$rt_numberConversionFloatArray[0] = n;
return $rt_numberConversionIntArray[0];
}
let $rt_intBitsToFloat = n => {
$rt_numberConversionIntArray[0] = n;
return $rt_numberConversionFloatArray[0];
}
let $rt_equalDoubles = (a, b) => {
if (a !== a) {
return b !== b;
}
$rt_numberConversionDoubleArray[0] = a;
$rt_numberConversionDoubleArray[1] = b;
return $rt_numberConversionIntArray[0] === $rt_numberConversionIntArray[2]
&& $rt_numberConversionIntArray[1] === $rt_numberConversionIntArray[3];
}
let JavaError;
if (typeof Reflect === 'object') {
let defaultMessage = teavm_globals.Symbol("defaultMessage");
JavaError = function JavaError(message, cause) {
let self = teavm_globals.Reflect.construct(teavm_globals.Error, [void 0, cause], JavaError);
teavm_globals.Object.setPrototypeOf(self, JavaError.prototype);
self[defaultMessage] = message;
return self;
}
JavaError.prototype = teavm_globals.Object.create(teavm_globals.Error.prototype, {
constructor: {
configurable: true,
writable: true,
value: JavaError
},
message: {
get() {
try {
let javaException = this[$rt_javaExceptionProp];
if (typeof javaException === 'object') {
let javaMessage = $rt_throwableMessage(javaException);
if (typeof javaMessage === "object") {
return javaMessage !== null ? javaMessage.toString() : null;
}
}
return this[defaultMessage];
} catch (e) {
return "Exception occurred trying to extract Java exception message: " + e
}
}
}
});
} else {
JavaError = teavm_globals.Error;
}
let $rt_javaException = e => e instanceof teavm_globals.Error && typeof e[$rt_javaExceptionProp] === 'object'
? e[$rt_javaExceptionProp]
: null;
let $rt_jsException = e => typeof e.$jsException === 'object' ? e.$jsException : null;
let $rt_wrapException = err => {
let ex = err[$rt_javaExceptionProp];
if (!ex) {
ex = $rt_createException($rt_str("(JavaScript) " + err.toString()));
err[$rt_javaExceptionProp] = ex;
ex.$jsException = err;
$rt_fillStack(err, ex);
}
return ex;
}
let $dbg_class = obj => { let $dbg_class = obj => {
let cls = obj.constructor; let cls = obj.constructor;
let arrayDegree = 0; let arrayDegree = 0;
@ -680,98 +78,6 @@ let $dbg_class = obj => {
return clsName; return clsName;
} }
function Long(lo, hi) {
this.lo = lo | 0;
this.hi = hi | 0;
}
Long.prototype.__teavm_class__ = () => {
return "long";
};
let Long_isPositive = a => (a.hi & 0x80000000) === 0;
let Long_isNegative = a => (a.hi & 0x80000000) !== 0;
let Long_MAX_NORMAL = 1 << 18;
let Long_ZERO;
let Long_create;
let Long_fromInt;
let Long_fromNumber;
let Long_toNumber;
let Long_hi;
let Long_lo;
if (typeof teavm_globals.BigInt !== "function") {
Long.prototype.toString = function() {
let result = [];
let n = this;
let positive = Long_isPositive(n);
if (!positive) {
n = Long_neg(n);
}
let radix = new Long(10, 0);
do {
let divRem = Long_divRem(n, radix);
result.push(teavm_globals.String.fromCharCode(48 + divRem[1].lo));
n = divRem[0];
} while (n.lo !== 0 || n.hi !== 0);
result = result.reverse().join('');
return positive ? result : "-" + result;
};
Long.prototype.valueOf = function() {
return Long_toNumber(this);
};
Long_ZERO = new Long(0, 0);
Long_fromInt = val =>new Long(val, (-(val < 0)) | 0);
Long_fromNumber = val => val >= 0
? new Long(val | 0, (val / 0x100000000) | 0)
: Long_neg(new Long(-val | 0, (-val / 0x100000000) | 0));
Long_create = (lo, hi) => new Long(lo, hi);
Long_toNumber = val => 0x100000000 * val.hi + (val.lo >>> 0);
Long_hi = val => val.hi;
Long_lo = val => val.lo;
} else {
Long_ZERO = teavm_globals.BigInt(0);
Long_create = (lo, hi) => teavm_globals.BigInt.asIntN(64, teavm_globals.BigInt.asUintN(64, teavm_globals.BigInt(lo))
| teavm_globals.BigInt.asUintN(64, (teavm_globals.BigInt(hi) << teavm_globals.BigInt(32))));
Long_fromInt = val => teavm_globals.BigInt.asIntN(64, teavm_globals.BigInt(val | 0));
Long_fromNumber = val => teavm_globals.BigInt.asIntN(64, teavm_globals.BigInt(
val >= 0 ? teavm_globals.Math.floor(val) : teavm_globals.Math.ceil(val)));
Long_toNumber = val => teavm_globals.Number(val);
Long_hi = val => teavm_globals.Number(teavm_globals.BigInt.asIntN(64, val >> teavm_globals.BigInt(32))) | 0;
Long_lo = val => teavm_globals.Number(teavm_globals.BigInt.asIntN(32, val)) | 0;
}
let $rt_imul = teavm_globals.Math.imul || function(a, b) {
let ah = (a >>> 16) & 0xFFFF;
let al = a & 0xFFFF;
let bh = (b >>> 16) & 0xFFFF;
let bl = b & 0xFFFF;
return (al * bl + (((ah * bl + al * bh) << 16) >>> 0)) | 0;
};
let $rt_udiv = (a, b) => ((a >>> 0) / (b >>> 0)) >>> 0;
let $rt_umod = (a, b) => ((a >>> 0) % (b >>> 0)) >>> 0;
let $rt_ucmp = (a, b) => {
a >>>= 0;
b >>>= 0;
return a < b ? -1 : a > b ? 1 : 0;
};
let $rt_checkBounds = (index, array) => {
if (index < 0 || index >= array.length) {
$rt_throwAIOOBE();
}
return index;
}
let $rt_checkUpperBound = (index, array) => {
if (index >= array.length) {
$rt_throwAIOOBE();
}
return index;
}
let $rt_checkLowerBound = index => {
if (index < 0) {
$rt_throwAIOOBE();
}
return index;
}
let $rt_classWithoutFields = superclass => { let $rt_classWithoutFields = superclass => {
if (superclass === 0) { if (superclass === 0) {
return function() {}; return function() {};
@ -783,64 +89,13 @@ let $rt_classWithoutFields = superclass => {
superclass.call(this); superclass.call(this);
}; };
} }
let $rt_charArrayToString = (array, offset, count) => {
let result = "";
let limit = offset + count;
for (let i = offset; i < limit; i = (i + 1024) | 0) {
let next = teavm_globals.Math.min(limit, (i + 1024) | 0);
result += teavm_globals.String.fromCharCode.apply(null, array.subarray(i, next));
}
return result;
}
let $rt_fullArrayToString = (array) => $rt_charArrayToString(array, 0, array.length);
let $rt_stringToCharArray = (string, begin, dst, dstBegin, count) => {
for (let i = 0; i < count; i = (i + 1) | 0) {
dst[dstBegin + i] = string.charCodeAt(begin + i);
}
}
let $rt_fastStringToCharArray = string => {
let array = new teavm_globals.Uint16Array(string.length);
for (let i = 0; i < array.length; ++i) {
array[i] = string.charCodeAt(i);
}
return new $rt_charArrayCls(array);
}
let $rt_substring = (string, start, end) => {
if (start === 0 && end === string.length) {
return string;
}
let result = start.substring(start, end - 1) + start.substring(end - 1, end);
$rt_substringSink = ($rt_substringSink + result.charCodeAt(result.length - 1)) | 0;
}
let $rt_substringSink = 0;
let $rt_cls = (cls) => teavm_javaMethod("java.lang.Class", let $rt_cls = (cls) => teavm_javaMethod("java.lang.Class",
"getClass(Lorg/teavm/platform/PlatformClass;)Ljava/lang/Class;")(cls); "getClass(Lorg/teavm/platform/PlatformClass;)Ljava/lang/Class;")(cls);
let $rt_str = str => str === null ? null : teavm_javaConstructor("java.lang.String", "(Ljava/lang/Object;)V")(str);
let $rt_ustr = str => str === null ? null : str[teavm_javaField("java.lang.String", "nativeString")];
let $rt_nullCheck = val => {
if (val === null) {
$rt_throw(teavm_javaConstructor("java.lang.NullPointerException", "()V")());
}
return val;
}
let $rt_stringClassInit = () => teavm_javaClassInit("java.lang.String")();
let $rt_objcls = () => teavm_javaClass("java.lang.Object"); let $rt_objcls = () => teavm_javaClass("java.lang.Object");
let $rt_createException = message => teavm_javaConstructor("java.lang.RuntimeException",
"(Ljava/lang/String;)V")(message);
let $rt_throwableMessage = t => teavm_javaMethod("java.lang.Throwable", "getMessage()Ljava/lang/String;")(t);
let $rt_throwableCause = t => teavm_javaMethod("java.lang.Throwable", "getCause()Ljava/lang/Throwable;")(t);
let $rt_stecls = () => teavm_javaClassExists("java.lang.StackTraceElement")
? teavm_javaClass("java.lang.StackTraceElement")
: $rt_objcls();
let $rt_throwAIOOBE = () => teavm_javaConstructorExists("java.lang.ArrayIndexOutOfBoundsException", "()V")
? $rt_throw(teavm_javaConstructor("java.lang.ArrayIndexOutOfBoundsException", "()V")())
: $rt_throw($rt_createException($rt_str("")));
let $rt_throwCCE = () => teavm_javaConstructorExists("java.lang.ClassCastException", "()V")
? $rt_throw(teavm_javaConstructor("java.lang.ClassCastException", "()V")())
: $rt_throw($rt_createException($rt_str("")));
let $rt_getThread = () => { let $rt_getThread = () => {
if (teavm_javaMethodExists("java.lang.Thread", "currentThread()Ljava/lang/Thread;")) { if (teavm_javaMethodExists("java.lang.Thread", "currentThread()Ljava/lang/Thread;")) {
@ -852,17 +107,3 @@ let $rt_setThread = t => {
return teavm_javaMethod("java.lang.Thread", "setCurrentThread(Ljava/lang/Thread;)V")(t); return teavm_javaMethod("java.lang.Thread", "setCurrentThread(Ljava/lang/Thread;)V")(t);
} }
} }
let $rt_createStackElement = (className, methodName, fileName, lineNumber) => {
if (teavm_javaConstructorExists("java.lang.StackTraceElement",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V")) {
return teavm_javaConstructor("java.lang.StackTraceElement",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V")(className, methodName, fileName, lineNumber);
} else {
return null;
}
}
let $rt_setStack = (e, stack) => {
if (teavm_javaMethodExists("java.lang.Throwable", "setStackTrace([Ljava/lang/StackTraceElement;)V")) {
teavm_javaMethod("java.lang.Throwable", "setStackTrace([Ljava/lang/StackTraceElement;)V")(e, stack);
}
}

View File

@ -0,0 +1,102 @@
/*
* Copyright 2023 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
let $rt_stringPool_instance;
let $rt_stringPool = strings => {
$rt_stringClassInit();
$rt_stringPool_instance = new teavm_globals.Array(strings.length);
for (let i = 0; i < strings.length; ++i) {
$rt_stringPool_instance[i] = $rt_intern($rt_str(strings[i]));
}
}
let $rt_s = index => $rt_stringPool_instance[index];
let $rt_charArrayToString = (array, offset, count) => {
let result = "";
let limit = offset + count;
for (let i = offset; i < limit; i = (i + 1024) | 0) {
let next = teavm_globals.Math.min(limit, (i + 1024) | 0);
result += teavm_globals.String.fromCharCode.apply(null, array.subarray(i, next));
}
return result;
}
let $rt_fullArrayToString = (array) => $rt_charArrayToString(array, 0, array.length);
let $rt_stringToCharArray = (string, begin, dst, dstBegin, count) => {
for (let i = 0; i < count; i = (i + 1) | 0) {
dst[dstBegin + i] = string.charCodeAt(begin + i);
}
}
let $rt_fastStringToCharArray = string => {
let array = new teavm_globals.Uint16Array(string.length);
for (let i = 0; i < array.length; ++i) {
array[i] = string.charCodeAt(i);
}
return new $rt_charArrayCls(array);
}
let $rt_substring = (string, start, end) => {
if (start === 0 && end === string.length) {
return string;
}
let result = start.substring(start, end - 1) + start.substring(end - 1, end);
$rt_substringSink = ($rt_substringSink + result.charCodeAt(result.length - 1)) | 0;
}
let $rt_substringSink = 0;
let $rt_str = str => str === null ? null : teavm_javaConstructor("java.lang.String", "(Ljava/lang/Object;)V")(str);
let $rt_ustr = str => str === null ? null : str[teavm_javaField("java.lang.String", "nativeString")];
let $rt_stringClassInit = () => teavm_javaClassInit("java.lang.String")();
let $rt_intern
if (teavm_javaMethodExists("java.lang.String", "intern()Ljava/lang/String;")) {
$rt_intern = function() {
let map = teavm_globals.Object.create(null);
let get;
if (typeof teavm_globals.WeakRef !== 'undefined') {
let registry = new teavm_globals.FinalizationRegistry(value => {
delete map[value];
});
get = str => {
let key = $rt_ustr(str);
let ref = map[key];
let result = typeof ref !== 'undefined' ? ref.deref() : void 0;
if (typeof result !== 'object') {
result = str;
map[key] = new teavm_globals.WeakRef(result);
registry.register(result, key);
}
return result;
}
} else {
get = str => {
let key = $rt_ustr(str);
let result = map[key];
if (typeof result !== 'object') {
result = str;
map[key] = result;
}
return result;
}
}
return get;
}();
} else {
$rt_intern = str => str;
}

View File

@ -0,0 +1,25 @@
/*
* Copyright 2019 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
let $rt_booleanArrayCls = $rt_arraycls($rt_booleancls);
let $rt_charArrayCls = $rt_arraycls($rt_charcls);
let $rt_byteArrayCls = $rt_arraycls($rt_bytecls);
let $rt_shortArrayCls = $rt_arraycls($rt_shortcls);
let $rt_intArrayCls = $rt_arraycls($rt_intcls);
let $rt_longArrayCls = $rt_arraycls($rt_longcls);
let $rt_floatArrayCls = $rt_arraycls($rt_floatcls);
let $rt_doubleArrayCls = $rt_arraycls($rt_doublecls);