📄 scriptruntime.java
字号:
} else { String s = toString(dblIndex); return setObjectProp(sobj, s, value, cx); } } public static Object setObjectIndex(Scriptable obj, int index, Object value, Context cx) { if (obj instanceof XMLObject) { XMLObject xmlObject = (XMLObject)obj; xmlObject.ecmaPut(cx, new Integer(index), value); } else { ScriptableObject.putProperty(obj, index, value); } return value; } public static boolean deleteObjectElem(Scriptable target, Object elem, Context cx) { boolean result; if (target instanceof XMLObject) { XMLObject xmlObject = (XMLObject)target; result = xmlObject.ecmaDelete(cx, elem); } else { String s = toStringIdOrIndex(cx, elem); if (s == null) { int index = lastIndexResult(cx); result = ScriptableObject.deleteProperty(target, index); } else { result = ScriptableObject.deleteProperty(target, s); } } return result; } public static boolean hasObjectElem(Scriptable target, Object elem, Context cx) { boolean result; if (target instanceof XMLObject) { XMLObject xmlObject = (XMLObject)target; result = xmlObject.ecmaHas(cx, elem); } else { String s = toStringIdOrIndex(cx, elem); if (s == null) { int index = lastIndexResult(cx); result = ScriptableObject.hasProperty(target, index); } else { result = ScriptableObject.hasProperty(target, s); } } return result; } public static Object refGet(Ref ref, Context cx) { return ref.get(cx); } public static Object refSet(Ref ref, Object value, Context cx) { return ref.set(cx, value); } public static Object refDel(Ref ref, Context cx) { return wrapBoolean(ref.delete(cx)); } static boolean isSpecialProperty(String s) { return s.equals("__proto__") || s.equals("__parent__"); } public static Ref specialRef(Object obj, String specialProperty, Context cx) { return SpecialRef.createSpecial(cx, obj, specialProperty); } /** * The delete operator * * See ECMA 11.4.1 * * In ECMA 0.19, the description of the delete operator (11.4.1) * assumes that the [[Delete]] method returns a value. However, * the definition of the [[Delete]] operator (8.6.2.5) does not * define a return value. Here we assume that the [[Delete]] * method doesn't return a value. */ public static Object delete(Object obj, Object id, Context cx) { Scriptable sobj = toObjectOrNull(cx, obj); if (sobj == null) { String idStr = (id == null) ? "null" : id.toString(); throw typeError2("msg.undef.prop.delete", toString(obj), idStr); } boolean result = deleteObjectElem(sobj, id, cx); return wrapBoolean(result); } /** * Looks up a name in the scope chain and returns its value. */ public static Object name(Context cx, Scriptable scope, String name) { Scriptable parent = scope.getParentScope(); if (parent == null) { Object result = topScopeName(cx, scope, name); if (result == Scriptable.NOT_FOUND) { throw notFoundError(scope, name); } return result; } return nameOrFunction(cx, scope, parent, name, false); } private static Object nameOrFunction(Context cx, Scriptable scope, Scriptable parentScope, String name, boolean asFunctionCall) { Object result; Scriptable thisObj = scope; // It is used only if asFunctionCall==true. XMLObject firstXMLObject = null; for (;;) { if (scope instanceof NativeWith) { Scriptable withObj = scope.getPrototype(); if (withObj instanceof XMLObject) { XMLObject xmlObj = (XMLObject)withObj; if (xmlObj.ecmaHas(cx, name)) { // function this should be the target object of with thisObj = xmlObj; result = xmlObj.ecmaGet(cx, name); break; } if (firstXMLObject == null) { firstXMLObject = xmlObj; } } else { result = ScriptableObject.getProperty(withObj, name); if (result != Scriptable.NOT_FOUND) { // function this should be the target object of with thisObj = withObj; break; } } } else if (scope instanceof NativeCall) { // NativeCall does not prototype chain and Scriptable.get // can be called directly. result = scope.get(name, scope); if (result != Scriptable.NOT_FOUND) { if (asFunctionCall) { // ECMA 262 requires that this for nested funtions // should be top scope thisObj = ScriptableObject. getTopLevelScope(parentScope); } break; } } else { // Can happen if Rhino embedding decided that nested // scopes are useful for what ever reasons. result = ScriptableObject.getProperty(scope, name); if (result != Scriptable.NOT_FOUND) { thisObj = scope; break; } } scope = parentScope; parentScope = parentScope.getParentScope(); if (parentScope == null) { result = topScopeName(cx, scope, name); if (result == Scriptable.NOT_FOUND) { if (firstXMLObject == null || asFunctionCall) { throw notFoundError(scope, name); } // The name was not found, but we did find an XML // object in the scope chain and we are looking for name, // not function. The result should be an empty XMLList // in name context. result = firstXMLObject.ecmaGet(cx, name); } // For top scope thisObj for functions is always scope itself. thisObj = scope; break; } } if (asFunctionCall) { if (!(result instanceof Callable)) { throw notFunctionError(result, name); } storeScriptable(cx, thisObj); } return result; } private static Object topScopeName(Context cx, Scriptable scope, String name) { if (cx.useDynamicScope) { scope = checkDynamicScope(cx.topCallScope, scope); } return ScriptableObject.getProperty(scope, name); } /** * Returns the object in the scope chain that has a given property. * * The order of evaluation of an assignment expression involves * evaluating the lhs to a reference, evaluating the rhs, and then * modifying the reference with the rhs value. This method is used * to 'bind' the given name to an object containing that property * so that the side effects of evaluating the rhs do not affect * which property is modified. * Typically used in conjunction with setName. * * See ECMA 10.1.4 */ public static Scriptable bind(Context cx, Scriptable scope, String id) { Scriptable firstXMLObject = null; Scriptable parent = scope.getParentScope(); childScopesChecks: if (parent != null) { // Check for possibly nested "with" scopes first while (scope instanceof NativeWith) { Scriptable withObj = scope.getPrototype(); if (withObj instanceof XMLObject) { XMLObject xmlObject = (XMLObject)withObj; if (xmlObject.ecmaHas(cx, id)) { return xmlObject; } if (firstXMLObject == null) { firstXMLObject = xmlObject; } } else { if (ScriptableObject.hasProperty(withObj, id)) { return withObj; } } scope = parent; parent = parent.getParentScope(); if (parent == null) { break childScopesChecks; } } for (;;) { if (ScriptableObject.hasProperty(scope, id)) { return scope; } scope = parent; parent = parent.getParentScope(); if (parent == null) { break childScopesChecks; } } } // scope here is top scope if (cx.useDynamicScope) { scope = checkDynamicScope(cx.topCallScope, scope); } if (ScriptableObject.hasProperty(scope, id)) { return scope; } // Nothing was found, but since XML objects always bind // return one if found return firstXMLObject; } public static Object setName(Scriptable bound, Object value, Context cx, Scriptable scope, String id) { if (bound != null) { if (bound instanceof XMLObject) { XMLObject xmlObject = (XMLObject)bound; xmlObject.ecmaPut(cx, id, value); } else { ScriptableObject.putProperty(bound, id, value); } } else { // "newname = 7;", where 'newname' has not yet // been defined, creates a new property in the // top scope unless strict mode is specified. if (cx.hasFeature(Context.FEATURE_STRICT_MODE) || cx.hasFeature(Context.FEATURE_STRICT_VARS)) { Context.reportWarning( ScriptRuntime.getMessage1("msg.assn.create.strict", id)); } // Find the top scope by walking up the scope chain. bound = ScriptableObject.getTopLevelScope(scope); if (cx.useDynamicScope) { bound = checkDynamicScope(cx.topCallScope, bound); } bound.put(id, bound, value); } return value; } public static Object setConst(Scriptable bound, Object value, Context cx, String id) { if (bound instanceof XMLObject) { XMLObject xmlObject = (XMLObject)bound; xmlObject.ecmaPut(cx, id, value); } else { ScriptableObject.putConstProperty(bound, id, value); } return value; } /** * This is the enumeration needed by the for..in statement. * * See ECMA 12.6.3. * * IdEnumeration maintains a ObjToIntMap to make sure a given * id is enumerated only once across multiple objects in a * prototype chain. * * XXX - ECMA delete doesn't hide properties in the prototype, * but js/ref does. This means that the js/ref for..in can * avoid maintaining a hash table and instead perform lookups * to see if a given property has already been enumerated. * */ private static class IdEnumeration implements Serializable { private static final long serialVersionUID = 1L; Scriptable obj; Object[] ids; int index; ObjToIntMap used; Object currentId; int enumType; /* one of ENUM_INIT_KEYS, ENUM_INIT_VALUES, ENUM_INIT_ARRAY */ // if true, integer ids will be returned as numbers rather than strings boolean enumNumbers; Scriptable iterator; } public static Scriptable toIterator(Context cx, Scriptable scope, Scriptable obj, boolean keyOnly) { if (ScriptableObject.hasProperty(obj, NativeIterator.ITERATOR_PROPERTY_NAME)) { Object v = ScriptableObject.getProperty(obj, NativeIterator.ITERATOR_PROPERTY_NAME); if (!(v instanceof Callable)) { throw typeError0("msg.invalid.iterator"); } Callable f = (Callable) v; Object[] args = new Object[] { keyOnly ? Boolean.TRUE : Boolean.FALSE }; v = f.call(cx, scope, obj, args); if (!(v instanceof Scriptable)) { throw typeError0("msg.iterator.primitive"); } return (Scriptable) v; } return null; } // for backwards compatibility with generated class files public static Object enumInit(Object value, Context cx, boolean enumValues) { return enumInit(value, cx, enumValues ? ENUMERATE_VALUES : ENUMERATE_KEYS); } public stati
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -