public virtual bool MoveNext() { // OPT this could be more efficient bool result; for (; ;) { if (obj == null) { result = false; break; } if (index == ids.Length) { obj = obj.GetPrototype(); this.ChangeObject(); continue; } object id = ids [index++]; if (used != null && used.has(id)) { continue; } if (id is string) { string strId = (string)id; if (!obj.Has(strId, obj)) { continue; // must have been deleted } currentId = strId; } else { int intId = Convert.ToInt32(id); if (!obj.Has(intId, obj)) { continue; // must have been deleted } currentId = Convert.ToString(intId); } result = true; break; } return(result); }
public object Set(Context cx, object value) { switch (type) { case Types.None: return(ScriptRuntime.setObjectProp(target, name, value, cx)); case Types.Proto: case Types.Parent: { IScriptable obj = ScriptConvert.ToObjectOrNull(cx, value); if (obj != null) { // Check that obj does not contain on its prototype/scope // chain to prevent cycles IScriptable search = obj; do { if (search == target) { throw Context.ReportRuntimeErrorById("msg.cyclic.value", name); } if (type == Types.Proto) { search = search.GetPrototype(); } else { search = search.ParentScope; } }while (search != null); } if (type == Types.Proto) { target.SetPrototype(obj); } else { target.ParentScope = obj; } return(obj); } default: throw Context.CodeBug(); } }
public object Get(Context cx) { switch (type) { case Types.None: return(ScriptRuntime.getObjectProp(target, name, cx)); case Types.Proto: return(target.GetPrototype()); case Types.Parent: return(target.ParentScope); default: throw Context.CodeBug(); } }
public virtual IScriptable Construct(Context cx, IScriptable scope, object [] args) { IScriptable result = CreateObject(cx, scope); if (result != null) { object val = Call(cx, scope, result, args); if (val is IScriptable) { result = (IScriptable)val; } } else { object val = Call(cx, scope, null, args); if (!(val is IScriptable)) { // It is program error not to return Scriptable from // the call method if createObject returns null. throw new Exception("Bad implementaion of call as constructor, name=" + FunctionName + " in " + GetType().FullName); } result = (IScriptable)val; if (result.GetPrototype() == null) { result.SetPrototype(GetClassPrototype()); } if (result.ParentScope == null) { IScriptable parent = ParentScope; if (result != parent) { result.ParentScope = parent; } } } return(result); }
public override object Call(Context cx, IScriptable scope, IScriptable thisObj, object [] args) { if (m_MethodInfos.Length == 0) { throw new ApplicationException("No methods defined for call"); } int index = FindFunction(cx, m_MethodInfos, args, paramsParameters); if (index < 0) { Type c = m_MethodInfos [0].DeclaringType; string sig = c.FullName + '.' + FunctionName + '(' + ScriptSignature(args) + ')'; throw Context.ReportRuntimeErrorById("msg.java.no_such_method", sig); } MethodBase meth = (MethodBase)m_MethodInfos [index]; ParameterInfo [] pis = meth.GetParameters(); // First, we marshall the args. object [] origArgs = args; for (int i = 0; i < args.Length; i++) { object arg = args [i]; if (paramsParameters [index] && i >= pis.Length - 1) { // params[] arg is always an array type Type arrayType = pis [pis.Length - 1].ParameterType; Type arrayElementType = arrayType.GetElementType(); object [] dummyArg = new object [args.Length - i]; for (int e = i; e < args.Length; e++) { dummyArg [e - i] = Context.JsToCli(arg, arrayElementType); } args = new object [i + 1]; args.CopyTo(args, 0); args [i] = dummyArg; } else { Type argType = pis [i].ParameterType; object coerced = Context.JsToCli(arg, argType); if (coerced != arg) { if (origArgs == args) { args = new object [args.Length]; args.CopyTo(args, 0); } args [i] = coerced; } } } object cliObject; if (meth.IsStatic) { cliObject = null; // don't need an object } else { IScriptable o = thisObj; Type c = meth.DeclaringType; for (; ;) { if (o == null) { throw Context.ReportRuntimeErrorById("msg.nonjava.method", FunctionName, ScriptConvert.ToString(thisObj), c.FullName); } if (o is Wrapper) { cliObject = ((Wrapper)o).Unwrap(); if (c.IsInstanceOfType(cliObject)) { break; } } o = o.GetPrototype(); } } object retval = null; try { retval = (meth as MethodBase).Invoke(cliObject, args); } catch (Exception ex) { Context.ThrowAsScriptRuntimeEx(ex); } Type staticType = meth.DeclaringType; if (meth is MethodInfo) { staticType = ((MethodInfo)meth).ReturnType; } object wrapped = cx.Wrap(scope, retval, staticType); if (wrapped == null && staticType == Type.GetType("System.Void")) { wrapped = Undefined.Value; } return(wrapped); }
private static IScriptable GetBase (IScriptable obj, int index) { do { if (obj.Has (index, obj)) break; obj = obj.GetPrototype (); } while (obj != null); return obj; }
private static IScriptable GetBase (IScriptable obj, string name) { do { if (obj.Has (name, obj)) break; obj = obj.GetPrototype (); } while (obj != null); return obj; }
/// <summary> Returns an array of all ids from an object and its prototypes. /// <p> /// </summary> /// <param name="obj">a JavaScript object /// </param> /// <returns> an array of all ids from all object in the prototype chain. /// If a given id occurs multiple times in the prototype chain, /// it will occur only once in this list. /// </returns> public static object [] GetPropertyIds (IScriptable obj) { if (obj == null) { return ScriptRuntime.EmptyArgs; } object [] result = obj.GetIds (); ObjToIntMap map = null; for (; ; ) { obj = obj.GetPrototype (); if (obj == null) { break; } object [] ids = obj.GetIds (); if (ids.Length == 0) { continue; } if (map == null) { if (result.Length == 0) { result = ids; continue; } map = new ObjToIntMap (result.Length + ids.Length); for (int i = 0; i != result.Length; ++i) { map.intern (result [i]); } result = null; // Allow to GC the result } for (int i = 0; i != ids.Length; ++i) { map.intern (ids [i]); } } if (map != null) { result = map.getKeys (); } return result; }
/// <summary> 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> /// </summary> /// <param name="obj">a JavaScript object /// </param> /// <param name="index">an integral index /// </param> /// <returns> 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 /// </returns> public static object GetProperty (IScriptable obj, int index) { IScriptable start = obj; object result; do { result = obj.Get (index, start); if (result != UniqueTag.NotFound) break; obj = obj.GetPrototype (); } while (obj != null); return result; }
/// <summary> Get arbitrary application-specific value associated with the top scope /// of the given scope. /// The method first calls {@link #getTopLevelScope(Scriptable scope)} /// and then searches the prototype chain of the top scope for the first /// object containing the associated value with the given key. /// /// </summary> /// <param name="scope">the starting scope. /// </param> /// <param name="key">key object to select particular value. /// </param> public static object GetTopScopeValue (IScriptable scope, object key) { scope = ScriptableObject.GetTopLevelScope (scope); for (; ; ) { if (scope is ScriptableObject) { ScriptableObject so = (ScriptableObject)scope; object value = so.GetAssociatedValue (key); if (value != null) { return value; } } scope = scope.GetPrototype (); if (scope == null) { return null; } } }
private static object nameOrFunction(Context cx, IScriptable scope, IScriptable parentScope, string name, bool asFunctionCall) { object result; IScriptable thisObj = scope; // It is used only if asFunctionCall==true. XMLObject firstXMLObject = null; for (; ; ) { if (scope is BuiltinWith) { IScriptable withObj = scope.GetPrototype (); if (withObj is 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 != UniqueTag.NotFound) { // function this should be the target object of with thisObj = withObj; break; } } } else if (scope is BuiltinCall) { // NativeCall does not prototype chain and Scriptable.get // can be called directly. result = scope.Get (name, scope); if (result != UniqueTag.NotFound) { if (asFunctionCall) { // ECMA 262 requires that this for nested funtions // should be top scope thisObj = ScriptableObject.GetTopLevelScope (parentScope); } break; } } else { // Can happen if embedding decided that nested // scopes are useful for what ever reasons. result = ScriptableObject.GetProperty (scope, name); if (result != UniqueTag.NotFound) { thisObj = scope; break; } } scope = parentScope; parentScope = parentScope.ParentScope; if (parentScope == null) { result = topScopeName (cx, scope, name); if (result == UniqueTag.NotFound) { 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 is ICallable)) { throw NotFunctionError (result, name); } storeScriptable (cx, thisObj); } return result; }
/// <summary> Delegates to /// /// </summary> /// <returns> true iff rhs appears in lhs' proto chain /// </returns> protected internal static bool jsDelegatesTo(IScriptable lhs, IScriptable rhs) { IScriptable proto = lhs.GetPrototype (); while (proto != null) { if (proto.Equals (rhs)) return true; proto = proto.GetPrototype (); } return false; }
/// <summary> 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 /// </summary> public static IScriptable bind(Context cx, IScriptable scope, string id) { IScriptable firstXMLObject = null; IScriptable parent = scope.ParentScope; if (parent != null) { // Check for possibly nested "with" scopes first while (scope is BuiltinWith) { IScriptable withObj = scope.GetPrototype (); if (withObj is 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.ParentScope; if (parent == null) { goto childScopesChecks_brk; } } for (; ; ) { if (ScriptableObject.HasProperty (scope, id)) { return scope; } scope = parent; parent = parent.ParentScope; if (parent == null) { goto childScopesChecks_brk; } } } childScopesChecks_brk: ; // 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 nameIncrDecr(IScriptable scopeChain, string id, int incrDecrMask) { IScriptable target; object value; { do { target = scopeChain; do { value = target.Get (id, scopeChain); if (value != UniqueTag.NotFound) { goto search_brk; } target = target.GetPrototype (); } while (target != null); scopeChain = scopeChain.ParentScope; } while (scopeChain != null); throw NotFoundError (scopeChain, id); } search_brk: ; return doScriptableIncrDecr (target, id, scopeChain, value, incrDecrMask); }
public override object ExecIdCall(IdFunctionObject f, Context cx, IScriptable scope, IScriptable thisObj, object [] args) { if (!f.HasTag(OBJECT_TAG)) { return(base.ExecIdCall(f, cx, scope, thisObj, args)); } int id = f.MethodId; switch (id) { case Id_constructor: { if (thisObj != null) { // BaseFunction.construct will set up parent, proto return(f.Construct(cx, scope, args)); } if (args.Length == 0 || args [0] == null || args [0] == Undefined.Value) { return(new BuiltinObject()); } return(ScriptConvert.ToObject(cx, scope, args [0])); } case Id_toLocaleString: // For now just alias toString case Id_toString: { if (cx.HasFeature(Context.Features.ToStringAsSource)) { string s = ScriptRuntime.defaultObjectToSource(cx, scope, thisObj, args); int L = s.Length; if (L != 0 && s [0] == '(' && s [L - 1] == ')') { // Strip () that surrounds toSource s = s.Substring(1, (L - 1) - (1)); } return(s); } return(ScriptRuntime.DefaultObjectToString(thisObj)); } case Id_valueOf: return(thisObj); case Id_hasOwnProperty: { bool result; if (args.Length == 0) { result = false; } else { string s = ScriptRuntime.ToStringIdOrIndex(cx, args [0]); if (s == null) { int index = ScriptRuntime.lastIndexResult(cx); result = thisObj.Has(index, thisObj); } else { result = thisObj.Has(s, thisObj); } } return(result); } case Id_propertyIsEnumerable: { bool result; if (args.Length == 0) { result = false; } else { string s = ScriptRuntime.ToStringIdOrIndex(cx, args [0]); if (s == null) { int index = ScriptRuntime.lastIndexResult(cx); result = thisObj.Has(index, thisObj); if (result && thisObj is ScriptableObject) { ScriptableObject so = (ScriptableObject)thisObj; int attrs = so.GetAttributes(index); result = ((attrs & ScriptableObject.DONTENUM) == 0); } } else { result = thisObj.Has(s, thisObj); if (result && thisObj is ScriptableObject) { ScriptableObject so = (ScriptableObject)thisObj; int attrs = so.GetAttributes(s); result = ((attrs & ScriptableObject.DONTENUM) == 0); } } } return(result); } case Id_isPrototypeOf: { bool result = false; if (args.Length != 0 && args [0] is IScriptable) { IScriptable v = (IScriptable)args [0]; do { v = v.GetPrototype(); if (v == thisObj) { result = true; break; } }while (v != null); } return(result); } case Id_toSource: return(ScriptRuntime.defaultObjectToSource(cx, scope, thisObj, args)); case Id___lookupGetter__: case Id___lookupSetter__: { if (args.Length < 1) { return(Undefined.Value); } string name = ScriptRuntime.ToStringIdOrIndex(cx, args [0]); int index = (name != null) ? name.GetHashCode() : ScriptRuntime.lastIndexResult(cx); // TODO: delegate way up to prototypes? ScriptableObject so = (thisObj as ScriptableObject); if (so == null) { throw ScriptRuntime.TypeError("this is not a scriptable object."); } if (id == Id___lookupGetter__) { return(so.LookupGetter(name)); } else { return(so.LookupSetter(name)); } } case Id___defineGetter__: case Id___defineSetter__: { if (args.Length < 2 || args.Length > 0 && !(args [1] is ICallable)) { object badArg = (args.Length > 1 ? args [1] : Undefined.Value); throw ScriptRuntime.NotFunctionError(badArg); } string name = ScriptRuntime.ToStringIdOrIndex(cx, args [0]); int index = (name != null) ? name.GetHashCode() : ScriptRuntime.lastIndexResult(cx); // TODO: delegate way up to prototypes? ScriptableObject so = (thisObj as ScriptableObject); if (so == null) { throw ScriptRuntime.TypeError("this is not a scriptable object."); } ICallable getterOrSetter = (ICallable)args [1]; if (id == Id___defineGetter__) { if (name == null) { so.DefineGetter(index, getterOrSetter); } else { so.DefineGetter(name, getterOrSetter); } } else { if (name == null) { so.DefineSetter(index, getterOrSetter); } else { so.DefineSetter(name, getterOrSetter); } } return(Undefined.Value); break; } default: throw new ArgumentException(Convert.ToString(id)); } }
public virtual IScriptable GetPrototype() { return(obj.GetPrototype()); }