Fix IndexedDB wrappers

This commit is contained in:
Alexey Andreev 2015-04-04 18:29:18 +03:00
parent c3f8764bdc
commit 30d601e807
10 changed files with 188 additions and 53 deletions

View File

@ -473,7 +473,11 @@ TeaVMThread.prototype.start = function(callback) {
throw new Error("Another thread is running"); throw new Error("Another thread is running");
} }
this.status = 0; this.status = 0;
this.completeCallback = callback ? callback : function() {}; this.completeCallback = callback ? callback : function(result) {
if (result instanceof Error) {
throw result;
}
};
this.run(); this.run();
} }
TeaVMThread.prototype.resume = function() { TeaVMThread.prototype.resume = function() {

View File

@ -1,3 +1,18 @@
/*
* Copyright 2015 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.dom.indexeddb; package org.teavm.dom.indexeddb;
import org.teavm.jso.JSObject; import org.teavm.jso.JSObject;

View File

@ -37,7 +37,7 @@ public abstract class IDBIndex implements JSObject, IDBCursorSource {
if (JS.getType(result) == JSType.STRING) { if (JS.getType(result) == JSType.STRING) {
return new String[] { JS.unwrapString(result) }; return new String[] { JS.unwrapString(result) };
} else { } else {
return JS.unwrapArray((JSStringArray)result); return JS.unwrapStringArray((JSStringArray)result);
} }
} }

View File

@ -1,3 +1,18 @@
/*
* Copyright 2015 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.dom.indexeddb; package org.teavm.dom.indexeddb;
import org.teavm.jso.JSBody; import org.teavm.jso.JSBody;

View File

@ -33,7 +33,7 @@ public abstract class IDBObjectStore implements JSObject, IDBCursorSource {
if (JS.getType(result) == JSType.STRING) { if (JS.getType(result) == JSType.STRING) {
return new String[] { JS.unwrapString(result) }; return new String[] { JS.unwrapString(result) };
} else { } else {
return JS.unwrapArray((JSStringArray)result); return JS.unwrapStringArray((JSStringArray)result);
} }
} }

View File

@ -24,7 +24,7 @@ import org.teavm.jso.JSProperty;
* @author Alexey Andreev * @author Alexey Andreev
*/ */
public abstract class IDBObjectStoreParameters implements JSObject { public abstract class IDBObjectStoreParameters implements JSObject {
@JSBody(params = "", script = "return {};") @JSBody(params = {}, script = "return {};")
public static native IDBObjectStoreParameters create(); public static native IDBObjectStoreParameters create();
public final IDBObjectStoreParameters keyPath(String... keys) { public final IDBObjectStoreParameters keyPath(String... keys) {

View File

@ -376,7 +376,7 @@ public final class JS {
return result; return result;
} }
public static String[] unwrapArray(JSStringArray array) { public static String[] unwrapStringArray(JSStringArray array) {
String[] result = new String[array.getLength()]; String[] result = new String[array.getLength()];
for (int i = 0; i < result.length; ++i) { for (int i = 0; i < result.length; ++i) {
result[i] = array.get(i); result[i] = array.get(i);
@ -384,18 +384,18 @@ public final class JS {
return result; return result;
} }
public static String[][] unwrapArray2(JSArray<JSStringArray> array) { public static String[][] unwrapStringArray2(JSArray<JSStringArray> array) {
String[][] result = new String[array.getLength()][]; String[][] result = new String[array.getLength()][];
for (int i = 0; i < result.length; ++i) { for (int i = 0; i < result.length; ++i) {
result[i] = unwrapArray(array.get(i)); result[i] = unwrapStringArray(array.get(i));
} }
return result; return result;
} }
public static String[][][] unwrapArray3(JSArray<JSArray<JSStringArray>> array) { public static String[][][] unwrapStringArray3(JSArray<JSArray<JSStringArray>> array) {
String[][][] result = new String[array.getLength()][][]; String[][][] result = new String[array.getLength()][][];
for (int i = 0; i < result.length; ++i) { for (int i = 0; i < result.length; ++i) {
result[i] = unwrapArray2(array.get(i)); result[i] = unwrapStringArray2(array.get(i));
} }
return result; return result;
} }

View File

@ -502,19 +502,26 @@ class JavascriptNativeProcessor {
if (type instanceof ValueType.Primitive) { if (type instanceof ValueType.Primitive) {
switch (((ValueType.Primitive)type).getKind()) { switch (((ValueType.Primitive)type).getKind()) {
case BOOLEAN: case BOOLEAN:
return unwrap(var, "unwrapBoolean", ValueType.BOOLEAN, location.getSourceLocation()); return unwrap(var, "unwrapBoolean", ValueType.parse(JSObject.class), ValueType.BOOLEAN,
location.getSourceLocation());
case BYTE: case BYTE:
return unwrap(var, "unwrapByte", ValueType.BYTE, location.getSourceLocation()); return unwrap(var, "unwrapByte", ValueType.parse(JSObject.class), ValueType.BYTE,
location.getSourceLocation());
case SHORT: case SHORT:
return unwrap(var, "unwrapShort", ValueType.SHORT, location.getSourceLocation()); return unwrap(var, "unwrapShort", ValueType.parse(JSObject.class), ValueType.SHORT,
location.getSourceLocation());
case INTEGER: case INTEGER:
return unwrap(var, "unwrapInt", ValueType.INTEGER, location.getSourceLocation()); return unwrap(var, "unwrapInt", ValueType.parse(JSObject.class), ValueType.INTEGER,
location.getSourceLocation());
case CHARACTER: case CHARACTER:
return unwrap(var, "unwrapCharacter", ValueType.CHARACTER, location.getSourceLocation()); return unwrap(var, "unwrapCharacter", ValueType.parse(JSObject.class), ValueType.CHARACTER,
location.getSourceLocation());
case DOUBLE: case DOUBLE:
return unwrap(var, "unwrapDouble", ValueType.DOUBLE, location.getSourceLocation()); return unwrap(var, "unwrapDouble", ValueType.parse(JSObject.class), ValueType.DOUBLE,
location.getSourceLocation());
case FLOAT: case FLOAT:
return unwrap(var, "unwrapFloat", ValueType.FLOAT, location.getSourceLocation()); return unwrap(var, "unwrapFloat", ValueType.parse(JSObject.class), ValueType.FLOAT,
location.getSourceLocation());
case LONG: case LONG:
break; break;
} }
@ -523,8 +530,9 @@ class JavascriptNativeProcessor {
if (className.equals(JSObject.class.getName())) { if (className.equals(JSObject.class.getName())) {
return var; return var;
} else if (className.equals("java.lang.String")) { } else if (className.equals("java.lang.String")) {
return unwrap(var, "unwrapString", ValueType.object("java.lang.String"), location.getSourceLocation()); return unwrap(var, "unwrapString", ValueType.parse(JSObject.class), ValueType.parse(String.class),
} else { location.getSourceLocation());
} else if (isNative(className)) {
Variable result = program.createVariable(); Variable result = program.createVariable();
CastInstruction castInsn = new CastInstruction(); CastInstruction castInsn = new CastInstruction();
castInsn.setReceiver(result); castInsn.setReceiver(result);
@ -534,16 +542,58 @@ class JavascriptNativeProcessor {
replacement.add(castInsn); replacement.add(castInsn);
return result; return result;
} }
} else if (type instanceof ValueType.Array) {
return unwrapArray(location, var, (ValueType.Array)type);
} }
diagnostics.error(location, "Unsupported type: {{t0}}", type); diagnostics.error(location, "Unsupported type: {{t0}}", type);
return var; return var;
} }
private Variable unwrap(Variable var, String methodName, ValueType resultType, InstructionLocation location) { private Variable unwrapArray(CallLocation location, Variable var, ValueType.Array type) {
ValueType itemType = type;
int degree = 0;
while (itemType instanceof ValueType.Array) {
++degree;
itemType = ((ValueType.Array)itemType).getItemType();
}
if (degree > 3) {
diagnostics.error(location, "Unsupported type: {{t0}}", type);
return var;
}
if (itemType instanceof ValueType.Object) {
String className = ((ValueType.Object)itemType).getClassName();
if (className.equals("java.lang.String")) {
String methodName = "unwrapStringArray";
if (degree > 1) {
methodName += degree;
}
ValueType argType = degree == 1 ? ValueType.parse(JSStringArray.class) :
ValueType.parse(JSArray.class);
return unwrap(var, methodName, argType, type, location.getSourceLocation());
} else if (isNative(className)) {
return unwrapObjectArray(location, var, degree, itemType, type);
}
}
diagnostics.error(location, "Unsupported type: {{t0}}", type);
return var;
}
private Variable unwrap(Variable var, String methodName, ValueType argType, ValueType resultType,
InstructionLocation location) {
if (!argType.isObject(JSObject.class.getName())) {
Variable castValue = program.createVariable();
CastInstruction castInsn = new CastInstruction();
castInsn.setValue(var);
castInsn.setReceiver(castValue);
castInsn.setLocation(location);
castInsn.setTargetType(argType);
replacement.add(castInsn);
var = castValue;
}
Variable result = program.createVariable(); Variable result = program.createVariable();
InvokeInstruction insn = new InvokeInstruction(); InvokeInstruction insn = new InvokeInstruction();
insn.setMethod(new MethodReference(JS.class.getName(), methodName, ValueType.object(JSObject.class.getName()), insn.setMethod(new MethodReference(JS.class.getName(), methodName, argType, resultType));
resultType));
insn.getArguments().add(var); insn.getArguments().add(var);
insn.setReceiver(result); insn.setReceiver(result);
insn.setType(InvocationType.SPECIAL); insn.setType(InvocationType.SPECIAL);
@ -552,6 +602,57 @@ class JavascriptNativeProcessor {
return result; return result;
} }
private Variable unwrapObjectArray(CallLocation location, Variable var, int degree, ValueType itemType,
ValueType expectedType) {
String methodName = "unwrapArray";
if (degree > 1) {
methodName += degree;
}
ValueType resultType = ValueType.parse(JSObject.class);
for (int i = 0; i < degree; ++i) {
resultType = ValueType.arrayOf(resultType);
}
Variable classVar = program.createVariable();
ClassConstantInstruction classInsn = new ClassConstantInstruction();
classInsn.setConstant(itemType);
classInsn.setReceiver(classVar);
classInsn.setLocation(location.getSourceLocation());
replacement.add(classInsn);
Variable castValue = program.createVariable();
CastInstruction castInsn = new CastInstruction();
castInsn.setValue(var);
castInsn.setReceiver(castValue);
castInsn.setLocation(location.getSourceLocation());
castInsn.setTargetType(ValueType.parse(JSArray.class));
replacement.add(castInsn);
var = castValue;
Variable result = program.createVariable();
InvokeInstruction insn = new InvokeInstruction();
insn.setMethod(new MethodReference(JS.class.getName(), methodName, ValueType.parse(Class.class),
ValueType.parse(JSArray.class), resultType));
insn.getArguments().add(classVar);
insn.getArguments().add(var);
insn.setReceiver(result);
insn.setType(InvocationType.SPECIAL);
insn.setLocation(location.getSourceLocation());
replacement.add(insn);
var = result;
Variable castResult = program.createVariable();
castInsn = new CastInstruction();
castInsn.setValue(var);
castInsn.setReceiver(castResult);
castInsn.setLocation(location.getSourceLocation());
castInsn.setTargetType(expectedType);
replacement.add(castInsn);
var = castResult;
return var;
}
private Variable wrapArgument(CallLocation location, Variable var, ValueType type) { private Variable wrapArgument(CallLocation location, Variable var, ValueType type) {
if (type instanceof ValueType.Object) { if (type instanceof ValueType.Object) {
String className = ((ValueType.Object)type).getClassName(); String className = ((ValueType.Object)type).getClassName();

View File

@ -18,8 +18,8 @@ package org.teavm.samples.hello;
import org.teavm.dom.ajax.ReadyStateChangeHandler; import org.teavm.dom.ajax.ReadyStateChangeHandler;
import org.teavm.dom.ajax.XMLHttpRequest; import org.teavm.dom.ajax.XMLHttpRequest;
import org.teavm.dom.browser.Window; import org.teavm.dom.browser.Window;
import org.teavm.dom.events.Event;
import org.teavm.dom.events.EventListener; import org.teavm.dom.events.EventListener;
import org.teavm.dom.events.MouseEvent;
import org.teavm.dom.html.HTMLButtonElement; import org.teavm.dom.html.HTMLButtonElement;
import org.teavm.dom.html.HTMLDocument; import org.teavm.dom.html.HTMLDocument;
import org.teavm.dom.html.HTMLElement; import org.teavm.dom.html.HTMLElement;
@ -36,8 +36,8 @@ public final class Client {
} }
public static void main(String[] args) { public static void main(String[] args) {
helloButton.addEventListener("click", new EventListener() { helloButton.addEventListener("click", new EventListener<MouseEvent>() {
@Override public void handleEvent(Event evt) { @Override public void handleEvent(MouseEvent evt) {
sayHello(); sayHello();
} }
}); });

View File

@ -16,8 +16,8 @@
package org.teavm.samples.video; package org.teavm.samples.video;
import org.teavm.dom.browser.Window; import org.teavm.dom.browser.Window;
import org.teavm.dom.events.Event;
import org.teavm.dom.events.EventListener; import org.teavm.dom.events.EventListener;
import org.teavm.dom.events.MouseEvent;
import org.teavm.dom.html.HTMLBodyElement; import org.teavm.dom.html.HTMLBodyElement;
import org.teavm.dom.html.HTMLButtonElement; import org.teavm.dom.html.HTMLButtonElement;
import org.teavm.dom.html.HTMLDocument; import org.teavm.dom.html.HTMLDocument;
@ -69,126 +69,126 @@ public final class Player {
HTMLButtonElement loadButton = (HTMLButtonElement)document.createElement("button"); HTMLButtonElement loadButton = (HTMLButtonElement)document.createElement("button");
loadButton.appendChild(document.createTextNode("load()")); loadButton.appendChild(document.createTextNode("load()"));
loadButton.addEventListener("click", new EventListener() { loadButton.addEventListener("click", new EventListener<MouseEvent>() {
@Override @Override
public void handleEvent(Event evt) { public void handleEvent(MouseEvent evt) {
video.load(); video.load();
} }
}); });
HTMLButtonElement playButton = (HTMLButtonElement)document.createElement("button"); HTMLButtonElement playButton = (HTMLButtonElement)document.createElement("button");
playButton.appendChild(document.createTextNode("play()")); playButton.appendChild(document.createTextNode("play()"));
playButton.addEventListener("click", new EventListener() { playButton.addEventListener("click", new EventListener<MouseEvent>() {
@Override @Override
public void handleEvent(Event evt) { public void handleEvent(MouseEvent evt) {
video.play(); video.play();
} }
}); });
HTMLButtonElement pauseButton = (HTMLButtonElement)document.createElement("button"); HTMLButtonElement pauseButton = (HTMLButtonElement)document.createElement("button");
pauseButton.appendChild(document.createTextNode("pause()")); pauseButton.appendChild(document.createTextNode("pause()"));
pauseButton.addEventListener("click", new EventListener() { pauseButton.addEventListener("click", new EventListener<MouseEvent>() {
@Override @Override
public void handleEvent(Event evt) { public void handleEvent(MouseEvent evt) {
video.pause(); video.pause();
} }
}); });
HTMLButtonElement currentTimePlusButton = (HTMLButtonElement)document.createElement("button"); HTMLButtonElement currentTimePlusButton = (HTMLButtonElement)document.createElement("button");
currentTimePlusButton.appendChild(document.createTextNode("currentTime+=10")); currentTimePlusButton.appendChild(document.createTextNode("currentTime+=10"));
currentTimePlusButton.addEventListener("click", new EventListener() { currentTimePlusButton.addEventListener("click", new EventListener<MouseEvent>() {
@Override @Override
public void handleEvent(Event evt) { public void handleEvent(MouseEvent evt) {
video.setCurrentTime(video.getCurrentTime() + 10); video.setCurrentTime(video.getCurrentTime() + 10);
} }
}); });
HTMLButtonElement currentTimeMinusButton = (HTMLButtonElement)document.createElement("button"); HTMLButtonElement currentTimeMinusButton = (HTMLButtonElement)document.createElement("button");
currentTimeMinusButton.appendChild(document.createTextNode("currentTime-=10")); currentTimeMinusButton.appendChild(document.createTextNode("currentTime-=10"));
currentTimeMinusButton.addEventListener("click", new EventListener() { currentTimeMinusButton.addEventListener("click", new EventListener<MouseEvent>() {
@Override @Override
public void handleEvent(Event evt) { public void handleEvent(MouseEvent evt) {
video.setCurrentTime(video.getCurrentTime() - 10); video.setCurrentTime(video.getCurrentTime() - 10);
} }
}); });
HTMLButtonElement currentTime50Button = (HTMLButtonElement)document.createElement("button"); HTMLButtonElement currentTime50Button = (HTMLButtonElement)document.createElement("button");
currentTime50Button.appendChild(document.createTextNode("currentTime=50")); currentTime50Button.appendChild(document.createTextNode("currentTime=50"));
currentTime50Button.addEventListener("click", new EventListener() { currentTime50Button.addEventListener("click", new EventListener<MouseEvent>() {
@Override @Override
public void handleEvent(Event evt) { public void handleEvent(MouseEvent evt) {
video.setCurrentTime(50); video.setCurrentTime(50);
} }
}); });
HTMLButtonElement playbackRateIncrementButton = (HTMLButtonElement)document.createElement("button"); HTMLButtonElement playbackRateIncrementButton = (HTMLButtonElement)document.createElement("button");
playbackRateIncrementButton.appendChild(document.createTextNode("playbackRate++")); playbackRateIncrementButton.appendChild(document.createTextNode("playbackRate++"));
playbackRateIncrementButton.addEventListener("click", new EventListener() { playbackRateIncrementButton.addEventListener("click", new EventListener<MouseEvent>() {
@Override @Override
public void handleEvent(Event evt) { public void handleEvent(MouseEvent evt) {
video.setPlaybackRate(video.getPlaybackRate() + 1); video.setPlaybackRate(video.getPlaybackRate() + 1);
} }
}); });
HTMLButtonElement playbackRateDecrementButton = (HTMLButtonElement)document.createElement("button"); HTMLButtonElement playbackRateDecrementButton = (HTMLButtonElement)document.createElement("button");
playbackRateDecrementButton.appendChild(document.createTextNode("playbackRate--")); playbackRateDecrementButton.appendChild(document.createTextNode("playbackRate--"));
playbackRateDecrementButton.addEventListener("click", new EventListener() { playbackRateDecrementButton.addEventListener("click", new EventListener<MouseEvent>() {
@Override @Override
public void handleEvent(Event evt) { public void handleEvent(MouseEvent evt) {
video.setPlaybackRate(video.getPlaybackRate() - 1); video.setPlaybackRate(video.getPlaybackRate() - 1);
} }
}); });
HTMLButtonElement playbackRatePlusButton = (HTMLButtonElement)document.createElement("button"); HTMLButtonElement playbackRatePlusButton = (HTMLButtonElement)document.createElement("button");
playbackRatePlusButton.appendChild(document.createTextNode("playbackRate+=0.1")); playbackRatePlusButton.appendChild(document.createTextNode("playbackRate+=0.1"));
playbackRatePlusButton.addEventListener("click", new EventListener() { playbackRatePlusButton.addEventListener("click", new EventListener<MouseEvent>() {
@Override @Override
public void handleEvent(Event evt) { public void handleEvent(MouseEvent evt) {
video.setPlaybackRate(video.getPlaybackRate() + 0.1); video.setPlaybackRate(video.getPlaybackRate() + 0.1);
} }
}); });
HTMLButtonElement playbackRateMinusButton = (HTMLButtonElement)document.createElement("button"); HTMLButtonElement playbackRateMinusButton = (HTMLButtonElement)document.createElement("button");
playbackRateMinusButton.appendChild(document.createTextNode("playbackRate-=0.1")); playbackRateMinusButton.appendChild(document.createTextNode("playbackRate-=0.1"));
playbackRateMinusButton.addEventListener("click", new EventListener() { playbackRateMinusButton.addEventListener("click", new EventListener<MouseEvent>() {
@Override @Override
public void handleEvent(Event evt) { public void handleEvent(MouseEvent evt) {
video.setPlaybackRate(video.getPlaybackRate() - 0.1); video.setPlaybackRate(video.getPlaybackRate() - 0.1);
} }
}); });
HTMLButtonElement volumePlusButton = (HTMLButtonElement)document.createElement("button"); HTMLButtonElement volumePlusButton = (HTMLButtonElement)document.createElement("button");
volumePlusButton.appendChild(document.createTextNode("volume+=0.1")); volumePlusButton.appendChild(document.createTextNode("volume+=0.1"));
volumePlusButton.addEventListener("click", new EventListener() { volumePlusButton.addEventListener("click", new EventListener<MouseEvent>() {
@Override @Override
public void handleEvent(Event evt) { public void handleEvent(MouseEvent evt) {
video.setVolume(video.getVolume() + 0.1f); video.setVolume(video.getVolume() + 0.1f);
} }
}); });
HTMLButtonElement volumeMinusButton = (HTMLButtonElement)document.createElement("button"); HTMLButtonElement volumeMinusButton = (HTMLButtonElement)document.createElement("button");
volumeMinusButton.appendChild(document.createTextNode("volume-=0.1")); volumeMinusButton.appendChild(document.createTextNode("volume-=0.1"));
volumeMinusButton.addEventListener("click", new EventListener() { volumeMinusButton.addEventListener("click", new EventListener<MouseEvent>() {
@Override @Override
public void handleEvent(Event evt) { public void handleEvent(MouseEvent evt) {
video.setVolume(video.getVolume() - 0.1f); video.setVolume(video.getVolume() - 0.1f);
} }
}); });
HTMLButtonElement muteButton = (HTMLButtonElement)document.createElement("button"); HTMLButtonElement muteButton = (HTMLButtonElement)document.createElement("button");
muteButton.appendChild(document.createTextNode("muted=true")); muteButton.appendChild(document.createTextNode("muted=true"));
muteButton.addEventListener("click", new EventListener() { muteButton.addEventListener("click", new EventListener<MouseEvent>() {
@Override @Override
public void handleEvent(Event evt) { public void handleEvent(MouseEvent evt) {
video.setMuted(true); video.setMuted(true);
} }
}); });
HTMLButtonElement unmuteButton = (HTMLButtonElement)document.createElement("button"); HTMLButtonElement unmuteButton = (HTMLButtonElement)document.createElement("button");
unmuteButton.appendChild(document.createTextNode("muted=false")); unmuteButton.appendChild(document.createTextNode("muted=false"));
unmuteButton.addEventListener("click", new EventListener() { unmuteButton.addEventListener("click", new EventListener<MouseEvent>() {
@Override @Override
public void handleEvent(Event evt) { public void handleEvent(MouseEvent evt) {
video.setMuted(false); video.setMuted(false);
} }
}); });