JS: relax several JSO declarations to accept Object instead of JSObject

This commit is contained in:
Alexey Andreev 2023-08-03 20:50:22 +02:00
parent 334e2829b3
commit f30a050bfd
16 changed files with 97 additions and 68 deletions

View File

@ -18,10 +18,9 @@ package org.teavm.jso.core;
import org.teavm.interop.NoSideEffects; import org.teavm.interop.NoSideEffects;
import org.teavm.jso.JSBody; import org.teavm.jso.JSBody;
import org.teavm.jso.JSIndexer; import org.teavm.jso.JSIndexer;
import org.teavm.jso.JSObject;
import org.teavm.jso.JSProperty; import org.teavm.jso.JSProperty;
public abstract class JSArray<T extends JSObject> implements JSArrayReader<T> { public abstract class JSArray<T> implements JSArrayReader<T> {
private JSArray() { private JSArray() {
} }
@ -85,18 +84,18 @@ public abstract class JSArray<T extends JSObject> implements JSArrayReader<T> {
@JSBody(script = "return new Array();") @JSBody(script = "return new Array();")
@NoSideEffects @NoSideEffects
public static native <T extends JSObject> JSArray<T> create(); public static native <T> JSArray<T> create();
@JSBody(params = "size", script = "return new Array(size);") @JSBody(params = "size", script = "return new Array(size);")
@NoSideEffects @NoSideEffects
public static native <T extends JSObject> JSArray<T> create(int size); public static native <T> JSArray<T> create(int size);
@JSBody(params = "object", script = "return Array.isArray(object);") @JSBody(params = "object", script = "return Array.isArray(object);")
@NoSideEffects @NoSideEffects
public static native boolean isArray(JSObject object); public static native boolean isArray(Object object);
@SafeVarargs @SafeVarargs
public static <S extends JSObject> JSArray<S> of(S... items) { public static <S> JSArray<S> of(S... items) {
JSArray<S> array = create(items.length); JSArray<S> array = create(items.length);
for (int i = 0; i < items.length; ++i) { for (int i = 0; i < items.length; ++i) {
array.set(i, items[i]); array.set(i, items[i]);

View File

@ -20,7 +20,7 @@ import org.teavm.jso.JSIndexer;
import org.teavm.jso.JSObject; import org.teavm.jso.JSObject;
import org.teavm.jso.JSProperty; import org.teavm.jso.JSProperty;
public interface JSArrayReader<T extends JSObject> extends JSObject { public interface JSArrayReader<T> extends JSObject {
@JSProperty @JSProperty
@NoSideEffects @NoSideEffects
int getLength(); int getLength();

View File

@ -27,7 +27,7 @@ public abstract class JSError implements JSObject {
+ "} catch (e) {" + "} catch (e) {"
+ "return catchClause(e);" + "return catchClause(e);"
+ "}") + "}")
public static native <T extends JSObject> T catchNative(TryClause<T> tryClause, CatchClause<T> catchClause); public static native <T> T catchNative(TryClause<T> tryClause, CatchClause<T> catchClause);
@JSBody(params = "object", script = "return object instanceof Error;") @JSBody(params = "object", script = "return object instanceof Error;")
public static native boolean isError(JSObject object); public static native boolean isError(JSObject object);
@ -42,12 +42,12 @@ public abstract class JSError implements JSObject {
public abstract String getName(); public abstract String getName();
@JSFunctor @JSFunctor
public interface TryClause<T extends JSObject> extends JSObject { public interface TryClause<T> extends JSObject {
T run(); T run();
} }
@JSFunctor @JSFunctor
public interface CatchClause<T extends JSObject> extends JSObject { public interface CatchClause<T> extends JSObject {
T accept(JSObject e); T accept(JSObject e);
} }
} }

View File

@ -15,12 +15,18 @@
*/ */
package org.teavm.jso.core; package org.teavm.jso.core;
import org.teavm.interop.NoSideEffects;
import org.teavm.jso.JSBody; import org.teavm.jso.JSBody;
import org.teavm.jso.JSObject; import org.teavm.jso.JSObject;
public abstract class JSFinalizationRegistry implements JSObject { public abstract class JSFinalizationRegistry implements JSObject {
public abstract void register(JSObject obj, JSObject token); public abstract void register(Object obj, Object token);
@JSBody(params = "consumer", script = "return new FinalizationRegistry(consumer);") @JSBody(params = "consumer", script = "return new FinalizationRegistry(consumer);")
public static native JSFinalizationRegistry create(JSFinalizationRegistryConsumer consumer); public static native JSFinalizationRegistry create(JSFinalizationRegistryConsumer consumer);
@JSBody(script = "return typeof FinalizationRegistry !== 'undefined';")
@NoSideEffects
public static native boolean isSupported();
} }

View File

@ -20,5 +20,5 @@ import org.teavm.jso.JSObject;
@JSFunctor @JSFunctor
public interface JSFinalizationRegistryConsumer extends JSObject { public interface JSFinalizationRegistryConsumer extends JSObject {
void accept(JSObject obj); void accept(Object obj);
} }

View File

@ -19,33 +19,31 @@ import org.teavm.jso.JSByRef;
import org.teavm.jso.JSObject; import org.teavm.jso.JSObject;
import org.teavm.jso.JSProperty; import org.teavm.jso.JSProperty;
public interface JSFunction extends JSObject { public abstract class JSFunction implements JSObject {
@JSProperty @JSProperty
int getLength(); public abstract int getLength();
@JSProperty @JSProperty
String getName(); public abstract String getName();
JSObject call(JSObject thisArg); public abstract Object call(Object thisArg);
JSObject call(JSObject thisArg, JSObject a); public abstract Object call(Object thisArg, Object a);
JSObject call(JSObject thisArg, JSObject a, JSObject b); public abstract Object call(Object thisArg, Object a, Object b);
JSObject call(JSObject thisArg, JSObject a, JSObject b, JSObject c); public abstract Object call(Object thisArg, Object a, Object b, Object c);
JSObject call(JSObject thisArg, JSObject a, JSObject b, JSObject c, public abstract Object call(Object thisArg, Object a, Object b, Object c, Object d);
JSObject d);
JSObject call(JSObject thisArg, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e); public abstract Object call(Object thisArg, Object a, Object b, Object c, Object d, Object e);
JSObject call(JSObject thisArg, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e, JSObject f); public abstract Object call(Object thisArg, Object a, Object b, Object c, Object d, Object e, Object f);
JSObject call(JSObject thisArg, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e, JSObject f, public abstract Object call(Object thisArg, Object a, Object b, Object c, Object d, Object e, Object f, Object g);
JSObject g);
JSObject call(JSObject thisArg, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e, JSObject f, public abstract Object call(Object thisArg, Object a, Object b, Object c, Object d, Object e, Object f, Object g,
JSObject g, JSObject h); Object h);
JSObject apply(JSObject thisArg, @JSByRef JSObject[] arguments); public abstract Object apply(Object thisArg, @JSByRef Object[] arguments);
} }

View File

@ -18,7 +18,7 @@ package org.teavm.jso.core;
import org.teavm.jso.JSIndexer; import org.teavm.jso.JSIndexer;
import org.teavm.jso.JSObject; import org.teavm.jso.JSObject;
public interface JSMapLike<T extends JSObject> extends JSObject { public interface JSMapLike<T> extends JSObject {
@JSIndexer @JSIndexer
T get(String key); T get(String key);

View File

@ -25,11 +25,11 @@ public final class JSObjects {
@JSBody(params = "object", script = "return Object.getOwnPropertyNames(object);") @JSBody(params = "object", script = "return Object.getOwnPropertyNames(object);")
@NoSideEffects @NoSideEffects
public static native String[] getOwnPropertyNames(JSObject object); public static native String[] getOwnPropertyNames(Object object);
@JSBody(params = "object", script = "return Object.keys(object);") @JSBody(params = "object", script = "return Object.keys(object);")
@NoSideEffects @NoSideEffects
public static native String[] keys(JSObject object); public static native String[] keys(Object object);
@JSBody(params = "object", script = "return Object.values(object);") @JSBody(params = "object", script = "return Object.values(object);")
@NoSideEffects @NoSideEffects
@ -45,7 +45,7 @@ public final class JSObjects {
@JSBody(params = "object", script = "return typeof object === 'undefined';") @JSBody(params = "object", script = "return typeof object === 'undefined';")
@NoSideEffects @NoSideEffects
public static native boolean isUndefined(JSObject object); public static native boolean isUndefined(Object object);
@JSBody(script = "return void 0;") @JSBody(script = "return void 0;")
@NoSideEffects @NoSideEffects
@ -53,16 +53,16 @@ public final class JSObjects {
@JSBody(params = "object", script = "return typeof object;") @JSBody(params = "object", script = "return typeof object;")
@NoSideEffects @NoSideEffects
public static native String typeOf(JSObject object); public static native String typeOf(Object object);
@JSBody(params = "object", script = "return object.toString();") @JSBody(params = "object", script = "return object.toString();")
public static native String toString(JSObject object); public static native String toString(Object object);
@JSBody(params = { "object", "name" }, script = "return name in object;") @JSBody(params = { "object", "name" }, script = "return name in object;")
@NoSideEffects @NoSideEffects
public static native boolean hasProperty(JSObject object, String name); public static native boolean hasProperty(Object object, String name);
@JSBody(params = "object", script = "return Object.getPrototypeOf(object);") @JSBody(params = "object", script = "return Object.getPrototypeOf(object);")
@NoSideEffects @NoSideEffects
public static native JSObject getPrototypeOf(JSObject object); public static native JSObject getPrototypeOf(Object object);
} }

View File

@ -16,15 +16,9 @@
package org.teavm.jso.core; package org.teavm.jso.core;
import org.teavm.jso.JSFunctor; import org.teavm.jso.JSFunctor;
import org.teavm.jso.JSObject;
/**
*
* @author Alexey Andreev
* @param <T>
*/
@JSFunctor @JSFunctor
@FunctionalInterface @FunctionalInterface
public interface JSSortFunction<T extends JSObject> { public interface JSSortFunction<T> {
int compare(T a, T b); int compare(T a, T b);
} }

View File

@ -19,14 +19,14 @@ import org.teavm.interop.NoSideEffects;
import org.teavm.jso.JSBody; import org.teavm.jso.JSBody;
import org.teavm.jso.JSObject; import org.teavm.jso.JSObject;
public abstract class JSSymbol<T extends JSObject> implements JSObject { public abstract class JSSymbol<T> implements JSObject {
@JSBody(params = "name", script = "return Symbol(name);") @JSBody(params = "name", script = "return Symbol(name);")
public static native <T extends JSObject> JSSymbol<T> create(String name); public static native <T> JSSymbol<T> create(String name);
@JSBody(params = "obj", script = "return obj[this];") @JSBody(params = "obj", script = "return obj[this];")
public native T get(JSObject obj); public native T get(Object obj);
@JSBody(params = { "obj", "value" }, script = "obj[this] = value;") @JSBody(params = { "obj", "value" }, script = "obj[this] = value;")
@NoSideEffects @NoSideEffects
public native void set(JSObject obj, T value); public native void set(Object obj, T value);
} }

View File

@ -19,7 +19,7 @@ import org.teavm.interop.NoSideEffects;
import org.teavm.jso.JSBody; import org.teavm.jso.JSBody;
import org.teavm.jso.JSObject; import org.teavm.jso.JSObject;
public abstract class JSWeakMap<K extends JSObject, V extends JSObject> implements JSObject { public abstract class JSWeakMap<K, V> implements JSObject {
public abstract V get(K key); public abstract V get(K key);
public abstract boolean has(K key); public abstract boolean has(K key);
@ -30,5 +30,9 @@ public abstract class JSWeakMap<K extends JSObject, V extends JSObject> implemen
@JSBody(script = "return new WeakMap();") @JSBody(script = "return new WeakMap();")
@NoSideEffects @NoSideEffects
public static native <K extends JSObject, V extends JSObject> JSWeakMap<K, V> create(); public static native <K, V> JSWeakMap<K, V> create();
@JSBody(script = "return typeof WeakMap !== 'undefined';")
@NoSideEffects
public static native boolean isSupported();
} }

View File

@ -19,12 +19,12 @@ import org.teavm.interop.NoSideEffects;
import org.teavm.jso.JSBody; import org.teavm.jso.JSBody;
import org.teavm.jso.JSObject; import org.teavm.jso.JSObject;
public abstract class JSWeakRef<T extends JSObject> implements JSObject { public abstract class JSWeakRef<T> implements JSObject {
public abstract T deref(); public abstract T deref();
@JSBody(params = "value", script = "return new WeakRef(value);") @JSBody(params = "value", script = "return new WeakRef(value);")
@NoSideEffects @NoSideEffects
public static native <T extends JSObject> JSWeakRef<T> create(T value); public static native <T> JSWeakRef<T> create(T value);
@JSBody(script = "return typeof WeakRef !== 'undefined';") @JSBody(script = "return typeof WeakRef !== 'undefined';")
@NoSideEffects @NoSideEffects

View File

@ -15,13 +15,12 @@
*/ */
package org.teavm.jso.dom.events; package org.teavm.jso.dom.events;
import org.teavm.jso.JSObject;
import org.teavm.jso.JSProperty; import org.teavm.jso.JSProperty;
import org.teavm.jso.typedarrays.ArrayBuffer; import org.teavm.jso.typedarrays.ArrayBuffer;
public interface MessageEvent extends Event { public interface MessageEvent extends Event {
@JSProperty @JSProperty
JSObject getData(); Object getData();
@JSProperty("data") @JSProperty("data")
String getDataAsString(); String getDataAsString();

View File

@ -15,14 +15,13 @@
*/ */
package org.teavm.jso.workers; package org.teavm.jso.workers;
import org.teavm.jso.JSObject;
import org.teavm.jso.JSProperty; import org.teavm.jso.JSProperty;
import org.teavm.jso.dom.events.EventListener; import org.teavm.jso.dom.events.EventListener;
import org.teavm.jso.dom.events.EventTarget; import org.teavm.jso.dom.events.EventTarget;
import org.teavm.jso.dom.events.MessageEvent; import org.teavm.jso.dom.events.MessageEvent;
public interface MessagePort extends EventTarget { public interface MessagePort extends EventTarget {
void postMessage(JSObject message); void postMessage(Object message);
void start(); void start();

View File

@ -16,7 +16,6 @@
package org.teavm.jso.workers; package org.teavm.jso.workers;
import org.teavm.jso.JSBody; import org.teavm.jso.JSBody;
import org.teavm.jso.JSObject;
import org.teavm.jso.JSProperty; import org.teavm.jso.JSProperty;
import org.teavm.jso.dom.events.EventListener; import org.teavm.jso.dom.events.EventListener;
import org.teavm.jso.dom.events.MessageEvent; import org.teavm.jso.dom.events.MessageEvent;
@ -28,7 +27,7 @@ public abstract class Worker implements AbstractWorker {
@JSProperty("onmessage") @JSProperty("onmessage")
public abstract void onMessage(EventListener<MessageEvent> listener); public abstract void onMessage(EventListener<MessageEvent> listener);
public abstract void postMessage(JSObject message); public abstract void postMessage(Object message);
public abstract void terminate(); public abstract void terminate();
} }

View File

@ -62,37 +62,37 @@ public final class JSWrapper {
if (wrappers != null) { if (wrappers != null) {
var type = JSObjects.typeOf(js); var type = JSObjects.typeOf(js);
if (type.equals("object") || type.equals("function")) { if (type.equals("object") || type.equals("function")) {
var existingRef = wrappers.get(js); var existingRef = get(wrappers, js);
var existing = !JSObjects.isUndefined(existingRef) ? existingRef.deref() : JSObjects.undefined(); var existing = !JSObjects.isUndefined(existingRef) ? deref(existingRef) : JSObjects.undefined();
if (JSObjects.isUndefined(existing)) { if (JSObjects.isUndefined(existing)) {
var wrapper = new JSWrapper(js); var wrapper = new JSWrapper(js);
wrappers.set(js, JSWeakRef.create(wrapperToJs(wrapper))); set(wrappers, js, createWeakRef(wrapperToJs(wrapper)));
return wrapper; return wrapper;
} else { } else {
return jsToWrapper(existing); return jsToWrapper(existing);
} }
} else if (type.equals("string")) { } else if (type.equals("string")) {
var jsString = (JSString) js; var jsString = (JSString) js;
var existingRef = stringWrappers.get(jsString); var existingRef = get(stringWrappers, jsString);
var existing = !JSObjects.isUndefined(existingRef) ? existingRef.deref() : JSObjects.undefined(); var existing = !JSObjects.isUndefined(existingRef) ? deref(existingRef) : JSObjects.undefined();
if (JSObjects.isUndefined(existing)) { if (JSObjects.isUndefined(existing)) {
var wrapper = new JSWrapper(js); var wrapper = new JSWrapper(js);
var wrapperAsJs = wrapperToJs(wrapper); var wrapperAsJs = wrapperToJs(wrapper);
stringWrappers.set(jsString, JSWeakRef.create(wrapperAsJs)); set(stringWrappers, jsString, createWeakRef(wrapperAsJs));
stringFinalizationRegistry.register(wrapperAsJs, jsString); register(stringFinalizationRegistry, wrapperAsJs, jsString);
return wrapper; return wrapper;
} else { } else {
return jsToWrapper(existing); return jsToWrapper(existing);
} }
} else if (type.equals("number")) { } else if (type.equals("number")) {
var jsNumber = (JSNumber) js; var jsNumber = (JSNumber) js;
var existingRef = numberWrappers.get(jsNumber); var existingRef = get(numberWrappers, jsNumber);
var existing = !JSObjects.isUndefined(existingRef) ? existingRef.deref() : JSObjects.undefined(); var existing = !JSObjects.isUndefined(existingRef) ? deref(existingRef) : JSObjects.undefined();
if (JSObjects.isUndefined(existing)) { if (JSObjects.isUndefined(existing)) {
var wrapper = new JSWrapper(js); var wrapper = new JSWrapper(js);
var wrapperAsJs = wrapperToJs(wrapper); var wrapperAsJs = wrapperToJs(wrapper);
numberWrappers.set(jsNumber, JSWeakRef.create(wrapperAsJs)); set(numberWrappers, jsNumber, createWeakRef(wrapperAsJs));
numberFinalizationRegistry.register(wrapperAsJs, jsNumber); register(numberFinalizationRegistry, wrapperAsJs, jsNumber);
return wrapper; return wrapper;
} else { } else {
return jsToWrapper(existing); return jsToWrapper(existing);
@ -102,6 +102,37 @@ public final class JSWrapper {
return new JSWrapper(js); return new JSWrapper(js);
} }
@JSBody(params = "target", script = "return new WeakRef(target);")
@NoSideEffects
private static native JSWeakRef<JSObject> createWeakRef(JSObject target);
@JSBody(params = "target", script = "return target.deref();")
@NoSideEffects
private static native JSObject deref(JSWeakRef<JSObject> target);
@JSBody(params = { "registry", "target", "token" }, script = "return registry.register(target, token);")
@NoSideEffects
private static native void register(JSFinalizationRegistry registry, JSObject target, JSObject token);
@JSBody(params = { "map", "key" }, script = "return map.get(key);")
@NoSideEffects
private static native JSWeakRef<JSObject> get(JSMap<? extends JSObject, JSWeakRef<JSObject>> map, JSObject key);
@JSBody(params = { "map", "key", "value" }, script = "map.set(key, value);")
@NoSideEffects
private static native void set(JSMap<? extends JSObject, JSWeakRef<JSObject>> map, JSObject key, JSObject value);
@JSBody(params = { "map", "key" }, script = "return map.get(key);")
@NoSideEffects
private static native JSWeakRef<JSObject> get(JSWeakMap<? extends JSObject, JSWeakRef<JSObject>> map,
JSObject key);
@JSBody(params = { "map", "key", "value" }, script = "map.set(key, value);")
@NoSideEffects
private static native void set(JSWeakMap<? extends JSObject, JSWeakRef<JSObject>> map, JSObject key,
JSObject value);
@NoSideEffects
public static Object maybeWrap(Object o) { public static Object maybeWrap(Object o) {
return o == null || isJava(o) ? o : wrap(o); return o == null || isJava(o) ? o : wrap(o);
} }