Subj : Re: Fwd: Rhino, Changes to JavaMembers.java To : netscape.public.mozilla.jseng From : Juerg Lehni Date : Thu Feb 17 2005 04:10 pm So here's the patch now: J Index: JavaMembers.java =================================================================== RCS file: /cvsroot/mozilla/js/rhino/src/org/mozilla/javascript/JavaMembers.java,v retrieving revision 1.53 diff -r1.53 JavaMembers.java 43a44 > import java.util.Vector; 93,94c94 < Object rval; < Class type; --- > Scriptable globalScope = ScriptableObject.getTopLevelScope(scope); 98,99c98 < rval = bp.getter.invoke(javaObject, Context.emptyArgs); < type = bp.getter.method().getReturnType(); --- > return bp.getter.call(cx, globalScope, scope, Context.emptyArgs); 102,103c101,104 < rval = field.get(isStatic ? null : javaObject); < type = field.getType(); --- > Object rval = field.get(isStatic ? null : javaObject); > Class type = field.getType(); > // Need to wrap the object before we return it. > return cx.getWrapFactory().wrap(cx, globalScope, rval, type); 108,110d108 < // Need to wrap the object before we return it. < scope = ScriptableObject.getTopLevelScope(scope); < return cx.getWrapFactory().wrap(cx, scope, rval, type); 135,141c133,136 < Class setType = bp.setter.argTypes[0]; < Object[] args = { Context.jsToJava(value, setType) }; < try { < bp.setter.invoke(javaObject, args); < } catch (Exception ex) { < throw Context.throwAsScriptRuntimeEx(ex); < } --- > NativeJavaMethod setter = (value == null) ? bp.mainSetter > : bp.setter; > Object[] args = { value }; > setter.call(Context.getContext(), ScriptableObject.getTopLevelScope(scope), scope, args); 460a456 > 462,464c458 < // We have a getter. Now, do we have a setter? < NativeJavaMethod njmSet = null; < MemberBox setter = null; --- > // We have a getter. Now, do we have setters? 465a460 > MemberBox[] setters = null; 470,473c465,467 < njmSet = (NativeJavaMethod)member; < Class type = getter.method().getReturnType(); < setter = extractSetMethod(type, njmSet.methods, < isStatic); --- > NativeJavaMethod njmSet = (NativeJavaMethod)member; > Class type = getter.method().getReturnType(); > setters = extractSetMethods(type, njmSet.methods, isStatic); 477c471 < BeanProperty bp = new BeanProperty(getter, setter); --- > BeanProperty bp = new BeanProperty(getter, setters); 504,505c498,499 < for (int methodIdx = 0; methodIdx < methods.length; methodIdx++) { < MemberBox method = methods[methodIdx]; --- > for (int i = 0; i < methods.length; i++) { > MemberBox method = methods[i]; 521c515 < private static MemberBox extractSetMethod(Class type, MemberBox[] methods, --- > private static MemberBox[] extractSetMethods(Class type, MemberBox[] methods, 524,553c518,573 < // < // Note: it may be preferable to allow NativeJavaMethod.findFunction() < // to find the appropriate setter; unfortunately, it requires an < // instance of the target arg to determine that. < // < < // Make two passes: one to find a method with direct type assignment, < // and one to find a widening conversion. < for (int pass = 1; pass <= 2; ++pass) { < for (int i = 0; i < methods.length; ++i) { < MemberBox method = methods[i]; < if (!isStatic || method.isStatic()) { < if (method.method().getReturnType() == Void.TYPE) { < Class[] params = method.argTypes; < if (params.length == 1) { < if (pass == 1) { < if (params[0] == type) { < return method; < } < } else { < if (pass != 2) Kit.codeBug(); < if (params[0].isAssignableFrom(type)) { < return method; < } < } < } < } < } < } < } --- > // find all setter methods that take one parameter and have a return type of void > // the method at [0] should be the version with the same type as - or an asignable > // type from - the getter method and will be used for setting null-values, which > // otherwise would be ambigous if there are several methods to handle a null value > // (e.g. a setter with the parameter of class Object and one of class String) > > MemberBox mainSetter = null; > Vector setMethods = new Vector(); > > // Make two passes: one to find a main setter method with direct type assignment, > // and one to find one with a widening conversion. > for (int pass = 1; pass <= 2; ++pass) { > for (int i = 0; i < methods.length; ++i) { > MemberBox method = methods[i]; > if (!isStatic || method.isStatic()) { > if (method.method().getReturnType() == Void.TYPE) { > Class[] params = method.argTypes; > if (params.length == 1) { > if (mainSetter == null) { // (still) looking for a main setter? > if (pass == 1) { > if (params[0] == type) { > mainSetter = method; > // just add it to the beginning of the list: > setMethods.add(0, mainSetter); > } > } else { > if (params[0].isAssignableFrom(type)) { > mainSetter = method; > // in pass 2, see wether it wasn't added already as a normal setter. > // if so, remove it in order to add it again at [0] > int pos = setMethods.indexOf(mainSetter); > if (pos >= 0) > setMethods.remove(pos); > setMethods.add(0, mainSetter); > } > } > } else { > // if we're in pass 1, just add all the suiting setters to the list. > // one of these may turn out to be the main setter in pass 2, so in pass 2, > // the setMethods needs to be checked if the setter was added already (see above). > setMethods.add(method); > } > } > } > } > } > // if a main setter was found, no second pass is needed: > if (mainSetter != null) > break; > } > > if (mainSetter != null) { > MemberBox[] setters = new MemberBox[setMethods.size()]; > setMethods.toArray(setters); > return setters; > } 636c656 < BeanProperty(MemberBox getter, MemberBox setter) --- > BeanProperty(MemberBox getter, MemberBox[] setters) 638,643c658,678 < this.getter = getter; < this.setter = setter; < } < < MemberBox getter; < MemberBox setter; --- > this.getter = new NativeJavaMethod(getter, getter.getName()); > > if (setters != null) { > setter = new NativeJavaMethod(setters); > // if there's more than one setter, setters[0] is the main setter, > // otherwise it's the same as setter: > if (setters.length > 1) { > mainSetter = new NativeJavaMethod(setters[0], setters[0].getName()); > } else { > mainSetter = setter; > } > } else { > setter = mainSetter = null; > } > } > > NativeJavaMethod getter; > NativeJavaMethod setter; > // main setter is the function with the same parameter type as the getter's return type. > // it is used for setting null values. > NativeJavaMethod mainSetter; .