📄 scriptableobject.java
字号:
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(ScriptableObject obj); * static void setFoo(ScriptableObject 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(ScriptableObject obj); * void setFoo(ScriptableObject 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) { if (delegateTo == null && (Modifier.isStatic(getter.getModifiers()))) delegateTo = HAS_STATIC_ACCESSORS; Class[] parmTypes = getter.getParameterTypes(); if (parmTypes.length != 0) { if (parmTypes.length != 1 || parmTypes[0] != ScriptRuntime.ScriptableObjectClass) { throw Context.reportRuntimeError1( "msg.bad.getter.parms", getter.toString()); } } else if (delegateTo != null) { throw Context.reportRuntimeError1( "msg.obj.getter.parms", getter.toString()); } if (setter != null) { if ((delegateTo == HAS_STATIC_ACCESSORS) != (Modifier.isStatic(setter.getModifiers()))) { throw Context.reportRuntimeError0("msg.getter.static"); } parmTypes = setter.getParameterTypes(); if (parmTypes.length == 2) { if (parmTypes[0] != ScriptRuntime.ScriptableObjectClass) { throw Context.reportRuntimeError0("msg.setter2.parms"); } if (delegateTo == null) { throw Context.reportRuntimeError1( "msg.setter1.parms", setter.toString()); } } else if (parmTypes.length == 1) { if (delegateTo != null) { throw Context.reportRuntimeError1( "msg.setter2.expected", setter.toString()); } } else { throw Context.reportRuntimeError0("msg.setter.parms"); } Class setterType = parmTypes[parmTypes.length - 1]; int setterTypeTag = FunctionObject.getTypeTag(setterType); if (setterTypeTag == FunctionObject.JAVA_UNSUPPORTED_TYPE) { throw Context.reportRuntimeError2( "msg.setter2.expected", setterType.getName(), setter.toString()); } } GetterSlot gslot = new GetterSlot(); gslot.delegateTo = delegateTo; gslot.getter = new MemberBox(getter); if (setter != null) { gslot.setter = new MemberBox(setter); } gslot.attributes = (short) attributes; Slot inserted = addSlot(propertyName, propertyName.hashCode(), gslot); if (inserted != gslot) { throw new RuntimeException("Property already exists"); } } /** * Search for names in a class, adding the resulting methods * as properties. * * <p> Uses reflection to find the methods of the given names. Then * FunctionObjects are constructed from the methods found, and * are added to this object as properties with the given names. * * @param names the names of the Methods to add as function properties * @param clazz the class to search for the Methods * @param attributes the attributes of the new properties * @see org.mozilla.javascript.FunctionObject */ public void defineFunctionProperties(String[] names, Class clazz, int attributes) { Method[] methods = FunctionObject.getMethodList(clazz); for (int i=0; i < names.length; i++) { String name = names[i]; Method m = FunctionObject.findSingleMethod(methods, name); if (m == null) { throw Context.reportRuntimeError2( "msg.method.not.found", name, clazz.getName()); } FunctionObject f = new FunctionObject(name, m, this); defineProperty(name, f, attributes); } } /** * Get the Object.prototype property. * See ECMA 15.2.4. */ public static Scriptable getObjectPrototype(Scriptable scope) { return getClassPrototype(scope, "Object"); } /** * Get the Function.prototype property. * See ECMA 15.3.4. */ public static Scriptable getFunctionPrototype(Scriptable scope) { return getClassPrototype(scope, "Function"); } /** * Get the prototype for the named class. * * For example, <code>getClassPrototype(s, "Date")</code> will first * walk up the parent chain to find the outermost scope, then will * search that scope for the Date constructor, and then will * return Date.prototype. If any of the lookups fail, or * the prototype is not a JavaScript object, then null will * be returned. * * @param scope an object in the scope chain * @param className the name of the constructor * @return the prototype for the named class, or null if it * cannot be found. */ public static Scriptable getClassPrototype(Scriptable scope, String className) { scope = getTopLevelScope(scope); Object ctor = getProperty(scope, className); Object proto; if (ctor instanceof BaseFunction) { proto = ((BaseFunction)ctor).getPrototypeProperty(); } else if (ctor instanceof Scriptable) { Scriptable ctorObj = (Scriptable)ctor; proto = ctorObj.get("prototype", ctorObj); } else { return null; } if (proto instanceof Scriptable) { return (Scriptable)proto; } return null; } /** * Get the global scope. * * <p>Walks the parent scope chain to find an object with a null * parent scope (the global object). * * @param obj a JavaScript object * @return the corresponding global scope */ public static Scriptable getTopLevelScope(Scriptable obj) { for (;;) { Scriptable parent = obj.getParentScope(); if (parent == null) { return obj; } obj = parent; } } /** * Seal this object. * * A sealed object may not have properties added or removed. Once * an object is sealed it may not be unsealed. * * @since 1.4R3 */ public synchronized void sealObject() { if (count >= 0) { count = -1 - count; } } /** * Return true if this object is sealed. * * It is an error to attempt to add or remove properties to * a sealed object. * * @return true if sealed, false otherwise. * @since 1.4R3 */ public final boolean isSealed() { return count < 0; } /** * Gets a named property from an object or any object in its prototype chain. * <p> * Searches the prototype chain for a property named <code>name</code>. * <p> * @param obj a JavaScript object * @param name a property name * @return the value of a property with name <code>name</code> found in * <code>obj</code> or any object in its prototype chain, or * <code>Scriptable.NOT_FOUND</code> if not found * @since 1.5R2 */ public static Object getProperty(Scriptable obj, String name) { Scriptable start = obj; Object result; do { result = obj.get(name, start); if (result != Scriptable.NOT_FOUND) break; obj = obj.getPrototype(); } while (obj != null); return result; } /** * Gets an indexed property from an object or any object in its prototype chain. * <p> * Searches the prototype chain for a property with integral index * <code>index</code>. Note that if you wish to look for properties with numerical * but non-integral indicies, you should use getProperty(Scriptable,String) with * the string value of the index. * <p> * @param obj a JavaScript object * @param index an integral index * @return the value of a property with index <code>index</code> found in * <code>obj</code> or any object in its prototype chain, or * <code>Scriptable.NOT_FOUND</code> if not found * @since 1.5R2 */ public static Object getProperty(Scriptable obj, int index) { Scriptable start = obj; Object result; do { result = obj.get(index, start); if (result != Scriptable.NOT_FOUND) break; obj = obj.getPrototype(); } while (obj != null); return result; } /** * Returns whether a named property is defined in an object or any object * in its prototype chain. * <p> * Searches the prototype chain for a property named <code>name</code>. * <p> * @param obj a JavaScript object * @param name a property name * @return the true if property was found * @since 1.5R2 */ public static boolean hasProperty(Scriptable obj, String name) { return null != getBase(obj, name); } /** * Returns whether an indexed property is defined in an object or any object * in its prototype chain. * <p> * Searches the prototype chain for a property with index <code>index</code>. * <p> * @param obj a JavaScript object * @param index a property index * @return the true if property was found * @since 1.5R2 */ public static boolean hasProperty(Scriptable obj, int index) { return null != getBase(obj, index); } /** * Puts a named property in an object or in an object in its prototype chain. * <p> * Seaches for the named property in the prototype chain. If it is found, * the value of the property in <code>obj</code> is changed through a call * to {@link Scriptable#put(String, Scriptable, Object)} on the prototype * passing <code>obj</code> as the <code>start</code> argument. This allows * the prototype to veto the property setting in case the prototype defines * the property with [[ReadOnly]] attribute. If the property is not found, * it is added in <code>obj</code>. * @param obj a JavaScript object * @param name a property name * @param value any JavaScript value accepted by Scriptable.put * @since 1.5R2 */ public static void putProperty(Scriptable obj, String name, Object value) { Scriptable base = getBase(obj, name); if (base == null) base = obj; base.put(name, obj, value); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -