Further removal of direct JavaScript generation from classlib

This commit is contained in:
Alexey Andreev 2015-02-09 19:36:45 +04:00
parent 82b110ad4c
commit dd25ae4759
27 changed files with 288 additions and 441 deletions

View File

@ -29,8 +29,6 @@ import org.teavm.vm.spi.TeaVMPlugin;
public class JCLPlugin implements TeaVMPlugin {
@Override
public void install(TeaVMHost host) {
host.add(new EnumDependencySupport());
host.add(new EnumTransformer());
host.add(new ObjectEnrichRenderer());
ServiceLoaderSupport serviceLoaderSupp = new ServiceLoaderSupport(host.getClassLoader());
host.add(serviceLoaderSupp);

View File

@ -0,0 +1,54 @@
/*
* 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.classlib.java.lang;
import org.teavm.classlib.impl.unicode.UnicodeHelper;
import org.teavm.classlib.impl.unicode.UnicodeSupport;
import org.teavm.model.MethodReference;
import org.teavm.platform.metadata.MetadataGenerator;
import org.teavm.platform.metadata.MetadataGeneratorContext;
import org.teavm.platform.metadata.Resource;
import org.teavm.platform.metadata.StringResource;
/**
*
* @author Alexey Andreev
*/
public class CharacterMetadataGenerator implements MetadataGenerator {
@Override
public Resource generateMetadata(MetadataGeneratorContext context, MethodReference method) {
switch (method.getName()) {
case "obtainDigitMapping":
return generateObtainDigitMapping(context);
case "obtainClasses":
return generateObtainClasses(context);
default:
return null;
}
}
private Resource generateObtainDigitMapping(MetadataGeneratorContext context) {
StringResource res = context.createResource(StringResource.class);
res.setValue(UnicodeHelper.encodeIntByte(UnicodeSupport.getDigitValues()));
return res;
}
private Resource generateObtainClasses(MetadataGeneratorContext context) {
StringResource res = context.createResource(StringResource.class);
res.setValue(UnicodeHelper.compressRle(UnicodeSupport.getClasses()));
return res;
}
}

View File

@ -1,88 +0,0 @@
/*
* Copyright 2014 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.classlib.java.lang;
import java.io.IOException;
import org.teavm.classlib.impl.unicode.UnicodeHelper;
import org.teavm.classlib.impl.unicode.UnicodeSupport;
import org.teavm.codegen.SourceWriter;
import org.teavm.dependency.DependencyAgent;
import org.teavm.dependency.DependencyPlugin;
import org.teavm.dependency.MethodDependency;
import org.teavm.javascript.spi.Generator;
import org.teavm.javascript.spi.GeneratorContext;
import org.teavm.model.CallLocation;
import org.teavm.model.MethodReference;
/**
*
* @author Alexey Andreev
*/
public class CharacterNativeGenerator implements Generator, DependencyPlugin {
@Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
switch (methodRef.getName()) {
case "toLowerCase":
writer.append("return String.fromCharCode(").append(context.getParameterName(1))
.append(").toLowerCase().charCodeAt(0)|0;").softNewLine();
break;
case "toUpperCase":
writer.append("return String.fromCharCode(").append(context.getParameterName(1))
.append(").toUpperCase().charCodeAt(0)|0;").softNewLine();
break;
case "obtainDigitMapping":
generateObtainDigitMapping(writer);
break;
case "obtainClasses":
generateObtainClasses(writer);
break;
}
}
@Override
public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) {
switch (method.getReference().getName()) {
case "obtainDigitMapping":
case "obtainClasses":
method.getResult().propagate(agent.getType("java.lang.String"));
break;
}
}
private void generateObtainDigitMapping(SourceWriter writer) throws IOException {
String str = UnicodeHelper.encodeIntByte(UnicodeSupport.getDigitValues());
writer.append("return $rt_str(");
splitString(writer, str);
writer.append(");").softNewLine();
}
private void generateObtainClasses(SourceWriter writer) throws IOException {
String str = UnicodeHelper.compressRle(UnicodeSupport.getClasses());
writer.append("return $rt_str(");
splitString(writer, str);
writer.append(");").softNewLine();
}
private void splitString(SourceWriter writer, String str) throws IOException {
for (int i = 0; i < str.length(); i += 512) {
if (i > 0) {
writer.ws().append("+").newLine();
}
int j = Math.min(i + 512, str.length());
writer.append("\"").append(str.substring(i, j)).append("\"");
}
}
}

View File

@ -1,37 +0,0 @@
/*
* Copyright 2013 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.classlib.java.lang;
import java.io.IOException;
import org.teavm.javascript.spi.Injector;
import org.teavm.javascript.spi.InjectorContext;
import org.teavm.model.*;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class ClassNativeGenerator implements Injector {
@Override
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
switch (methodRef.getName()) {
case "getEnumConstantsImpl":
context.writeExpr(context.getArgument(0));
context.getWriter().append(".values()");
break;
}
}
}

View File

@ -1,41 +0,0 @@
/*
* Copyright 2013 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.classlib.java.lang;
import java.io.IOException;
import org.teavm.codegen.SourceWriter;
import org.teavm.javascript.spi.Generator;
import org.teavm.javascript.spi.GeneratorContext;
import org.teavm.model.MethodReference;
/**
*
* @author Alexey Andreev
*/
public class ConsoleOutputStreamGenerator implements Generator {
@Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
if (methodRef.getClassName().endsWith("_stderr")) {
if (methodRef.getName().equals("write")) {
writer.append("$rt_putStderr(").append(context.getParameterName(1)).append(");").softNewLine();
}
} else if (methodRef.getClassName().endsWith("_stdout")) {
if (methodRef.getName().equals("write")) {
writer.append("$rt_putStdout(").append(context.getParameterName(1)).append(");").softNewLine();
}
}
}
}

View File

@ -1,110 +0,0 @@
/*
* Copyright 2013 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.classlib.java.lang;
import java.io.IOException;
import org.teavm.codegen.SourceWriter;
import org.teavm.dependency.*;
import org.teavm.javascript.spi.Generator;
import org.teavm.javascript.spi.GeneratorContext;
import org.teavm.javascript.spi.Injector;
import org.teavm.javascript.spi.InjectorContext;
import org.teavm.model.CallLocation;
import org.teavm.model.MethodReference;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class ObjectNativeGenerator implements Generator, Injector, DependencyPlugin {
@Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
switch (methodRef.getDescriptor().getName()) {
case "<init>":
generateInit(context, writer);
break;
case "hashCode":
case "identity":
generateHashCode(context, writer);
break;
case "clone":
generateClone(context, writer);
break;
}
}
@Override
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
switch (methodRef.getName()) {
case "getClass":
generateGetClass(context);
break;
case "wrap":
generateWrap(context);
break;
}
}
@Override
public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) {
switch (method.getReference().getName()) {
case "clone":
method.getVariable(0).connect(method.getResult());
break;
case "getClass":
achieveGetClass(agent, method);
break;
case "wrap":
method.getVariable(1).connect(method.getResult());
break;
}
}
private void generateInit(GeneratorContext context, SourceWriter writer) throws IOException {
writer.append(context.getParameterName(0)).append(".$id = $rt_nextId();").softNewLine();
}
private void generateGetClass(InjectorContext context) throws IOException {
SourceWriter writer = context.getWriter();
writer.append("$rt_cls(");
context.writeExpr(context.getArgument(0));
writer.append(".constructor)");
}
private void achieveGetClass(DependencyAgent agent, MethodDependency method) {
MethodReference initMethod = new MethodReference(Class.class, "createNew", Class.class);
agent.linkMethod(initMethod, null).use();
method.getResult().propagate(agent.getType("java.lang.Class"));
}
private void generateHashCode(GeneratorContext context, SourceWriter writer) throws IOException {
writer.append("return ").append(context.getParameterName(0)).append(".$id;").softNewLine();
}
private void generateClone(GeneratorContext context, SourceWriter writer) throws IOException {
String obj = context.getParameterName(0);
writer.append("var copy = new ").append(obj).append(".constructor();").softNewLine();
writer.append("for (var field in " + obj + ") {").softNewLine().indent();
writer.append("if (!" + obj + ".hasOwnProperty(field)) {").softNewLine().indent();
writer.append("continue;").softNewLine().outdent().append("}").softNewLine();
writer.append("copy[field] = " + obj + "[field];").softNewLine().outdent().append("}").softNewLine();
writer.append("return copy;").softNewLine();
}
private void generateWrap(InjectorContext context) throws IOException {
context.writeExpr(context.getArgument(0));
}
}

View File

@ -1,49 +0,0 @@
/*
* Copyright 2013 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.classlib.java.lang;
import java.io.IOException;
import org.teavm.dependency.DependencyAgent;
import org.teavm.dependency.DependencyPlugin;
import org.teavm.dependency.MethodDependency;
import org.teavm.javascript.spi.Injector;
import org.teavm.javascript.spi.InjectorContext;
import org.teavm.model.CallLocation;
import org.teavm.model.MethodReference;
/**
*
* @author Alexey Andreev
*/
public class StringNativeGenerator implements Injector, DependencyPlugin {
@Override
public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) {
switch (method.getReference().getName()) {
case "wrap":
method.getVariable(1).connect(method.getResult());
break;
}
}
@Override
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
switch (methodRef.getName()) {
case "wrap":
context.writeExpr(context.getArgument(0));
break;
}
}
}

