diff --git a/classlib/src/main/java/org/teavm/classlib/java/net/impl/TXHRURLConnection.java b/classlib/src/main/java/org/teavm/classlib/java/net/impl/TXHRURLConnection.java index ae408e2d4..7fffd9fcd 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/net/impl/TXHRURLConnection.java +++ b/classlib/src/main/java/org/teavm/classlib/java/net/impl/TXHRURLConnection.java @@ -65,7 +65,7 @@ public class TXHRURLConnection extends THttpURLConnection { return; } - xhr = XMLHttpRequest.create(); + xhr = new XMLHttpRequest(); xhr.open(method, url.toString()); for (Map.Entry> entry : getRequestProperties().entrySet()) { for (String value : entry.getValue()) { @@ -97,7 +97,7 @@ public class TXHRURLConnection extends THttpURLConnection { responseCode = -1; } - Int8Array array = Int8Array.create((ArrayBuffer) xhr.getResponse()); + var array = new Int8Array((ArrayBuffer) xhr.getResponse()); byte[] bytes = new byte[array.getLength()]; for (int i = 0; i < bytes.length; ++i) { bytes[i] = array.get(i); @@ -119,7 +119,7 @@ public class TXHRURLConnection extends THttpURLConnection { if (outputStream != null) { byte[] bytes = outputStream.toByteArray(); - Int8Array array = Int8Array.create(bytes.length); + var array = new Int8Array(bytes.length); for (int i = 0; i < bytes.length; ++i) { array.set(i, bytes[i]); } diff --git a/classlib/src/main/java/org/teavm/classlib/java/nio/TByteOrder.java b/classlib/src/main/java/org/teavm/classlib/java/nio/TByteOrder.java index 79ef0e5b4..bc3ca6a1d 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/nio/TByteOrder.java +++ b/classlib/src/main/java/org/teavm/classlib/java/nio/TByteOrder.java @@ -34,10 +34,10 @@ public final class TByteOrder { public static TByteOrder nativeOrder() { if (nativeOrder == null) { if (PlatformDetector.isJavaScript()) { - var buffer = ArrayBuffer.create(2); - var shortArray = Int16Array.create(buffer); + var buffer = new ArrayBuffer(2); + var shortArray = new Int16Array(buffer); shortArray.set(0, (short) 1); - var byteArray = Int8Array.create(buffer); + var byteArray = new Int8Array(buffer); nativeOrder = byteArray.get(0) == 0 ? BIG_ENDIAN : LITTLE_ENDIAN; } else { var array = new short[1]; diff --git a/classlib/src/main/java/org/teavm/classlib/java/security/TSecureRandom.java b/classlib/src/main/java/org/teavm/classlib/java/security/TSecureRandom.java index 76d2f3f54..044854866 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/security/TSecureRandom.java +++ b/classlib/src/main/java/org/teavm/classlib/java/security/TSecureRandom.java @@ -75,7 +75,7 @@ public class TSecureRandom extends TRandom { @Override public void nextBytes(byte[] bytes) { if (PlatformDetector.isJavaScript() && Crypto.isSupported()) { - Uint8Array buffer = Uint8Array.create(bytes.length); + var buffer = new Uint8Array(bytes.length); Crypto.current().getRandomValues(buffer); for (int i = 0; i < bytes.length; ++i) { diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/TDate.java b/classlib/src/main/java/org/teavm/classlib/java/util/TDate.java index f2f3dd39a..5dfeaf5b3 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/util/TDate.java +++ b/classlib/src/main/java/org/teavm/classlib/java/util/TDate.java @@ -64,7 +64,7 @@ public class TDate implements TComparable { public TDate(int year, int month, int date, int hrs, int min, int sec) { this(PlatformDetector.isLowLevel() ? initDateLowLevel(year, month, date, hrs, min, sec) - : (long) JSDate.create(year, month, date, hrs, min, sec).getTime()); + : (long) new JSDate(year, month, date, hrs, min, sec).getTime()); if (!PlatformDetector.isLowLevel()) { setYear(year); } @@ -127,7 +127,7 @@ public class TDate implements TComparable { if (PlatformDetector.isLowLevel()) { return getYearLowLevel(value); } - return JSDate.create(value).getFullYear() - 1900; + return new JSDate(value).getFullYear() - 1900; } @Import(name = "teavm_date_getYear") @@ -143,7 +143,7 @@ public class TDate implements TComparable { value = setYearLowLevel(value, year); return; } - JSDate date = JSDate.create(value); + var date = new JSDate(value); date.setFullYear(year + 1900); value = (long) date.getTime(); } @@ -160,7 +160,7 @@ public class TDate implements TComparable { if (PlatformDetector.isLowLevel()) { return getMonthLowLevel(value); } - return JSDate.create(value).getMonth(); + return new JSDate(value).getMonth(); } @Import(name = "teavm_date_getMonth") @@ -176,7 +176,7 @@ public class TDate implements TComparable { value = setMonthLowLevel(value, month); return; } - JSDate date = JSDate.create(value); + var date = new JSDate(value); date.setMonth(month); value = (long) date.getTime(); } @@ -193,7 +193,7 @@ public class TDate implements TComparable { if (PlatformDetector.isLowLevel()) { return getDateLowLevel(value); } - return JSDate.create(value).getDate(); + return new JSDate(value).getDate(); } @Import(name = "teavm_date_getDate") @@ -209,7 +209,7 @@ public class TDate implements TComparable { value = setDateLowLevel(value, date); return; } - JSDate d = JSDate.create(value); + var d = new JSDate(value); d.setDate(date); this.value = (long) d.getTime(); } @@ -226,7 +226,7 @@ public class TDate implements TComparable { if (PlatformDetector.isLowLevel()) { return getDayLowLevel(value); } - return JSDate.create(value).getDay(); + return new JSDate(value).getDay(); } @Import(name = "teavm_date_getDay") @@ -239,7 +239,7 @@ public class TDate implements TComparable { if (PlatformDetector.isLowLevel()) { return getHoursLowLevel(value); } - return JSDate.create(value).getHours(); + return new JSDate(value).getHours(); } @Import(name = "teavm_date_getHours") @@ -389,12 +389,12 @@ public class TDate implements TComparable { @Deprecated public String toLocaleString() { - return JSDate.create(value).toLocaleFormat("%c"); + return new JSDate(value).toLocaleFormat("%c"); } @Deprecated public String toGMTString() { - return JSDate.create(value).toUTCString(); + return new JSDate(value).toUTCString(); } @Deprecated diff --git a/jso/apis/src/main/java/org/teavm/jso/ajax/XMLHttpRequest.java b/jso/apis/src/main/java/org/teavm/jso/ajax/XMLHttpRequest.java index bcecfa1b9..345f61c4c 100644 --- a/jso/apis/src/main/java/org/teavm/jso/ajax/XMLHttpRequest.java +++ b/jso/apis/src/main/java/org/teavm/jso/ajax/XMLHttpRequest.java @@ -16,6 +16,7 @@ package org.teavm.jso.ajax; import org.teavm.jso.JSBody; +import org.teavm.jso.JSClass; import org.teavm.jso.JSObject; import org.teavm.jso.JSProperty; import org.teavm.jso.dom.events.Event; @@ -23,7 +24,8 @@ import org.teavm.jso.dom.events.EventListener; import org.teavm.jso.dom.events.EventTarget; import org.teavm.jso.dom.xml.Document; -public abstract class XMLHttpRequest implements JSObject, EventTarget { +@JSClass +public class XMLHttpRequest implements JSObject, EventTarget { public static final int UNSET = 0; public static final int OPENED = 1; @@ -34,52 +36,55 @@ public abstract class XMLHttpRequest implements JSObject, EventTarget { public static final int DONE = 4; - public abstract void open(String method, String url); + public XMLHttpRequest() { + } - public abstract void open(String method, String url, boolean async); + public native void open(String method, String url); - public abstract void open(String method, String url, boolean async, String user); + public native void open(String method, String url, boolean async); - public abstract void open(String method, String url, boolean async, String user, String password); + public native void open(String method, String url, boolean async, String user); - public abstract void send(); + public native void open(String method, String url, boolean async, String user, String password); - public abstract void send(String data); + public native void send(); - public abstract void send(JSObject data); + public native void send(String data); - public abstract void setRequestHeader(String name, String value); + public native void send(JSObject data); - public abstract String getAllResponseHeaders(); + public native void setRequestHeader(String name, String value); - public abstract String getResponseHeader(String name); + public native String getAllResponseHeaders(); + + public native String getResponseHeader(String name); @JSProperty("onreadystatechange") - public abstract void setOnReadyStateChange(ReadyStateChangeHandler handler); + public native void setOnReadyStateChange(ReadyStateChangeHandler handler); @JSProperty("onreadystatechange") - public abstract void setOnReadyStateChange(EventListener handler); + public native void setOnReadyStateChange(EventListener handler); @JSProperty("onabort") - public abstract void onAbort(EventListener eventListener); + public native void onAbort(EventListener eventListener); @JSProperty("onerror") - public abstract void onError(EventListener eventListener); + public native void onError(EventListener eventListener); @JSProperty("onload") - public abstract void onLoad(EventListener eventListener); + public native void onLoad(EventListener eventListener); @JSProperty("onloadstart") - public abstract void onLoadStart(EventListener eventListener); + public native void onLoadStart(EventListener eventListener); @JSProperty("onloadend") - public abstract void onLoadEnd(EventListener eventListener); + public native void onLoadEnd(EventListener eventListener); @JSProperty("onprogress") - public abstract void onProgress(EventListener eventListener); + public native void onProgress(EventListener eventListener); @JSProperty("ontimeout") - public abstract void onTimeout(EventListener eventListener); + public native void onTimeout(EventListener eventListener); public final void onComplete(Runnable runnable) { setOnReadyStateChange(() -> { @@ -89,37 +94,53 @@ public abstract class XMLHttpRequest implements JSObject, EventTarget { }); } - public abstract void overrideMimeType(String mimeType); + public native void overrideMimeType(String mimeType); @JSProperty - public abstract int getReadyState(); + public native int getReadyState(); @JSProperty - public abstract String getResponseText(); + public native String getResponseText(); @JSProperty - public abstract Document getResponseXML(); + public native Document getResponseXML(); @JSProperty - public abstract JSObject getResponse(); + public native JSObject getResponse(); @JSProperty - public abstract int getStatus(); + public native int getStatus(); @JSProperty - public abstract String getStatusText(); + public native String getStatusText(); @JSProperty - public abstract void setResponseType(String type); + public native void setResponseType(String type); @JSProperty - public abstract String getResponseType(); + public native String getResponseType(); @JSBody(script = "return new XMLHttpRequest();") + @Deprecated public static native XMLHttpRequest create(); - public abstract void abort(); + public native void abort(); @JSProperty - public abstract String getResponseURL(); + public native String getResponseURL(); + + @Override + public native void addEventListener(String type, EventListener listener, boolean useCapture); + + @Override + public native void addEventListener(String type, EventListener listener); + + @Override + public native void removeEventListener(String type, EventListener listener, boolean useCapture); + + @Override + public native void removeEventListener(String type, EventListener listener); + + @Override + public native boolean dispatchEvent(Event evt); } diff --git a/jso/apis/src/main/java/org/teavm/jso/browser/Navigator.java b/jso/apis/src/main/java/org/teavm/jso/browser/Navigator.java index 4dfb4d99e..af955cb8d 100644 --- a/jso/apis/src/main/java/org/teavm/jso/browser/Navigator.java +++ b/jso/apis/src/main/java/org/teavm/jso/browser/Navigator.java @@ -16,29 +16,33 @@ package org.teavm.jso.browser; import org.teavm.jso.JSBody; +import org.teavm.jso.JSClass; +import org.teavm.jso.JSObject; +import org.teavm.jso.JSProperty; import org.teavm.jso.gamepad.Gamepad; import org.teavm.jso.geolocation.Geolocation; -public final class Navigator { +@JSClass(name = "navigator") +public final class Navigator implements JSObject { private Navigator() { } - @JSBody(script = "return navigator.onLine;") + @JSProperty("onLine") public static native boolean isOnline(); - @JSBody(script = "return navigator.geolocation;") + @JSProperty public static native Geolocation getGeolocation(); @JSBody(script = "return (\"geolocation\" in navigator);") public static native boolean isGeolocationAvailable(); - @JSBody(script = "return navigator.language;") + @JSProperty public static native String getLanguage(); - @JSBody(script = "return navigator.languages;") + @JSProperty public static native String[] getLanguages(); - @JSBody(script = "return navigator.getGamepads();") + @JSProperty public static native Gamepad[] getGamepads(); @JSBody(script = "return navigator.hardwareConcurrency") diff --git a/jso/apis/src/main/java/org/teavm/jso/browser/Performance.java b/jso/apis/src/main/java/org/teavm/jso/browser/Performance.java index a67c5c10e..6eeb23223 100644 --- a/jso/apis/src/main/java/org/teavm/jso/browser/Performance.java +++ b/jso/apis/src/main/java/org/teavm/jso/browser/Performance.java @@ -16,13 +16,14 @@ package org.teavm.jso.browser; import org.teavm.jso.JSBody; +import org.teavm.jso.JSClass; import org.teavm.jso.JSObject; +@JSClass(name = "performance") public final class Performance implements JSObject { private Performance() { } - @JSBody(script = "return performance.now();") public static native double now(); @JSBody(script = "return typeof(performance) !== 'undefined';") diff --git a/jso/apis/src/main/java/org/teavm/jso/canvas/ImageData.java b/jso/apis/src/main/java/org/teavm/jso/canvas/ImageData.java index bd4a68df3..26b11a64b 100644 --- a/jso/apis/src/main/java/org/teavm/jso/canvas/ImageData.java +++ b/jso/apis/src/main/java/org/teavm/jso/canvas/ImageData.java @@ -16,29 +16,40 @@ package org.teavm.jso.canvas; import org.teavm.jso.JSBody; +import org.teavm.jso.JSClass; import org.teavm.jso.JSObject; import org.teavm.jso.JSProperty; import org.teavm.jso.typedarrays.Uint8ClampedArray; -public abstract class ImageData implements JSObject { - private ImageData() { +@JSClass +public class ImageData implements JSObject { + public ImageData(Uint8ClampedArray array, int width) { + } + + public ImageData(int width, int height) { + } + + public ImageData(Uint8ClampedArray array, int width, int height) { } @JSProperty - public abstract int getWidth(); + public native int getWidth(); @JSProperty - public abstract int getHeight(); + public native int getHeight(); @JSProperty - public abstract Uint8ClampedArray getData(); + public native Uint8ClampedArray getData(); @JSBody(params = { "array", "width" }, script = "return new ImageData(array, width);") + @Deprecated public static native ImageData create(Uint8ClampedArray array, int width); @JSBody(params = { "width", "height" }, script = "return new ImageData(width, height);") + @Deprecated public static native ImageData create(int width, int height); @JSBody(params = { "array", "width", "height" }, script = "return new ImageData(array, width, height);") + @Deprecated public static native ImageData create(Uint8ClampedArray array, int width, int height); } diff --git a/jso/apis/src/main/java/org/teavm/jso/canvas/Path2D.java b/jso/apis/src/main/java/org/teavm/jso/canvas/Path2D.java index bb9ed9d18..bfc230897 100644 --- a/jso/apis/src/main/java/org/teavm/jso/canvas/Path2D.java +++ b/jso/apis/src/main/java/org/teavm/jso/canvas/Path2D.java @@ -17,50 +17,61 @@ package org.teavm.jso.canvas; import org.teavm.interop.NoSideEffects; import org.teavm.jso.JSBody; +import org.teavm.jso.JSClass; import org.teavm.jso.JSObject; -public abstract class Path2D implements JSObject { - private Path2D() { +@JSClass +public class Path2D implements JSObject { + public Path2D() { + } + + public Path2D(Path2D path) { + } + + public Path2D(String svg) { } @JSBody(script = "return new Path2D();") @NoSideEffects + @Deprecated public static native Path2D create(); @JSBody(params = "path", script = "return new Path2D(path);") @NoSideEffects + @Deprecated public static native Path2D create(Path2D path); @JSBody(params = "svg", script = "return new Path2D(svg);") @NoSideEffects + @Deprecated public static native Path2D create(String svg); - public abstract void addPath(Path2D path); + public native void addPath(Path2D path); - public abstract void closePath(); + public native void closePath(); - public abstract void moveTo(double x, double y); + public native void moveTo(double x, double y); - public abstract void lineTo(double x, double y); + public native void lineTo(double x, double y); - public abstract void bezierCurveTo(double cp1x, double cp1y, double cp2x, double cp2y, double x, double y); + public native void bezierCurveTo(double cp1x, double cp1y, double cp2x, double cp2y, double x, double y); - public abstract void quadraticCurveTo(double cpx, double cpy, double x, double y); + public native void quadraticCurveTo(double cpx, double cpy, double x, double y); - public abstract void arc(double x, double y, double radius, double startAngle, double endAngle); + public native void arc(double x, double y, double radius, double startAngle, double endAngle); - public abstract void arc(double x, double y, double radius, double startAngle, double endAngle, + public native void arc(double x, double y, double radius, double startAngle, double endAngle, boolean counterclockwise); - public abstract void arcTo(double x1, double y1, double x2, double y2, double radius); + public native void arcTo(double x1, double y1, double x2, double y2, double radius); - public abstract void ellipse(double x, double y, double radiusX, double radiusY, double rotation, + public native void ellipse(double x, double y, double radiusX, double radiusY, double rotation, double startAngle, double endAngle); - public abstract void ellipse(double x, double y, double radiusX, double radiusY, double rotation, + public native void ellipse(double x, double y, double radiusX, double radiusY, double rotation, double startAngle, double endAngle, boolean counterclockwise); - public abstract void rect(double x, double y, double width, double height); + public native void rect(double x, double y, double width, double height); - public abstract void roundRect(double x, double y, double width, double height, JSObject radii); + public native void roundRect(double x, double y, double width, double height, JSObject radii); } diff --git a/jso/apis/src/main/java/org/teavm/jso/core/JSArray.java b/jso/apis/src/main/java/org/teavm/jso/core/JSArray.java index 1ea7c5e51..7671383ee 100644 --- a/jso/apis/src/main/java/org/teavm/jso/core/JSArray.java +++ b/jso/apis/src/main/java/org/teavm/jso/core/JSArray.java @@ -17,80 +17,92 @@ package org.teavm.jso.core; import org.teavm.interop.NoSideEffects; import org.teavm.jso.JSBody; +import org.teavm.jso.JSClass; import org.teavm.jso.JSIndexer; import org.teavm.jso.JSProperty; -public abstract class JSArray implements JSArrayReader { - private JSArray() { +@JSClass(name = "Array") +public class JSArray implements JSArrayReader { + public JSArray(int size) { + } + + public JSArray() { } @JSIndexer - public abstract void set(int index, T value); + public native void set(int index, T value); - public abstract int push(T a); + public native int push(T a); - public abstract int push(T a, T b); + public native int push(T a, T b); - public abstract int push(T a, T b, T c); + public native int push(T a, T b, T c); - public abstract int push(T a, T b, T c, T d); + public native int push(T a, T b, T c, T d); - public abstract T shift(); + public native T shift(); - public abstract String join(String separator); + public native String join(String separator); - public abstract String join(); + public native String join(); - public abstract JSArray concat(JSArrayReader a); + public native JSArray concat(JSArrayReader a); - public abstract JSArray concat(JSArrayReader a, JSArrayReader b); + public native JSArray concat(JSArrayReader a, JSArrayReader b); - public abstract JSArray concat(JSArrayReader a, JSArrayReader b, JSArrayReader c); + public native JSArray concat(JSArrayReader a, JSArrayReader b, JSArrayReader c); - public abstract JSArray concat(JSArrayReader a, JSArrayReader b, JSArrayReader c, JSArrayReader d); + public native JSArray concat(JSArrayReader a, JSArrayReader b, JSArrayReader c, JSArrayReader d); - public abstract T pop(); + public native T pop(); - public abstract int unshift(T a); + public native int unshift(T a); - public abstract int unshift(T a, T b); + public native int unshift(T a, T b); - public abstract int unshift(T a, T b, T c); + public native int unshift(T a, T b, T c); - public abstract int unshift(T a, T b, T c, T d); + public native int unshift(T a, T b, T c, T d); - public abstract JSArray slice(int start); + public native JSArray slice(int start); - public abstract JSArray slice(int start, int end); + public native JSArray slice(int start, int end); - public abstract JSArray reverse(); + public native JSArray reverse(); - public abstract JSArray sort(JSSortFunction function); + public native JSArray sort(JSSortFunction function); - public abstract JSArray sort(); + public native JSArray sort(); - public abstract JSArray splice(int start, int count); + public native JSArray splice(int start, int count); - public abstract JSArray splice(int start, int count, T a); + public native JSArray splice(int start, int count, T a); - public abstract JSArray splice(int start, int count, T a, T b); + public native JSArray splice(int start, int count, T a, T b); - public abstract JSArray splice(int start, int count, T a, T b, T c); + public native JSArray splice(int start, int count, T a, T b, T c); - public abstract JSArray splice(int start, int count, T a, T b, T c, T d); + public native JSArray splice(int start, int count, T a, T b, T c, T d); @JSProperty - public abstract void setLength(int len); + public native void setLength(int len); + + @Override + public native int getLength(); + + @Override + public native T get(int index); @JSBody(script = "return new Array();") @NoSideEffects + @Deprecated public static native JSArray create(); @JSBody(params = "size", script = "return new Array(size);") @NoSideEffects + @Deprecated public static native JSArray create(int size); - @JSBody(params = "object", script = "return Array.isArray(object);") @NoSideEffects public static native boolean isArray(Object object); diff --git a/jso/apis/src/main/java/org/teavm/jso/core/JSDate.java b/jso/apis/src/main/java/org/teavm/jso/core/JSDate.java index ee7069e99..e94967d70 100644 --- a/jso/apis/src/main/java/org/teavm/jso/core/JSDate.java +++ b/jso/apis/src/main/java/org/teavm/jso/core/JSDate.java @@ -17,164 +17,187 @@ package org.teavm.jso.core; import org.teavm.interop.NoSideEffects; import org.teavm.jso.JSBody; +import org.teavm.jso.JSClass; import org.teavm.jso.JSMethod; import org.teavm.jso.JSObject; -public abstract class JSDate implements JSObject { +@JSClass(name = "Date") +public class JSDate implements JSObject { + public JSDate() { + } + + public JSDate(double millis) { + } + + public JSDate(int year, int month) { + } + + public JSDate(int year, int month, int day) { + } + + public JSDate(int year, int month, int day, int hour) { + } + + public JSDate(int year, int month, int day, int hour, int minute) { + } + + public JSDate(int year, int month, int day, int hour, int minute, int second) { + } + + public JSDate(int year, int month, int day, int hour, int minute, int second, int millisecond) { + } + @JSBody(script = "return new Date();") @NoSideEffects + @Deprecated public static native JSDate create(); @JSBody(params = "millis", script = "return new Date(millis);") @NoSideEffects + @Deprecated public static native JSDate create(double millis); @JSBody(params = { "year", "month" }, script = "return new Date(year, month);") @NoSideEffects + @Deprecated public static native JSDate create(int year, int month); @JSBody(params = { "year", "month", "day" }, script = "return new Date(year, month, day);") @NoSideEffects + @Deprecated public static native JSDate create(int year, int month, int day); @JSBody(params = { "year", "month", "day", "hour" }, script = "return new Date(year, month, day, hour);") @NoSideEffects + @Deprecated public static native JSDate create(int year, int month, int day, int hour); @JSBody(params = { "year", "month", "day", "hour", "minute" }, script = "return new Date(year, month, day, hour, minute);") @NoSideEffects + @Deprecated public static native JSDate create(int year, int month, int day, int hour, int minute); @JSBody(params = { "year", "month", "day", "hour", "minute", "second" }, script = "return new Date(year, month, day, hour, minute, second);") @NoSideEffects + @Deprecated public static native JSDate create(int year, int month, int day, int hour, int minute, int second); @JSBody(params = { "year", "month", "day", "hour", "minute", "second", "millisecond" }, script = "return new Date(year, month, day, hour, minute, second, millisecond);") @NoSideEffects + @Deprecated public static native JSDate create(int year, int month, int day, int hour, int minute, int second, int millisecond); - @JSBody(params = {}, script = "return Date.now();") @NoSideEffects public static native double now(); - @JSBody(params = "stringValue", script = "return Date.parse(stringValue);") @NoSideEffects public static native double parse(String stringValue); - @JSBody(params = { "year", "month" }, script = "return Date.UTC(year, month);") @NoSideEffects public static native double UTC(int year, int month); - @JSBody(params = { "year", "month", "day" }, script = "return Date.UTC(year, month, day);") @NoSideEffects public static native double UTC(int year, int month, int day); - @JSBody(params = { "year", "month", "day", "hour" }, script = "return Date.UTC(year, month, day, hour);") @NoSideEffects public static native double UTC(int year, int month, int day, int hour); - @JSBody(params = { "year", "month", "day", "hour", "minute" }, - script = "return Date.UTC(year, month, day, hour, minute);") @NoSideEffects public static native double UTC(int year, int month, int day, int hour, int minute); - @JSBody(params = { "year", "month", "day", "hour", "minute", "second" }, - script = "return Date.UTC(year, month, day, hour, minute, second);") @NoSideEffects public static native double UTC(int year, int month, int day, int hour, int minute, int second); - @JSBody(params = { "year", "month", "day", "hour", "minute", "second", "millisecond" }, - script = "return Date.UTC(year, month, day, hour, minute, second, millisecond);") @NoSideEffects public static native double UTC(int year, int month, int day, int hour, int minute, int second, int millisecond); - public abstract int getDate(); + public native int getDate(); - public abstract int getDay(); + public native int getDay(); - public abstract int getFullYear(); + public native int getFullYear(); - public abstract int getHours(); + public native int getHours(); - public abstract int getMilliseconds(); + public native int getMilliseconds(); - public abstract int getMinutes(); + public native int getMinutes(); - public abstract int getMonth(); + public native int getMonth(); - public abstract int getSeconds(); + public native int getSeconds(); - public abstract double getTime(); + public native double getTime(); - public abstract int getTimezoneOffset(); + public native int getTimezoneOffset(); - public abstract int getUTCDate(); + public native int getUTCDate(); - public abstract int getUTCDay(); + public native int getUTCDay(); - public abstract int getUTCFullYear(); + public native int getUTCFullYear(); - public abstract int getUTCHours(); + public native int getUTCHours(); - public abstract int getUTCMilliseconds(); + public native int getUTCMilliseconds(); - public abstract int getUTCMinutes(); + public native int getUTCMinutes(); - public abstract int getUTCMonth(); + public native int getUTCMonth(); - public abstract int getUTCSeconds(); + public native int getUTCSeconds(); - public abstract void setDate(int date); + public native void setDate(int date); - public abstract void setFullYear(int fullYear); + public native void setFullYear(int fullYear); - public abstract void setHours(int hours); + public native void setHours(int hours); - public abstract void setMilliseconds(int milliseconds); + public native void setMilliseconds(int milliseconds); - public abstract void setMinutes(int minutes); + public native void setMinutes(int minutes); - public abstract void setMonth(int month); + public native void setMonth(int month); - public abstract void setSeconds(int seconds); + public native void setSeconds(int seconds); - public abstract void setTime(double time); + public native void setTime(double time); - public abstract void setUTCDate(int date); + public native void setUTCDate(int date); - public abstract void setUTCFullYear(int fullYear); + public native void setUTCFullYear(int fullYear); - public abstract void setUTCHours(int hours); + public native void setUTCHours(int hours); - public abstract void setUTCMilliseconds(int milliseconds); + public native void setUTCMilliseconds(int milliseconds); - public abstract void setUTCMinutes(int minutes); + public native void setUTCMinutes(int minutes); - public abstract void setUTCMonth(int month); + public native void setUTCMonth(int month); - public abstract void setUTCSeconds(int seconds); + public native void setUTCSeconds(int seconds); - public abstract String toDateString(); + public native String toDateString(); - public abstract String toISOString(); + public native String toISOString(); - public abstract String toJSON(); + public native String toJSON(); - public abstract String toLocaleDateString(); + public native String toLocaleDateString(); - public abstract String toLocaleString(); + public native String toLocaleString(); - public abstract String toLocaleTimeString(); + public native String toLocaleTimeString(); @JSMethod("toString") - public abstract String stringValue(); + public native String stringValue(); - public abstract String toTimeString(); + public native String toTimeString(); - public abstract String toUTCString(); + public native String toUTCString(); - public abstract String toLocaleFormat(String format); + public native String toLocaleFormat(String format); } diff --git a/jso/apis/src/main/java/org/teavm/jso/core/JSFinalizationRegistry.java b/jso/apis/src/main/java/org/teavm/jso/core/JSFinalizationRegistry.java index 53eeca28a..9129713f8 100644 --- a/jso/apis/src/main/java/org/teavm/jso/core/JSFinalizationRegistry.java +++ b/jso/apis/src/main/java/org/teavm/jso/core/JSFinalizationRegistry.java @@ -17,15 +17,20 @@ package org.teavm.jso.core; import org.teavm.interop.NoSideEffects; import org.teavm.jso.JSBody; +import org.teavm.jso.JSClass; import org.teavm.jso.JSObject; -public abstract class JSFinalizationRegistry implements JSObject { - public abstract void register(Object obj, Object token); +@JSClass(name = "FinalizationRegistry") +public class JSFinalizationRegistry implements JSObject { + public JSFinalizationRegistry(JSFinalizationRegistryConsumer consumer) { + } + + public native void register(Object obj, Object token); @JSBody(params = "consumer", script = "return new FinalizationRegistry(consumer);") + @Deprecated public static native JSFinalizationRegistry create(JSFinalizationRegistryConsumer consumer); - @JSBody(script = "return typeof FinalizationRegistry !== 'undefined';") @NoSideEffects public static native boolean isSupported(); diff --git a/jso/apis/src/main/java/org/teavm/jso/core/JSMap.java b/jso/apis/src/main/java/org/teavm/jso/core/JSMap.java index bda5ecb15..43fd49ad9 100644 --- a/jso/apis/src/main/java/org/teavm/jso/core/JSMap.java +++ b/jso/apis/src/main/java/org/teavm/jso/core/JSMap.java @@ -17,20 +17,26 @@ package org.teavm.jso.core; import org.teavm.interop.NoSideEffects; import org.teavm.jso.JSBody; +import org.teavm.jso.JSClass; import org.teavm.jso.JSObject; -public abstract class JSMap implements JSObject { - public abstract V get(K key); +@JSClass(name = "Map") +public class JSMap implements JSObject { + public JSMap() { + } - public abstract boolean has(K key); + public native V get(K key); - public abstract JSMap set(K key, V value); + public native boolean has(K key); - public abstract boolean delete(K key); + public native JSMap set(K key, V value); - public abstract void clear(); + public native boolean delete(K key); + + public native void clear(); @JSBody(script = "return new Map();") @NoSideEffects + @Deprecated public static native JSMap create(); } diff --git a/jso/apis/src/main/java/org/teavm/jso/core/JSPromise.java b/jso/apis/src/main/java/org/teavm/jso/core/JSPromise.java index 5a3d9890a..a4f2ba00e 100644 --- a/jso/apis/src/main/java/org/teavm/jso/core/JSPromise.java +++ b/jso/apis/src/main/java/org/teavm/jso/core/JSPromise.java @@ -17,6 +17,7 @@ package org.teavm.jso.core; import org.teavm.interop.NoSideEffects; import org.teavm.jso.JSBody; +import org.teavm.jso.JSClass; import org.teavm.jso.JSFunctor; import org.teavm.jso.JSMethod; import org.teavm.jso.JSObject; @@ -32,8 +33,9 @@ import org.teavm.jso.util.function.JSSupplier; * * @param The type this promise returns when resolving successfully. */ -public abstract class JSPromise implements JSObject { - private JSPromise() { +@JSClass(name = "Promise") +public class JSPromise implements JSObject { + public JSPromise(Executor executor) { } /** Interface for a function wrapped by a promise. */ @@ -49,63 +51,58 @@ public abstract class JSPromise implements JSObject { @JSBody(params = "executor", script = "return new Promise(executor);") @NoSideEffects + @Deprecated public static native JSPromise create(Executor executor); - @JSBody(params = "promises", script = "return Promise.any(promises);") @NoSideEffects public static native JSPromise any(JSArrayReader> promises); // TODO: Allow passing differently typed promises via a JSTuple interface - @JSBody(params = "promises", script = "return Promise.all(promises);") @NoSideEffects public static native JSPromise> all(JSArrayReader> promises); // TODO: Allow passing differently typed promises via a JSTuple interface - @JSBody(params = "promises", script = "return Promise.allSettled(promises);") @NoSideEffects public static native JSPromise>> allSettled(JSArrayReader> promises); - @JSBody(params = "promises", script = "return Promise.race(promises);") @NoSideEffects public static native JSPromise race(JSArrayReader> promises); - @JSBody(params = "value", script = "return Promise.resolve(value);") @NoSideEffects public static native JSPromise resolve(V value); - @JSBody(params = "reason", script = "return Promise.reject(reason);") @NoSideEffects public static native JSPromise reject(Object reason); /** Call {@code onFulfilled} with the success value, resolving with its return value. */ - public abstract JSPromise then(JSFunction onFulfilled); + public native JSPromise then(JSFunction onFulfilled); /** Call {@code onFulfilled} with the success value or {@code onRejected} with the reject reason, * resolving with its return value. */ - public abstract JSPromise then(JSFunction onFulfilled, JSFunction onRejected); + public native JSPromise then(JSFunction onFulfilled, JSFunction onRejected); /** Call {@code onFulfilled} with the success value, returning a new promise. */ @JSMethod("then") - public abstract JSPromise flatThen(JSFunction> onFulfilled); + public native JSPromise flatThen(JSFunction> onFulfilled); /** Call {@code onFulfilled} with the success value or {@code onRejected} with the reject reason, * returning a new promise. */ @JSMethod("then") - public abstract JSPromise flatThen(JSFunction> onFulfilled, + public native JSPromise flatThen(JSFunction> onFulfilled, JSFunction> onRejected); /** Call {@code onRejected} with the reject reason, resolving with its return value. */ @JSMethod("catch") - public abstract JSPromise catchError(JSFunction onRejected); + public native JSPromise catchError(JSFunction onRejected); /** Call {@code onRejected} with the reject reason, returning a new promise. */ @JSMethod("catch") - public abstract JSPromise flatCatchError(JSFunction> onRejected); + public native JSPromise flatCatchError(JSFunction> onRejected); /** Call {@code onFinally} after settling, ignoring the return value. */ @JSMethod("finally") - public abstract JSPromise onSettled(JSSupplier onFinally); + public native JSPromise onSettled(JSSupplier onFinally); /** Interface for the return values of {@ref #allSettled()}. */ public interface FulfillmentValue extends JSObject { diff --git a/jso/apis/src/main/java/org/teavm/jso/core/JSRegExp.java b/jso/apis/src/main/java/org/teavm/jso/core/JSRegExp.java index 9f34c8552..69ff32622 100644 --- a/jso/apis/src/main/java/org/teavm/jso/core/JSRegExp.java +++ b/jso/apis/src/main/java/org/teavm/jso/core/JSRegExp.java @@ -17,16 +17,26 @@ package org.teavm.jso.core; import org.teavm.interop.NoSideEffects; import org.teavm.jso.JSBody; +import org.teavm.jso.JSClass; import org.teavm.jso.JSObject; import org.teavm.jso.JSProperty; -public abstract class JSRegExp implements JSObject { +@JSClass(name = "RegExp") +public class JSRegExp implements JSObject { + public JSRegExp(String pattern) { + } + + public JSRegExp(String pattern, String flags) { + } + @JSBody(params = "pattern", script = "return new RegExp(pattern);") @NoSideEffects + @Deprecated public static native JSRegExp create(String pattern); @JSBody(params = { "pattern", "flags" }, script = "return new RegExp(pattern, flags);") @NoSideEffects + @Deprecated public static native JSRegExp create(String pattern, String flags); public static JSRegExp create(String pattern, JSRegExpFlag... flags) { @@ -60,23 +70,23 @@ public abstract class JSRegExp implements JSObject { } @JSProperty - public abstract boolean isGlobal(); + public native boolean isGlobal(); @JSProperty - public abstract boolean isIgnoreCase(); + public native boolean isIgnoreCase(); @JSProperty - public abstract boolean isMultiline(); + public native boolean isMultiline(); @JSProperty - public abstract int getLastIndex(); + public native int getLastIndex(); @JSProperty - public abstract JSString getSource(); + public native JSString getSource(); - public abstract JSArray exec(JSString text); + public native JSArray exec(JSString text); - public abstract boolean test(JSString text); + public native boolean test(JSString text); - public abstract boolean test(String text); + public native boolean test(String text); } diff --git a/jso/apis/src/main/java/org/teavm/jso/core/JSString.java b/jso/apis/src/main/java/org/teavm/jso/core/JSString.java index 837e498ab..301746ef8 100644 --- a/jso/apis/src/main/java/org/teavm/jso/core/JSString.java +++ b/jso/apis/src/main/java/org/teavm/jso/core/JSString.java @@ -36,7 +36,6 @@ public abstract class JSString implements JSObject { @NoSideEffects public static native JSString valueOf(String str); - @JSBody(params = "code", script = "return String.fromCharCode(code)") @NoSideEffects public static native JSString fromCharCode(int code); diff --git a/jso/apis/src/main/java/org/teavm/jso/core/JSSymbol.java b/jso/apis/src/main/java/org/teavm/jso/core/JSSymbol.java index d528693e2..ce34f8fb5 100644 --- a/jso/apis/src/main/java/org/teavm/jso/core/JSSymbol.java +++ b/jso/apis/src/main/java/org/teavm/jso/core/JSSymbol.java @@ -19,7 +19,10 @@ import org.teavm.interop.NoSideEffects; import org.teavm.jso.JSBody; import org.teavm.jso.JSObject; -public abstract class JSSymbol implements JSObject { +public class JSSymbol implements JSObject { + private JSSymbol() { + } + @JSBody(params = "name", script = "return Symbol(name);") public static native JSSymbol create(String name); diff --git a/jso/apis/src/main/java/org/teavm/jso/core/JSWeakMap.java b/jso/apis/src/main/java/org/teavm/jso/core/JSWeakMap.java index 196ffe72b..f7498a0a3 100644 --- a/jso/apis/src/main/java/org/teavm/jso/core/JSWeakMap.java +++ b/jso/apis/src/main/java/org/teavm/jso/core/JSWeakMap.java @@ -17,19 +17,25 @@ package org.teavm.jso.core; import org.teavm.interop.NoSideEffects; import org.teavm.jso.JSBody; +import org.teavm.jso.JSClass; import org.teavm.jso.JSObject; -public abstract class JSWeakMap implements JSObject { - public abstract V get(K key); +@JSClass(name = "WeakMap") +public class JSWeakMap implements JSObject { + public JSWeakMap() { + } - public abstract boolean has(K key); + public native V get(K key); - public abstract JSWeakMap set(K key, V value); + public native boolean has(K key); - public abstract boolean remove(K key); + public native JSWeakMap set(K key, V value); + + public native boolean remove(K key); @JSBody(script = "return new WeakMap();") @NoSideEffects + @Deprecated public static native JSWeakMap create(); @JSBody(script = "return typeof WeakMap !== 'undefined';") diff --git a/jso/apis/src/main/java/org/teavm/jso/core/JSWeakRef.java b/jso/apis/src/main/java/org/teavm/jso/core/JSWeakRef.java index 98680ff04..47ab05d3a 100644 --- a/jso/apis/src/main/java/org/teavm/jso/core/JSWeakRef.java +++ b/jso/apis/src/main/java/org/teavm/jso/core/JSWeakRef.java @@ -17,13 +17,19 @@ package org.teavm.jso.core; import org.teavm.interop.NoSideEffects; import org.teavm.jso.JSBody; +import org.teavm.jso.JSClass; import org.teavm.jso.JSObject; +@JSClass(name = "WeakRef") public abstract class JSWeakRef implements JSObject { + public JSWeakRef(T value) { + } + public abstract T deref(); @JSBody(params = "value", script = "return new WeakRef(value);") @NoSideEffects + @Deprecated public static native JSWeakRef create(T value); @JSBody(script = "return typeof WeakRef !== 'undefined';") diff --git a/jso/apis/src/main/java/org/teavm/jso/json/JSON.java b/jso/apis/src/main/java/org/teavm/jso/json/JSON.java index ff9073b1d..187c4f3e5 100644 --- a/jso/apis/src/main/java/org/teavm/jso/json/JSON.java +++ b/jso/apis/src/main/java/org/teavm/jso/json/JSON.java @@ -15,16 +15,15 @@ */ package org.teavm.jso.json; -import org.teavm.jso.JSBody; +import org.teavm.jso.JSClass; import org.teavm.jso.JSObject; -public final class JSON { +@JSClass +public final class JSON implements JSObject { private JSON() { } - @JSBody(params = "object", script = "return JSON.stringify(object);") public static native String stringify(JSObject object); - @JSBody(params = "string", script = "return JSON.parse(string);") public static native JSObject parse(String string); } diff --git a/jso/apis/src/main/java/org/teavm/jso/typedarrays/ArrayBuffer.java b/jso/apis/src/main/java/org/teavm/jso/typedarrays/ArrayBuffer.java index 5d4b79c18..28cb3c628 100644 --- a/jso/apis/src/main/java/org/teavm/jso/typedarrays/ArrayBuffer.java +++ b/jso/apis/src/main/java/org/teavm/jso/typedarrays/ArrayBuffer.java @@ -16,15 +16,24 @@ package org.teavm.jso.typedarrays; import org.teavm.jso.JSBody; +import org.teavm.jso.JSClass; import org.teavm.jso.JSObject; import org.teavm.jso.JSProperty; -public abstract class ArrayBuffer implements JSObject { - @JSProperty - public abstract int getByteLength(); +@JSClass +public class ArrayBuffer implements JSObject { + public ArrayBuffer() { + } - public abstract ArrayBuffer slice(int begin, int end); + public ArrayBuffer(int length) { + } + + @JSProperty + public native int getByteLength(); + + public native ArrayBuffer slice(int begin, int end); @JSBody(params = "length", script = "return new ArrayBuffer(length);") + @Deprecated public static native ArrayBuffer create(int length); } diff --git a/jso/apis/src/main/java/org/teavm/jso/typedarrays/ArrayBufferView.java b/jso/apis/src/main/java/org/teavm/jso/typedarrays/ArrayBufferView.java index 76921ec5c..0dda80145 100644 --- a/jso/apis/src/main/java/org/teavm/jso/typedarrays/ArrayBufferView.java +++ b/jso/apis/src/main/java/org/teavm/jso/typedarrays/ArrayBufferView.java @@ -25,42 +25,42 @@ public abstract class ArrayBufferView implements JSObject { } @JSProperty - public abstract int getLength(); + public native int getLength(); @JSProperty - public abstract int getByteLength(); + public native int getByteLength(); @JSProperty - public abstract int getByteOffset(); + public native int getByteOffset(); @JSProperty - public abstract ArrayBuffer getBuffer(); + public native ArrayBuffer getBuffer(); - public abstract void set(ArrayBufferView other, int offset); + public native void set(ArrayBufferView other, int offset); - public abstract void set(ArrayBufferView other); + public native void set(ArrayBufferView other); - public abstract void set(JSArrayReader other, int offset); + public native void set(JSArrayReader other, int offset); - public abstract void set(JSArrayReader other); + public native void set(JSArrayReader other); - public abstract void set(@JSByRef byte[] other, int offset); + public native void set(@JSByRef byte[] other, int offset); - public abstract void set(@JSByRef byte[] other); + public native void set(@JSByRef byte[] other); - public abstract void set(@JSByRef short[] other, int offset); + public native void set(@JSByRef short[] other, int offset); - public abstract void set(@JSByRef short[] other); + public native void set(@JSByRef short[] other); - public abstract void set(@JSByRef int[] other, int offset); + public native void set(@JSByRef int[] other, int offset); - public abstract void set(@JSByRef int[] other); + public native void set(@JSByRef int[] other); - public abstract void set(@JSByRef float[] other, int offset); + public native void set(@JSByRef float[] other, int offset); - public abstract void set(@JSByRef float[] other); + public native void set(@JSByRef float[] other); - public abstract void set(@JSByRef double[] other, int offset); + public native void set(@JSByRef double[] other, int offset); - public abstract void set(@JSByRef double[] other); + public native void set(@JSByRef double[] other); } diff --git a/jso/apis/src/main/java/org/teavm/jso/typedarrays/DataView.java b/jso/apis/src/main/java/org/teavm/jso/typedarrays/DataView.java index dd851a37f..19ba22536 100644 --- a/jso/apis/src/main/java/org/teavm/jso/typedarrays/DataView.java +++ b/jso/apis/src/main/java/org/teavm/jso/typedarrays/DataView.java @@ -16,65 +16,80 @@ package org.teavm.jso.typedarrays; import org.teavm.jso.JSBody; +import org.teavm.jso.JSClass; -public abstract class DataView extends ArrayBufferView { - public abstract byte getInt8(int byteOffset); +@JSClass +public class DataView extends ArrayBufferView { + public DataView(ArrayBuffer buffer) { + } - public abstract short getUint8(int byteOffset); + public DataView(ArrayBufferView buffer) { + } - public abstract short getInt16(int byteOffset); + public DataView(ArrayBuffer buffer, int offset, int length) { + } - public abstract short getInt16(int byteOffset, boolean littleEndian); + public DataView(ArrayBuffer buffer, int offset) { + } - public abstract int getUint16(int byteOffset); + public native byte getInt8(int byteOffset); - public abstract int getUint16(int byteOffset, boolean littleEndian); + public native short getUint8(int byteOffset); - public abstract int getInt32(int byteOffset); + public native short getInt16(int byteOffset); - public abstract int getInt32(int byteOffset, boolean littleEndian); + public native short getInt16(int byteOffset, boolean littleEndian); - public abstract int getUint32(int byteOffset); + public native int getUint16(int byteOffset); - public abstract int getUint32(int byteOffset, boolean littleEndian); + public native int getUint16(int byteOffset, boolean littleEndian); - public abstract float getFloat32(int byteOffset); + public native int getInt32(int byteOffset); - public abstract float getFloat32(int byteOffset, boolean littleEndian); + public native int getInt32(int byteOffset, boolean littleEndian); - public abstract double getFloat64(int byteOffset); + public native int getUint32(int byteOffset); - public abstract double getFloat64(int byteOffset, boolean littleEndian); + public native int getUint32(int byteOffset, boolean littleEndian); - public abstract void setInt8(int byteOffset, int value); + public native float getFloat32(int byteOffset); - public abstract void setUint8(int byteOffset, int value); + public native float getFloat32(int byteOffset, boolean littleEndian); - public abstract void setInt16(int byteOffset, int value); + public native double getFloat64(int byteOffset); - public abstract void setInt16(int byteOffset, int value, boolean littleEndian); + public native double getFloat64(int byteOffset, boolean littleEndian); - public abstract void setUint16(int byteOffset, int value); + public native void setInt8(int byteOffset, int value); - public abstract void setUint16(int byteOffset, int value, boolean littleEndian); + public native void setUint8(int byteOffset, int value); - public abstract void setInt32(int byteOffset, int value); + public native void setInt16(int byteOffset, int value); - public abstract void setInt32(int byteOffset, int value, boolean littleEndian); + public native void setInt16(int byteOffset, int value, boolean littleEndian); - public abstract void setUint32(int byteOffset, int value); + public native void setUint16(int byteOffset, int value); - public abstract void setUint32(int byteOffset, int value, boolean littleEndian); + public native void setUint16(int byteOffset, int value, boolean littleEndian); - public abstract void setFloat32(int byteOffset, float value); + public native void setInt32(int byteOffset, int value); - public abstract void setFloat32(int byteOffset, float value, boolean littleEndian); + public native void setInt32(int byteOffset, int value, boolean littleEndian); - public abstract void setFloat64(int byteOffset, double value); + public native void setUint32(int byteOffset, int value); - public abstract void setFloat64(int byteOffset, double value, boolean littleEndian); + public native void setUint32(int byteOffset, int value, boolean littleEndian); + + public native void setFloat32(int byteOffset, float value); + + public native void setFloat32(int byteOffset, float value, boolean littleEndian); + + public native void setFloat64(int byteOffset, double value); + + public native void setFloat64(int byteOffset, double value, boolean littleEndian); @JSBody(params = "buffer", script = "return new DataView(buffer);") + @Deprecated public static native DataView create(ArrayBuffer buffer); @JSBody(params = "buffer", script = "return new DataView(buffer);") diff --git a/jso/apis/src/main/java/org/teavm/jso/typedarrays/Float32Array.java b/jso/apis/src/main/java/org/teavm/jso/typedarrays/Float32Array.java index 64647df3a..1ddc4ee06 100644 --- a/jso/apis/src/main/java/org/teavm/jso/typedarrays/Float32Array.java +++ b/jso/apis/src/main/java/org/teavm/jso/typedarrays/Float32Array.java @@ -16,27 +16,49 @@ package org.teavm.jso.typedarrays; import org.teavm.jso.JSBody; +import org.teavm.jso.JSClass; import org.teavm.jso.JSIndexer; -public abstract class Float32Array extends ArrayBufferView { - @JSIndexer - public abstract float get(int index); +@JSClass +public class Float32Array extends ArrayBufferView { + public Float32Array(int length) { + } + + public Float32Array(ArrayBuffer buffer) { + } + + public Float32Array(ArrayBufferView buffer) { + } + + public Float32Array(ArrayBuffer buffer, int offset, int length) { + } + + public Float32Array(ArrayBuffer buffer, int offset) { + } @JSIndexer - public abstract void set(int index, float value); + public native float get(int index); + + @JSIndexer + public native void set(int index, float value); @JSBody(params = "length", script = "return new Float32Array(length);") + @Deprecated public static native Float32Array create(int length); @JSBody(params = "buffer", script = "return new Float32Array(buffer);") + @Deprecated public static native Float32Array create(ArrayBuffer buffer); @JSBody(params = "buffer", script = "return new Float32Array(buffer);") + @Deprecated public static native Float32Array create(ArrayBufferView buffer); @JSBody(params = { "buffer", "offset", "length" }, script = "return new Float32Array(buffer, offset, length);") + @Deprecated public static native Float32Array create(ArrayBuffer buffer, int offset, int length); @JSBody(params = { "buffer", "offset" }, script = "return new Float32Array(buffer, offset);") + @Deprecated public static native Float32Array create(ArrayBuffer buffer, int offset); } diff --git a/jso/apis/src/main/java/org/teavm/jso/typedarrays/Float64Array.java b/jso/apis/src/main/java/org/teavm/jso/typedarrays/Float64Array.java index d1379f931..815336a43 100644 --- a/jso/apis/src/main/java/org/teavm/jso/typedarrays/Float64Array.java +++ b/jso/apis/src/main/java/org/teavm/jso/typedarrays/Float64Array.java @@ -16,27 +16,49 @@ package org.teavm.jso.typedarrays; import org.teavm.jso.JSBody; +import org.teavm.jso.JSClass; import org.teavm.jso.JSIndexer; -public abstract class Float64Array extends ArrayBufferView { - @JSIndexer - public abstract double get(int index); +@JSClass +public class Float64Array extends ArrayBufferView { + public Float64Array(int length) { + } + + public Float64Array(ArrayBuffer buffer) { + } + + public Float64Array(ArrayBufferView buffer) { + } + + public Float64Array(ArrayBuffer buffer, int offset, int length) { + } + + public Float64Array(ArrayBuffer buffer, int offset) { + } @JSIndexer - public abstract void set(int index, double value); + public native double get(int index); + + @JSIndexer + public native void set(int index, double value); @JSBody(params = "length", script = "return new Float64Array(length);") + @Deprecated public static native Float64Array create(int length); @JSBody(params = "buffer", script = "return new Float64Array(buffer);") + @Deprecated public static native Float64Array create(ArrayBuffer buffer); @JSBody(params = "buffer", script = "return new Float64Array(buffer);") + @Deprecated public static native Float64Array create(ArrayBufferView buffer); @JSBody(params = { "buffer", "offset", "length" }, script = "return new Float64Array(buffer, offset, length);") + @Deprecated public static native Float64Array create(ArrayBuffer buffer, int offset, int length); @JSBody(params = { "buffer", "offset" }, script = "return new Float64Array(buffer, offset);") + @Deprecated public static native Float64Array create(ArrayBuffer buffer, int offset); } diff --git a/jso/apis/src/main/java/org/teavm/jso/typedarrays/Int16Array.java b/jso/apis/src/main/java/org/teavm/jso/typedarrays/Int16Array.java index caaa5d0bf..87ce6444e 100644 --- a/jso/apis/src/main/java/org/teavm/jso/typedarrays/Int16Array.java +++ b/jso/apis/src/main/java/org/teavm/jso/typedarrays/Int16Array.java @@ -16,27 +16,49 @@ package org.teavm.jso.typedarrays; import org.teavm.jso.JSBody; +import org.teavm.jso.JSClass; import org.teavm.jso.JSIndexer; -public abstract class Int16Array extends ArrayBufferView { - @JSIndexer - public abstract short get(int index); +@JSClass +public class Int16Array extends ArrayBufferView { + public Int16Array(int length) { + } + + public Int16Array(ArrayBuffer buffer) { + } + + public Int16Array(ArrayBufferView buffer) { + } + + public Int16Array(ArrayBuffer buffer, int offset, int length) { + } + + public Int16Array(ArrayBuffer buffer, int offset) { + } @JSIndexer - public abstract void set(int index, short value); + public native short get(int index); + + @JSIndexer + public native void set(int index, short value); @JSBody(params = "length", script = "return new Int16Array(length);") + @Deprecated public static native Int16Array create(int length); @JSBody(params = "buffer", script = "return new Int16Array(buffer);") + @Deprecated public static native Int16Array create(ArrayBuffer buffer); @JSBody(params = "buffer", script = "return new Int16Array(buffer);") + @Deprecated public static native Int16Array create(ArrayBufferView buffer); @JSBody(params = { "buffer", "offset", "length" }, script = "return new Int16Array(buffer, offset, length);") + @Deprecated public static native Int16Array create(ArrayBuffer buffer, int offset, int length); @JSBody(params = { "buffer", "offset" }, script = "return new Int16Array(buffer, offset);") + @Deprecated public static native Int16Array create(ArrayBuffer buffer, int offset); } diff --git a/jso/apis/src/main/java/org/teavm/jso/typedarrays/Int32Array.java b/jso/apis/src/main/java/org/teavm/jso/typedarrays/Int32Array.java index 0f92358c9..9dbaf3e81 100644 --- a/jso/apis/src/main/java/org/teavm/jso/typedarrays/Int32Array.java +++ b/jso/apis/src/main/java/org/teavm/jso/typedarrays/Int32Array.java @@ -17,31 +17,55 @@ package org.teavm.jso.typedarrays; import org.teavm.jso.JSBody; import org.teavm.jso.JSByRef; +import org.teavm.jso.JSClass; import org.teavm.jso.JSIndexer; -public abstract class Int32Array extends ArrayBufferView { - @JSIndexer - public abstract int get(int index); +@JSClass +public class Int32Array extends ArrayBufferView { + public Int32Array(int length) { + } + + public Int32Array(ArrayBuffer buffer) { + } + + public Int32Array(ArrayBufferView buffer) { + } + + public Int32Array(ArrayBuffer buffer, int offset, int length) { + } + + public Int32Array(ArrayBuffer buffer, int offset) { + } @JSIndexer - public abstract void set(int index, int value); + public native int get(int index); - public abstract void set(@JSByRef int[] data, int offset); + @JSIndexer + public native void set(int index, int value); - public abstract void set(@JSByRef int[] data); + @Override + public native void set(@JSByRef int[] data, int offset); + + @Override + public native void set(@JSByRef int[] data); @JSBody(params = "length", script = "return new Int32Array(length);") + @Deprecated public static native Int32Array create(int length); @JSBody(params = "buffer", script = "return new Int32Array(buffer);") + @Deprecated public static native Int32Array create(ArrayBuffer buffer); @JSBody(params = "buffer", script = "return new Int32Array(buffer);") + @Deprecated public static native Int32Array create(ArrayBufferView buffer); @JSBody(params = { "buffer", "offset", "length" }, script = "return new Int32Array(buffer, offset, length);") + @Deprecated public static native Int32Array create(ArrayBuffer buffer, int offset, int length); @JSBody(params = { "buffer", "offset" }, script = "return new Int32Array(buffer, offset);") + @Deprecated public static native Int32Array create(ArrayBuffer buffer, int offset); } diff --git a/jso/apis/src/main/java/org/teavm/jso/typedarrays/Int8Array.java b/jso/apis/src/main/java/org/teavm/jso/typedarrays/Int8Array.java index ed42d640c..c15c31546 100644 --- a/jso/apis/src/main/java/org/teavm/jso/typedarrays/Int8Array.java +++ b/jso/apis/src/main/java/org/teavm/jso/typedarrays/Int8Array.java @@ -16,27 +16,49 @@ package org.teavm.jso.typedarrays; import org.teavm.jso.JSBody; +import org.teavm.jso.JSClass; import org.teavm.jso.JSIndexer; -public abstract class Int8Array extends ArrayBufferView { - @JSIndexer - public abstract byte get(int index); +@JSClass +public class Int8Array extends ArrayBufferView { + public Int8Array(int length) { + } + + public Int8Array(ArrayBuffer buffer) { + } + + public Int8Array(ArrayBufferView buffer) { + } + + public Int8Array(ArrayBuffer buffer, int offset, int length) { + } + + public Int8Array(ArrayBuffer buffer, int offset) { + } @JSIndexer - public abstract void set(int index, byte value); + public native byte get(int index); + + @JSIndexer + public native void set(int index, byte value); @JSBody(params = "length", script = "return new Int8Array(length);") + @Deprecated public static native Int8Array create(int length); @JSBody(params = "buffer", script = "return new Int8Array(buffer);") + @Deprecated public static native Int8Array create(ArrayBuffer buffer); @JSBody(params = "buffer", script = "return new Int8Array(buffer);") + @Deprecated public static native Int8Array create(ArrayBufferView buffer); @JSBody(params = { "buffer", "offset", "length" }, script = "return new Int8Array(buffer, offset, length);") + @Deprecated public static native Int8Array create(ArrayBuffer buffer, int offset, int length); @JSBody(params = { "buffer", "offset" }, script = "return new Int8Array(buffer, offset);") + @Deprecated public static native Int8Array create(ArrayBuffer buffer, int offset); } diff --git a/jso/apis/src/main/java/org/teavm/jso/typedarrays/Uint16Array.java b/jso/apis/src/main/java/org/teavm/jso/typedarrays/Uint16Array.java index 177975a0f..fc130d2f1 100644 --- a/jso/apis/src/main/java/org/teavm/jso/typedarrays/Uint16Array.java +++ b/jso/apis/src/main/java/org/teavm/jso/typedarrays/Uint16Array.java @@ -16,27 +16,49 @@ package org.teavm.jso.typedarrays; import org.teavm.jso.JSBody; +import org.teavm.jso.JSClass; import org.teavm.jso.JSIndexer; -public abstract class Uint16Array extends ArrayBufferView { - @JSIndexer - public abstract int get(int index); +@JSClass +public class Uint16Array extends ArrayBufferView { + public Uint16Array(int length) { + } + + public Uint16Array(ArrayBuffer buffer) { + } + + public Uint16Array(ArrayBufferView buffer) { + } + + public Uint16Array(ArrayBuffer buffer, int offset, int length) { + } + + public Uint16Array(ArrayBuffer buffer, int offset) { + } @JSIndexer - public abstract void set(int index, int value); + public native int get(int index); + + @JSIndexer + public native void set(int index, int value); @JSBody(params = "length", script = "return new Uint16Array(length);") + @Deprecated public static native Uint16Array create(int length); @JSBody(params = "buffer", script = "return new Uint16Array(buffer);") + @Deprecated public static native Uint16Array create(ArrayBuffer buffer); @JSBody(params = "buffer", script = "return new Uint16Array(buffer);") + @Deprecated public static native Uint16Array create(ArrayBufferView buffer); @JSBody(params = { "buffer", "offset", "length" }, script = "return new Uint16Array(buffer, offset, length);") + @Deprecated public static native Uint16Array create(ArrayBuffer buffer, int offset, int length); @JSBody(params = { "buffer", "offset" }, script = "return new Uint16Array(buffer, offset);") + @Deprecated public static native Uint16Array create(ArrayBuffer buffer, int offset); } diff --git a/jso/apis/src/main/java/org/teavm/jso/typedarrays/Uint8Array.java b/jso/apis/src/main/java/org/teavm/jso/typedarrays/Uint8Array.java index dbb1fc959..9a41b0c93 100644 --- a/jso/apis/src/main/java/org/teavm/jso/typedarrays/Uint8Array.java +++ b/jso/apis/src/main/java/org/teavm/jso/typedarrays/Uint8Array.java @@ -16,27 +16,49 @@ package org.teavm.jso.typedarrays; import org.teavm.jso.JSBody; +import org.teavm.jso.JSClass; import org.teavm.jso.JSIndexer; -public abstract class Uint8Array extends ArrayBufferView { - @JSIndexer - public abstract short get(int index); +@JSClass +public class Uint8Array extends ArrayBufferView { + public Uint8Array(int length) { + } + + public Uint8Array(ArrayBuffer buffer) { + } + + public Uint8Array(ArrayBufferView buffer) { + } + + public Uint8Array(ArrayBuffer buffer, int offset, int length) { + } + + public Uint8Array(ArrayBuffer buffer, int offset) { + } @JSIndexer - public abstract void set(int index, short value); + public native short get(int index); + + @JSIndexer + public native void set(int index, short value); @JSBody(params = "length", script = "return new Uint8Array(length);") + @Deprecated public static native Uint8Array create(int length); @JSBody(params = "buffer", script = "return new Uint8Array(buffer);") + @Deprecated public static native Uint8Array create(ArrayBuffer buffer); @JSBody(params = "buffer", script = "return new Uint8Array(buffer);") + @Deprecated public static native Uint8Array create(ArrayBufferView buffer); @JSBody(params = { "buffer", "offset", "length" }, script = "return new Uint8Array(buffer, offset, length);") + @Deprecated public static native Uint8Array create(ArrayBuffer buffer, int offset, int length); @JSBody(params = { "buffer", "offset" }, script = "return new Uint8Array(buffer, offset);") + @Deprecated public static native Uint8Array create(ArrayBuffer buffer, int offset); } diff --git a/jso/apis/src/main/java/org/teavm/jso/typedarrays/Uint8ClampedArray.java b/jso/apis/src/main/java/org/teavm/jso/typedarrays/Uint8ClampedArray.java index 6fbdb6545..6d45b7d2e 100644 --- a/jso/apis/src/main/java/org/teavm/jso/typedarrays/Uint8ClampedArray.java +++ b/jso/apis/src/main/java/org/teavm/jso/typedarrays/Uint8ClampedArray.java @@ -16,26 +16,47 @@ package org.teavm.jso.typedarrays; import org.teavm.jso.JSBody; +import org.teavm.jso.JSClass; import org.teavm.jso.JSIndexer; -public abstract class Uint8ClampedArray extends ArrayBufferView { - @JSIndexer - public abstract short get(int index); +@JSClass +public class Uint8ClampedArray extends ArrayBufferView { + public Uint8ClampedArray(int length) { + } + + public Uint8ClampedArray(ArrayBuffer buffer) { + } + + public Uint8ClampedArray(ArrayBufferView buffer) { + } + + public Uint8ClampedArray(ArrayBuffer buffer, int offset, int length) { + } + + public Uint8ClampedArray(ArrayBuffer buffer, int offset) { + } @JSIndexer - public abstract void set(int index, int value); + public native short get(int index); + + @JSIndexer + public native void set(int index, int value); @JSBody(params = "length", script = "return new Uint8ClampedArray(length);") + @Deprecated public static native Uint8ClampedArray create(int length); @JSBody(params = "buffer", script = "return new Uint8ClampedArray(buffer);") + @Deprecated public static native Uint8ClampedArray create(ArrayBuffer buffer); @JSBody(params = "buffer", script = "return new Uint8ClampedArray(buffer);") + @Deprecated public static native Uint8ClampedArray create(ArrayBufferView buffer); @JSBody(params = { "buffer", "offset", "length" }, script = "return new " + "Uint8ClampedArray(buffer, offset, length);") + @Deprecated public static native Uint8ClampedArray create(ArrayBuffer buffer, int offset, int length); @JSBody(params = { "buffer", "offset" }, script = "return new Uint8ClampedArray(buffer, offset);") diff --git a/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioContext.java b/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioContext.java index 50718756b..b98a8e58a 100644 --- a/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioContext.java +++ b/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioContext.java @@ -17,6 +17,7 @@ package org.teavm.jso.webaudio; import org.teavm.jso.JSBody; import org.teavm.jso.JSByRef; +import org.teavm.jso.JSClass; import org.teavm.jso.JSObject; import org.teavm.jso.JSProperty; import org.teavm.jso.dom.events.EventListener; @@ -24,108 +25,110 @@ import org.teavm.jso.dom.html.HTMLMediaElement; import org.teavm.jso.typedarrays.ArrayBuffer; import org.teavm.jso.typedarrays.Float32Array; -public abstract class AudioContext implements JSObject { +@JSClass +public class AudioContext implements JSObject { public static final String STATE_SUSPENDED = "suspended"; public static final String STATE_RUNNING = "running"; public static final String STATE_CLOSE = "close"; @JSProperty - public abstract AudioDestinationNode getDestination(); + public native AudioDestinationNode getDestination(); @JSProperty - public abstract float getSampleRate(); + public native float getSampleRate(); @JSProperty - public abstract double getCurrentTime(); + public native double getCurrentTime(); @JSProperty - public abstract AudioListener getListener(); + public native AudioListener getListener(); @JSProperty - public abstract String getState(); + public native String getState(); @JSProperty("onstatechange") - public abstract void setOnStateChange(EventListener listener); + public native void setOnStateChange(EventListener listener); @JSProperty("onstatechange") - public abstract EventListener getOnStateChange(); + public native EventListener getOnStateChange(); - public abstract void suspend(); + public native void suspend(); - public abstract void resume(); + public native void resume(); - public abstract void close(); + public native void close(); - public abstract AudioBuffer createBuffer(int numberOfChannels, int length, float sampleRate); + public native AudioBuffer createBuffer(int numberOfChannels, int length, float sampleRate); - public abstract AudioBuffer decodeAudioData(ArrayBuffer audioData, DecodeSuccessCallback successCallback, + public native AudioBuffer decodeAudioData(ArrayBuffer audioData, DecodeSuccessCallback successCallback, DecodeErrorCallback errorCallback); - public abstract AudioBuffer decodeAudioData(ArrayBuffer audioData, DecodeSuccessCallback successCallback); + public native AudioBuffer decodeAudioData(ArrayBuffer audioData, DecodeSuccessCallback successCallback); - public abstract AudioBuffer decodeAudioData(ArrayBuffer audioData); + public native AudioBuffer decodeAudioData(ArrayBuffer audioData); - public abstract AudioBufferSourceNode createBufferSource(); + public native AudioBufferSourceNode createBufferSource(); - public abstract MediaElementAudioSourceNode createMediaElementSource(HTMLMediaElement mediaElement); + public native MediaElementAudioSourceNode createMediaElementSource(HTMLMediaElement mediaElement); - public abstract MediaStreamAudioSourceNode createMediaStreamSource(MediaStream mediaStream); + public native MediaStreamAudioSourceNode createMediaStreamSource(MediaStream mediaStream); - public abstract MediaStreamAudioDestinationNode createMediaStreamDestination(); + public native MediaStreamAudioDestinationNode createMediaStreamDestination(); - public abstract AudioWorker createAudioWorker(); + public native AudioWorker createAudioWorker(); - public abstract ScriptProcessorNode createScriptProcessor(int bufferSize, int numberOfInputChannels, + public native ScriptProcessorNode createScriptProcessor(int bufferSize, int numberOfInputChannels, int numberOfOutputChannels); - public abstract ScriptProcessorNode createScriptProcessor(int bufferSize, int numberOfInputChannels); + public native ScriptProcessorNode createScriptProcessor(int bufferSize, int numberOfInputChannels); - public abstract ScriptProcessorNode createScriptProcessor(int bufferSize); + public native ScriptProcessorNode createScriptProcessor(int bufferSize); - public abstract ScriptProcessorNode createScriptProcessor(); + public native ScriptProcessorNode createScriptProcessor(); - public abstract AnalyserNode createAnalyser(); + public native AnalyserNode createAnalyser(); - public abstract GainNode createGain(); + public native GainNode createGain(); - public abstract DelayNode createDelay(double maxDelayTime); + public native DelayNode createDelay(double maxDelayTime); - public abstract DelayNode createDelay(); + public native DelayNode createDelay(); - public abstract BiquadFilterNode createBiquadFilter(); + public native BiquadFilterNode createBiquadFilter(); - public abstract IIRFilterNode createIIRFilter(Float32Array feedforward, Float32Array feedback); + public native IIRFilterNode createIIRFilter(Float32Array feedforward, Float32Array feedback); - public abstract WaveShaperNode createWaveShaper(); + public native WaveShaperNode createWaveShaper(); - public abstract PannerNode createPanner(); + public native PannerNode createPanner(); - public abstract StereoPannerNode createStereoPanner(); + public native StereoPannerNode createStereoPanner(); - public abstract ConvolverNode createConvolver(); + public native ConvolverNode createConvolver(); - public abstract ChannelSplitterNode createChannelSplitter(int numberOfOutputs); + public native ChannelSplitterNode createChannelSplitter(int numberOfOutputs); - public abstract ChannelSplitterNode createChannelSplitter(); + public native ChannelSplitterNode createChannelSplitter(); - public abstract ChannelMergerNode createChannelMerger(int numberOfInputs); + public native ChannelMergerNode createChannelMerger(int numberOfInputs); - public abstract ChannelMergerNode createChannelMerger(); + public native ChannelMergerNode createChannelMerger(); - public abstract DynamicsCompressorNode createDynamicsCompressor(); + public native DynamicsCompressorNode createDynamicsCompressor(); - public abstract OscillatorNode createOscillator(); + public native OscillatorNode createOscillator(); - public abstract PeriodicWave createPeriodicWave(Float32Array real, Float32Array image, + public native PeriodicWave createPeriodicWave(Float32Array real, Float32Array image, PeriodicWaveConstraints constraints); - public abstract PeriodicWave createPeriodicWave(@JSByRef float[] real, @JSByRef float[] image, + public native PeriodicWave createPeriodicWave(@JSByRef float[] real, @JSByRef float[] image, PeriodicWaveConstraints constraints); - public abstract PeriodicWave createPeriodicWave(Float32Array real, Float32Array image); + public native PeriodicWave createPeriodicWave(Float32Array real, Float32Array image); - public abstract PeriodicWave createPeriodicWave(@JSByRef float[] real, @JSByRef float[] image); + public native PeriodicWave createPeriodicWave(@JSByRef float[] real, @JSByRef float[] image); - @JSBody(script = "var Context = window.AudioContext || window.webkitAudioContext; return new Context();") + @JSBody(script = "return new Context();") + @Deprecated public static native AudioContext create(); } diff --git a/jso/apis/src/main/java/org/teavm/jso/webaudio/OfflineAudioContext.java b/jso/apis/src/main/java/org/teavm/jso/webaudio/OfflineAudioContext.java index f81d634a2..b98a036d9 100644 --- a/jso/apis/src/main/java/org/teavm/jso/webaudio/OfflineAudioContext.java +++ b/jso/apis/src/main/java/org/teavm/jso/webaudio/OfflineAudioContext.java @@ -15,20 +15,22 @@ */ package org.teavm.jso.webaudio; +import org.teavm.jso.JSClass; import org.teavm.jso.JSProperty; import org.teavm.jso.dom.events.EventListener; -public abstract class OfflineAudioContext extends AudioContext { +@JSClass +public class OfflineAudioContext extends AudioContext { @JSProperty("oncomplete") - public abstract void setOnComplete(EventListener event); + public native void setOnComplete(EventListener event); @JSProperty("oncomplete") - public abstract EventListener getOnComplete(); + public native EventListener getOnComplete(); - public abstract AudioBuffer startRendering(); + public native AudioBuffer startRendering(); @Override - public abstract void resume(); + public native void resume(); - public abstract void suspend(double suspendTime); + public native void suspend(double suspendTime); } diff --git a/jso/apis/src/main/java/org/teavm/jso/websocket/WebSocket.java b/jso/apis/src/main/java/org/teavm/jso/websocket/WebSocket.java index b58b6c632..ffbb4c521 100644 --- a/jso/apis/src/main/java/org/teavm/jso/websocket/WebSocket.java +++ b/jso/apis/src/main/java/org/teavm/jso/websocket/WebSocket.java @@ -16,6 +16,7 @@ package org.teavm.jso.websocket; import org.teavm.jso.JSBody; +import org.teavm.jso.JSClass; import org.teavm.jso.JSObject; import org.teavm.jso.JSProperty; import org.teavm.jso.dom.events.Event; @@ -24,60 +25,73 @@ import org.teavm.jso.dom.events.MessageEvent; import org.teavm.jso.typedarrays.ArrayBuffer; import org.teavm.jso.typedarrays.ArrayBufferView; -public abstract class WebSocket implements JSObject { +@JSClass +public class WebSocket implements JSObject { + public WebSocket(String url) { + } + + public WebSocket(String url, String protocols) { + } + + public WebSocket(String url, String[] protocols) { + } + @JSProperty("onclose") - public abstract void onClose(EventListener eventListener); + public native void onClose(EventListener eventListener); @JSProperty("onerror") - public abstract void onError(EventListener eventListener); + public native void onError(EventListener eventListener); @JSProperty("onmessage") - public abstract void onMessage(EventListener eventListener); + public native void onMessage(EventListener eventListener); @JSProperty("onopen") - public abstract void onOpen(EventListener eventListener); + public native void onOpen(EventListener eventListener); @JSBody(params = "url", script = "return new WebSocket(url);") + @Deprecated public static native WebSocket create(String url); @JSBody(params = { "url", "protocols" }, script = "return new WebSocket(url, protocols);") + @Deprecated public static native WebSocket create(String url, String protocols); @JSBody(params = { "url", "protocols" }, script = "return new WebSocket(url, protocols);") + @Deprecated public static native WebSocket create(String url, String[] protocols); - public abstract void close(); + public native void close(); - public abstract void close(int code); + public native void close(int code); - public abstract void close(int code, String reason); + public native void close(int code, String reason); - public abstract void send(String data); + public native void send(String data); - public abstract void send(ArrayBuffer data); + public native void send(ArrayBuffer data); - public abstract void send(ArrayBufferView data); + public native void send(ArrayBufferView data); @JSProperty - public abstract String getBinaryType(); + public native String getBinaryType(); @JSProperty - public abstract void setBinaryType(String binaryType); + public native void setBinaryType(String binaryType); @JSProperty - public abstract int getBufferedAmount(); + public native int getBufferedAmount(); @JSProperty - public abstract String getExtensions(); + public native String getExtensions(); @JSProperty - public abstract String getProtocol(); + public native String getProtocol(); @JSProperty - public abstract int getReadyState(); + public native int getReadyState(); @JSProperty - public abstract String getUrl(); + public native String getUrl(); @JSBody(script = "return typeof WebSocket !== 'undefined';") public static native boolean isSupported(); diff --git a/jso/apis/src/main/java/org/teavm/jso/workers/SharedWorker.java b/jso/apis/src/main/java/org/teavm/jso/workers/SharedWorker.java index c8165d280..ccd63a433 100644 --- a/jso/apis/src/main/java/org/teavm/jso/workers/SharedWorker.java +++ b/jso/apis/src/main/java/org/teavm/jso/workers/SharedWorker.java @@ -17,11 +17,36 @@ package org.teavm.jso.workers; import org.teavm.jso.JSBody; import org.teavm.jso.JSProperty; +import org.teavm.jso.dom.events.ErrorEvent; +import org.teavm.jso.dom.events.Event; +import org.teavm.jso.dom.events.EventListener; + +public class SharedWorker implements AbstractWorker { + public SharedWorker(String url) { + } -public abstract class SharedWorker implements AbstractWorker { @JSBody(params = "url", script = "return new SharedWorker(url);") + @Deprecated public static native Worker create(String url); @JSProperty - public abstract MessagePort getPort(); + public native MessagePort getPort(); + + @Override + public native void onError(EventListener listener); + + @Override + public native void addEventListener(String type, EventListener listener, boolean useCapture); + + @Override + public native void addEventListener(String type, EventListener listener); + + @Override + public native void removeEventListener(String type, EventListener listener, boolean useCapture); + + @Override + public native void removeEventListener(String type, EventListener listener); + + @Override + public native boolean dispatchEvent(Event evt); } diff --git a/jso/apis/src/main/java/org/teavm/jso/workers/Worker.java b/jso/apis/src/main/java/org/teavm/jso/workers/Worker.java index 95876f9a4..63beb5e4b 100644 --- a/jso/apis/src/main/java/org/teavm/jso/workers/Worker.java +++ b/jso/apis/src/main/java/org/teavm/jso/workers/Worker.java @@ -16,18 +16,44 @@ package org.teavm.jso.workers; import org.teavm.jso.JSBody; +import org.teavm.jso.JSClass; import org.teavm.jso.JSProperty; +import org.teavm.jso.dom.events.ErrorEvent; +import org.teavm.jso.dom.events.Event; import org.teavm.jso.dom.events.EventListener; import org.teavm.jso.dom.events.MessageEvent; -public abstract class Worker implements AbstractWorker { +@JSClass +public class Worker implements AbstractWorker { + public Worker(String url) { + } + @JSBody(params = "url", script = "return new Worker(url);") + @Deprecated public static native Worker create(String url); @JSProperty("onmessage") - public abstract void onMessage(EventListener listener); + public native void onMessage(EventListener listener); - public abstract void postMessage(Object message); + public native void postMessage(Object message); - public abstract void terminate(); + public native void terminate(); + + @Override + public native void onError(EventListener listener); + + @Override + public native void addEventListener(String type, EventListener listener, boolean useCapture); + + @Override + public native void addEventListener(String type, EventListener listener); + + @Override + public native void removeEventListener(String type, EventListener listener, boolean useCapture); + + @Override + public native void removeEventListener(String type, EventListener listener); + + @Override + public native boolean dispatchEvent(Event evt); } diff --git a/jso/core/src/main/java/org/teavm/jso/JSModule.java b/jso/core/src/main/java/org/teavm/jso/JSModule.java new file mode 100644 index 000000000..6715bd4cd --- /dev/null +++ b/jso/core/src/main/java/org/teavm/jso/JSModule.java @@ -0,0 +1,27 @@ +/* + * Copyright 2024 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. + */ +package org.teavm.jso; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface JSModule { + String value(); +} diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/JS.java b/jso/impl/src/main/java/org/teavm/jso/impl/JS.java index 76b762acf..3a53d789e 100644 --- a/jso/impl/src/main/java/org/teavm/jso/impl/JS.java +++ b/jso/impl/src/main/java/org/teavm/jso/impl/JS.java @@ -140,7 +140,7 @@ final class JS { if (array == null) { return null; } - JSArray result = JSArray.create(array.length); + var result = new JSArray(array.length); for (int i = 0; i < array.length; ++i) { result.set(i, array[i]); } @@ -155,7 +155,7 @@ final class JS { if (array == null) { return null; } - JSArray result = JSArray.create(array.length); + var result = new JSArray(array.length); for (int i = 0; i < array.length; ++i) { result.set(i, f.apply(array[i])); } @@ -178,7 +178,7 @@ final class JS { if (array == null) { return null; } - JSArray result = JSArray.create(array.length); + var result = new JSArray(array.length); for (int i = 0; i < array.length; ++i) { result.set(i, JSBoolean.valueOf(array[i])); } @@ -193,7 +193,7 @@ final class JS { if (array == null) { return null; } - JSArray result = JSArray.create(array.length); + var result = new JSArray(array.length); for (int i = 0; i < array.length; ++i) { result.set(i, JSNumber.valueOf(array[i])); } @@ -208,7 +208,7 @@ final class JS { if (array == null) { return null; } - JSArray result = JSArray.create(array.length); + var result = new JSArray(array.length); for (int i = 0; i < array.length; ++i) { result.set(i, JSNumber.valueOf(array[i])); } @@ -223,7 +223,7 @@ final class JS { if (array == null) { return null; } - JSArray result = JSArray.create(array.length); + var result = new JSArray(array.length); for (int i = 0; i < array.length; ++i) { result.set(i, JSNumber.valueOf(array[i])); } @@ -238,7 +238,7 @@ final class JS { if (array == null) { return null; } - JSArray result = JSArray.create(array.length); + var result = new JSArray(array.length); for (int i = 0; i < array.length; ++i) { result.set(i, JSNumber.valueOf(array[i])); } @@ -253,7 +253,7 @@ final class JS { if (array == null) { return null; } - JSArray result = JSArray.create(array.length); + var result = new JSArray(array.length); for (int i = 0; i < array.length; ++i) { result.set(i, JSString.valueOf(array[i])); } @@ -268,7 +268,7 @@ final class JS { if (array == null) { return null; } - JSArray result = JSArray.create(array.length); + var result = new JSArray(array.length); for (int i = 0; i < array.length; ++i) { result.set(i, JSNumber.valueOf(array[i])); } @@ -283,7 +283,7 @@ final class JS { if (array == null) { return null; } - JSArray result = JSArray.create(array.length); + var result = new JSArray(array.length); for (int i = 0; i < array.length; ++i) { result.set(i, JSNumber.valueOf(array[i])); } @@ -516,6 +516,71 @@ final class JS { JSObject d, JSObject e, JSObject f, JSObject g, JSObject h, JSObject i, JSObject j, JSObject k, JSObject l, JSObject m); + @InjectedBy(JSNativeInjector.class) + @PluggableDependency(JSNativeInjector.class) + public static native JSObject construct(JSObject cls); + + @InjectedBy(JSNativeInjector.class) + @PluggableDependency(JSNativeInjector.class) + public static native JSObject construct(JSObject cls, JSObject a); + + @InjectedBy(JSNativeInjector.class) + @PluggableDependency(JSNativeInjector.class) + public static native JSObject construct(JSObject cls, JSObject a, JSObject b); + + @InjectedBy(JSNativeInjector.class) + @PluggableDependency(JSNativeInjector.class) + public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c); + + @InjectedBy(JSNativeInjector.class) + @PluggableDependency(JSNativeInjector.class) + public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c, JSObject d); + + @InjectedBy(JSNativeInjector.class) + @PluggableDependency(JSNativeInjector.class) + public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e); + + @InjectedBy(JSNativeInjector.class) + @PluggableDependency(JSNativeInjector.class) + public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e, + JSObject f); + + @InjectedBy(JSNativeInjector.class) + @PluggableDependency(JSNativeInjector.class) + public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e, + JSObject f, JSObject g); + + @InjectedBy(JSNativeInjector.class) + @PluggableDependency(JSNativeInjector.class) + public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e, + JSObject f, JSObject g, JSObject h); + + @InjectedBy(JSNativeInjector.class) + @PluggableDependency(JSNativeInjector.class) + public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e, + JSObject f, JSObject g, JSObject h, JSObject i); + + @InjectedBy(JSNativeInjector.class) + @PluggableDependency(JSNativeInjector.class) + public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e, + JSObject f, JSObject g, JSObject h, JSObject i, JSObject j); + + @InjectedBy(JSNativeInjector.class) + @PluggableDependency(JSNativeInjector.class) + public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e, + JSObject f, JSObject g, JSObject h, JSObject i, JSObject j, JSObject k); + + @InjectedBy(JSNativeInjector.class) + @PluggableDependency(JSNativeInjector.class) + public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e, + JSObject f, JSObject g, JSObject h, JSObject i, JSObject j, JSObject k, JSObject l); + + @InjectedBy(JSNativeInjector.class) + @PluggableDependency(JSNativeInjector.class) + public static native JSObject construct(JSObject cls, JSObject a, JSObject b, JSObject c, JSObject d, JSObject e, + JSObject f, JSObject g, JSObject h, JSObject i, JSObject j, JSObject k, JSObject l, JSObject m); + + @InjectedBy(JSNativeInjector.class) @JSBody(params = { "instance", "index" }, script = "return instance[index];") public static native JSObject get(JSObject instance, JSObject index); @@ -541,4 +606,12 @@ final class JS { @GeneratedBy(JSNativeGenerator.class) @PluggableDependency(JSNativeInjector.class) public static native JSObject functionAsObject(JSObject instance, JSObject property); + + @InjectedBy(JSNativeInjector.class) + @NoSideEffects + public static native JSObject global(String name); + + @InjectedBy(JSNativeInjector.class) + @NoSideEffects + public static native JSObject importModule(String name); } diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/JSAliasRenderer.java b/jso/impl/src/main/java/org/teavm/jso/impl/JSAliasRenderer.java index 01c7678b0..4b65aa810 100644 --- a/jso/impl/src/main/java/org/teavm/jso/impl/JSAliasRenderer.java +++ b/jso/impl/src/main/java/org/teavm/jso/impl/JSAliasRenderer.java @@ -239,7 +239,7 @@ class JSAliasRenderer implements RendererListener, VirtualMethodContributor { return true; } for (var method : cls.getMethods()) { - if (!method.hasModifier(ElementModifier.STATIC) && getPublicAlias(method) != null) { + if (getPublicAlias(method) != null) { return true; } } diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/JSAnnotationCache.java b/jso/impl/src/main/java/org/teavm/jso/impl/JSAnnotationCache.java new file mode 100644 index 000000000..b6ca2ba6a --- /dev/null +++ b/jso/impl/src/main/java/org/teavm/jso/impl/JSAnnotationCache.java @@ -0,0 +1,128 @@ +/* + * Copyright 2024 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. + */ +package org.teavm.jso.impl; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import org.teavm.diagnostics.Diagnostics; +import org.teavm.model.AccessLevel; +import org.teavm.model.CallLocation; +import org.teavm.model.ClassReaderSource; +import org.teavm.model.ElementModifier; +import org.teavm.model.MethodReader; +import org.teavm.model.MethodReference; + +abstract class JSAnnotationCache { + private ClassReaderSource classes; + protected Diagnostics diagnostics; + private Map> data = new HashMap<>(); + + JSAnnotationCache(ClassReaderSource classes, Diagnostics diagnostics) { + this.classes = classes; + this.diagnostics = diagnostics; + } + + T get(MethodReference methodReference, CallLocation location) { + var result = getValue(methodReference, location); + return result != null ? result.annotation : null; + } + + private Value getValue(MethodReference methodReference, CallLocation location) { + var result = data.get(methodReference); + if (result == null) { + result = extract(methodReference, location); + data.put(methodReference, result); + } + return result; + } + + private Value extract(MethodReference methodReference, CallLocation location) { + var cls = classes.get(methodReference.getClassName()); + if (cls == null) { + return new Value<>(null, methodReference); + } + var method = cls.getMethod(methodReference.getDescriptor()); + if (method == null || method.hasModifier(ElementModifier.STATIC) + || method.getLevel() == AccessLevel.PRIVATE) { + for (var candidateMethod : cls.getMethods()) { + if (candidateMethod.getName().equals(methodReference.getName()) + && !candidateMethod.hasModifier(ElementModifier.STATIC) + && !candidateMethod.hasModifier(ElementModifier.FINAL) + && candidateMethod.getLevel() != AccessLevel.PRIVATE + && Arrays.equals(candidateMethod.getParameterTypes(), methodReference.getParameterTypes())) { + method = candidateMethod; + break; + } + } + } + + if (method != null) { + methodReference = method.getReference(); + var annotation = take(method, location); + if (annotation != null) { + return new Value<>(annotation, methodReference); + } + } + + var candidates = new HashMap(); + if (cls.getParent() != null) { + var value = getValue(new MethodReference(cls.getParent(), methodReference.getDescriptor()), location); + if (value.annotation != null) { + candidates.put(value.source, value.annotation); + } + } + for (var itf : cls.getInterfaces()) { + var value = getValue(new MethodReference(itf, methodReference.getDescriptor()), location); + if (value != null) { + candidates.put(value.source, value.annotation); + } + } + if (candidates.isEmpty()) { + return new Value<>(null, methodReference); + } + if (candidates.size() == 1) { + var entry = candidates.entrySet().iterator().next(); + return new Value<>(entry.getValue(), entry.getKey()); + } + + T annot = null; + MethodReference lastMethod = null; + for (var entry : candidates.entrySet()) { + if (annot != null && !annot.equals(entry.getValue())) { + diagnostics.error(location, "Method '{{m0}}' has inconsistent JS annotations from overridden " + + "methods '{{m1}}' and '{{m2}}', so it should be annotated explicitly", + methodReference, lastMethod, entry.getKey()); + return new Value<>(null, methodReference); + } + annot = entry.getValue(); + lastMethod = entry.getKey(); + } + return new Value<>(annot, methodReference); + } + + protected abstract T take(MethodReader method, CallLocation location); + + private static class Value { + final T annotation; + final MethodReference source; + + Value(T annotation, MethodReference source) { + this.annotation = annotation; + this.source = source; + } + } +} diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/JSClassProcessor.java b/jso/impl/src/main/java/org/teavm/jso/impl/JSClassProcessor.java index b7787ad97..461d00dea 100644 --- a/jso/impl/src/main/java/org/teavm/jso/impl/JSClassProcessor.java +++ b/jso/impl/src/main/java/org/teavm/jso/impl/JSClassProcessor.java @@ -18,6 +18,7 @@ package org.teavm.jso.impl; import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -35,10 +36,7 @@ import org.teavm.interop.NoSideEffects; import org.teavm.jso.JSBody; import org.teavm.jso.JSByRef; import org.teavm.jso.JSFunctor; -import org.teavm.jso.JSIndexer; -import org.teavm.jso.JSMethod; import org.teavm.jso.JSObject; -import org.teavm.jso.JSProperty; import org.teavm.model.AnnotationContainerReader; import org.teavm.model.AnnotationHolder; import org.teavm.model.AnnotationReader; @@ -63,6 +61,7 @@ import org.teavm.model.instructions.AssignInstruction; import org.teavm.model.instructions.CastInstruction; import org.teavm.model.instructions.ClassConstantInstruction; import org.teavm.model.instructions.ConstructArrayInstruction; +import org.teavm.model.instructions.ConstructInstruction; import org.teavm.model.instructions.ExitInstruction; import org.teavm.model.instructions.GetElementInstruction; import org.teavm.model.instructions.IntegerConstantInstruction; @@ -91,6 +90,8 @@ class JSClassProcessor { private final JSBodyRepository repository; private final JavaInvocationProcessor javaInvocationProcessor; private Program program; + private int[] variableAliases; + private boolean[] nativeConstructedObjects; private JSTypeInference types; private final List replacement = new ArrayList<>(); private final JSTypeHelper typeHelper; @@ -98,6 +99,7 @@ class JSClassProcessor { private final Map overriddenMethodCache = new HashMap<>(); private JSValueMarshaller marshaller; private IncrementalDependencyRegistration incrementalCache; + private JSImportAnnotationCache annotationCache; JSClassProcessor(ClassReaderSource classSource, JSTypeHelper typeHelper, JSBodyRepository repository, Diagnostics diagnostics, IncrementalDependencyRegistration incrementalCache) { @@ -107,6 +109,8 @@ class JSClassProcessor { this.diagnostics = diagnostics; this.incrementalCache = incrementalCache; javaInvocationProcessor = new JavaInvocationProcessor(typeHelper, repository, classSource, diagnostics); + + annotationCache = new JSImportAnnotationCache(classSource, diagnostics); } public ClassReaderSource getClassSource() { @@ -220,6 +224,48 @@ class JSClassProcessor { private void setCurrentProgram(Program program) { this.program = program; marshaller = new JSValueMarshaller(diagnostics, typeHelper, classSource, program, replacement); + findVariableAliases(); + } + + private void findVariableAliases() { + if (program == null) { + return; + } + variableAliases = new int[program.variableCount()]; + nativeConstructedObjects = new boolean[program.variableCount()]; + var resolved = new boolean[program.variableCount()]; + Arrays.fill(resolved, true); + for (var i = 0; i < variableAliases.length; ++i) { + variableAliases[i] = i; + } + for (var block : program.getBasicBlocks()) { + for (var instruction : block) { + if (instruction instanceof AssignInstruction) { + var assign = (AssignInstruction) instruction; + var from = assign.getAssignee().getIndex(); + var to = assign.getReceiver().getIndex(); + variableAliases[to] = from; + resolved[assign.getAssignee().getIndex()] = true; + } else if (instruction instanceof ConstructInstruction) { + var construct = (ConstructInstruction) instruction; + if (typeHelper.isJavaScriptClass(construct.getType())) { + nativeConstructedObjects[construct.getReceiver().getIndex()] = true; + } + } + } + } + for (var i = 0; i < variableAliases.length; ++i) { + getVariableAlias(i, resolved); + } + } + + private int getVariableAlias(int index, boolean[] resolved) { + if (resolved[index]) { + return variableAliases[index]; + } + resolved[index] = true; + variableAliases[index] = getVariableAlias(variableAliases[index], resolved); + return variableAliases[index]; } void processProgram(MethodHolder methodToProcess) { @@ -266,9 +312,28 @@ class JSClassProcessor { methodToProcess.getResultType())); } else if (insn instanceof ClassConstantInstruction) { processClassConstant((ClassConstantInstruction) insn); + } else if (insn instanceof ConstructInstruction) { + processConstructObject((ConstructInstruction) insn); + } else if (insn instanceof AssignInstruction) { + var assign = (AssignInstruction) insn; + var index = variableAliases[assign.getReceiver().getIndex()]; + if (nativeConstructedObjects[index]) { + assign.delete(); + } } } } + + var varMapper = new InstructionVariableMapper(v -> { + if (v.getIndex() < nativeConstructedObjects.length + && nativeConstructedObjects[variableAliases[v.getIndex()]]) { + return program.variableAt(variableAliases[v.getIndex()]); + } + return v; + }); + for (var block : program.getBasicBlocks()) { + varMapper.apply(block); + } } private void processInvokeArgs(InvokeInstruction invoke, MethodReader methodToInvoke) { @@ -346,6 +411,12 @@ class JSClassProcessor { insn.setConstant(processType(insn.getConstant())); } + private void processConstructObject(ConstructInstruction insn) { + if (nativeConstructedObjects[insn.getReceiver().getIndex()]) { + insn.delete(); + } + } + private ValueType processType(ValueType type) { return processType(typeHelper, type); } @@ -485,11 +556,21 @@ class JSClassProcessor { return false; } - if (method.hasModifier(ElementModifier.STATIC)) { - return false; + if (method.getName().equals("")) { + return processConstructor(method, callLocation, invoke); } + var isStatic = method.hasModifier(ElementModifier.STATIC); + if (isStatic) { + switch (method.getOwnerName()) { + case "org.teavm.platform.PlatformQueue": + return false; + } + } if (method.getProgram() != null && method.getProgram().basicBlockCount() > 0) { + if (isStatic) { + return false; + } MethodReader overridden = getOverriddenMethod(method); if (overridden != null) { diagnostics.error(callLocation, "JS final method {{m0}} overrides {{m1}}. " @@ -511,13 +592,18 @@ class JSClassProcessor { return false; } - if (method.getAnnotations().get(JSProperty.class.getName()) != null) { - return processProperty(method, callLocation, invoke); - } else if (method.getAnnotations().get(JSIndexer.class.getName()) != null) { - return processIndexer(method, callLocation, invoke); - } else { - return processMethod(method, callLocation, invoke); + var annot = annotationCache.get(method.getReference(), callLocation); + if (annot != null) { + switch (annot.kind) { + case PROPERTY: + return processProperty(method, annot.name, callLocation, invoke); + case INDEXER: + return processIndexer(method, callLocation, invoke); + case METHOD: + return processMethod(method, annot.name, callLocation, invoke); + } } + return processMethod(method, null, callLocation, invoke); } private boolean processJSBodyInvocation(MethodReader method, CallLocation callLocation, InvokeInstruction invoke, @@ -577,16 +663,17 @@ class JSClassProcessor { return true; } - private boolean processProperty(MethodReader method, CallLocation callLocation, InvokeInstruction invoke) { + private boolean processProperty(MethodReader method, String suggestedName, CallLocation callLocation, + InvokeInstruction invoke) { boolean pure = method.getAnnotations().get(NO_SIDE_EFFECTS) != null; - if (isProperGetter(method)) { - String propertyName = extractSuggestedPropertyName(method); + if (isProperGetter(method, suggestedName)) { + var propertyName = suggestedName; if (propertyName == null) { propertyName = method.getName().charAt(0) == 'i' ? cutPrefix(method.getName(), 2) : cutPrefix(method.getName(), 3); } Variable result = invoke.getReceiver() != null ? program.createVariable() : null; - addPropertyGet(propertyName, invoke.getInstance(), result, invoke.getLocation(), pure); + addPropertyGet(propertyName, getCallTarget(invoke), result, invoke.getLocation(), pure); if (result != null) { result = marshaller.unwrapReturnValue(callLocation, result, method.getResultType(), false, canBeOnlyJava(invoke.getReceiver())); @@ -594,15 +681,15 @@ class JSClassProcessor { } return true; } - if (isProperSetter(method)) { - String propertyName = extractSuggestedPropertyName(method); + if (isProperSetter(method, suggestedName)) { + var propertyName = suggestedName; if (propertyName == null) { propertyName = cutPrefix(method.getName(), 3); } var value = invoke.getArguments().get(0); value = marshaller.wrapArgument(callLocation, value, method.parameterType(0), types.typeOf(value), false); - addPropertySet(propertyName, invoke.getInstance(), value, invoke.getLocation(), pure); + addPropertySet(propertyName, getCallTarget(invoke), value, invoke.getLocation(), pure); return true; } diagnostics.error(callLocation, "Method {{m0}} is not a proper native JavaScript property " @@ -610,17 +697,11 @@ class JSClassProcessor { return false; } - private String extractSuggestedPropertyName(MethodReader method) { - AnnotationReader annot = method.getAnnotations().get(JSProperty.class.getName()); - AnnotationValue value = annot.getValue("value"); - return value != null ? value.getString() : null; - } - private boolean processIndexer(MethodReader method, CallLocation callLocation, InvokeInstruction invoke) { if (isProperGetIndexer(method.getDescriptor())) { Variable result = invoke.getReceiver() != null ? program.createVariable() : null; var index = invoke.getArguments().get(0); - addIndexerGet(invoke.getInstance(), marshaller.wrapArgument(callLocation, index, + addIndexerGet(getCallTarget(invoke), marshaller.wrapArgument(callLocation, index, method.parameterType(0), types.typeOf(index), false), result, invoke.getLocation()); if (result != null) { result = marshaller.unwrapReturnValue(callLocation, result, method.getResultType(), false, @@ -635,7 +716,7 @@ class JSClassProcessor { var value = invoke.getArguments().get(1); value = marshaller.wrapArgument(callLocation, value, method.parameterType(1), types.typeOf(value), false); - addIndexerSet(invoke.getInstance(), index, value, invoke.getLocation()); + addIndexerSet(getCallTarget(invoke), index, value, invoke.getLocation()); return true; } diagnostics.error(callLocation, "Method {{m0}} is not a proper native JavaScript indexer " @@ -678,17 +759,11 @@ class JSClassProcessor { return type != JSType.JS && type != JSType.MIXED; } - private boolean processMethod(MethodReader method, CallLocation callLocation, InvokeInstruction invoke) { - String name = method.getName(); - - AnnotationReader methodAnnot = method.getAnnotations().get(JSMethod.class.getName()); - if (methodAnnot != null) { - AnnotationValue redefinedMethodName = methodAnnot.getValue("value"); - if (redefinedMethodName != null) { - name = redefinedMethodName.getString(); - } + private boolean processMethod(MethodReader method, String name, CallLocation callLocation, + InvokeInstruction invoke) { + if (name == null) { + name = method.getName(); } - boolean[] byRefParams = new boolean[method.parameterCount() + 1]; if (!validateSignature(method, callLocation, byRefParams)) { return false; @@ -700,7 +775,7 @@ class JSClassProcessor { newInvoke.setType(InvocationType.SPECIAL); newInvoke.setReceiver(result); List newArguments = new ArrayList<>(); - newArguments.add(invoke.getInstance()); + newArguments.add(getCallTarget(invoke)); newArguments.add(marshaller.addStringWrap(marshaller.addString(name, invoke.getLocation()), invoke.getLocation())); newInvoke.setLocation(invoke.getLocation()); @@ -721,6 +796,38 @@ class JSClassProcessor { return true; } + private Variable getCallTarget(InvokeInstruction invoke) { + return invoke.getInstance() != null + ? invoke.getInstance() + : marshaller.classRef(invoke.getMethod().getClassName(), invoke.getLocation()); + } + + private boolean processConstructor(MethodReader method, CallLocation callLocation, InvokeInstruction invoke) { + var byRefParams = new boolean[method.parameterCount() + 1]; + if (!validateSignature(method, callLocation, byRefParams)) { + return false; + } + + var result = program.variableAt(variableAliases[invoke.getInstance().getIndex()]); + var newInvoke = new InvokeInstruction(); + newInvoke.setMethod(JSMethods.construct(method.parameterCount())); + newInvoke.setType(InvocationType.SPECIAL); + newInvoke.setReceiver(result); + var newArguments = new ArrayList(); + newArguments.add(marshaller.classRef(invoke.getMethod().getClassName(), invoke.getLocation())); + newInvoke.setLocation(invoke.getLocation()); + for (int i = 0; i < invoke.getArguments().size(); ++i) { + var arg = invoke.getArguments().get(i); + arg = marshaller.wrapArgument(callLocation, arg, + method.parameterType(i), types.typeOf(arg), byRefParams[i]); + newArguments.add(arg); + } + newInvoke.setArguments(newArguments.toArray(new Variable[0])); + replacement.add(newInvoke); + + return true; + } + private void requireJSBody(Diagnostics diagnostics, MethodReader methodToProcess) { if (!repository.processedMethods.add(methodToProcess.getReference())) { return; @@ -997,11 +1104,11 @@ class JSClassProcessor { return null; } - private boolean isProperGetter(MethodReader method) { + private boolean isProperGetter(MethodReader method, String suggestedName) { if (method.parameterCount() > 0 || !typeHelper.isSupportedType(method.getResultType())) { return false; } - if (extractSuggestedPropertyName(method) != null) { + if (suggestedName != null) { return true; } @@ -1013,13 +1120,13 @@ class JSClassProcessor { return isProperPrefix(method.getName(), "get"); } - private boolean isProperSetter(MethodReader method) { + private boolean isProperSetter(MethodReader method, String suggestedName) { if (method.parameterCount() != 1 || !typeHelper.isSupportedType(method.parameterType(0)) || method.getResultType() != ValueType.VOID) { return false; } - return extractSuggestedPropertyName(method) != null || isProperPrefix(method.getName(), "set"); + return suggestedName != null || isProperPrefix(method.getName(), "set"); } private boolean isProperPrefix(String name, String prefix) { diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/JSImportAnnotationCache.java b/jso/impl/src/main/java/org/teavm/jso/impl/JSImportAnnotationCache.java new file mode 100644 index 000000000..70cdd4d75 --- /dev/null +++ b/jso/impl/src/main/java/org/teavm/jso/impl/JSImportAnnotationCache.java @@ -0,0 +1,66 @@ +/* + * Copyright 2024 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. + */ +package org.teavm.jso.impl; + +import java.util.Arrays; +import org.teavm.diagnostics.Diagnostics; +import org.teavm.jso.JSIndexer; +import org.teavm.jso.JSMethod; +import org.teavm.jso.JSProperty; +import org.teavm.model.AnnotationReader; +import org.teavm.model.CallLocation; +import org.teavm.model.ClassReaderSource; +import org.teavm.model.MethodReader; + +class JSImportAnnotationCache extends JSAnnotationCache { + JSImportAnnotationCache(ClassReaderSource classes, Diagnostics diagnostics) { + super(classes, diagnostics); + } + + @Override + protected JSImportDescriptor take(MethodReader method, CallLocation location) { + var propertyAnnot = method.getAnnotations().get(JSProperty.class.getName()); + var indexerAnnot = method.getAnnotations().get(JSIndexer.class.getName()); + var methodAnnot = method.getAnnotations().get(JSMethod.class.getName()); + var found = false; + for (var annot : Arrays.asList(propertyAnnot, indexerAnnot, methodAnnot)) { + if (annot != null) { + if (!found) { + found = true; + } else { + diagnostics.error(location, "@JSProperty, @JSIndexer and @JSMethod are mutually exclusive " + + "and can't appear simultaneously on {{m}}", method.getReference()); + return null; + } + } + } + if (propertyAnnot != null) { + return new JSImportDescriptor(JSImportKind.PROPERTY, extractValue(propertyAnnot)); + } + if (indexerAnnot != null) { + return new JSImportDescriptor(JSImportKind.INDEXER, null); + } + if (methodAnnot != null) { + return new JSImportDescriptor(JSImportKind.METHOD, extractValue(methodAnnot)); + } + return null; + } + + private String extractValue(AnnotationReader annotation) { + var value = annotation.getValue("value"); + return value != null ? value.getString() : null; + } +} diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/JSImportDescriptor.java b/jso/impl/src/main/java/org/teavm/jso/impl/JSImportDescriptor.java new file mode 100644 index 000000000..28e169780 --- /dev/null +++ b/jso/impl/src/main/java/org/teavm/jso/impl/JSImportDescriptor.java @@ -0,0 +1,45 @@ +/* + * Copyright 2024 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. + */ +package org.teavm.jso.impl; + +import java.util.Objects; + +class JSImportDescriptor { + final JSImportKind kind; + final String name; + + JSImportDescriptor(JSImportKind kind, String name) { + this.kind = kind; + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof JSImportDescriptor)) { + return false; + } + var that = (JSImportDescriptor) o; + return kind == that.kind && Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + return Objects.hash(kind, name); + } +} diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/JSImportKind.java b/jso/impl/src/main/java/org/teavm/jso/impl/JSImportKind.java new file mode 100644 index 000000000..71b0c4be9 --- /dev/null +++ b/jso/impl/src/main/java/org/teavm/jso/impl/JSImportKind.java @@ -0,0 +1,22 @@ +/* + * Copyright 2024 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. + */ +package org.teavm.jso.impl; + +enum JSImportKind { + PROPERTY, + INDEXER, + METHOD +} diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/JSMethods.java b/jso/impl/src/main/java/org/teavm/jso/impl/JSMethods.java index 542ca2cdd..d0374c378 100644 --- a/jso/impl/src/main/java/org/teavm/jso/impl/JSMethods.java +++ b/jso/impl/src/main/java/org/teavm/jso/impl/JSMethods.java @@ -114,15 +114,24 @@ final class JSMethods { public static final MethodReference FUNCTION_AS_OBJECT = new MethodReference(JS.class, "functionAsObject", JSObject.class, JSObject.class, JSObject.class); + public static final MethodReference GLOBAL = new MethodReference(JS.class, "global", String.class, JSObject.class); + public static final MethodReference IMPORT_MODULE = new MethodReference(JS.class, "importModule", + String.class, JSObject.class); + public static final ValueType JS_OBJECT = ValueType.object(JSObject.class.getName()); public static final ValueType JS_ARRAY = ValueType.object(JSArray.class.getName()); private static final MethodReference[] INVOKE_METHODS = new MethodReference[13]; + private static final MethodReference[] CONSTRUCT_METHODS = new MethodReference[13]; static { for (int i = 0; i < INVOKE_METHODS.length; ++i) { - ValueType[] signature = new ValueType[i + 3]; + var signature = new ValueType[i + 3]; Arrays.fill(signature, JS_OBJECT); INVOKE_METHODS[i] = new MethodReference(JS.class.getName(), "invoke", signature); + + var constructSignature = new ValueType[i + 2]; + Arrays.fill(constructSignature, JS_OBJECT); + CONSTRUCT_METHODS[i] = new MethodReference(JS.class.getName(), "construct", constructSignature); } } @@ -132,4 +141,8 @@ final class JSMethods { public static MethodReference invoke(int parameterCount) { return INVOKE_METHODS[parameterCount]; } + + public static MethodReference construct(int parameterCount) { + return CONSTRUCT_METHODS[parameterCount]; + } } diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/JSNativeInjector.java b/jso/impl/src/main/java/org/teavm/jso/impl/JSNativeInjector.java index cf000048f..fb621fa4f 100644 --- a/jso/impl/src/main/java/org/teavm/jso/impl/JSNativeInjector.java +++ b/jso/impl/src/main/java/org/teavm/jso/impl/JSNativeInjector.java @@ -71,21 +71,20 @@ public class JSNativeInjector implements Injector, DependencyPlugin { } writer.append(')'); break; - case "instantiate": + case "construct": if (context.getPrecedence().ordinal() >= Precedence.FUNCTION_CALL.ordinal()) { writer.append("("); } writer.append("new "); context.writeExpr(context.getArgument(0), Precedence.GROUPING); - renderProperty(context.getArgument(1), context); - writer.append("("); - for (int i = 2; i < context.argumentCount(); ++i) { - if (i > 2) { + writer.append('('); + for (int i = 1; i < context.argumentCount(); ++i) { + if (i > 1) { writer.append(',').ws(); } context.writeExpr(context.getArgument(i), Precedence.min()); } - writer.append(")"); + writer.append(')'); if (context.getPrecedence().ordinal() >= Precedence.FUNCTION_CALL.ordinal()) { writer.append(")"); } @@ -152,6 +151,18 @@ public class JSNativeInjector implements Injector, DependencyPlugin { case "dataToArray": dataToArray(context, "$rt_objcls"); break; + case "global": { + var cst = (ConstantExpr) context.getArgument(0); + var name = (String) cst.getValue(); + writer.appendGlobal(name); + break; + } + case "importModule": { + var cst = (ConstantExpr) context.getArgument(0); + var name = (String) cst.getValue(); + writer.appendFunction(context.importModule(name)); + break; + } default: if (methodRef.getName().startsWith("unwrap")) { @@ -172,7 +183,7 @@ public class JSNativeInjector implements Injector, DependencyPlugin { public void methodReached(DependencyAgent agent, MethodDependency method) { switch (method.getReference().getName()) { case "invoke": - case "instantiate": + case "construct": case "function": if (reachedFunctorMethods.add(method.getReference()) && !method.isMissing()) { for (int i = 0; i < method.getReference().parameterCount(); ++i) { diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/JSObjectClassTransformer.java b/jso/impl/src/main/java/org/teavm/jso/impl/JSObjectClassTransformer.java index dec9d8b6c..2cb7259d5 100644 --- a/jso/impl/src/main/java/org/teavm/jso/impl/JSObjectClassTransformer.java +++ b/jso/impl/src/main/java/org/teavm/jso/impl/JSObjectClassTransformer.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import org.teavm.diagnostics.Diagnostics; +import org.teavm.jso.JSClass; import org.teavm.jso.JSExport; import org.teavm.jso.JSMethod; import org.teavm.jso.JSObject; @@ -82,6 +83,11 @@ class JSObjectClassTransformer implements ClassHolderTransformer { } processor.createJSMethods(cls); + if (cls.hasModifier(ElementModifier.ABSTRACT) + || cls.getAnnotations().get(JSClass.class.getName()) != null && isJavaScriptClass(cls)) { + return; + } + MethodReference functorMethod = processor.isFunctor(cls.getName()); if (functorMethod != null) { if (processor.isFunctor(cls.getParent()) != null) { @@ -277,6 +283,18 @@ class JSObjectClassTransformer implements ClassHolderTransformer { } } + private boolean isJavaScriptClass(ClassReader cls) { + if (cls.getParent() != null && typeHelper.isJavaScriptClass(cls.getParent())) { + return true; + } + for (var itf : cls.getInterfaces()) { + if (typeHelper.isJavaScriptClass(itf)) { + return true; + } + } + return false; + } + private boolean addInterfaces(ExposedClass exposedCls, ClassReader cls) { boolean added = false; for (String ifaceName : cls.getInterfaces()) { diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/JSTypeHelper.java b/jso/impl/src/main/java/org/teavm/jso/impl/JSTypeHelper.java index 5d6c759e0..5d497d52c 100644 --- a/jso/impl/src/main/java/org/teavm/jso/impl/JSTypeHelper.java +++ b/jso/impl/src/main/java/org/teavm/jso/impl/JSTypeHelper.java @@ -17,6 +17,7 @@ package org.teavm.jso.impl; import java.util.HashMap; import java.util.Map; +import org.teavm.jso.JSClass; import org.teavm.jso.JSObject; import org.teavm.model.ClassReader; import org.teavm.model.ClassReaderSource; @@ -43,15 +44,20 @@ class JSTypeHelper { } public boolean isJavaScriptImplementation(String className) { - return knownJavaScriptImplementations - .computeIfAbsent(className, k -> examineIfJavaScriptImplementation(className)); + return knownJavaScriptImplementations.computeIfAbsent(className, k -> + examineIfJavaScriptImplementation(className)); } private boolean examineIfJavaScriptClass(String className) { ClassReader cls = classSource.get(className); - if (cls == null || !(cls.hasModifier(ElementModifier.INTERFACE) || cls.hasModifier(ElementModifier.ABSTRACT))) { + if (cls == null) { return false; } + if (!(cls.hasModifier(ElementModifier.INTERFACE) || cls.hasModifier(ElementModifier.ABSTRACT))) { + if (cls.getAnnotations().get(JSClass.class.getName()) == null) { + return false; + } + } if (cls.getParent() != null) { if (isJavaScriptClass(cls.getParent())) { return true; @@ -65,7 +71,7 @@ class JSTypeHelper { return false; } ClassReader cls = classSource.get(className); - if (cls == null) { + if (cls == null || cls.getAnnotations().get(JSClass.class.getName()) != null) { return false; } if (cls.getParent() != null) { diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/JSValueMarshaller.java b/jso/impl/src/main/java/org/teavm/jso/impl/JSValueMarshaller.java index 6c3812798..a8e8dcc6b 100644 --- a/jso/impl/src/main/java/org/teavm/jso/impl/JSValueMarshaller.java +++ b/jso/impl/src/main/java/org/teavm/jso/impl/JSValueMarshaller.java @@ -18,7 +18,9 @@ package org.teavm.jso.impl; import java.util.ArrayList; import java.util.List; import org.teavm.diagnostics.Diagnostics; +import org.teavm.jso.JSClass; import org.teavm.jso.JSFunctor; +import org.teavm.jso.JSModule; import org.teavm.jso.JSObject; import org.teavm.model.CallLocation; import org.teavm.model.ClassReader; @@ -553,4 +555,90 @@ class JSValueMarshaller { replacement.add(nameInsn); return var; } + + Variable classRef(String className, TextLocation location) { + String name = null; + String module = null; + var cls = classSource.get(className); + if (cls != null) { + name = cls.getSimpleName(); + var jsExport = cls.getAnnotations().get(JSClass.class.getName()); + if (jsExport != null) { + var nameValue = jsExport.getValue("name"); + if (nameValue != null) { + var nameValueString = nameValue.getString(); + if (!nameValueString.isEmpty()) { + name = nameValueString; + } + } + } + var jsModule = cls.getAnnotations().get(JSModule.class.getName()); + if (jsModule != null) { + module = jsModule.getValue("value").getString(); + } + } + if (name == null) { + name = cls.getName().substring(cls.getName().lastIndexOf('.') + 1); + } + return module != null ? moduleRef(module, name, location) : globalRef(name, location); + } + + Variable globalRef(String name, TextLocation location) { + var nameInsn = new StringConstantInstruction(); + nameInsn.setReceiver(program.createVariable()); + nameInsn.setConstant(name); + nameInsn.setLocation(location); + replacement.add(nameInsn); + + var invoke = new InvokeInstruction(); + invoke.setType(InvocationType.SPECIAL); + invoke.setMethod(JSMethods.GLOBAL); + invoke.setArguments(nameInsn.getReceiver()); + invoke.setReceiver(program.createVariable()); + invoke.setLocation(location); + replacement.add(invoke); + + return invoke.getReceiver(); + } + + Variable moduleRef(String module, String name, TextLocation location) { + var moduleNameInsn = new StringConstantInstruction(); + moduleNameInsn.setReceiver(program.createVariable()); + moduleNameInsn.setConstant(module); + moduleNameInsn.setLocation(location); + replacement.add(moduleNameInsn); + + var invoke = new InvokeInstruction(); + invoke.setType(InvocationType.SPECIAL); + invoke.setMethod(JSMethods.IMPORT_MODULE); + invoke.setArguments(moduleNameInsn.getReceiver()); + invoke.setReceiver(program.createVariable()); + invoke.setLocation(location); + replacement.add(invoke); + + var nameInsn = new StringConstantInstruction(); + nameInsn.setReceiver(program.createVariable()); + nameInsn.setConstant(name); + nameInsn.setLocation(location); + replacement.add(nameInsn); + + var wrapName = new InvokeInstruction(); + wrapName.setType(InvocationType.SPECIAL); + wrapName.setMethod(referenceCache.getCached(new MethodReference(JS.class, "wrap", + String.class, JSObject.class))); + wrapName.setReceiver(program.createVariable()); + wrapName.setArguments(nameInsn.getReceiver()); + wrapName.setLocation(location); + replacement.add(wrapName); + + var get = new InvokeInstruction(); + get.setType(InvocationType.SPECIAL); + get.setMethod(JSMethods.GET_PURE); + get.setReceiver(program.createVariable()); + get.setArguments(invoke.getReceiver(), wrapName.getReceiver()); + get.setLocation(location); + replacement.add(get); + + return get.getReceiver(); + } } diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/JSWrapper.java b/jso/impl/src/main/java/org/teavm/jso/impl/JSWrapper.java index bf81f91df..04d76feb8 100644 --- a/jso/impl/src/main/java/org/teavm/jso/impl/JSWrapper.java +++ b/jso/impl/src/main/java/org/teavm/jso/impl/JSWrapper.java @@ -28,13 +28,13 @@ import org.teavm.jso.core.JSWeakMap; import org.teavm.jso.core.JSWeakRef; public final class JSWrapper { - private static final JSWeakMap hashCodes = JSWeakMap.create(); + private static final JSWeakMap hashCodes = new JSWeakMap<>(); private static final JSWeakMap> wrappers = JSWeakRef.isSupported() - ? JSWeakMap.create() : null; + ? new JSWeakMap<>() : null; private static final JSMap> stringWrappers = JSWeakRef.isSupported() - ? JSMap.create() : null; + ? new JSMap<>() : null; private static final JSMap> numberWrappers = JSWeakRef.isSupported() - ? JSMap.create() : null; + ? new JSMap<>() : null; private static JSWeakRef undefinedWrapper; private static final JSFinalizationRegistry stringFinalizationRegistry; private static final JSFinalizationRegistry numberFinalizationRegistry; @@ -44,10 +44,10 @@ public final class JSWrapper { static { stringFinalizationRegistry = stringWrappers != null - ? JSFinalizationRegistry.create(token -> stringWrappers.delete((JSString) token)) + ? new JSFinalizationRegistry(token -> stringWrappers.delete((JSString) token)) : null; numberFinalizationRegistry = numberWrappers != null - ? JSFinalizationRegistry.create(token -> numberWrappers.delete((JSNumber) token)) + ? new JSFinalizationRegistry(token -> numberWrappers.delete((JSNumber) token)) : null; } diff --git a/samples/hello/src/teavm/java/org/teavm/samples/hello/Client.java b/samples/hello/src/teavm/java/org/teavm/samples/hello/Client.java index 4ce9fc6f5..b6c603c86 100644 --- a/samples/hello/src/teavm/java/org/teavm/samples/hello/Client.java +++ b/samples/hello/src/teavm/java/org/teavm/samples/hello/Client.java @@ -37,7 +37,7 @@ public final class Client { private static void sayHello() { helloButton.setDisabled(true); thinkingPanel.getStyle().setProperty("display", ""); - var xhr = XMLHttpRequest.create(); + var xhr = new XMLHttpRequest(); xhr.onComplete(() -> receiveResponse(xhr.getResponseText())); xhr.open("GET", "hello"); xhr.send(); diff --git a/samples/promise/src/main/java/org/teavm/samples/promise/PromiseExample.java b/samples/promise/src/main/java/org/teavm/samples/promise/PromiseExample.java index 5b08d5049..cd2aa9834 100644 --- a/samples/promise/src/main/java/org/teavm/samples/promise/PromiseExample.java +++ b/samples/promise/src/main/java/org/teavm/samples/promise/PromiseExample.java @@ -103,7 +103,7 @@ public final class PromiseExample { } private static void runSimplePromise() { - var promise = JSPromise.create((resolve, reject) -> { + new JSPromise<>((resolve, reject) -> { report("Simple promise execution"); report("Resolving with 'success'"); @@ -112,7 +112,7 @@ public final class PromiseExample { } private static void runComplexPromise() { - var promise = JSPromise.create((resolve, reject) -> { + new JSPromise<>((resolve, reject) -> { report("Complex promise execution"); report("Resolving with 'step1'"); @@ -155,7 +155,7 @@ public final class PromiseExample { .flatThen(value -> { report("Resolved with '" + value + "'"); report("... and resolve with new promise"); - return JSPromise.create((resolve, reject) -> { + return new JSPromise<>((resolve, reject) -> { report("Inner promise"); report("Reject with 'step from inner'"); reject.accept("step from inner"); @@ -176,7 +176,7 @@ public final class PromiseExample { } private static void runLongRunningPromise(Object lock) { - var promise = JSPromise.create((resolve, reject) -> { + var promise = new JSPromise<>((resolve, reject) -> { report("Long promise exection"); report("Wait for a while..."); Window.setTimeout(() -> { @@ -193,7 +193,7 @@ public final class PromiseExample { } private static void combinePromises(Object lock) throws InterruptedException { - JSArray> promises = JSArray.create(3); + var promises = new JSArray>(3); report("Start 3 successful promises"); promises.set(0, JSPromise.resolve("success1")); @@ -245,7 +245,7 @@ public final class PromiseExample { var settledPromises = JSPromise.allSettled(promises); settledPromises.then(value -> { - report(Integer.toString(value.getLength()) + " promises settled to:"); + report(value.getLength() + " promises settled to:"); for (int i = 0; i < value.getLength(); ++i) { var item = value.get(i); var msg = "-- Promise " + i + " " + item.getStatus() + " with: "; @@ -313,9 +313,9 @@ public final class PromiseExample { } report("Start 3 delayed promises"); - promises.set(0, JSPromise.create((resolve, reject) -> Window.setTimeout(() -> resolve.accept("success1"), 200))); - promises.set(1, JSPromise.create((resolve, reject) -> Window.setTimeout(() -> reject.accept("failure1"), 100))); - promises.set(2, JSPromise.create((resolve, reject) -> Window.setTimeout(() -> resolve.accept("success3"), 50))); + promises.set(0, new JSPromise<>((resolve, reject) -> Window.setTimeout(() -> resolve.accept("success1"), 200))); + promises.set(1, new JSPromise<>((resolve, reject) -> Window.setTimeout(() -> reject.accept("failure1"), 100))); + promises.set(2, new JSPromise<>((resolve, reject) -> Window.setTimeout(() -> resolve.accept("success3"), 50))); anyPromise = JSPromise.race(promises); anyPromise.then(value -> { @@ -337,9 +337,9 @@ public final class PromiseExample { } report("Start 3 delayed promises"); - promises.set(0, JSPromise.create((resolve, reject) -> Window.setTimeout(() -> resolve.accept("success1"), 200))); - promises.set(1, JSPromise.create((resolve, reject) -> Window.setTimeout(() -> reject.accept("failure1"), 50))); - promises.set(2, JSPromise.create((resolve, reject) -> Window.setTimeout(() -> resolve.accept("success3"), 100))); + promises.set(0, new JSPromise<>((resolve, reject) -> Window.setTimeout(() -> resolve.accept("success1"), 200))); + promises.set(1, new JSPromise<>((resolve, reject) -> Window.setTimeout(() -> reject.accept("failure1"), 50))); + promises.set(2, new JSPromise<>((resolve, reject) -> Window.setTimeout(() -> resolve.accept("success3"), 100))); anyPromise = JSPromise.race(promises); anyPromise.then(value -> { @@ -397,11 +397,11 @@ public final class PromiseExample { } report("Pass promise to native method"); - handlePromise(JSPromise.create((resolve, reject) -> { + handlePromise(new JSPromise<>((resolve, reject) -> { resolve.accept(JSString.valueOf("Resolved from Java")); })); - handlePromise(JSPromise.create((resolve, reject) -> { + handlePromise(new JSPromise<>((resolve, reject) -> { reject.accept(JSString.valueOf("Rejected from Java")); })); } diff --git a/samples/software3d/src/jvmMain/kotlin/org/teavm/samples/software3d/teavm/Controller.kt b/samples/software3d/src/jvmMain/kotlin/org/teavm/samples/software3d/teavm/Controller.kt index 00835f2b1..55c2ed816 100644 --- a/samples/software3d/src/jvmMain/kotlin/org/teavm/samples/software3d/teavm/Controller.kt +++ b/samples/software3d/src/jvmMain/kotlin/org/teavm/samples/software3d/teavm/Controller.kt @@ -55,7 +55,7 @@ class Controller( WorkerType.KOTLIN_JS -> "kjs/software3d.js" } workers = (0 until tasks).map { index -> - Worker.create(scriptName).apply { + Worker(scriptName).apply { postMessage(JSObjects.createWithoutProto>().apply { set("type", JSString.valueOf("init")) set("width", JSNumber.valueOf(width)) @@ -118,8 +118,8 @@ class Controller( private fun displayBuffers(buffers: Array) { for (y in 0 until height) { val buffer = buffers[y % buffers.size]!! - val array = Uint8ClampedArray.create(buffer, width * 4 * (y / buffers.size), width * 4) - val imageData = ImageData.create(array, width, 1) + val array = Uint8ClampedArray(buffer, width * 4 * (y / buffers.size), width * 4) + val imageData = ImageData(array, width, 1) context.putImageData(imageData, 0.0, y.toDouble()) } } diff --git a/samples/web-apis/src/main/java/org/teavm/samples/webapis/Storage.java b/samples/web-apis/src/main/java/org/teavm/samples/webapis/Storage.java index 8e568b445..4825c942f 100644 --- a/samples/web-apis/src/main/java/org/teavm/samples/webapis/Storage.java +++ b/samples/web-apis/src/main/java/org/teavm/samples/webapis/Storage.java @@ -41,7 +41,7 @@ public final class Storage { var key = document.getElementById("key").cast().getValue(); var value = document.getElementById("value").cast().getValue(); - if (key != null && key.length() > 0 && value != null && value.length() > 0) { + if (key != null && !key.isEmpty() && value != null && !value.isEmpty()) { storage.setItem(key, value); draw(); } @@ -49,7 +49,7 @@ public final class Storage { HTMLButtonElement deleteButton = document.getElementById("delete-button").cast(); deleteButton.listenClick(e -> { String key = document.getElementById("key").cast().getValue(); - if (key != null && key.length() > 0) { + if (key != null && !key.isEmpty()) { storage.removeItem(key); draw(); } diff --git a/tests/src/test/java/org/teavm/jso/test/ClassWithConstructor.java b/tests/src/test/java/org/teavm/jso/test/ClassWithConstructor.java new file mode 100644 index 000000000..e2741717a --- /dev/null +++ b/tests/src/test/java/org/teavm/jso/test/ClassWithConstructor.java @@ -0,0 +1,36 @@ +/* + * Copyright 2024 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. + */ +package org.teavm.jso.test; + +import org.teavm.jso.JSClass; +import org.teavm.jso.JSObject; +import org.teavm.jso.JSProperty; + +@JSClass +public class ClassWithConstructor implements JSObject { + public ClassWithConstructor(int foo) { + } + + public ClassWithConstructor() { + } + + @JSProperty + public native int getFoo(); + + public native String bar(); + + public static native String staticMethod(); +} diff --git a/tests/src/test/java/org/teavm/jso/test/ClassWithConstructorInModule.java b/tests/src/test/java/org/teavm/jso/test/ClassWithConstructorInModule.java new file mode 100644 index 000000000..529b7f406 --- /dev/null +++ b/tests/src/test/java/org/teavm/jso/test/ClassWithConstructorInModule.java @@ -0,0 +1,36 @@ +/* + * Copyright 2024 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. + */ +package org.teavm.jso.test; + +import org.teavm.jso.JSClass; +import org.teavm.jso.JSModule; +import org.teavm.jso.JSObject; +import org.teavm.jso.JSProperty; + +@JSClass(name = "ClassWithConstructor") +@JSModule("./testModule.js") +public class ClassWithConstructorInModule implements JSObject { + public ClassWithConstructorInModule(int foo) { + } + + public ClassWithConstructorInModule() { + } + + @JSProperty + public native int getFoo(); + + public native String bar(); +} diff --git a/tests/src/test/java/org/teavm/jso/test/ImportClassTest.java b/tests/src/test/java/org/teavm/jso/test/ImportClassTest.java index 73ee8efc7..5c2adfdf5 100644 --- a/tests/src/test/java/org/teavm/jso/test/ImportClassTest.java +++ b/tests/src/test/java/org/teavm/jso/test/ImportClassTest.java @@ -21,6 +21,7 @@ import org.junit.runner.RunWith; import org.teavm.jso.JSBody; import org.teavm.jso.JSIndexer; import org.teavm.jso.JSObject; +import org.teavm.junit.AttachJavaScript; import org.teavm.junit.EachTestCompiledSeparately; import org.teavm.junit.OnlyPlatform; import org.teavm.junit.SkipJVM; @@ -41,6 +42,23 @@ public class ImportClassTest { assertEquals(42, o.get("bar")); } + @Test + @AttachJavaScript("org/teavm/jso/test/classWithConstructor.js") + public void constructor() { + var o = new ClassWithConstructor(); + assertEquals(99, o.getFoo()); + assertEquals("bar called", o.bar()); + + o = new ClassWithConstructor(23); + assertEquals(23, o.getFoo()); + } + + @Test + @AttachJavaScript("org/teavm/jso/test/classWithConstructor.js") + public void staticMethod() { + assertEquals("static method called", ClassWithConstructor.staticMethod()); + } + @JSBody(script = "return {};") private static native O create(); diff --git a/tests/src/test/java/org/teavm/jso/test/ImportModuleTest.java b/tests/src/test/java/org/teavm/jso/test/ImportModuleTest.java index 46ddd2151..a8a47576c 100644 --- a/tests/src/test/java/org/teavm/jso/test/ImportModuleTest.java +++ b/tests/src/test/java/org/teavm/jso/test/ImportModuleTest.java @@ -56,6 +56,18 @@ public class ImportModuleTest { assertEquals(23, runTestFunction()); } + @Test + @JsModuleTest + @ServeJS(from = "org/teavm/jso/test/classWithConstructorInModule.js", as = "testModule.js") + public void classConstructor() { + var o = new ClassWithConstructorInModule(); + assertEquals(99, o.getFoo()); + assertEquals("bar called", o.bar()); + + o = new ClassWithConstructorInModule(23); + assertEquals(23, o.getFoo()); + } + @JSBody( script = "return testModule.foo();", imports = @JSBodyImport(alias = "testModule", fromModule = "./testModule.js") diff --git a/tests/src/test/resources/org/teavm/jso/test/classWithConstructor.js b/tests/src/test/resources/org/teavm/jso/test/classWithConstructor.js new file mode 100644 index 000000000..4558db502 --- /dev/null +++ b/tests/src/test/resources/org/teavm/jso/test/classWithConstructor.js @@ -0,0 +1,33 @@ +/* + * Copyright 2024 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. + */ + +class ClassWithConstructor { + constructor(foo) { + this._foo = foo || 99; + } + + get foo() { + return this._foo; + } + + bar() { + return "bar called"; + } + + static staticMethod() { + return "static method called"; + } +} \ No newline at end of file diff --git a/tests/src/test/resources/org/teavm/jso/test/classWithConstructorInModule.js b/tests/src/test/resources/org/teavm/jso/test/classWithConstructorInModule.js new file mode 100644 index 000000000..e88e51471 --- /dev/null +++ b/tests/src/test/resources/org/teavm/jso/test/classWithConstructorInModule.js @@ -0,0 +1,29 @@ +/* + * Copyright 2024 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. + */ + +export class ClassWithConstructor { + constructor(foo) { + this._foo = foo || 99; + } + + get foo() { + return this._foo; + } + + bar() { + return "bar called"; + } +} \ No newline at end of file diff --git a/tools/deobfuscator-js/src/main/java/org/teavm/tooling/deobfuscate/js/Deobfuscator.java b/tools/deobfuscator-js/src/main/java/org/teavm/tooling/deobfuscate/js/Deobfuscator.java index 267765c8a..d4753fd9a 100644 --- a/tools/deobfuscator-js/src/main/java/org/teavm/tooling/deobfuscate/js/Deobfuscator.java +++ b/tools/deobfuscator-js/src/main/java/org/teavm/tooling/deobfuscate/js/Deobfuscator.java @@ -34,14 +34,14 @@ import org.teavm.jso.typedarrays.Int8Array; import org.teavm.model.MethodReference; public final class Deobfuscator { - private static final JSRegExp FRAME_PATTERN = JSRegExp.create("" + private static final JSRegExp FRAME_PATTERN = new JSRegExp("" + "(^ +at ([^(]+) *\\((.+):([0-9]+):([0-9]+)\\) *$)|" + "(^([^@]*)@(.+):([0-9]+):([0-9]+)$)"); private DebugInformation debugInformation; private String classesFileName; public Deobfuscator(ArrayBuffer buffer, String classesFileName) throws IOException { - Int8Array array = Int8Array.create(buffer); + var array = new Int8Array(buffer); debugInformation = DebugInformation.read(new Int8ArrayInputStream(array)); this.classesFileName = classesFileName; } @@ -51,7 +51,7 @@ public final class Deobfuscator { } private static void loadDeobfuscator(String fileName, String classesFileName) { - XMLHttpRequest xhr = XMLHttpRequest.create(); + var xhr = new XMLHttpRequest(); xhr.setResponseType("arraybuffer"); xhr.onComplete(() -> { installDeobfuscator(xhr.getResponse().cast(), classesFileName);