Skip to content

Commit

Permalink
jso: pass primitive arrays to JS as TypedArrays
Browse files Browse the repository at this point in the history
  • Loading branch information
konsoletyper committed Feb 7, 2025
1 parent e28b27c commit 7fdaf3c
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 47 deletions.
2 changes: 1 addition & 1 deletion core/src/main/js/wasm-gc-runtime/runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ function jsoImports(imports, context) {
rethrowJsAsJava(e);
}
},
concatArray: (a, b) => a.concat(b),
concatArray: (a, b) => [...a, ...b],
getJavaException: e => e[javaExceptionSymbol],
jsExports: () => context.userExports
};
Expand Down
81 changes: 44 additions & 37 deletions jso/impl/src/main/java/org/teavm/jso/impl/JS.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@
import org.teavm.jso.core.JSBoolean;
import org.teavm.jso.core.JSNumber;
import org.teavm.jso.core.JSString;
import org.teavm.jso.typedarrays.BigInt64Array;
import org.teavm.jso.typedarrays.Float32Array;
import org.teavm.jso.typedarrays.Float64Array;
import org.teavm.jso.typedarrays.Int16Array;
import org.teavm.jso.typedarrays.Int32Array;
import org.teavm.jso.typedarrays.Int8Array;
import org.teavm.jso.typedarrays.Uint16Array;

public final class JS {
private JS() {
Expand Down Expand Up @@ -172,7 +179,7 @@ private JS() {
@NoSideEffects
public static native String unwrapString(JSObject value);

public static <T extends JSObject> JSArray<T> wrap(T[] array) {
public static <T extends JSObject> JSObject wrap(T[] array) {
if (array == null) {
return null;
}
Expand All @@ -183,7 +190,7 @@ public static <T extends JSObject> JSArray<T> wrap(T[] array) {
return result;
}

public static <T> JSArray<T> wrap(T[] array) {
public static <T> JSObject wrap(T[] array) {
if (array == null) {
return null;
}
Expand All @@ -194,11 +201,11 @@ public static <T> JSArray<T> wrap(T[] array) {
return result;
}

public static <T extends JSObject> WrapFunction<T[], JSArray<T>> arrayWrapper() {
public static <T extends JSObject> WrapFunction<T[], JSObject> arrayWrapper() {
return JS::wrap;
}

public static <T extends JSObject, S> JSArray<T> map(S[] array, WrapFunction<S, T> f) {
public static <T extends JSObject, S> JSObject map(S[] array, WrapFunction<S, T> f) {
if (array == null) {
return null;
}
Expand All @@ -217,11 +224,11 @@ public interface UnwrapFunction<S extends JSObject, T> {
T apply(S obj);
}

public static <T extends JSObject, S> WrapFunction<S[], JSArray<T>> arrayMapper(WrapFunction<S, T> f) {
public static <T extends JSObject, S> WrapFunction<S[], JSObject> arrayMapper(WrapFunction<S, T> f) {
return array -> map(array, f);
}

public static JSArray<JSBoolean> wrap(boolean[] array) {
public static JSObject wrap(boolean[] array) {
if (array == null) {
return null;
}
Expand All @@ -232,87 +239,87 @@ public static JSArray<JSBoolean> wrap(boolean[] array) {
return result;
}

public static WrapFunction<boolean[], JSArray<JSBoolean>> booleanArrayWrapper() {
public static WrapFunction<boolean[], JSObject> booleanArrayWrapper() {
return JS::wrap;
}

public static JSArray<JSNumber> wrap(byte[] array) {
public static JSObject wrap(byte[] array) {
if (array == null) {
return null;
}
var result = new JSArray<JSNumber>(array.length);
var result = new Int8Array(array.length);
for (int i = 0; i < array.length; ++i) {
result.set(i, JSNumber.valueOf(array[i]));
result.set(i, array[i]);
}
return result;
}

public static WrapFunction<byte[], JSArray<JSNumber>> byteArrayWrapper() {
public static WrapFunction<byte[], JSObject> byteArrayWrapper() {
return JS::wrap;
}

public static JSArray<JSNumber> wrap(short[] array) {
public static JSObject wrap(short[] array) {
if (array == null) {
return null;
}
var result = new JSArray<JSNumber>(array.length);
var result = new Int16Array(array.length);
for (int i = 0; i < array.length; ++i) {
result.set(i, JSNumber.valueOf(array[i]));
result.set(i, array[i]);
}
return result;
}

public static WrapFunction<short[], JSArray<JSNumber>> shortArrayWrapper() {
public static WrapFunction<short[], JSObject> shortArrayWrapper() {
return JS::wrap;
}

public static JSArray<JSNumber> wrap(char[] array) {
public static JSObject wrap(char[] array) {
if (array == null) {
return null;
}
var result = new JSArray<JSNumber>(array.length);
var result = new Uint16Array(array.length);
for (int i = 0; i < array.length; ++i) {
result.set(i, JSNumber.valueOf(array[i]));
result.set(i, array[i]);
}
return result;
}

public static WrapFunction<char[], JSArray<JSNumber>> charArrayWrapper() {
public static WrapFunction<char[], JSObject> charArrayWrapper() {
return JS::wrap;
}

public static JSArray<JSNumber> wrap(int[] array) {
public static JSObject wrap(int[] array) {
if (array == null) {
return null;
}
var result = new JSArray<JSNumber>(array.length);
var result = new Int32Array(array.length);
for (int i = 0; i < array.length; ++i) {
result.set(i, JSNumber.valueOf(array[i]));
result.set(i, array[i]);
}
return result;
}

public static WrapFunction<int[], JSArray<JSNumber>> intArrayWrapper() {
public static WrapFunction<int[], JSObject> intArrayWrapper() {
return JS::wrap;
}

public static JSArray<JSBigInt> wrap(long[] array) {
public static JSObject wrap(long[] array) {
if (array == null) {
return null;
}
var result = new JSArray<JSBigInt>(array.length);
var result = new BigInt64Array(array.length);
for (int i = 0; i < array.length; ++i) {
result.set(i, JSBigInt.valueOf(array[i]));
result.set(i, array[i]);
}
return result;
}

public static WrapFunction<long[], JSArray<JSBigInt>> longArrayWrapper() {
public static WrapFunction<long[], JSObject> longArrayWrapper() {
return JS::wrap;
}

@NoSideEffects
public static JSArray<JSString> wrap(String[] array) {
public static JSObject wrap(String[] array) {
if (array == null) {
return null;
}
Expand All @@ -323,37 +330,37 @@ public static JSArray<JSString> wrap(String[] array) {
return result;
}

public static WrapFunction<String[], JSArray<JSString>> stringArrayWrapper() {
public static WrapFunction<String[], JSObject> stringArrayWrapper() {
return JS::wrap;
}

public static JSArray<JSNumber> wrap(float[] array) {
public static JSObject wrap(float[] array) {
if (array == null) {
return null;
}
var result = new JSArray<JSNumber>(array.length);
var result = new Float32Array(array.length);
for (int i = 0; i < array.length; ++i) {
result.set(i, JSNumber.valueOf(array[i]));
result.set(i, array[i]);
}
return result;
}

public static WrapFunction<float[], JSArray<JSNumber>> floatArrayWrapper() {
public static WrapFunction<float[], JSObject> floatArrayWrapper() {
return JS::wrap;
}

public static JSArray<JSNumber> wrap(double[] array) {
public static JSObject wrap(double[] array) {
if (array == null) {
return null;
}
var result = new JSArray<JSNumber>(array.length);
var result = new Float64Array(array.length);
for (int i = 0; i < array.length; ++i) {
result.set(i, JSNumber.valueOf(array[i]));
result.set(i, array[i]);
}
return result;
}

public static WrapFunction<double[], JSArray<JSNumber>> doubleArrayWrapper() {
public static WrapFunction<double[], JSObject> doubleArrayWrapper() {
return JS::wrap;
}

Expand Down
12 changes: 4 additions & 8 deletions jso/impl/src/main/java/org/teavm/jso/impl/JSValueMarshaller.java
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ Variable wrap(Variable var, ValueType type, JSType jsType, TextLocation location
if (degree <= 1) {
InvokeInstruction insn = new InvokeInstruction();
insn.setMethod(referenceCache.getCached(new MethodReference(JS.class.getName(), "wrap",
getWrappedType(type), getWrapperType(type))));
getWrappedType(type), getWrapperType())));
insn.setArguments(var);
insn.setReceiver(result);
insn.setType(InvocationType.SPECIAL);
Expand Down Expand Up @@ -218,7 +218,7 @@ Variable wrap(Variable var, ValueType type, JSType jsType, TextLocation location

insn = new InvokeInstruction();
insn.setMethod(referenceCache.getCached(new MethodReference(JS.class.getName(), "map",
getWrappedType(type), ValueType.parse(JS.WrapFunction.class), getWrapperType(type))));
getWrappedType(type), ValueType.parse(JS.WrapFunction.class), getWrapperType())));
insn.setArguments(var, function);
insn.setReceiver(result);
insn.setType(InvocationType.SPECIAL);
Expand Down Expand Up @@ -344,12 +344,8 @@ private ValueType getWrappedType(ValueType type) {
}
}

private ValueType getWrapperType(ValueType type) {
if (type instanceof ValueType.Array) {
return JSMethods.JS_ARRAY;
} else {
return JSMethods.JS_OBJECT;
}
private ValueType getWrapperType() {
return JSMethods.JS_OBJECT;
}

private MethodReference getWrapperFunction(ValueType type) {
Expand Down
4 changes: 3 additions & 1 deletion tests/src/test/resources/org/teavm/jso/export/assert.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ function assertEquals(a, b) {
if (a == b) {
return
}
if (a instanceof Array && b instanceof Array && a.length === b.length) {
if ((a instanceof Array || ArrayBuffer.isView(a))
&& (b instanceof Array || ArrayBuffer.isView(b))
&& a.length === b.length) {
let allEqual = true;
for (let i = 0; i < a.length; ++i) {
if (a[i] != b[i]) {
Expand Down

0 comments on commit 7fdaf3c

Please sign in to comment.