View File

@ -48,9 +48,6 @@ public class SystemNativeGenerator implements Generator, DependencyPlugin {
.appendField(new FieldReference("java.lang.System", "err"))
.ws().append('=').ws().append(context.getParameterName(1)).append(";").softNewLine();
break;
case "identityHashCode":
writer.append("return ").append(context.getParameterName(1)).append(".$id;").softNewLine();
break;
}
}

View File

@ -16,7 +16,6 @@
package org.teavm.classlib.java.lang;
import org.teavm.classlib.java.io.TSerializable;
import org.teavm.javascript.spi.GeneratedBy;
/**
*
@ -80,7 +79,6 @@ public class TBoolean extends TObject implements TSerializable, TComparable<TBoo
}
@Override
@GeneratedBy(ObjectNativeGenerator.class)
public int hashCode() {
return value ? 1231 : 1237;
}

View File

@ -17,8 +17,9 @@ package org.teavm.classlib.java.lang;
import org.teavm.classlib.impl.charset.UTF16Helper;
import org.teavm.classlib.impl.unicode.UnicodeHelper;
import org.teavm.dependency.PluggableDependency;
import org.teavm.javascript.spi.GeneratedBy;
import org.teavm.platform.Platform;
import org.teavm.platform.metadata.MetadataProvider;
import org.teavm.platform.metadata.StringResource;
/**
*
@ -222,18 +223,21 @@ public class TCharacter extends TObject implements TComparable<TCharacter> {
return UTF16Helper.lowSurrogate(codePoint);
}
// TODO: implement toLowerCase/toUpperCase/toTitleCase using UnicodeData.txt instead of built-in JS
@GeneratedBy(CharacterNativeGenerator.class)
public static native char toLowerCase(char ch);
public static char toLowerCase(char ch) {
return (char)toLowerCase((int)ch);
}
@GeneratedBy(CharacterNativeGenerator.class)
public static native int toLowerCase(int ch);
public static int toLowerCase(int ch) {
return Platform.stringFromCharCode(ch).toLowerCase().charCodeAt(0);
}
@GeneratedBy(CharacterNativeGenerator.class)
public static native char toUpperCase(char ch);
public static char toUpperCase(char ch) {
return (char)toUpperCase((int)ch);
}
@GeneratedBy(CharacterNativeGenerator.class)
public static native int toUpperCase(int codePoint);
public static int toUpperCase(int codePoint) {
return Platform.stringFromCharCode(codePoint).toUpperCase().charCodeAt(0);
}
public static int digit(char ch, int radix) {
return digit((int)ch, radix);
@ -286,25 +290,23 @@ public class TCharacter extends TObject implements TComparable<TCharacter> {
private static int[] getDigitMapping() {
if (digitMapping == null) {
digitMapping = UnicodeHelper.decodeIntByte(obtainDigitMapping());
digitMapping = UnicodeHelper.decodeIntByte(obtainDigitMapping().getValue());
}
return digitMapping;
}
@GeneratedBy(CharacterNativeGenerator.class)
@PluggableDependency(CharacterNativeGenerator.class)
private static native String obtainDigitMapping();
@MetadataProvider(CharacterMetadataGenerator.class)
private static native StringResource obtainDigitMapping();
private static UnicodeHelper.Range[] getClasses() {
if (classMapping == null) {
classMapping = UnicodeHelper.extractRle(obtainClasses());
classMapping = UnicodeHelper.extractRle(obtainClasses().getValue());
}
return classMapping;
}
@GeneratedBy(CharacterNativeGenerator.class)
@PluggableDependency(CharacterNativeGenerator.class)
private static native String obtainClasses();
@MetadataProvider(CharacterMetadataGenerator.class)
private static native StringResource obtainClasses();
public static int toChars(int codePoint, char[] dst, int dstIndex) {
if (codePoint >= UTF16Helper.SUPPLEMENTARY_PLANE) {

View File

@ -16,7 +16,6 @@
package org.teavm.classlib.java.lang;
import org.teavm.classlib.impl.DeclaringClassMetadataGenerator;
import org.teavm.javascript.spi.InjectedBy;
import org.teavm.platform.Platform;
import org.teavm.platform.PlatformClass;
import org.teavm.platform.metadata.ClassResource;
@ -144,12 +143,9 @@ public class TClass<T> extends TObject {
@SuppressWarnings("unchecked")
public T[] getEnumConstants() {
return isEnum() ? (T[])getEnumConstantsImpl(platformClass) : null;
return isEnum() ? (T[])Platform.getEnumConstants(platformClass) : null;
}
@InjectedBy(ClassNativeGenerator.class)
private static native Object[] getEnumConstantsImpl(PlatformClass cls);
@SuppressWarnings("unchecked")
public T cast(TObject obj) {
if (obj != null && !isAssignableFrom((TClass<?>)(Object)obj.getClass())) {

View File

@ -17,7 +17,7 @@ package org.teavm.classlib.java.lang;
import org.teavm.classlib.java.io.TIOException;
import org.teavm.classlib.java.io.TOutputStream;
import org.teavm.javascript.spi.GeneratedBy;
import org.teavm.platform.Platform;
/**
*
@ -25,6 +25,7 @@ import org.teavm.javascript.spi.GeneratedBy;
*/
class TConsoleOutputStream_stderr extends TOutputStream {
@Override
@GeneratedBy(ConsoleOutputStreamGenerator.class)
public native void write(int b) throws TIOException;
public void write(int b) throws TIOException {
Platform.getConsole().error(b);
}
}

