mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Adds implementations of some JCL classes
This commit is contained in:
parent
281d4b8e05
commit
f3ae632786
|
@ -17,6 +17,9 @@ package org.teavm.classlib.java.lang;
|
|||
|
||||
import java.io.IOException;
|
||||
import org.teavm.codegen.SourceWriter;
|
||||
import org.teavm.dependency.DependencyChecker;
|
||||
import org.teavm.dependency.DependencyPlugin;
|
||||
import org.teavm.dependency.MethodDependency;
|
||||
import org.teavm.javascript.ni.Generator;
|
||||
import org.teavm.javascript.ni.GeneratorContext;
|
||||
import org.teavm.javascript.ni.Injector;
|
||||
|
@ -27,7 +30,7 @@ import org.teavm.model.MethodReference;
|
|||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class ClassNativeGenerator implements Generator, Injector {
|
||||
public class ClassNativeGenerator implements Generator, Injector, DependencyPlugin {
|
||||
@Override
|
||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef)
|
||||
throws IOException {
|
||||
|
@ -35,6 +38,9 @@ public class ClassNativeGenerator implements Generator, Injector {
|
|||
case "getComponentType0":
|
||||
generateGetComponentType(context, writer);
|
||||
break;
|
||||
case "getSuperclass":
|
||||
generateGetSuperclass(context, writer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,6 +50,12 @@ public class ClassNativeGenerator implements Generator, Injector {
|
|||
writer.append("return item != null ? $rt_cls(item) : null;").softNewLine();
|
||||
}
|
||||
|
||||
private void generateGetSuperclass(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
String thisArg = context.getParameterName(0);
|
||||
writer.append("var superclass = " + thisArg + ".$data.$meta.superclass;").softNewLine();
|
||||
writer.append("return superclass ? $rt_cls(superclass) : null;").softNewLine();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
|
||||
switch (methodRef.getName()) {
|
||||
|
@ -59,6 +71,9 @@ public class ClassNativeGenerator implements Generator, Injector {
|
|||
case "intClass":
|
||||
generateIntClass(context);
|
||||
break;
|
||||
case "wrap":
|
||||
context.writeExpr(context.getArgument(0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,4 +102,17 @@ public class ClassNativeGenerator implements Generator, Injector {
|
|||
private void generateIntClass(InjectorContext context) throws IOException {
|
||||
context.getWriter().append("$rt_cls($rt_intcls())");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void methodAchieved(DependencyChecker checker, MethodDependency graph) {
|
||||
switch (graph.getReference().getName()) {
|
||||
case "booleanClass":
|
||||
case "intClass":
|
||||
case "wrap":
|
||||
case "getSuperclass":
|
||||
case "getComponentType0":
|
||||
graph.getResult().propagate("java.lang.Class");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package org.teavm.classlib.java.lang;
|
||||
|
||||
import org.teavm.dependency.PluggableDependency;
|
||||
import org.teavm.javascript.ni.GeneratedBy;
|
||||
import org.teavm.javascript.ni.InjectedBy;
|
||||
|
||||
|
@ -22,7 +23,7 @@ import org.teavm.javascript.ni.InjectedBy;
|
|||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class TClass<T> extends TObject {
|
||||
public class TClass<T extends TObject> extends TObject {
|
||||
TString name;
|
||||
boolean primitive;
|
||||
boolean array;
|
||||
|
@ -60,15 +61,26 @@ public class TClass<T> extends TObject {
|
|||
}
|
||||
|
||||
@GeneratedBy(ClassNativeGenerator.class)
|
||||
@PluggableDependency(ClassNativeGenerator.class)
|
||||
private native TClass<?> getComponentType0();
|
||||
|
||||
@InjectedBy(ClassNativeGenerator.class)
|
||||
@PluggableDependency(ClassNativeGenerator.class)
|
||||
static native TClass<TBoolean> booleanClass();
|
||||
|
||||
@InjectedBy(ClassNativeGenerator.class)
|
||||
@PluggableDependency(ClassNativeGenerator.class)
|
||||
static native TClass<TInteger> intClass();
|
||||
|
||||
@InjectedBy(ClassNativeGenerator.class)
|
||||
@PluggableDependency(ClassNativeGenerator.class)
|
||||
public static native <S extends TObject> TClass<S> wrap(Class<S> cls);
|
||||
|
||||
public boolean desiredAssertionStatus() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@GeneratedBy(ClassNativeGenerator.class)
|
||||
@PluggableDependency(ClassNativeGenerator.class)
|
||||
public native TClass<? super T> getSuperclass();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class TCloneNotSupportedException extends TException {
|
||||
private static final long serialVersionUID = 4908200987785128012L;
|
||||
|
||||
public TCloneNotSupportedException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public TCloneNotSupportedException(TString message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public interface TCloneable {
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* 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 org.teavm.classlib.java.io.TSerializable;
|
||||
import org.teavm.javascript.ni.Rename;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public abstract class TEnum<E extends TEnum<E>> extends TObject implements TComparable<E>, TSerializable {
|
||||
private TString name;
|
||||
private int ordinal;
|
||||
|
||||
protected TEnum(TString name, int ordinal) {
|
||||
this.name = name;
|
||||
this.ordinal = ordinal;
|
||||
}
|
||||
|
||||
public final TString name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public final int ordinal() {
|
||||
return ordinal;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Rename("toString")
|
||||
public TString toString0() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(TObject other) {
|
||||
return this == other;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final TObject clone() throws TCloneNotSupportedException {
|
||||
throw new TCloneNotSupportedException();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public final TClass<E> getDeclaringClass() {
|
||||
TClass<?> thisClass = TClass.wrap(getClass());
|
||||
TClass<?> superClass = thisClass.getSuperclass();
|
||||
return (TClass<E>)(superClass == TClass.wrap(TEnum.class) ? thisClass : superClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int compareTo(E o) {
|
||||
if (o.getDeclaringClass() != getDeclaringClass()) {
|
||||
throw new TIllegalArgumentException(TString.wrap("Can't compare " +
|
||||
getDeclaringClass().getName().toString() + " to " +
|
||||
o.getDeclaringClass().getName().toString()));
|
||||
}
|
||||
return TInteger.compare(ordinal, o.ordinal());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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 org.teavm.classlib.java.util.TIterator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public interface TIterable<T extends TObject> {
|
||||
TIterator<T> iterator();
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class TLong extends TNumber {
|
||||
private long value;
|
||||
|
||||
public TLong(long value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static TLong valueOf(long value) {
|
||||
return new TLong(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int intValue() {
|
||||
return (int)value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long longValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float floatValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double doubleValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
|
@ -59,7 +59,7 @@ public class TObject {
|
|||
@Override
|
||||
@GeneratedBy(ObjectNativeGenerator.class)
|
||||
@PluggableDependency(ObjectNativeGenerator.class)
|
||||
protected native TObject clone();
|
||||
protected native TObject clone() throws TCloneNotSupportedException;
|
||||
|
||||
@Rename("notify")
|
||||
public final void notify0() {
|
||||
|
|
|
@ -53,7 +53,7 @@ public class TStringBuilder extends TAbstractStringBuilder implements TAppendabl
|
|||
}
|
||||
|
||||
@Override
|
||||
protected TStringBuilder append(double value) {
|
||||
public TStringBuilder append(double value) {
|
||||
super.append(value);
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ package org.teavm.classlib.java.util;
|
|||
|
||||
import org.teavm.classlib.java.lang.TMath;
|
||||
import org.teavm.classlib.java.lang.TObject;
|
||||
import org.teavm.classlib.java.lang.TString;
|
||||
import org.teavm.classlib.java.lang.TStringBuilder;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -40,4 +42,121 @@ public class TArrays extends TObject {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static TString toString(TObject[] a) {
|
||||
TStringBuilder sb = new TStringBuilder();
|
||||
sb.append(TString.wrap("["));
|
||||
for (int i = 0; i < a.length; ++i) {
|
||||
if (i > 0) {
|
||||
sb.append(TString.wrap(", "));
|
||||
}
|
||||
sb.append(a[i]);
|
||||
}
|
||||
sb.append(TString.wrap("]"));
|
||||
return TString.wrap(sb.toString());
|
||||
}
|
||||
|
||||
public static TString toString(boolean[] a) {
|
||||
TStringBuilder sb = new TStringBuilder();
|
||||
sb.append(TString.wrap("["));
|
||||
for (int i = 0; i < a.length; ++i) {
|
||||
if (i > 0) {
|
||||
sb.append(TString.wrap(", "));
|
||||
}
|
||||
sb.append(a[i]);
|
||||
}
|
||||
sb.append(TString.wrap("]"));
|
||||
return TString.wrap(sb.toString());
|
||||
}
|
||||
|
||||
public static TString toString(byte[] a) {
|
||||
TStringBuilder sb = new TStringBuilder();
|
||||
sb.append(TString.wrap("["));
|
||||
for (int i = 0; i < a.length; ++i) {
|
||||
if (i > 0) {
|
||||
sb.append(TString.wrap(", "));
|
||||
}
|
||||
sb.append(a[i]);
|
||||
}
|
||||
sb.append(TString.wrap("]"));
|
||||
return TString.wrap(sb.toString());
|
||||
}
|
||||
|
||||
public static TString toString(short[] a) {
|
||||
TStringBuilder sb = new TStringBuilder();
|
||||
sb.append(TString.wrap("["));
|
||||
for (int i = 0; i < a.length; ++i) {
|
||||
if (i > 0) {
|
||||
sb.append(TString.wrap(", "));
|
||||
}
|
||||
sb.append(a[i]);
|
||||
}
|
||||
sb.append(TString.wrap("]"));
|
||||
return TString.wrap(sb.toString());
|
||||
}
|
||||
|
||||
public static TString toString(char[] a) {
|
||||
TStringBuilder sb = new TStringBuilder();
|
||||
sb.append(TString.wrap("["));
|
||||
for (int i = 0; i < a.length; ++i) {
|
||||
if (i > 0) {
|
||||
sb.append(TString.wrap(", "));
|
||||
}
|
||||
sb.append(a[i]);
|
||||
}
|
||||
sb.append(TString.wrap("]"));
|
||||
return TString.wrap(sb.toString());
|
||||
}
|
||||
|
||||
public static TString toString(int[] a) {
|
||||
TStringBuilder sb = new TStringBuilder();
|
||||
sb.append(TString.wrap("["));
|
||||
for (int i = 0; i < a.length; ++i) {
|
||||
if (i > 0) {
|
||||
sb.append(TString.wrap(", "));
|
||||
}
|
||||
sb.append(a[i]);
|
||||
}
|
||||
sb.append(TString.wrap("]"));
|
||||
return TString.wrap(sb.toString());
|
||||
}
|
||||
|
||||
public static TString toString(long[] a) {
|
||||
TStringBuilder sb = new TStringBuilder();
|
||||
sb.append(TString.wrap("["));
|
||||
for (int i = 0; i < a.length; ++i) {
|
||||
if (i > 0) {
|
||||
sb.append(TString.wrap(", "));
|
||||
}
|
||||
sb.append(a[i]);
|
||||
}
|
||||
sb.append(TString.wrap("]"));
|
||||
return TString.wrap(sb.toString());
|
||||
}
|
||||
|
||||
public static TString toString(float[] a) {
|
||||
TStringBuilder sb = new TStringBuilder();
|
||||
sb.append(TString.wrap("["));
|
||||
for (int i = 0; i < a.length; ++i) {
|
||||
if (i > 0) {
|
||||
sb.append(TString.wrap(", "));
|
||||
}
|
||||
sb.append(a[i]);
|
||||
}
|
||||
sb.append(TString.wrap("]"));
|
||||
return TString.wrap(sb.toString());
|
||||
}
|
||||
|
||||
public static TString toString(double[] a) {
|
||||
TStringBuilder sb = new TStringBuilder();
|
||||
sb.append(TString.wrap("["));
|
||||
for (int i = 0; i < a.length; ++i) {
|
||||
if (i > 0) {
|
||||
sb.append(TString.wrap(", "));
|
||||
}
|
||||
sb.append(a[i]);
|
||||
}
|
||||
sb.append(TString.wrap("]"));
|
||||
return TString.wrap(sb.toString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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.util;
|
||||
|
||||
import org.teavm.classlib.java.lang.TObject;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public interface TIterator<E extends TObject> {
|
||||
boolean hasNext();
|
||||
|
||||
E next();
|
||||
|
||||
void remove();
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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.util.concurrent;
|
||||
|
||||
import org.teavm.classlib.java.lang.TException;
|
||||
import org.teavm.classlib.java.lang.TObject;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public interface TCallable<V extends TObject> {
|
||||
V call() throws TException;
|
||||
}
|
|
@ -33,6 +33,26 @@ public class ClassTest {
|
|||
assertEquals("java.lang.Object", new Object().getClass().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void superClassFound() {
|
||||
assertEquals(Number.class, Integer.class.getSuperclass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void superClassOfObjectIsNull() {
|
||||
assertNull(Object.class.getSuperclass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void superClassOfArrayIsObject() {
|
||||
assertEquals(Object.class, Runnable[].class.getSuperclass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void superClassOfPrimitiveIsNull() {
|
||||
assertNull(int.class.getSuperclass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void objectClassConsideredNotArray() {
|
||||
assertFalse(Object.class.isArray());
|
||||
|
|
|
@ -189,6 +189,10 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
|||
writer.appendClass(iface);
|
||||
}
|
||||
writer.append("]");
|
||||
if (cls.getParentName() != null) {
|
||||
writer.append(",").ws();
|
||||
writer.append("superclass").ws().append(":").ws().appendClass(cls.getParentName());
|
||||
}
|
||||
writer.ws().append("};").softNewLine();
|
||||
if (!cls.getModifiers().contains(NodeModifier.INTERFACE)) {
|
||||
writer.appendClass(cls.getName()).append("_$clinit").ws().append("=").ws().append("function()").ws()
|
||||
|
|
|
@ -108,7 +108,7 @@ $rt_arraycls = function(cls) {
|
|||
};
|
||||
arraycls.prototype = new ($rt_objcls())();
|
||||
arraycls.prototype.constructor = arraycls;
|
||||
arraycls.$meta = { item : cls, supertypes : [$rt_objcls()], primitive : false };
|
||||
arraycls.$meta = { item : cls, supertypes : [$rt_objcls()], primitive : false, superclass : $rt_objcls() };
|
||||
cls.$array = arraycls;
|
||||
}
|
||||
return cls.$array;
|
||||
|
|
|
@ -84,9 +84,9 @@
|
|||
<scanDependencies>true</scanDependencies>
|
||||
<outputDir>${project.build.directory}/javascript-tck</outputDir>
|
||||
<adapterClass>org.teavm.html4j.testing.KOTestAdapter</adapterClass>
|
||||
<wildcards>
|
||||
<!-- <wildcards>
|
||||
<param>net.java.html.js.tests.*Test</param>
|
||||
</wildcards>
|
||||
</wildcards> -->
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
|
|
Loading…
Reference in New Issue
Block a user