?? scriptruntime.java
字號:
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_VARS)) { throw Context.reportRuntimeError1("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; } /** * 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 { Scriptable obj; Object[] ids; int index; ObjToIntMap used; String currentId; boolean enumValues; } public static Object enumInit(Object value, Context cx, boolean enumValues) { IdEnumeration x = new IdEnumeration(); x.obj = toObjectOrNull(cx, value); if (x.obj != null) { // null or undefined do not cause errors but rather lead to empty // "for in" loop x.enumValues = enumValues; // enumInit should read all initial ids before returning // or "for (a.i in a)" would wrongly enumerate i in a as well enumChangeObject(x); } return x; } public static Boolean enumNext(Object enumObj) { // OPT this could be more efficient boolean result; IdEnumeration x = (IdEnumeration)enumObj; for (;;) { if (x.obj == null) { result = false; break; } if (x.index == x.ids.length) { x.obj = x.obj.getPrototype(); enumChangeObject(x); continue; } Object id = x.ids[x.index++]; if (x.used != null && x.used.has(id)) { continue; } if (id instanceof String) { String strId = (String)id; if (!x.obj.has(strId, x.obj)) continue; // must have been deleted x.currentId = strId; } else { int intId = ((Number)id).intValue(); if (!x.obj.has(intId, x.obj)) continue; // must have been deleted x.currentId = String.valueOf(intId); } result = true; break; } return wrapBoolean(result); } public static Object enumId(Object enumObj, Context cx) { IdEnumeration x = (IdEnumeration)enumObj; if (!x.enumValues) return x.currentId; Object result; String s = toStringIdOrIndex(cx, x.currentId); if (s == null) { int index = lastIndexResult(cx); result = x.obj.get(index, x.obj); } else { result = x.obj.get(s, x.obj); } return result; } private static void enumChangeObject(IdEnumeration x) { Object[] ids = null; while (x.obj != null) { ids = x.obj.getIds(); if (ids.length != 0) { break; } x.obj = x.obj.getPrototype(); } if (x.obj != null && x.ids != null) { Object[] previous = x.ids; int L = previous.length; if (x.used == null) { x.used = new ObjToIntMap(L); } for (int i = 0; i != L; ++i) { x.used.intern(previous[i]); } } x.ids = ids; x.index = 0; } /** * Prepare for calling name(...): return function corresponding to * name and make current top scope available * as ScriptRuntime.lastStoredScriptable() for consumption as thisObj. * The caller must call ScriptRuntime.lastStoredScriptable() immediately * after calling this method. */ public static Callable getNameFunctionAndThis(String name, Context cx, Scriptable scope) { Scriptable parent = scope.getParentScope(); if (parent == null) { Object result = topScopeName(cx, scope, name); if (!(result instanceof Callable)) { if (result == Scriptable.NOT_FOUND) { throw notFoundError(scope, name); } else { throw notFunctionError(result, name); } } // Top scope is not NativeWith or NativeCall => thisObj == scope Scriptable thisObj = scope; storeScriptable(cx, thisObj); return (Callable)result; } // name will call storeScriptable(cx, thisObj); return (Callable)nameOrFunction(cx, scope, parent, name, true); } /** * Prepare for calling obj[id](...): return function corresponding to * obj[id] and make obj properly converted to Scriptable available * as ScriptRuntime.lastStoredScriptable() for consumption as thisObj. * The caller must call ScriptRuntime.lastStoredScriptable() immediately * after calling this method. */ public static Callable getElemFunctionAndThis(Object obj, Object elem, Context cx) { String s = toStringIdOrIndex(cx, elem); if (s != null) { return getPropFunctionAndThis(obj, s, cx); } int index = lastIndexResult(cx); Scriptable thisObj = toObjectOrNull(cx, obj); if (thisObj == null) { throw undefCallError(obj, String.valueOf(index)); } Object value; for (;;) { // Ignore XML lookup as requred by ECMA 357, 11.2.2.1 value = ScriptableObject.getProperty(thisObj, index); if (value != Scriptable.NOT_FOUND) { break; } if (!(thisObj instanceof XMLObject)) { break; } XMLObject xmlObject = (XMLObject)thisObj; Scriptable extra = xmlObject.getExtraMethodSource(cx); if (extra == null) { break; } thisObj = extra; } if (!(value instanceof Callable)) { throw notFunctionError(value, elem); } storeScriptable(cx, thisObj); return (Callable)value; } /** * Prepare for calling obj.property(...): return function corr
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -