📄 scriptableobject.java
字号:
"msg.zero.arg.ctor", clazz.getName()); } Scriptable proto = (Scriptable) protoCtor.newInstance(ScriptRuntime.emptyArgs); String className = proto.getClassName(); // Set the prototype's prototype, trying to map Java inheritance to JS // prototype-based inheritance if requested to do so. Scriptable superProto = null; if (mapInheritance) { Class superClass = clazz.getSuperclass(); if (ScriptRuntime.ScriptableClass.isAssignableFrom(superClass) && !Modifier.isAbstract(superClass.getModifiers())) { String name = ScriptableObject.defineClass(scope, superClass, sealed, mapInheritance); if (name != null) { superProto = ScriptableObject.getClassPrototype(scope, name); } } } if (superProto == null) { superProto = ScriptableObject.getObjectPrototype(scope); } proto.setPrototype(superProto); // Find out whether there are any methods that begin with // "js". If so, then only methods that begin with special // prefixes will be defined as JavaScript entities. final String functionPrefix = "jsFunction_"; final String staticFunctionPrefix = "jsStaticFunction_"; final String getterPrefix = "jsGet_"; final String setterPrefix = "jsSet_"; final String ctorName = "jsConstructor"; Member ctorMember = FunctionObject.findSingleMethod(methods, ctorName); if (ctorMember == null) { if (ctors.length == 1) { ctorMember = ctors[0]; } else if (ctors.length == 2) { if (ctors[0].getParameterTypes().length == 0) ctorMember = ctors[1]; else if (ctors[1].getParameterTypes().length == 0) ctorMember = ctors[0]; } if (ctorMember == null) { throw Context.reportRuntimeError1( "msg.ctor.multiple.parms", clazz.getName()); } } FunctionObject ctor = new FunctionObject(className, ctorMember, scope); if (ctor.isVarArgsMethod()) { throw Context.reportRuntimeError1 ("msg.varargs.ctor", ctorMember.getName()); } ctor.initAsConstructor(scope, proto); Method finishInit = null; for (int i=0; i < methods.length; i++) { if (methods[i] == ctorMember) { continue; } String name = methods[i].getName(); if (name.equals("finishInit")) { Class[] parmTypes = methods[i].getParameterTypes(); if (parmTypes.length == 3 && parmTypes[0] == ScriptRuntime.ScriptableClass && parmTypes[1] == FunctionObject.class && parmTypes[2] == ScriptRuntime.ScriptableClass && Modifier.isStatic(methods[i].getModifiers())) { finishInit = methods[i]; continue; } } // ignore any compiler generated methods. if (name.indexOf('$') != -1) continue; if (name.equals(ctorName)) continue; String prefix = null; if (name.startsWith(functionPrefix)) { prefix = functionPrefix; } else if (name.startsWith(staticFunctionPrefix)) { prefix = staticFunctionPrefix; if (!Modifier.isStatic(methods[i].getModifiers())) { throw Context.reportRuntimeError( "jsStaticFunction must be used with static method."); } } else if (name.startsWith(getterPrefix)) { prefix = getterPrefix; } else if (name.startsWith(setterPrefix)) { prefix = setterPrefix; } else { continue; } name = name.substring(prefix.length()); if (prefix == setterPrefix) continue; // deal with set when we see get if (prefix == getterPrefix) { if (!(proto instanceof ScriptableObject)) { throw Context.reportRuntimeError2( "msg.extend.scriptable", proto.getClass().toString(), name); } Method setter = FunctionObject.findSingleMethod( methods, setterPrefix + name); int attr = ScriptableObject.PERMANENT | ScriptableObject.DONTENUM | (setter != null ? 0 : ScriptableObject.READONLY); ((ScriptableObject) proto).defineProperty(name, null, methods[i], setter, attr); continue; } FunctionObject f = new FunctionObject(name, methods[i], proto); if (f.isVarArgsConstructor()) { throw Context.reportRuntimeError1 ("msg.varargs.fun", ctorMember.getName()); } Scriptable dest = prefix == staticFunctionPrefix ? ctor : proto; defineProperty(dest, name, f, DONTENUM); if (sealed) { f.sealObject(); } } // Call user code to complete initialization if necessary. if (finishInit != null) { Object[] finishArgs = { scope, ctor, proto }; finishInit.invoke(null, finishArgs); } // Seal the object if necessary. if (sealed) { ctor.sealObject(); if (proto instanceof ScriptableObject) { ((ScriptableObject) proto).sealObject(); } } return ctor; } /** * Define a JavaScript property. * * Creates the property with an initial value and sets its attributes. * * @param propertyName the name of the property to define. * @param value the initial value of the property * @param attributes the attributes of the JavaScript property * @see org.mozilla.javascript.Scriptable#put(String, Scriptable, Object) */ public void defineProperty(String propertyName, Object value, int attributes) { checkNotSealed(propertyName, 0); put(propertyName, this, value); setAttributes(propertyName, attributes); } /** * Utility method to add properties to arbitrary Scriptable object. * If destination is instance of ScriptableObject, calls * defineProperty there, otherwise calls put in destination * ignoring attributes */ public static void defineProperty(Scriptable destination, String propertyName, Object value, int attributes) { if (!(destination instanceof ScriptableObject)) { destination.put(propertyName, destination, value); return; } ScriptableObject so = (ScriptableObject)destination; so.defineProperty(propertyName, value, attributes); } /** * Utility method to add properties to arbitrary Scriptable object. * If destination is instance of ScriptableObject, calls * defineProperty there, otherwise calls put in destination * ignoring attributes */ public static void defineConstProperty(Scriptable destination, String propertyName) { if (destination instanceof ConstProperties) { ConstProperties cp = (ConstProperties)destination; cp.defineConst(propertyName, destination); } else defineProperty(destination, propertyName, Undefined.instance, CONST); } /** * Define a JavaScript property with getter and setter side effects. * * If the setter is not found, the attribute READONLY is added to * the given attributes. <p> * * The getter must be a method with zero parameters, and the setter, if * found, must be a method with one parameter.<p> * * @param propertyName the name of the property to define. This name * also affects the name of the setter and getter * to search for. If the propertyId is "foo", then * <code>clazz</code> will be searched for "getFoo" * and "setFoo" methods. * @param clazz the Java class to search for the getter and setter * @param attributes the attributes of the JavaScript property * @see org.mozilla.javascript.Scriptable#put(String, Scriptable, Object) */ public void defineProperty(String propertyName, Class clazz, int attributes) { int length = propertyName.length(); if (length == 0) throw new IllegalArgumentException(); char[] buf = new char[3 + length]; propertyName.getChars(0, length, buf, 3); buf[3] = Character.toUpperCase(buf[3]); buf[0] = 'g'; buf[1] = 'e'; buf[2] = 't'; String getterName = new String(buf); buf[0] = 's'; String setterName = new String(buf); Method[] methods = FunctionObject.getMethodList(clazz); Method getter = FunctionObject.findSingleMethod(methods, getterName); Method setter = FunctionObject.findSingleMethod(methods, setterName); if (setter == null) attributes |= ScriptableObject.READONLY; defineProperty(propertyName, null, getter, setter == null ? null : setter, attributes); } /** * Define a JavaScript property. * * Use this method only if you wish to define getters and setters for * a given property in a ScriptableObject. To create a property without * special getter or setter side effects, use * <code>defineProperty(String,int)</code>. * * If <code>setter</code> is null, the attribute READONLY is added to * the given attributes.<p> * * Several forms of getters or setters are allowed. In all cases the * type of the value parameter can be any one of the following types: * Object, String, boolean, Scriptable, byte, short, int, long, float, * or double. The runtime will perform appropriate conversions based * upon the type of the parameter (see description in FunctionObject). * The first forms are nonstatic methods of the class referred to * by 'this': * <pre> * Object getFoo(); * void setFoo(SomeType value);</pre> * Next are static methods that may be of any class; the object whose * property is being accessed is passed in as an extra argument: * <pre> * static Object getFoo(Scriptable obj); * static void setFoo(Scriptable obj, SomeType value);</pre> * Finally, it is possible to delegate to another object entirely using * the <code>delegateTo</code> parameter. In this case the methods are * nonstatic methods of the class delegated to, and the object whose * property is being accessed is passed in as an extra argument: * <pre> * Object getFoo(Scriptable obj); * void setFoo(Scriptable obj, SomeType value);</pre> * * @param propertyName the name of the property to define. * @param delegateTo an object to call the getter and setter methods on, * or null, depending on the form used above. * @param getter the method to invoke to get the value of the property * @param setter the method to invoke to set the value of the property * @param attributes the attributes of the JavaScript property */ public void defineProperty(String propertyName, Object delegateTo, Method getter, Method setter, int attributes) { MemberBox getterBox = null; if (getter != null) { getterBox = new MemberBox(getter); boolean delegatedForm; if (!Modifier.isStatic(getter.getModifiers())) { delegatedForm = (delegateTo != null); getterBox.delegateTo = delegateTo; } else { delegatedForm = true; // Ignore delegateTo for static getter but store // non-null delegateTo indicator. getterBox.delegateTo = Void.TYPE; } String errorId = null; Class[] parmTypes = getter.getParameterTypes(); if (parmTypes.length == 0) { if (delegatedForm) { errorId = "msg.obj.getter.parms"; } } else if (parmTypes.length == 1) { Object argType = parmTypes[0]; // Allow ScriptableObject for compatibility if (!(argType == ScriptRuntime.ScriptableClass || argType == ScriptRuntime.ScriptableObjectClass)) { errorId = "msg.bad.getter.parms"; } else if (!delegatedForm) { errorId = "msg.bad.getter.parms"; } } else { errorId = "msg.bad.getter.parms"; } if (errorId != null) { throw Context.reportRuntimeError1(errorId, getter.toString()); } } MemberBox setterBox = null; if (setter != null) { if (setter.getReturnType() != Void.TYPE) throw Context.reportRuntimeError1("msg.setter.return", setter.toString()); setterBox = new MemberBox(setter); boolean delegatedForm; if (!Modifier.isStatic(setter.getModifiers())) { delegatedForm = (delegateTo != null); setterBox.delegateTo = delegateTo; } else { delegatedForm = true; // Ignore delegateTo for static setter but store // non-null delegateTo indicator. setterBox.delegateTo = Void.TYPE; } String errorId = null; Class[] parmTypes = setter.getParameterTypes();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -