X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/dbf05bfd2ab79568fe706daa9112037192d4d9dd..97bec96b43b66ab78af95d2b6c6c24f0d0a8006a:/Java/Cycript.java diff --git a/Java/Cycript.java b/Java/Cycript.java index 76ac7fc..8fb7817 100644 --- a/Java/Cycript.java +++ b/Java/Cycript.java @@ -1,5 +1,5 @@ -/* Cycript - Optimizing JavaScript Compiler/Runtime - * Copyright (C) 2009-2015 Jay Freeman (saurik) +/* Cycript - The Truly Universal Scripting Language + * Copyright (C) 2009-2016 Jay Freeman (saurik) */ /* GNU Affero General Public License, Version 3 {{{ */ @@ -22,11 +22,76 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; +import java.lang.reflect.Proxy; public class Cycript { -public class OnInvoke implements InvocationHandler { - native public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; +public static Method GetMethod(Class type, String name, Class... types) { + try { + return type.getMethod(name, types); + } catch (NoSuchMethodException e) { + throw new RuntimeException(); + } +} + +public static final Method Object$equals = GetMethod(Object.class, "equals", Object.class); +public static final Method Object$hashCode = GetMethod(Object.class, "hashCode"); + +public static native void delete(long protect); + +public static native Object handle(long protect, String property, Object[] arguments) + throws Throwable; + +public static class Wrapper + extends RuntimeException + implements InvocationHandler +{ + private long protect_; + + public Wrapper(long protect) { + protect_ = protect; + } + + protected void finalize() + throws Throwable + { + delete(protect_); + } + + public long getProtect() { + return protect_; + } + + public Object call(String property, Object[] arguments) { + try { + return handle(protect_, property, arguments); + } catch (Throwable throwable) { + return new RuntimeException(throwable); + } + } + + public String toString() { + return call("toString", null).toString(); + } + + public Object invoke(Object proxy, Method method, Object[] args) + throws Throwable + { + if (false) + return null; + else if (method.equals(Object$equals)) + // XXX: this assumes there is only one proxy + return proxy == args[0]; + else if (method == Object$hashCode) + // XXX: this assumes there is only one wrapper + return hashCode(); + else + return handle(protect_, method.getName(), args); + } +} + +public static Object proxy(Class proxy, Wrapper wrapper) { + return Proxy.newProxyInstance(proxy.getClassLoader(), new Class[] {proxy}, wrapper); } }