From 97aa42d87ba6c5632a2887d55b625a8f8c45c787 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Fri, 12 Apr 2024 13:45:12 +0200 Subject: [PATCH] jso apis: new convention for event registration --- .../org/teavm/jso/ajax/XMLHttpRequest.java | 44 +++++++++------ .../teavm/jso/browser/WindowEventTarget.java | 24 +++++++++ .../org/teavm/jso/dom/events/EventTarget.java | 10 ++++ .../jso/dom/events/FocusEventTarget.java | 12 +++++ .../jso/dom/events/GamepadEventTarget.java | 11 ++++ .../jso/dom/events/KeyboardEventTarget.java | 18 +++++++ .../teavm/jso/dom/events/LoadEventTarget.java | 6 +++ .../jso/dom/events/MouseEventTarget.java | 54 +++++++++++++++++++ .../teavm/jso/dom/events/Registration.java | 44 +++++++++++++++ .../teavm/jso/dom/events/StorageEvent.java | 4 -- .../jso/dom/events/WheelEventTarget.java | 6 +++ .../jso/geolocation/PositionHandler.java | 3 -- .../jso/webaudio/AudioBufferSourceNode.java | 5 ++ .../org/teavm/jso/webaudio/AudioContext.java | 24 ++++++++- .../org/teavm/jso/webaudio/AudioNode.java | 3 +- .../org/teavm/jso/webaudio/AudioWorker.java | 12 ++++- .../jso/webaudio/AudioWorkerGlobalScope.java | 13 ++++- .../teavm/jso/webaudio/AudioWorkerNode.java | 5 ++ .../AudioWorkerNodeCreationEvent.java | 5 +- .../webaudio/AudioWorkerNodeProcessor.java | 5 ++ .../jso/webaudio/OfflineAudioContext.java | 5 ++ .../teavm/jso/webaudio/OscillatorNode.java | 5 ++ .../jso/webaudio/ScriptProcessorNode.java | 5 ++ .../org/teavm/jso/websocket/WebSocket.java | 39 ++++++++++---- .../org/teavm/jso/workers/AbstractWorker.java | 7 +-- .../org/teavm/jso/workers/MessagePort.java | 12 +++-- .../org/teavm/jso/workers/SharedWorker.java | 6 +-- .../java/org/teavm/jso/workers/Worker.java | 9 ++-- .../java/org/teavm/samples/hello/Client.java | 2 +- samples/kotlin/build.gradle.kts | 6 +-- .../kotlin/org/teavm/samples/kotlin/Hello.kt | 2 +- .../org/teavm/samples/scala/Client.scala | 2 +- .../teavm/samples/software3d/teavm/Worker.kt | 2 +- .../org/teavm/samples/webapis/Storage.java | 6 +-- .../java/org/teavm/samples/webapis/Video.java | 28 +++++----- 35 files changed, 364 insertions(+), 80 deletions(-) create mode 100644 jso/apis/src/main/java/org/teavm/jso/dom/events/Registration.java 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 345f61c4c..7ab01821d 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 @@ -22,6 +22,7 @@ import org.teavm.jso.JSProperty; import org.teavm.jso.dom.events.Event; import org.teavm.jso.dom.events.EventListener; import org.teavm.jso.dom.events.EventTarget; +import org.teavm.jso.dom.events.Registration; import org.teavm.jso.dom.xml.Document; @JSClass @@ -65,29 +66,40 @@ public class XMLHttpRequest implements JSObject, EventTarget { @JSProperty("onreadystatechange") public native void setOnReadyStateChange(EventListener handler); - @JSProperty("onabort") - public native void onAbort(EventListener eventListener); + public final Registration onReadyStateChange(EventListener handler) { + return onEvent("readystatechange", handler); + } - @JSProperty("onerror") - public native void onError(EventListener eventListener); + public final Registration onAbort(EventListener eventListener) { + return onEvent("abort", eventListener); + } - @JSProperty("onload") - public native void onLoad(EventListener eventListener); + public final Registration onError(EventListener eventListener) { + return onEvent("error", eventListener); + } - @JSProperty("onloadstart") - public native void onLoadStart(EventListener eventListener); + public final Registration onLoad(EventListener eventListener) { + return onEvent("load", eventListener); + } - @JSProperty("onloadend") - public native void onLoadEnd(EventListener eventListener); + public final Registration onLoadStart(EventListener eventListener) { + return onEvent("loadstart", eventListener); + } - @JSProperty("onprogress") - public native void onProgress(EventListener eventListener); + public final Registration onLoadEnd(EventListener eventListener) { + return onEvent("loadend", eventListener); + } - @JSProperty("ontimeout") - public native void onTimeout(EventListener eventListener); + public final Registration onProgress(EventListener eventListener) { + return onEvent("progress", eventListener); + } - public final void onComplete(Runnable runnable) { - setOnReadyStateChange(() -> { + public final Registration onTimeout(EventListener eventListener) { + return onEvent("timeout", eventListener); + } + + public final Registration onComplete(Runnable runnable) { + return onReadyStateChange(event -> { if (getReadyState() == DONE) { runnable.run(); } diff --git a/jso/apis/src/main/java/org/teavm/jso/browser/WindowEventTarget.java b/jso/apis/src/main/java/org/teavm/jso/browser/WindowEventTarget.java index 5c1420a5a..296213a2d 100644 --- a/jso/apis/src/main/java/org/teavm/jso/browser/WindowEventTarget.java +++ b/jso/apis/src/main/java/org/teavm/jso/browser/WindowEventTarget.java @@ -25,30 +25,54 @@ import org.teavm.jso.dom.events.KeyboardEventTarget; import org.teavm.jso.dom.events.LoadEventTarget; import org.teavm.jso.dom.events.MessageEvent; import org.teavm.jso.dom.events.MouseEventTarget; +import org.teavm.jso.dom.events.Registration; +import org.teavm.jso.dom.events.StorageEvent; public interface WindowEventTarget extends EventTarget, FocusEventTarget, MouseEventTarget, KeyboardEventTarget, LoadEventTarget, GamepadEventTarget { + @Deprecated default void listenBeforeOnload(EventListener listener) { addEventListener("beforeunload", listener); } + @Deprecated default void neglectBeforeOnload(EventListener listener) { removeEventListener("beforeunload", listener); } + @Deprecated default void listenMessage(EventListener listener) { addEventListener("message", listener); } + @Deprecated default void neglectMessage(EventListener listener) { removeEventListener("message", listener); } + @Deprecated default void listenHashChange(EventListener listener) { addEventListener("hashchange", listener); } + @Deprecated default void neglectHashChange(EventListener listener) { removeEventListener("hashchange", listener); } + + default Registration onBeforeUnload(EventListener listener) { + return onEvent("beforeunload", listener); + } + + default Registration onMessage(EventListener listener) { + return onEvent("message", listener); + } + + default Registration onHashChange(EventListener listener) { + return onEvent("hashchange", listener); + } + + default Registration onStorage(EventListener listener) { + return onEvent("storage", listener); + } } diff --git a/jso/apis/src/main/java/org/teavm/jso/dom/events/EventTarget.java b/jso/apis/src/main/java/org/teavm/jso/dom/events/EventTarget.java index 3ab19c124..70869cc8b 100644 --- a/jso/apis/src/main/java/org/teavm/jso/dom/events/EventTarget.java +++ b/jso/apis/src/main/java/org/teavm/jso/dom/events/EventTarget.java @@ -27,4 +27,14 @@ public interface EventTarget extends JSObject { void removeEventListener(String type, EventListener listener); boolean dispatchEvent(Event evt); + + default Registration onEvent(String type, boolean useCapture, EventListener listener) { + addEventListener(type, listener, useCapture); + return new Registration(this, type, listener, useCapture); + } + + default Registration onEvent(String type, EventListener listener) { + addEventListener(type, listener); + return new Registration(this, type, listener, null); + } } diff --git a/jso/apis/src/main/java/org/teavm/jso/dom/events/FocusEventTarget.java b/jso/apis/src/main/java/org/teavm/jso/dom/events/FocusEventTarget.java index 7fb6a8fba..0ba63b334 100644 --- a/jso/apis/src/main/java/org/teavm/jso/dom/events/FocusEventTarget.java +++ b/jso/apis/src/main/java/org/teavm/jso/dom/events/FocusEventTarget.java @@ -16,19 +16,31 @@ package org.teavm.jso.dom.events; public interface FocusEventTarget extends EventTarget { + @Deprecated default void listenFocus(EventListener listener) { addEventListener("focus", listener); } + @Deprecated default void neglectFocus(EventListener listener) { removeEventListener("focus", listener); } + @Deprecated default void listenBlur(EventListener listener) { addEventListener("blur", listener); } + @Deprecated default void neglectBlur(EventListener listener) { removeEventListener("blur", listener); } + + default Registration onFocus(EventListener listener) { + return onEvent("focus", listener); + } + + default Registration onBlur(EventListener listener) { + return onEvent("blur", listener); + } } diff --git a/jso/apis/src/main/java/org/teavm/jso/dom/events/GamepadEventTarget.java b/jso/apis/src/main/java/org/teavm/jso/dom/events/GamepadEventTarget.java index 3605b981f..c11a05821 100644 --- a/jso/apis/src/main/java/org/teavm/jso/dom/events/GamepadEventTarget.java +++ b/jso/apis/src/main/java/org/teavm/jso/dom/events/GamepadEventTarget.java @@ -18,20 +18,31 @@ package org.teavm.jso.dom.events; import org.teavm.jso.gamepad.GamepadEvent; public interface GamepadEventTarget extends EventTarget { + @Deprecated default void listenGamepadConnected(EventListener listener) { addEventListener("gamepadconnected", listener); } + @Deprecated default void neglectGamepadConnected(EventListener listener) { removeEventListener("gamepadconnected", listener); } + @Deprecated default void listenGamepadDisconnected(EventListener listener) { addEventListener("gamepaddisconnected", listener); } + @Deprecated default void neglectGamepadDisconnected(EventListener listener) { removeEventListener("gamepaddisconnected", listener); } + default Registration onGamepadConnected(EventListener listener) { + return onEvent("gamepadconnected", listener); + } + + default Registration onGamepadDisconnected(EventListener listener) { + return onEvent("gamepaddisconnected", listener); + } } diff --git a/jso/apis/src/main/java/org/teavm/jso/dom/events/KeyboardEventTarget.java b/jso/apis/src/main/java/org/teavm/jso/dom/events/KeyboardEventTarget.java index b6306cf5e..5369f6943 100644 --- a/jso/apis/src/main/java/org/teavm/jso/dom/events/KeyboardEventTarget.java +++ b/jso/apis/src/main/java/org/teavm/jso/dom/events/KeyboardEventTarget.java @@ -16,27 +16,45 @@ package org.teavm.jso.dom.events; public interface KeyboardEventTarget extends EventTarget { + @Deprecated default void listenKeyDown(EventListener listener) { addEventListener("keydown", listener); } + @Deprecated default void neglectKeyDown(EventListener listener) { removeEventListener("keydown", listener); } + @Deprecated default void listenKeyUp(EventListener listener) { addEventListener("keyup", listener); } + @Deprecated default void neglectKeyUp(EventListener listener) { removeEventListener("keyup", listener); } + @Deprecated default void listenKeyPress(EventListener listener) { addEventListener("keypress", listener); } + @Deprecated default void neglectKeyPress(EventListener listener) { removeEventListener("keypress", listener); } + + default Registration onKeyDown(EventListener listener) { + return onEvent("keydown", listener); + } + + default Registration onKeyUp(EventListener listener) { + return onEvent("keyup", listener); + } + + default Registration onKeyPress(EventListener listener) { + return onEvent("keypress", listener); + } } diff --git a/jso/apis/src/main/java/org/teavm/jso/dom/events/LoadEventTarget.java b/jso/apis/src/main/java/org/teavm/jso/dom/events/LoadEventTarget.java index 6f9ba6a50..a6ba7eb34 100644 --- a/jso/apis/src/main/java/org/teavm/jso/dom/events/LoadEventTarget.java +++ b/jso/apis/src/main/java/org/teavm/jso/dom/events/LoadEventTarget.java @@ -16,11 +16,17 @@ package org.teavm.jso.dom.events; public interface LoadEventTarget extends EventTarget { + @Deprecated default void listenLoad(EventListener listener) { addEventListener("load", listener); } + @Deprecated default void neglectLoad(EventListener listener) { addEventListener("load", listener); } + + default Registration onLoad(EventListener listener) { + return onEvent("load", listener); + } } diff --git a/jso/apis/src/main/java/org/teavm/jso/dom/events/MouseEventTarget.java b/jso/apis/src/main/java/org/teavm/jso/dom/events/MouseEventTarget.java index 7c296551e..b8ce85915 100644 --- a/jso/apis/src/main/java/org/teavm/jso/dom/events/MouseEventTarget.java +++ b/jso/apis/src/main/java/org/teavm/jso/dom/events/MouseEventTarget.java @@ -16,75 +16,129 @@ package org.teavm.jso.dom.events; public interface MouseEventTarget extends EventTarget { + @Deprecated default void listenClick(EventListener listener) { addEventListener("click", listener); } + @Deprecated default void neglectClick(EventListener listener) { removeEventListener("click", listener); } + @Deprecated default void listenDoubleClick(EventListener listener) { addEventListener("dblclick", listener); } + @Deprecated default void neglectDoubleClick(EventListener listener) { removeEventListener("dblclick", listener); } + @Deprecated default void listenMouseDown(EventListener listener) { addEventListener("mousedown", listener); } + @Deprecated default void neglectMouseDown(EventListener listener) { removeEventListener("mousedown", listener); } + @Deprecated default void listenMouseUp(EventListener listener) { addEventListener("mouseup", listener); } + @Deprecated default void neglectMouseUp(EventListener listener) { removeEventListener("mouseup", listener); } + @Deprecated default void listenMouseMove(EventListener listener) { addEventListener("mousemove", listener); } + @Deprecated default void neglectMouseMove(EventListener listener) { removeEventListener("mousemove", listener); } + @Deprecated default void listenMouseOver(EventListener listener) { addEventListener("mouseover", listener); } + @Deprecated default void neglectMouseOver(EventListener listener) { removeEventListener("mouseover", listener); } + @Deprecated default void listenMouseEnter(EventListener listener) { addEventListener("mouseenter", listener); } + @Deprecated default void neglectMouseEnter(EventListener listener) { removeEventListener("mouseenter", listener); } + @Deprecated default void listenMouseLeave(EventListener listener) { addEventListener("mouseleave", listener); } + @Deprecated default void neglectMouseLeave(EventListener listener) { removeEventListener("mouseleave", listener); } + @Deprecated default void listenMouseOut(EventListener listener) { addEventListener("mouseout", listener); } + @Deprecated default void neglectMouseOut(EventListener listener) { removeEventListener("mouseout", listener); } + + default Registration onClick(EventListener listener) { + return onEvent("click", listener); + } + + default Registration onDoubleClick(EventListener listener) { + return onEvent("dblclick", listener); + } + + default Registration onMouseDown(EventListener listener) { + return onEvent("mousedown", listener); + } + + default Registration onMouseUp(EventListener listener) { + return onEvent("mouseup", listener); + } + + default Registration onMouseMove(EventListener listener) { + return onEvent("mousemove", listener); + } + + default Registration onMouseOver(EventListener listener) { + return onEvent("mouseover", listener); + } + + default Registration onMouseEnter(EventListener listener) { + return onEvent("mouseenter", listener); + } + + default Registration onMouseLeave(EventListener listener) { + return onEvent("mouseleave", listener); + } + + default Registration onMouseOut(EventListener listener) { + return onEvent("mouseout", listener); + } } diff --git a/jso/apis/src/main/java/org/teavm/jso/dom/events/Registration.java b/jso/apis/src/main/java/org/teavm/jso/dom/events/Registration.java new file mode 100644 index 000000000..4628829ed --- /dev/null +++ b/jso/apis/src/main/java/org/teavm/jso/dom/events/Registration.java @@ -0,0 +1,44 @@ +/* + * Copyright 2024 konsoletyper. + * + * 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.dom.events; + +public class Registration { + private EventTarget target; + private String type; + private EventListener listener; + private Boolean useCapture; + + Registration(EventTarget target, String type, EventListener listener, Boolean useCapture) { + this.target = target; + this.type = type; + this.listener = listener; + this.useCapture = useCapture; + } + + public void dispose() { + if (target != null) { + if (useCapture != null) { + target.removeEventListener(type, listener, useCapture); + } else { + target.removeEventListener(type, listener); + } + target = null; + type = null; + listener = null; + useCapture = null; + } + } +} diff --git a/jso/apis/src/main/java/org/teavm/jso/dom/events/StorageEvent.java b/jso/apis/src/main/java/org/teavm/jso/dom/events/StorageEvent.java index 1967ff688..a55eead47 100644 --- a/jso/apis/src/main/java/org/teavm/jso/dom/events/StorageEvent.java +++ b/jso/apis/src/main/java/org/teavm/jso/dom/events/StorageEvent.java @@ -18,10 +18,6 @@ package org.teavm.jso.dom.events; import org.teavm.jso.JSProperty; import org.teavm.jso.browser.Storage; -/** - * - * @author Junji Takakura - */ public interface StorageEvent extends Event { @JSProperty diff --git a/jso/apis/src/main/java/org/teavm/jso/dom/events/WheelEventTarget.java b/jso/apis/src/main/java/org/teavm/jso/dom/events/WheelEventTarget.java index 743e9782c..eacdc0839 100644 --- a/jso/apis/src/main/java/org/teavm/jso/dom/events/WheelEventTarget.java +++ b/jso/apis/src/main/java/org/teavm/jso/dom/events/WheelEventTarget.java @@ -16,11 +16,17 @@ package org.teavm.jso.dom.events; public interface WheelEventTarget extends EventTarget { + @Deprecated default void listenWheel(EventListener listener) { addEventListener("wheel", listener); } + @Deprecated default void neglectWheel(EventListener listener) { removeEventListener("wheel", listener); } + + default Registration onWheel(EventListener listener) { + return onEvent("wheel", listener); + } } diff --git a/jso/apis/src/main/java/org/teavm/jso/geolocation/PositionHandler.java b/jso/apis/src/main/java/org/teavm/jso/geolocation/PositionHandler.java index f506c9d3e..fdf33dab9 100644 --- a/jso/apis/src/main/java/org/teavm/jso/geolocation/PositionHandler.java +++ b/jso/apis/src/main/java/org/teavm/jso/geolocation/PositionHandler.java @@ -18,9 +18,6 @@ package org.teavm.jso.geolocation; import org.teavm.jso.JSFunctor; import org.teavm.jso.JSObject; -/** - * - */ @JSFunctor public interface PositionHandler extends JSObject { void handlePosition(Position position); diff --git a/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioBufferSourceNode.java b/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioBufferSourceNode.java index 2ef914e7d..5503cafdb 100644 --- a/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioBufferSourceNode.java +++ b/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioBufferSourceNode.java @@ -17,6 +17,7 @@ package org.teavm.jso.webaudio; import org.teavm.jso.JSProperty; import org.teavm.jso.dom.events.EventListener; +import org.teavm.jso.dom.events.Registration; public interface AudioBufferSourceNode extends AudioNode { @JSProperty @@ -55,6 +56,10 @@ public interface AudioBufferSourceNode extends AudioNode { @JSProperty("onended") EventListener getOnEnded(); + default Registration onEnded(EventListener eventListener) { + return onEvent("ended", eventListener); + } + void start(double when, double offset, double duration); void start(double when, double 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 b98a8e58a..fc8404ed7 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 @@ -20,13 +20,16 @@ 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.Event; import org.teavm.jso.dom.events.EventListener; +import org.teavm.jso.dom.events.EventTarget; +import org.teavm.jso.dom.events.Registration; import org.teavm.jso.dom.html.HTMLMediaElement; import org.teavm.jso.typedarrays.ArrayBuffer; import org.teavm.jso.typedarrays.Float32Array; @JSClass -public class AudioContext implements JSObject { +public class AudioContext implements JSObject, EventTarget { public static final String STATE_SUSPENDED = "suspended"; public static final String STATE_RUNNING = "running"; public static final String STATE_CLOSE = "close"; @@ -52,6 +55,10 @@ public class AudioContext implements JSObject { @JSProperty("onstatechange") public native EventListener getOnStateChange(); + public final Registration onStateChange(EventListener listener) { + return onEvent("statechange", listener); + } + public native void suspend(); public native void resume(); @@ -131,4 +138,19 @@ public class AudioContext implements JSObject { @JSBody(script = "return new Context();") @Deprecated public static native AudioContext create(); + + @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/webaudio/AudioNode.java b/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioNode.java index b7ed28ff7..3feae7b2c 100644 --- a/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioNode.java +++ b/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioNode.java @@ -17,8 +17,9 @@ package org.teavm.jso.webaudio; import org.teavm.jso.JSObject; import org.teavm.jso.JSProperty; +import org.teavm.jso.dom.events.EventTarget; -public interface AudioNode extends JSObject { +public interface AudioNode extends JSObject, EventTarget { String CHANNEL_COUNT_MODE_MAX = "max"; String CHANNEL_COUNT_MODE_CLAMPED_MAX = "clamped-max"; String CHANNEL_COUNT_MODE_EXPLICIT = "explicit"; diff --git a/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioWorker.java b/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioWorker.java index d0c56b83c..987c4f2d8 100644 --- a/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioWorker.java +++ b/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioWorker.java @@ -19,8 +19,10 @@ import org.teavm.jso.JSByRef; import org.teavm.jso.JSObject; import org.teavm.jso.JSProperty; import org.teavm.jso.dom.events.EventListener; +import org.teavm.jso.dom.events.EventTarget; +import org.teavm.jso.dom.events.Registration; -public interface AudioWorker extends JSObject { +public interface AudioWorker extends EventTarget { @JSProperty AudioWorkerParamDescriptor[] getParameters(); @@ -30,12 +32,20 @@ public interface AudioWorker extends JSObject { @JSProperty(value = "onmessage") EventListener getOnMessage(); + default Registration onMessage(EventListener listener) { + return onEvent("message", listener); + } + @JSProperty(value = "onloaded") void setOnLoaded(EventListener event); @JSProperty(value = "onloaded") EventListener getOnLoaded(); + default Registration onLoaded(EventListener listener) { + return onEvent("loaded", listener); + } + void terminate(); void postMessage(JSObject message, @JSByRef JSObject[] transfer); diff --git a/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioWorkerGlobalScope.java b/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioWorkerGlobalScope.java index bf1dc1478..9b6f8ab36 100644 --- a/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioWorkerGlobalScope.java +++ b/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioWorkerGlobalScope.java @@ -15,11 +15,12 @@ */ package org.teavm.jso.webaudio; -import org.teavm.jso.JSObject; import org.teavm.jso.JSProperty; import org.teavm.jso.dom.events.EventListener; +import org.teavm.jso.dom.events.EventTarget; +import org.teavm.jso.dom.events.Registration; -public interface AudioWorkerGlobalScope extends JSObject { +public interface AudioWorkerGlobalScope extends EventTarget { @JSProperty float getSampleRate(); @@ -29,12 +30,20 @@ public interface AudioWorkerGlobalScope extends JSObject { @JSProperty("onaudioprocess") EventListener getOnAudioProcess(); + default Registration onAudioProcess(EventListener listener) { + return onEvent("audioprocess", listener); + } + @JSProperty("onnodecreate") void setOnNodeCreate(EventListener event); @JSProperty("onnodecreate") EventListener getOnNodeCreate(); + default Registration onNodeCreate(EventListener listener) { + return onEvent("nodecreate", listener); + } + @JSProperty AudioWorkerParamDescriptor[] getParameters(); diff --git a/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioWorkerNode.java b/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioWorkerNode.java index 171321274..d6693b276 100644 --- a/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioWorkerNode.java +++ b/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioWorkerNode.java @@ -19,6 +19,7 @@ import org.teavm.jso.JSByRef; import org.teavm.jso.JSObject; import org.teavm.jso.JSProperty; import org.teavm.jso.dom.events.EventListener; +import org.teavm.jso.dom.events.Registration; public interface AudioWorkerNode extends AudioNode { @JSProperty("onmessage") @@ -27,6 +28,10 @@ public interface AudioWorkerNode extends AudioNode { @JSProperty("onmessage") EventListener getOnMessage(); + default Registration onMessage(EventListener listener) { + return onEvent("message", listener); + } + void postMessage(JSObject message, @JSByRef JSObject[] transfer); void postMessage(JSObject message, JSObject transfer); diff --git a/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioWorkerNodeCreationEvent.java b/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioWorkerNodeCreationEvent.java index 45fb135f0..34ec342c3 100644 --- a/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioWorkerNodeCreationEvent.java +++ b/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioWorkerNodeCreationEvent.java @@ -15,6 +15,7 @@ */ package org.teavm.jso.webaudio; +import org.teavm.jso.JSObject; import org.teavm.jso.JSProperty; import org.teavm.jso.core.JSArray; @@ -23,9 +24,9 @@ public interface AudioWorkerNodeCreationEvent extends MediaEvent { AudioWorkerNodeProcessor getNode(); @JSProperty - JSArray getInputs(); + JSArray getInputs(); @JSProperty - JSArray getOutputs(); + JSArray getOutputs(); } diff --git a/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioWorkerNodeProcessor.java b/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioWorkerNodeProcessor.java index b06935ca7..bbb7a182f 100644 --- a/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioWorkerNodeProcessor.java +++ b/jso/apis/src/main/java/org/teavm/jso/webaudio/AudioWorkerNodeProcessor.java @@ -19,6 +19,7 @@ import org.teavm.jso.JSObject; import org.teavm.jso.JSProperty; import org.teavm.jso.dom.events.EventListener; import org.teavm.jso.dom.events.EventTarget; +import org.teavm.jso.dom.events.Registration; public interface AudioWorkerNodeProcessor extends EventTarget { @JSProperty("onmessage") @@ -27,6 +28,10 @@ public interface AudioWorkerNodeProcessor extends EventTarget { @JSProperty("onmessage") EventListener getOnMessage(); + default Registration onMessage(EventListener listener) { + return onEvent("message", listener); + } + void postMessage(JSObject message, JSObject[] transfer); void postMessage(JSObject message, JSObject transfer); 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 b98a036d9..00fbae679 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 @@ -18,6 +18,7 @@ package org.teavm.jso.webaudio; import org.teavm.jso.JSClass; import org.teavm.jso.JSProperty; import org.teavm.jso.dom.events.EventListener; +import org.teavm.jso.dom.events.Registration; @JSClass public class OfflineAudioContext extends AudioContext { @@ -27,6 +28,10 @@ public class OfflineAudioContext extends AudioContext { @JSProperty("oncomplete") public native EventListener getOnComplete(); + public final Registration onComplete(EventListener listener) { + return onEvent("complete", listener); + } + public native AudioBuffer startRendering(); @Override diff --git a/jso/apis/src/main/java/org/teavm/jso/webaudio/OscillatorNode.java b/jso/apis/src/main/java/org/teavm/jso/webaudio/OscillatorNode.java index 849a0b8f7..612434750 100644 --- a/jso/apis/src/main/java/org/teavm/jso/webaudio/OscillatorNode.java +++ b/jso/apis/src/main/java/org/teavm/jso/webaudio/OscillatorNode.java @@ -17,6 +17,7 @@ package org.teavm.jso.webaudio; import org.teavm.jso.JSProperty; import org.teavm.jso.dom.events.EventListener; +import org.teavm.jso.dom.events.Registration; public interface OscillatorNode extends AudioNode { String TYPE_SINE = "sine"; @@ -43,6 +44,10 @@ public interface OscillatorNode extends AudioNode { @JSProperty("onended") EventListener getOnEnded(); + default Registration onEnded(EventListener listener) { + return onEvent("ended", listener); + } + void start(double when); void start(); diff --git a/jso/apis/src/main/java/org/teavm/jso/webaudio/ScriptProcessorNode.java b/jso/apis/src/main/java/org/teavm/jso/webaudio/ScriptProcessorNode.java index fc600c64e..684be1fca 100644 --- a/jso/apis/src/main/java/org/teavm/jso/webaudio/ScriptProcessorNode.java +++ b/jso/apis/src/main/java/org/teavm/jso/webaudio/ScriptProcessorNode.java @@ -17,6 +17,7 @@ package org.teavm.jso.webaudio; import org.teavm.jso.JSProperty; import org.teavm.jso.dom.events.EventListener; +import org.teavm.jso.dom.events.Registration; public interface ScriptProcessorNode extends AudioNode { @JSProperty("onaudioprocess") @@ -25,6 +26,10 @@ public interface ScriptProcessorNode extends AudioNode { @JSProperty("onaudioprocess") void setOnAudioProcess(EventListener event); + default Registration onAudioProcess(EventListener listener) { + return onEvent("audioprocess", listener); + } + @JSProperty int getBufferSize(); } 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 ffbb4c521..f60fb2026 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 @@ -21,12 +21,14 @@ import org.teavm.jso.JSObject; import org.teavm.jso.JSProperty; import org.teavm.jso.dom.events.Event; import org.teavm.jso.dom.events.EventListener; +import org.teavm.jso.dom.events.EventTarget; import org.teavm.jso.dom.events.MessageEvent; +import org.teavm.jso.dom.events.Registration; import org.teavm.jso.typedarrays.ArrayBuffer; import org.teavm.jso.typedarrays.ArrayBufferView; @JSClass -public class WebSocket implements JSObject { +public class WebSocket implements JSObject, EventTarget { public WebSocket(String url) { } @@ -36,17 +38,21 @@ public class WebSocket implements JSObject { public WebSocket(String url, String[] protocols) { } - @JSProperty("onclose") - public native void onClose(EventListener eventListener); + public final Registration onClose(EventListener eventListener) { + return onEvent("close", eventListener); + } - @JSProperty("onerror") - public native void onError(EventListener eventListener); + public final Registration onError(EventListener eventListener) { + return onEvent("error", eventListener); + } - @JSProperty("onmessage") - public native void onMessage(EventListener eventListener); + public final Registration onMessage(EventListener eventListener) { + return onEvent("message", eventListener); + } - @JSProperty("onopen") - public native void onOpen(EventListener eventListener); + public final Registration onOpen(EventListener eventListener) { + return onEvent("open", eventListener); + } @JSBody(params = "url", script = "return new WebSocket(url);") @Deprecated @@ -95,4 +101,19 @@ public class WebSocket implements JSObject { @JSBody(script = "return typeof WebSocket !== 'undefined';") public static native boolean isSupported(); + + @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/AbstractWorker.java b/jso/apis/src/main/java/org/teavm/jso/workers/AbstractWorker.java index 223ec17da..173fe1924 100644 --- a/jso/apis/src/main/java/org/teavm/jso/workers/AbstractWorker.java +++ b/jso/apis/src/main/java/org/teavm/jso/workers/AbstractWorker.java @@ -16,12 +16,13 @@ package org.teavm.jso.workers; import org.teavm.jso.JSObject; -import org.teavm.jso.JSProperty; import org.teavm.jso.dom.events.ErrorEvent; import org.teavm.jso.dom.events.EventListener; import org.teavm.jso.dom.events.EventTarget; +import org.teavm.jso.dom.events.Registration; public interface AbstractWorker extends JSObject, EventTarget { - @JSProperty("onerror") - void onError(EventListener listener); + default Registration onError(EventListener listener) { + return onEvent("error", listener); + } } diff --git a/jso/apis/src/main/java/org/teavm/jso/workers/MessagePort.java b/jso/apis/src/main/java/org/teavm/jso/workers/MessagePort.java index be6eb97cb..e667e4c81 100644 --- a/jso/apis/src/main/java/org/teavm/jso/workers/MessagePort.java +++ b/jso/apis/src/main/java/org/teavm/jso/workers/MessagePort.java @@ -15,10 +15,10 @@ */ package org.teavm.jso.workers; -import org.teavm.jso.JSProperty; import org.teavm.jso.dom.events.EventListener; import org.teavm.jso.dom.events.EventTarget; import org.teavm.jso.dom.events.MessageEvent; +import org.teavm.jso.dom.events.Registration; public interface MessagePort extends EventTarget { void postMessage(Object message); @@ -27,9 +27,11 @@ public interface MessagePort extends EventTarget { void close(); - @JSProperty("onmessage") - void onMessage(EventListener message); + default Registration onMessage(EventListener message) { + return onEvent("message", message); + } - @JSProperty("onmessageerror") - void onMessageError(EventListener message); + default Registration onMessageError(EventListener message) { + return onEvent("messageerror", message); + } } 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 ccd63a433..e2342a7ce 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 @@ -16,11 +16,14 @@ 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.Registration; +@JSClass public class SharedWorker implements AbstractWorker { public SharedWorker(String url) { } @@ -32,9 +35,6 @@ public class SharedWorker implements AbstractWorker { @JSProperty public native MessagePort getPort(); - @Override - public native void onError(EventListener listener); - @Override public native void addEventListener(String type, EventListener listener, boolean useCapture); 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 63beb5e4b..7738d4139 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 @@ -22,6 +22,7 @@ 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; +import org.teavm.jso.dom.events.Registration; @JSClass public class Worker implements AbstractWorker { @@ -32,16 +33,14 @@ public class Worker implements AbstractWorker { @Deprecated public static native Worker create(String url); - @JSProperty("onmessage") - public native void onMessage(EventListener listener); + public Registration onMessage(EventListener listener) { + return onEvent("message", listener); + } public native void postMessage(Object message); public native void terminate(); - @Override - public native void onError(EventListener listener); - @Override public native void addEventListener(String type, EventListener listener, boolean useCapture); 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 b6c603c86..80149e853 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 @@ -31,7 +31,7 @@ public final class Client { } public static void main(String[] args) { - helloButton.listenClick(evt -> sayHello()); + helloButton.onClick(evt -> sayHello()); } private static void sayHello() { diff --git a/samples/kotlin/build.gradle.kts b/samples/kotlin/build.gradle.kts index 479bd6d47..4459d579b 100644 --- a/samples/kotlin/build.gradle.kts +++ b/samples/kotlin/build.gradle.kts @@ -15,7 +15,7 @@ */ plugins { - kotlin("multiplatform") version "1.9.20" + kotlin("jvm") version "1.9.20" war id("org.teavm") } @@ -29,6 +29,4 @@ teavm.js { mainClass = "org.teavm.samples.kotlin.HelloKt" } -kotlin { - jvm() -} \ No newline at end of file +kotlin.jvmToolchain(17) diff --git a/samples/kotlin/src/main/kotlin/org/teavm/samples/kotlin/Hello.kt b/samples/kotlin/src/main/kotlin/org/teavm/samples/kotlin/Hello.kt index d893d163f..e40ab1481 100644 --- a/samples/kotlin/src/main/kotlin/org/teavm/samples/kotlin/Hello.kt +++ b/samples/kotlin/src/main/kotlin/org/teavm/samples/kotlin/Hello.kt @@ -20,5 +20,5 @@ import org.teavm.jso.browser.* fun main() { val document = Window.current().document - document.getElementById("hello-kotlin").addEventListener("click") { Window.alert("Hello, developer!") } + document.getElementById("hello-kotlin").onClick { Window.alert("Hello, developer!") } } diff --git a/samples/scala/src/teavm/scala/org/teavm/samples/scala/Client.scala b/samples/scala/src/teavm/scala/org/teavm/samples/scala/Client.scala index ae2cff137..d1f3882e4 100644 --- a/samples/scala/src/teavm/scala/org/teavm/samples/scala/Client.scala +++ b/samples/scala/src/teavm/scala/org/teavm/samples/scala/Client.scala @@ -11,7 +11,7 @@ object Client { val exprElem = doc.getElementById("expr").asInstanceOf[HTMLInputElement] val calcElem = doc.getElementById("calculate") val resultList = doc.getElementById("result-list") - calcElem.listenClick((e: MouseEvent) => { + calcElem.onClick((e: MouseEvent) => { parse(exprElem.getValue.toSeq) match { case (None, _) => Window.alert("Error parsing expression"); case (Some(x), Nil) => diff --git a/samples/software3d/src/jvmMain/kotlin/org/teavm/samples/software3d/teavm/Worker.kt b/samples/software3d/src/jvmMain/kotlin/org/teavm/samples/software3d/teavm/Worker.kt index 3bf045e98..f01f841db 100644 --- a/samples/software3d/src/jvmMain/kotlin/org/teavm/samples/software3d/teavm/Worker.kt +++ b/samples/software3d/src/jvmMain/kotlin/org/teavm/samples/software3d/teavm/Worker.kt @@ -26,7 +26,7 @@ import org.teavm.samples.software3d.scenes.geometry fun worker() { val worker = RenderWorker() - Window.worker().listenMessage { + Window.worker().onMessage { val dataJson = it.data as JSMapLike<*> when ((dataJson["type"] as JSString).stringValue()) { "init" -> worker.init(dataJson) 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 4825c942f..54cc2943d 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 @@ -37,7 +37,7 @@ public final class Storage { } HTMLButtonElement saveButton = document.getElementById("save-button").cast(); - saveButton.listenClick(e -> { + saveButton.onClick(e -> { var key = document.getElementById("key").cast().getValue(); var value = document.getElementById("value").cast().getValue(); @@ -47,7 +47,7 @@ public final class Storage { } }); HTMLButtonElement deleteButton = document.getElementById("delete-button").cast(); - deleteButton.listenClick(e -> { + deleteButton.onClick(e -> { String key = document.getElementById("key").cast().getValue(); if (key != null && !key.isEmpty()) { storage.removeItem(key); @@ -55,7 +55,7 @@ public final class Storage { } }); HTMLButtonElement deleteAllButton = document.getElementById("delete-all-button").cast(); - deleteAllButton.listenClick(e -> { + deleteAllButton.onClick(e -> { storage.clear(); draw(); }); diff --git a/samples/web-apis/src/main/java/org/teavm/samples/webapis/Video.java b/samples/web-apis/src/main/java/org/teavm/samples/webapis/Video.java index 7020ddf21..851fe411e 100644 --- a/samples/web-apis/src/main/java/org/teavm/samples/webapis/Video.java +++ b/samples/web-apis/src/main/java/org/teavm/samples/webapis/Video.java @@ -57,30 +57,30 @@ public final class Video { var divButtons = document.createElement("div") .withAttr("id", "button") - .withChild("button", elem -> elem.withText("load()").listenClick(evt -> video.load())) - .withChild("button", elem -> elem.withText("play()").listenClick(evt -> video.play())) - .withChild("button", elem -> elem.withText("pause()").listenClick(evt -> video.pause())) + .withChild("button", elem -> elem.withText("load()").onClick(evt -> video.load())) + .withChild("button", elem -> elem.withText("play()").onClick(evt -> video.play())) + .withChild("button", elem -> elem.withText("pause()").onClick(evt -> video.pause())) .withChild("br") .withChild("button", elem -> elem.withText("currentTime+=10") - .listenClick(evt -> video.addCurrentTime(10))) + .onClick(evt -> video.addCurrentTime(10))) .withChild("button", elem -> elem.withText("currentTime-=10") - .listenClick(evt -> video.addCurrentTime(-10))) + .onClick(evt -> video.addCurrentTime(-10))) .withChild("button", elem -> elem.withText("currentTime-=50") - .listenClick(evt -> video.setCurrentTime(50))) + .onClick(evt -> video.setCurrentTime(50))) .withChild("br") .withChild("button", elem -> elem.withText("playbackRate++") - .listenClick(evt -> video.addPlaybackRate(1))) + .onClick(evt -> video.addPlaybackRate(1))) .withChild("button", elem -> elem.withText("playbackRate--") - .listenClick(evt -> video.addPlaybackRate(-1))) + .onClick(evt -> video.addPlaybackRate(-1))) .withChild("button", elem -> elem.withText("playbackRate+=0.1") - .listenClick(evt -> video.addPlaybackRate(0.1))) + .onClick(evt -> video.addPlaybackRate(0.1))) .withChild("button", elem -> elem.withText("playbackRate-=0.1") - .listenClick(evt -> video.addPlaybackRate(-0.1))) + .onClick(evt -> video.addPlaybackRate(-0.1))) .withChild("br") - .withChild("button", elem -> elem.withText("volume+=1").listenClick(evt -> video.addVolume(0.1F))) - .withChild("button", elem -> elem.withText("volume-=1").listenClick(evt -> video.addVolume(-0.1F))) - .withChild("button", elem -> elem.withText("mute").listenClick(evt -> video.setMuted(true))) - .withChild("button", elem -> elem.withText("unmute").listenClick(evt -> video.setMuted(false))); + .withChild("button", elem -> elem.withText("volume+=1").onClick(evt -> video.addVolume(0.1F))) + .withChild("button", elem -> elem.withText("volume-=1").onClick(evt -> video.addVolume(-0.1F))) + .withChild("button", elem -> elem.withText("mute").onClick(evt -> video.setMuted(true))) + .withChild("button", elem -> elem.withText("unmute").onClick(evt -> video.setMuted(false))); var body = document.getBody(); body.appendChild(divVideo);