Compare commits
4 Commits
0.9.15-bet
...
0.9.19-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
b5b63c4342
|
|||
|
18f70a0d58
|
|||
|
d38b600366
|
|||
|
0ac7af2ea3
|
@@ -1,15 +1,21 @@
|
|||||||
package me.topchetoeu.jscript.runtime.values;
|
package me.topchetoeu.jscript.runtime.values;
|
||||||
|
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.runtime.Context;
|
import me.topchetoeu.jscript.runtime.Context;
|
||||||
|
import me.topchetoeu.jscript.runtime.Extensions;
|
||||||
|
import me.topchetoeu.jscript.runtime.Key;
|
||||||
|
|
||||||
public class NativeWrapper extends ObjectValue {
|
public class NativeWrapper extends ObjectValue {
|
||||||
|
private static final Key<WeakHashMap<Object, NativeWrapper>> WRAPPERS = new Key<>();
|
||||||
private static final Object NATIVE_PROTO = new Object();
|
private static final Object NATIVE_PROTO = new Object();
|
||||||
public final Object wrapped;
|
public final Object wrapped;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ObjectValue getPrototype(Context ctx) {
|
public ObjectValue getPrototype(Context ctx) {
|
||||||
if (ctx.environment != null && prototype == NATIVE_PROTO) {
|
if (ctx.environment != null && prototype == NATIVE_PROTO) {
|
||||||
var res = ctx.environment.wrappers.getProto(wrapped.getClass());
|
var clazz = wrapped.getClass();
|
||||||
|
var res = ctx.environment.wrappers.getProto(clazz);
|
||||||
if (res != null) return res;
|
if (res != null) return res;
|
||||||
}
|
}
|
||||||
return super.getPrototype(ctx);
|
return super.getPrototype(ctx);
|
||||||
@@ -28,8 +34,20 @@ public class NativeWrapper extends ObjectValue {
|
|||||||
return wrapped.hashCode();
|
return wrapped.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public NativeWrapper(Object wrapped) {
|
private NativeWrapper(Object wrapped) {
|
||||||
this.wrapped = wrapped;
|
this.wrapped = wrapped;
|
||||||
prototype = NATIVE_PROTO;
|
prototype = NATIVE_PROTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static NativeWrapper of(Extensions exts, Object wrapped) {
|
||||||
|
var wrappers = exts == null ? null : exts.get(WRAPPERS);
|
||||||
|
|
||||||
|
if (wrappers == null) return new NativeWrapper(wrapped);
|
||||||
|
if (wrappers.containsKey(wrapped)) return wrappers.get(wrapped);
|
||||||
|
|
||||||
|
var res = new NativeWrapper(wrapped);
|
||||||
|
wrappers.put(wrapped, res);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,9 +58,8 @@ public class Values {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <T> T wrapper(Object val, Class<T> clazz) {
|
public static <T> T wrapper(Object val, Class<T> clazz) {
|
||||||
if (!isWrapper(val)) val = new NativeWrapper(val);
|
if (isWrapper(val)) val = ((NativeWrapper)val).wrapped;
|
||||||
var res = (NativeWrapper)val;
|
if (val != null && clazz.isInstance(val)) return (T)val;
|
||||||
if (res != null && clazz.isInstance(res.wrapped)) return (T)res.wrapped;
|
|
||||||
else return null;
|
else return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -471,7 +470,7 @@ public class Values {
|
|||||||
else return ctx.environment.wrappers.getConstr((Class<?>)val);
|
else return ctx.environment.wrappers.getConstr((Class<?>)val);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NativeWrapper(val);
|
return NativeWrapper.of(ctx, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@@ -536,7 +535,7 @@ public class Values {
|
|||||||
if (obj == null) return null;
|
if (obj == null) return null;
|
||||||
if (clazz.isInstance(obj)) return (T)obj;
|
if (clazz.isInstance(obj)) return (T)obj;
|
||||||
if (clazz.isAssignableFrom(NativeWrapper.class)) {
|
if (clazz.isAssignableFrom(NativeWrapper.class)) {
|
||||||
return (T)new NativeWrapper(obj);
|
return (T)NativeWrapper.of(ctx, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ConvertException(type(obj), clazz.getSimpleName());
|
throw new ConvertException(type(obj), clazz.getSimpleName());
|
||||||
|
|||||||
@@ -288,8 +288,23 @@ public class NativeWrapperProvider implements WrapperProvider {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateProtoChain(Class<?> clazz, ObjectValue proto, FunctionValue constr) {
|
||||||
|
var parent = clazz;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
parent = parent.getSuperclass();
|
||||||
|
if (parent == null) return;
|
||||||
|
|
||||||
|
var parentProto = getProto(parent);
|
||||||
|
var parentConstr = getConstr(parent);
|
||||||
|
|
||||||
|
if (parentProto != null) Values.setPrototype(Context.NULL, proto, parentProto);
|
||||||
|
if (parentConstr != null) Values.setPrototype(Context.NULL, constr, parentConstr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void initType(Class<?> clazz, FunctionValue constr, ObjectValue proto) {
|
private void initType(Class<?> clazz, FunctionValue constr, ObjectValue proto) {
|
||||||
if (constr != null && proto != null) return;
|
if (constr != null && proto != null || ignore.contains(clazz)) return;
|
||||||
// i vomit
|
// i vomit
|
||||||
if (
|
if (
|
||||||
clazz == Object.class ||
|
clazz == Object.class ||
|
||||||
@@ -316,32 +331,35 @@ public class NativeWrapperProvider implements WrapperProvider {
|
|||||||
prototypes.put(clazz, proto);
|
prototypes.put(clazz, proto);
|
||||||
constructors.put(clazz, constr);
|
constructors.put(clazz, constr);
|
||||||
|
|
||||||
var parent = clazz;
|
updateProtoChain(clazz, proto, constr);
|
||||||
|
|
||||||
while (true) {
|
|
||||||
parent = parent.getSuperclass();
|
|
||||||
if (parent == null) return;
|
|
||||||
|
|
||||||
var parentProto = getProto(parent);
|
|
||||||
var parentConstr = getConstr(parent);
|
|
||||||
|
|
||||||
if (parentProto != null) Values.setPrototype(Context.NULL, proto, parentProto);
|
|
||||||
if (parentConstr != null) Values.setPrototype(Context.NULL, constr, parentConstr);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObjectValue getProto(Class<?> clazz) {
|
public ObjectValue getProto(Class<?> clazz) {
|
||||||
initType(clazz, constructors.get(clazz), prototypes.get(clazz));
|
initType(clazz, constructors.get(clazz), prototypes.get(clazz));
|
||||||
return prototypes.get(clazz);
|
while (clazz != null) {
|
||||||
|
var res = prototypes.get(clazz);
|
||||||
|
if (res != null) return res;
|
||||||
|
clazz = clazz.getSuperclass();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
public ObjectValue getNamespace(Class<?> clazz) {
|
public ObjectValue getNamespace(Class<?> clazz) {
|
||||||
if (!namespaces.containsKey(clazz)) namespaces.put(clazz, makeNamespace(env, clazz));
|
if (!namespaces.containsKey(clazz)) namespaces.put(clazz, makeNamespace(env, clazz));
|
||||||
return namespaces.get(clazz);
|
while (clazz != null) {
|
||||||
|
var res = namespaces.get(clazz);
|
||||||
|
if (res != null) return res;
|
||||||
|
clazz = clazz.getSuperclass();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
public FunctionValue getConstr(Class<?> clazz) {
|
public FunctionValue getConstr(Class<?> clazz) {
|
||||||
initType(clazz, constructors.get(clazz), prototypes.get(clazz));
|
initType(clazz, constructors.get(clazz), prototypes.get(clazz));
|
||||||
return constructors.get(clazz);
|
while (clazz != null) {
|
||||||
|
var res = constructors.get(clazz);
|
||||||
|
if (res != null) return res;
|
||||||
|
clazz = clazz.getSuperclass();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public WrapperProvider fork(Environment env) {
|
@Override public WrapperProvider fork(Environment env) {
|
||||||
@@ -357,6 +375,12 @@ public class NativeWrapperProvider implements WrapperProvider {
|
|||||||
prototypes.put(clazz, proto);
|
prototypes.put(clazz, proto);
|
||||||
constructors.put(clazz, constructor);
|
constructors.put(clazz, constructor);
|
||||||
ignore.remove(clazz);
|
ignore.remove(clazz);
|
||||||
|
|
||||||
|
for (var el : prototypes.keySet()) {
|
||||||
|
if (clazz.isAssignableFrom(el)) {
|
||||||
|
updateProtoChain(el, getProto(el), getConstr(el));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
prototypes.remove(clazz);
|
prototypes.remove(clazz);
|
||||||
|
|||||||
Reference in New Issue
Block a user