fix: make global cache of native wrappers

This commit is contained in:
TopchetoEU 2024-03-28 16:08:07 +02:00
parent 18f70a0d58
commit b5b63c4342
Signed by: topchetoeu
GPG Key ID: 6531B8583E5F6ED4
2 changed files with 22 additions and 6 deletions

View File

@ -1,8 +1,13 @@
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;
@ -29,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;
}
} }

View File

@ -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());