//=========================================================== // Member Access //=========================================================== /// <summary> /// このオブジェクトの持つメンバを検索します /// </summary> public virtual JavaScript.Object this[string propName] { get{ if (propName == "__proto__") { return(this.__proto__); } //--本来のメンバ JavaScript.Object o = this.members_get(propName); if (o != null) { return(o); } #if doublehash //--隠しメンバ if (null != (o = this.pmembers_get(propName))) { return(o); } #endif //--継承元のメンバ if (null != (o = this._proto)) { if (null != (o = o[propName])) { return(o); } } return(null); } set{ this.members_set(propName, value); } }
//=========================================================== // Other Methods //=========================================================== #if doublehash // 通常メンバのみのコピー public void CopyMembers(JavaScript.Object source) { foreach (string key in source.members.Keys) { this.members[key] = source.members[key]; } }
public JavaScript.Object Add(JavaScript.Object num2) { JavaScript.Number n2 = num2 as JavaScript.Number; if (n2 != null) { if (this.isInt) { if (n2.isInt) { return(Global.ConvertFromManaged(this.numL + n2.numL)); } else { return(Global.ConvertFromManaged(this.numL + n2.numD)); } } else { if (n2.isInt) { return(Global.ConvertFromManaged(this.numD + n2.numL)); } else { return(Global.ConvertFromManaged(this.numD + n2.numD)); } } } throw new System.NotImplementedException("文字列オブジェクトに変換して加算を実行"); }
public JavaScript.Object Subtract(JavaScript.Object num2) { JavaScript.Number n2 = num2 as JavaScript.Number; if (n2 != null) { if (this.isInt) { if (n2.isInt) { return(Global.ConvertFromManaged(this.numL - n2.numL)); } else { return(Global.ConvertFromManaged(this.numL - n2.numD)); } } else { if (n2.isInt) { return(Global.ConvertFromManaged(this.numD - n2.numL)); } else { return(Global.ConvertFromManaged(this.numD - n2.numD)); } } } throw new System.NotImplementedException("指定した物の減算には対応していません…"); }
//================================================= // 初期化 //================================================= static Global() { Global._global = new Object(new Null()); Global._global["CollectGarbage"] = new ManagedDelegate(typeof(System.GC), "Collect"); Object.Initialize(); Number.Initialize(); Array.Initialize(); }
/// <summary> /// _members の指定した名前に新しくメンバを設定します /// </summary> /// <param name="propName">メンバの名前</param> /// <param name="obj">設定するオブジェクト</param> protected void pmembers_set(string propName, JavaScript.Object obj) { if (this.pmembers == null) { this.pmembers = new Generic::Dictionary <string, JavaScript.Object>(); } this.pmembers[propName] = obj; }
public static Number Construct(JavaScript.Object o) { if (Number.instanceof(o)) { return((Number)o); } throw new System.ArgumentException("数に対応するオブジェクトを指定して下さい"); }
//=========================================================== // 静的コンストラクタ //=========================================================== //TODO: 初期化段階で確実に呼び出しがかかる様にする // (もし、new Number を呼び出す前にこちらが呼び出される事が保証されるのならば特別な処理は要らない) // → static Global から呼び出す事にした。 internal static new void Initialize() { Global._global["Number"] = new ManagedDelegate(typeof(Number), "Construct"); JavaScript.Object o = JavaScript.Object.Construct(); o[":+:"] = new ManagedJSBinaryOperator(typeof(Number).GetMethod("Add")); o[":-:"] = new ManagedJSBinaryOperator(typeof(Number).GetMethod("Subtract")); o[":*:"] = new ManagedJSBinaryOperator(typeof(Number).GetMethod("Multiply")); Global._global["Number"]["prototype"] = o; }
/// <summary> /// parent の当該プロパティから値を取得します /// </summary> /// <param name="parent">プロパティの持ち主であるオブジェクト</param> /// <returns>プロパティから取得した値を返します</returns> public virtual JavaScript.Object GetValue(JavaScript.Object parent) { JavaScript.FunctionBase f = this[":propget:"] as JavaScript.FunctionBase; if (f == null) { throw new System.NotSupportedException(GET_NOTSUPPORT); } return(f.Invoke(parent, new JavaScript.Array())); }
/// <summary> /// parent の当該プロパティに値を設定します /// </summary> /// <param name="parent">プロパティの持ち主であるオブジェクト</param> /// <param name="value">プロパティに設定する値</param> public virtual void SetValue(JavaScript.Object parent, JavaScript.Object value) { JavaScript.FunctionBase f = this[":propput:"] as JavaScript.FunctionBase; if (f == null) { throw new System.NotSupportedException(SET_NOTSUPPORT); } f.Invoke(parent, Array.Construct(value)); }
//=========================================================== // Invoke //=========================================================== public override Object Invoke(JavaScript.Object dummy, Array arguments) { System.Reflection.MethodInfo m; try{ m = this.SelectOverload(arguments); }catch (System.Exception e) { throw e; } object ret = m.Invoke(this.obj, FunctionBase.ConvertParams(m, arguments)); return(Global.ConvertFromManaged(ret)); }
/// <summary> /// 子孫を辿っていきます /// </summary> /// <param name="index"> /// 次に検索するべき names の位置。 /// このメソッドを持つインスタンスが /// names[index] と言う名のメンバを持つ事が期待されています。 /// 負の値を指定した時は 0 と見なされます。 /// </param> /// <param name="dest">names の何番目(Base0)に対応する Javascript.Object を取得するかを指定します</param> /// <param name="names"> /// オブジェクトの系譜。 /// Object.prototype.myProperty の場合は <code>new string[]{"Object","prototype","myProperty"}</code> と表現されます /// </param> /// <returns> /// dest で指定した Javascript.Object を返します。 /// 指定した物がプロパティの場合、その値を返します。 /// </returns> /// <exception cref="Null.UndefinedException"> /// 指定したメンバが未定義だった場合に発生します。 /// </exception> internal virtual JavaScript.Object TraceMember(int index, int dest, string[] names) { JavaScript.Object o = this[names[index]]; if (o == null) { throw new Null.UndefinedException(null, index, names); } if (o is JavaScript.PropertyBase) { o = ((JavaScript.PropertyBase)o).GetValue(this); } return(index < dest?o.TraceMember(index + 1, dest, names) : o); }
public JavaScript.Object InvokeBinaryOperator(JavaScript.Object left, JavaScript.Object right) { if (this.minfo.IsStatic) { return((JavaScript.Object) this.minfo.Invoke(null, new object[] { left, right })); } else { if (!Global.IsCastable(left.GetType(), this.minfo.DeclaringType)) { throw new System.ArgumentException("ManagedJSBinaryOperator: 指定した引数は this パラメータの型に合致しません。", "left"); } return((JavaScript.Object) this.minfo.Invoke(left, new object[] { right })); } }
/// <summary> /// Object 木を辿って目的のメンバの値を返します /// </summary> /// <param name="index"> /// 次に検索するべき names の位置。 /// このメソッドを持つインスタンスが /// names[index] と言う名のメンバを持つ事が期待されています。 /// </param> /// <param name="names">オブジェクトの系譜。<see cref="afh.Javascript.Object.TraceMember"/></param> /// <returns> /// 見つかったメンバを返します。 /// 指定したメンバ自体が未定義だった場合には null 値を返します。 /// </returns> /// <exception cref="Null.UndefinedException"> /// 指定したメンバに辿り着く前に未定義があった場合に発生します。 /// 指定したメンバ自体が未定義だった場合には発生しません。 /// </exception> public JavaScript.Object GetValue(int index, string[] names) { JavaScript.Object o = this.TraceMember(index, names.Length - 1, names); if (this is JavaScript.ManagedObject && o is JavaScript.ManagedMethod) { //--ManagedMethod の場合 return(new JavaScript.ManagedDelegate( ((JavaScript.ManagedObject) this).Value, (JavaScript.ManagedMethod)o )); } else { return(o); } }
/// <summary> /// Object 木を辿って目的のメンバを設定します /// </summary> /// <param name="obj">設定値を表すオブジェクトです</param> /// <param name="index"> /// 次に検索するべき names の位置。 /// このメソッドを持つインスタンスが /// names[index] と言う名のメンバを持つ事が期待されています。 /// </param> /// <param name="names">オブジェクトの系譜。<see cref="afh.Javascript.Object.TraceMember"/></param> /// <exception cref="Null.UndefinedException"> /// 指定したメンバが未定義だった場合に発生します。 /// </exception> public void SetValue(JavaScript.Object obj, int index, string[] names) { //--直接の親と key の取得 int dest = names.Length - 2; JavaScript.Object parent = index <= dest?this.TraceMember(index, dest, names) : this; string key = names[dest + 1]; //--値の設定 if (parent[key] is JavaScript.PropertyBase) { ((JavaScript.PropertyBase)parent[key]).SetValue(parent, obj); } else { parent[key] = obj; } }
/// <summary> /// Object 木を辿って目的のメンバ関数を実行します /// </summary> /// <param name="index"> /// 次に検索するべき names の位置。 /// このメソッドを持つインスタンスが /// names[index] と言う名のメンバを持つ事が期待されています。 /// </param> /// <param name="names">オブジェクトの系譜。<see cref="afh.Javascript.Object.TraceMember"/></param> /// <returns>見つかったメンバを実行した結果を返します</returns> /// <exception cref="Null.UndefinedException"> /// 指定したメンバが未定義だった場合に発生します。 /// </exception> public JavaScript.Object InvokeMember(int index, string[] names, JavaScript.Array arguments) { //--直接の親と key の取得 int dest = names.Length - 2; JavaScript.Object parent = index <= dest?this.TraceMember(index, dest, names) : this; string key = names[dest + 1]; //--Invoke try{ return(((FunctionBase)parent[key]).Invoke(parent, arguments)); }catch (System.NullReferenceException e) { //※: 一回目の NullReferenceException は時間がかかる throw new Null.UndefinedException(e); }catch (System.InvalidCastException e) { throw new System.Exception("指定したオブジェクトは関数ではありません", e); }catch (System.Exception e) { throw e; } }
//=========================================================== // Invoke //=========================================================== /// <summary> /// 指定したオブジェクトの当該メソッドを実行します /// </summary> /// <param name="obj">オブジェクトを指定します</param> /// <param name="arguments">メソッドに渡す引数を指定します</param> /// <returns>メソッドの結果を返します</returns> /// <remarks> /// 案1: Type と Methods を保持し Invoke の命令が来たら /// <list> /// <item><description>Type と obj を照合</description></item> /// <item><description>引数リストの比較</description></item> /// <item><description>実行</description></item> /// </list> /// </remarks> public override JavaScript.Object Invoke(JavaScript.Object obj, JavaScript.Array arguments) { // ManagedObject 以外の時 (Javascript.Object を直接指定した場合の時) にも対応する事にする。 // 古いコード // if(!(obj is Javascript.ManagedObject))throw new System.ArgumentException(INVOKE_NOTMANAGED,"obj"); // object o=((Javascript.ManagedObject)obj).Value; object o = (obj is JavaScript.ManagedObject)?((JavaScript.ManagedObject)obj).Value:obj; //CHECK>×: IsSubclassOf で継承した interface も確認する事が出来るかどうか if (!Global.IsCastable(o.GetType(), this.type)) { throw new System.ArgumentException(INVOKE_NOTSUPPORTED, "obj"); } System.Reflection.MethodInfo m; try{ m = this.SelectOverload(arguments); }catch (System.Exception e) { throw e; } object ret = m.Invoke(o, FunctionBase.ConvertParams(m, arguments)); return(Global.ConvertFromManaged(ret)); }
/// <summary> /// この関数を実行します。 /// </summary> /// <param name="obj">この関数を保持する Object です。関数内からは this で参照されます</param> /// <param name="arguments">この関数に渡される引数の配列を設定します</param> /// <returns>この関数を実行した結果を返します</returns> public abstract JavaScript.Object Invoke(JavaScript.Object obj, JavaScript.Array arguments);
//=========================================================== // 演算子 //=========================================================== public static bool instanceof(JavaScript.Object o) { return(o is JavaScript.Number); //Global.IsCastable(o.GetType(),typeof(Javascript.Number)); }
internal static new void Initialize() { Global._global["Array"] = new ManagedDelegate(typeof(Array), "Construct"); JavaScript.Object o = JavaScript.Object.Construct(); Global._global["Array"]["prototype"] = o; }
/// <summary> /// FunctionBase のコンストラクタ /// prototype を設定します /// </summary> protected FunctionBase() { this["prototype"] = new JavaScript.Object(); }
public Object(JavaScript.Object __proto__) : this() { this.__proto__ = __proto__; }