View File

@ -17,7 +17,7 @@ package org.teavm.classlib.java.lang;
import org.teavm.classlib.java.io.TIOException;
import org.teavm.classlib.java.io.TOutputStream;
import org.teavm.javascript.spi.GeneratedBy;
import org.teavm.platform.Platform;
/**
*
@ -25,6 +25,7 @@ import org.teavm.javascript.spi.GeneratedBy;
*/
class TConsoleOutputStream_stdout extends TOutputStream {
@Override
@GeneratedBy(ConsoleOutputStreamGenerator.class)
public native void write(int b) throws TIOException;
public void write(int b) throws TIOException {
Platform.getConsole().output(b);
}
}

View File

@ -15,11 +15,9 @@
*/
package org.teavm.classlib.java.lang;
import org.teavm.dependency.PluggableDependency;
import org.teavm.javascript.spi.GeneratedBy;
import org.teavm.javascript.spi.InjectedBy;
import org.teavm.javascript.spi.Rename;
import org.teavm.javascript.spi.Superclass;
import org.teavm.platform.Platform;
/**
*
@ -31,18 +29,20 @@ public class TObject {
public TObject() {
}
@GeneratedBy(ObjectNativeGenerator.class)
@Rename("<init>")
private native void init();
private void init() {
Platform.getPlatformObject(this).setId(Platform.nextObjectId());
}
@InjectedBy(ObjectNativeGenerator.class)
@Rename("getClass")
@PluggableDependency(ObjectNativeGenerator.class)
public native final TClass<?> getClass0();
public final TClass<?> getClass0() {
return TClass.getClass(Platform.getPlatformObject(this).getPlatformClass());
}
@Override
@GeneratedBy(ObjectNativeGenerator.class)
public native int hashCode();
public int hashCode() {
return identity();
}
@Rename("equals")
public boolean equals0(TObject other) {
@ -54,13 +54,19 @@ public class TObject {
return getClass().getName() + "@" + TInteger.toHexString(identity());
}
@GeneratedBy(ObjectNativeGenerator.class)
native int identity();
int identity() {
return Platform.getPlatformObject(this).getId();
}
@GeneratedBy(ObjectNativeGenerator.class)
@PluggableDependency(ObjectNativeGenerator.class)
@Override
protected native Object clone() throws TCloneNotSupportedException;
protected Object clone() throws TCloneNotSupportedException {
if (!(this instanceof TCloneable) && Platform.getPlatformObject(this)
.getPlatformClass().getMetadata().getArrayItem() == null) {
throw new TCloneNotSupportedException();
}
Platform.getPlatformObject(this).setId(Platform.nextObjectId());
return Platform.clone(this);
}
@Rename("notify")
public final void notify0() {
@ -88,7 +94,7 @@ public class TObject {
protected void finalize() throws TThrowable {
}
@InjectedBy(ObjectNativeGenerator.class)
@PluggableDependency(ObjectNativeGenerator.class)
public static native TObject wrap(Object obj);
public static TObject wrap(Object obj) {
return (TObject)obj;
}
}

View File

@ -23,8 +23,6 @@ import org.teavm.classlib.java.util.TComparator;
import org.teavm.classlib.java.util.THashMap;
import org.teavm.classlib.java.util.TMap;
import org.teavm.classlib.java.util.regex.TPattern;
import org.teavm.dependency.PluggableDependency;
import org.teavm.javascript.spi.InjectedBy;
/**
*
@ -592,9 +590,9 @@ public class TString extends TObject implements TSerializable, TComparable<TStri
return hashCode;
}
@InjectedBy(StringNativeGenerator.class)
@PluggableDependency(StringNativeGenerator.class)
public static native TString wrap(String str);
public static TString wrap(String str) {
return (TString)(Object)str;
}
public TString toLowerCase() {
if (isEmpty()) {

View File

@ -93,9 +93,9 @@ public final class TSystem extends TObject {
return currentTimeMillis() * 10000000;
}
@GeneratedBy(SystemNativeGenerator.class)
@PluggableDependency(SystemNativeGenerator.class)
public static native int identityHashCode(Object x);
public static int identityHashCode(Object x) {
return ((TObject)x).identity();
}
public static TString lineSeparator() {
return TString.wrap("\n");

View File

@ -1,49 +0,0 @@
/*
* 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.classlib.java.lang;
import java.io.IOException;
import org.teavm.codegen.SourceWriter;
import org.teavm.javascript.spi.Generator;
import org.teavm.javascript.spi.GeneratorContext;
import org.teavm.model.MethodReference;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class ThreadNativeGenerator implements Generator {
@Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
if (methodRef.getName().equals("sleep")) {
generateSleep(context, writer);
} else if (methodRef.getName().equals("yield")) {
generateYield(context, writer);
}
}
private void generateSleep(GeneratorContext context, SourceWriter writer) throws IOException {
writer.append("setTimeout(function() {").indent().softNewLine();
writer.append(context.getCompleteContinuation()).append("($rt_asyncResult(null));").softNewLine();
writer.outdent().append("},").ws().append(context.getParameterName(1)).append(");").softNewLine();
}
private void generateYield(GeneratorContext context, SourceWriter writer) throws IOException {
writer.append("setTimeout(function() {").indent().softNewLine();
writer.append(context.getCompleteContinuation()).append("($rt_asyncResult(null));").softNewLine();
writer.outdent().append("},").ws().append("0);").softNewLine();
}
}

View File

@ -34,6 +34,10 @@ public final class Platform {
return (PlatformObject)JS.marshall(obj);
}
@GeneratedBy(PlatformGenerator.class)
@PluggableDependency(PlatformGenerator.class)
public static native Object clone(Object obj);
public static boolean isInstance(PlatformObject obj, PlatformClass cls) {
return obj != null && !JS.isUndefined(obj.getPlatformClass().getMetadata()) &&
isAssignable(obj.getPlatformClass(), cls);
@ -60,6 +64,14 @@ public final class Platform {
return (PlatformPrimitives)JS.getGlobal();
}
public static PlatformConsole getConsole() {
return (PlatformConsole)JS.getGlobal();
}
public static int nextObjectId() {
return ((PlatformHelper)JS.getGlobal()).nextId();
}
@GeneratedBy(PlatformGenerator.class)
@PluggableDependency(PlatformGenerator.class)
public static native <T> T newInstance(PlatformClass cls);
@ -75,4 +87,12 @@ public final class Platform {
@InjectedBy(PlatformGenerator.class)
@PluggableDependency(PlatformGenerator.class)
public static native PlatformClass classFromResource(ClassResource resource);
@InjectedBy(PlatformGenerator.class)
@PluggableDependency(PlatformGenerator.class)
public static native Enum<?>[] getEnumConstants(PlatformClass cls);
public static PlatformString stringFromCharCode(int charCode) {
return ((PlatformHelper)JS.getGlobal()).getStringClass().fromCharCode(charCode);
}
}

View File

@ -0,0 +1,31 @@
/*
* 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.platform;
import org.teavm.jso.JSMethod;
import org.teavm.jso.JSObject;
/**
*
* @author Alexey Andreev
*/
public interface PlatformConsole extends JSObject {
@JSMethod("rt_putStdout")
void output(int b);
@JSMethod("rt_putStderr")
void error(int b);
}

View File

@ -0,0 +1,32 @@
/*
* 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.platform;
import org.teavm.jso.JSMethod;
import org.teavm.jso.JSObject;
import org.teavm.jso.JSProperty;
/**
*
* @author Alexey Andreev
*/
interface PlatformHelper extends JSObject {
@JSMethod("$rt_nextId")
int nextId();
@JSProperty("String")
PlatformStringClass getStringClass();
}

View File

@ -25,4 +25,10 @@ import org.teavm.jso.JSProperty;
public interface PlatformObject extends JSObject {
@JSProperty("constructor")
PlatformClass getPlatformClass();
@JSProperty("$id")
int getId();
@JSProperty("$id")
void setId(int id);
}

View File

@ -0,0 +1,30 @@
/*
* 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.platform;
import org.teavm.jso.JSObject;
/**
*
* @author Alexey Andreev
*/
public interface PlatformString extends JSObject {
PlatformString toUpperCase();
PlatformString toLowerCase();
int charCodeAt(int index);
}

View File

@ -0,0 +1,26 @@
/*
* 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.platform;
import org.teavm.jso.JSObject;
/**
*
* @author Alexey Andreev
*/
interface PlatformStringClass extends JSObject {
PlatformString fromCharCode(int charCode);
}

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.classlib.impl;
package org.teavm.platform.plugin;
import org.teavm.dependency.*;
import org.teavm.model.CallLocation;
@ -21,6 +21,7 @@ import org.teavm.model.ClassReader;
import org.teavm.model.MethodDescriptor;
import org.teavm.model.MethodReader;
import org.teavm.model.ValueType;
import org.teavm.platform.Platform;
/**
*
@ -53,8 +54,8 @@ public class EnumDependencySupport implements DependencyListener {
@Override
public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) {
if (method.getReference().getClassName().equals("java.lang.Class") &&
method.getReference().getName().equals("getEnumConstantsImpl")) {
if (method.getReference().getClassName().equals(Platform.class.getName()) &&
method.getReference().getName().equals("getEnumConstants")) {
unlocked = true;
allEnums.connect(method.getResult().getArrayItem());
method.getResult().propagate(agent.getType("[java.lang.Enum"));

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.classlib.impl;
package org.teavm.platform.plugin;
import org.teavm.diagnostics.Diagnostics;
import org.teavm.javascript.spi.PreserveOriginalName;

View File

@ -37,6 +37,9 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin
case "asJavaClass":
method.getResult().propagate(agent.getType("java.lang.Class"));
return;
case "clone":
method.getVariable(0).connect(method.getResult());
break;
}
}
@ -47,6 +50,10 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin
case "classFromResource":
context.writeExpr(context.getArgument(0));
return;
case "getEnumConstants":
context.writeExpr(context.getArgument(0));
context.getWriter().append(".values()");
break;
}
}
@ -59,6 +66,9 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin
case "lookupClass":
generateLookup(context, writer);
break;
case "clone":
generateClone(context, writer);
break;
}
}
@ -95,4 +105,16 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin
writer.append("default: return null;").softNewLine();
writer.outdent().append("}").softNewLine();
}
private void generateClone(GeneratorContext context, SourceWriter writer) throws IOException {
String obj = context.getParameterName(1);
writer.append("var copy").ws().append("=").ws().append("new ").append(obj).append(".constructor();")
.softNewLine();
writer.append("for").ws().append("(var field in " + obj + ")").ws().append("{").softNewLine().indent();
writer.append("if").ws().append("(!" + obj + ".hasOwnProperty(field))").ws().append("{").softNewLine().indent();
writer.append("continue;").softNewLine().outdent().append("}").softNewLine();
writer.append("copy[field]").ws().append("=").ws().append(obj).append("[field];")
.softNewLine().outdent().append("}").softNewLine();
writer.append("return copy;").softNewLine();
}
}

View File

@ -32,5 +32,7 @@ public class PlatformPlugin implements TeaVMPlugin {
host.add(new AsyncMethodProcessor());
host.add(new NewInstanceDependencySupport());
host.add(new ClassLookupDependencySupport());
host.add(new EnumDependencySupport());
host.add(new EnumTransformer());
}
}