/// <summary> /// serialization this typedefinition to binary format and /// send to native side /// </summary> /// <param name="writer"></param> internal void WriteDefinitionToStream(BinaryWriter writer) { //---------------------- //this is our custom protocol/convention with the MiniJsBridge //we may change this in the future //eg. use json serialization/deserialization //---------------------- //1. kind/flags writer.Write((short)this.MemberId); //2. member id writer.Write((short)0); //3. typename WriteUtf16String(this.MemberName, writer); //4. num of field int j = fields.Count; writer.Write((short)j); for (int i = 0; i < j; ++i) { JsFieldDefinition fielddef = fields[i]; //field flags writer.Write((short)0); //*** field id -- unique field id within one type writer.Write((short)fielddef.MemberId); //field name WriteUtf16String(fielddef.MemberName, writer); } //------------------ j = methods.Count; writer.Write((short)j); for (int i = 0; i < j; ++i) { JsMethodDefinition methoddef = methods[i]; //method flags writer.Write((short)0); //id writer.Write((short)methoddef.MemberId); //method name WriteUtf16String(methoddef.MemberName, writer); } //property j = props.Count; writer.Write((short)j); for (int i = 0; i < j; ++i) { JsPropertyDefinition property = this.props[i]; //flags writer.Write((short)0); //id writer.Write((short)property.MemberId); //name WriteUtf16String(property.MemberName, writer); } }
public void AddMore(JsMethodDefinition anotherMethod) { if (_members == null) { _members = new List <JsMethodDefinition>(); _members.Add(_onlyOneMember); _onlyOneMember = null; } _members.Add(anotherMethod); }
public void AddMoreMember(JsMethodDefinition anotherMethod) { if (members == null) { members = new List <JsMethodDefinition>(); members.Add(onlyOneMember); onlyOneMember = null; } members.Add(anotherMethod); }
void EngineListener_MethodCall(int mIndex, int methodKind, IntPtr metArgs) { switch (methodKind) { case 1: { //property get if (mIndex == 0) { return; } //------------------------------------------ JsMethodDefinition getterMethod = registerProperties[mIndex].GetterMethod; if (getterMethod != null) { getterMethod.InvokeMethod(new ManagedMethodArgs(this, metArgs)); } } break; case 2: { //property set if (mIndex == 0) { return; } //------------------------------------------ JsMethodDefinition setterMethod = registerProperties[mIndex].SetterMethod; if (setterMethod != null) { setterMethod.InvokeMethod(new ManagedMethodArgs(this, metArgs)); } } break; default: { if (mIndex == 0) { return; } JsMethodDefinition foundMet = registerMethods[mIndex]; if (foundMet != null) { foundMet.InvokeMethod(new ManagedMethodArgs(this, metArgs)); } } break; } }
internal void CollectionTypeMembers(JsTypeDefinition jsTypeDefinition) { List <JsMethodDefinition> methods = jsTypeDefinition.GetMethods(); int j = methods.Count; for (int i = 0; i < j; ++i) { JsMethodDefinition met = methods[i]; met.SetMemberId(registerMethods.Count); registerMethods.Add(met); } List <JsPropertyDefinition> properties = jsTypeDefinition.GetProperties(); j = properties.Count; for (int i = 0; i < j; ++i) { var p = properties[i]; p.SetMemberId(registerProperties.Count); registerProperties.Add(p); } }
protected override JsTypeDefinition OnBuildRequest(Type t) { JsTypeDefinition typedefinition = new JsTypeDefinition(t.Name); //------- //only instance /public method /prop*** Dictionary <string, JsMethodGroup> methodGroups = new Dictionary <string, JsMethodGroup>(); foreach (MethodInfo met in GetMehodIter(t, BindingFlags.Instance | BindingFlags.Public)) { var jsMethodDef = new JsMethodDefinition(met.Name, met); JsMethodGroup existingGroup; if (!methodGroups.TryGetValue(met.Name, out existingGroup)) { //create new one existingGroup = new JsMethodGroup(met.Name, jsMethodDef); methodGroups.Add(met.Name, existingGroup); } else { existingGroup.AddMoreMember(jsMethodDef); } } //----------------- foreach (JsMethodGroup metGroup in methodGroups.Values) { JsMethodDefinition selectedMethod = metGroup.GetJsMethod(); if (selectedMethod != null) { typedefinition.AddMember(metGroup.GetJsMethod()); } } //----------------- foreach (var property in GetPropertyIter(t, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public)) { typedefinition.AddMember(new JsPropertyDefinition(property.Name, property)); } return(typedefinition); }
public void AddMember(JsMethodDefinition methodDef) { methodDef.SetOwner(this); methods.Add(methodDef); }
public JsMethodDefinition SelectBestMethod(Type[] inputArgTypes) { if (_onlyOneMember != null) { return(_onlyOneMember); } //------------------------------ //TODO: check performance here //TODO: review How Roslyn select best method *** //----------------------------- //best fit? int memberCount = _members.Count; int[] bestScores = new int[memberCount]; int maxBestScore = -1; int candidateMaxIndex = 0; bool hasOnly1Candidate = true; for (int m = memberCount - 1; m >= 0; --m) { JsMethodDefinition met = _members[m]; int convScore = 0; for (int argNo = _argCount - 1; argNo >= 0; --argNo) { //pick one arg Type inputArgType = inputArgTypes[argNo]; Type parType = met.Parameters[argNo].ParameterType; if (inputArgType == null) { //if input value is null //special mx convScore += CalculateTypeDepth(parType, typeof(object)); } else if (parType == inputArgType) { //exact type convScore += 255; } else if (IsAssignable(parType, inputArgType)) { //assignable //check inheritance depth? //find conversion energy (depth) convScore += CalculateTypeDepth(inputArgType, parType); } else { //can't assign //can't use this method convScore = -1; argNo = -1; //not check more => go next method } } bestScores[m] = convScore; //store value , for later use ,TODO: review here if (convScore > maxBestScore) { maxBestScore = convScore; candidateMaxIndex = m; hasOnly1Candidate = true; } else if (convScore == maxBestScore) { hasOnly1Candidate = false; } } //----------------------------- //find max best score //TODO: check if we have more than 1 best value //----------------------------- if (maxBestScore < 0) { return(null); } if (hasOnly1Candidate) { return(_members[candidateMaxIndex]); } //TODO: review ... //find member with max score JsMethodDefinition[] candidateMethods = new JsMethodDefinition[memberCount]; int n = 0; for (int i = memberCount - 1; i >= 0; --i) { if (bestScores[i] == maxBestScore) { candidateMethods[n] = _members[i]; n++; } } if (n > 1) { //more than 1 best method } else { //only 1 return(candidateMethods[0]); } return(null); }
public SameArgMethodList(int argCount, JsMethodDefinition onlyOneMember) { _argCount = argCount; _onlyOneMember = onlyOneMember; }
public virtual JsMethodDefinition GetJsMethod() { if (onlyOneMember != null) { return(onlyOneMember); } else { //if we have > 1 member //create a 'wrapper' method for all method in this group //------ //analyze method based on arg count and the arg type //quite complex //------ //this is a default .... resolver //you can provide a special method overload resolution //for each method group if (sameArgNumMethodLists == null) { sameArgNumMethodLists = new Dictionary <int, SameArgMethodList>(); int j = members.Count; for (int i = 0; i < j; ++i) { JsMethodDefinition met = members[i]; ParameterInfo[] pars = met.Parameters; if (pars != null) { SameArgMethodList existingMethods; int count = pars.Length; if (!sameArgNumMethodLists.TryGetValue(count, out existingMethods)) { existingMethods = new SameArgMethodList(count, met); sameArgNumMethodLists.Add(count, existingMethods); } else { existingMethods.AddMore(met); } } else { //delegate base? // //TODO : review this again return(null); } } } return(new JsMethodDefinition(this.Name, args => { //how to select the best over method based on input args: //this resolve at runtime=> may be slow //TODO: review here again //num of arg not match //TODO & //LIMITATION: this version dose NOT support //1. default parameter //2. param args //invoke method var thisArg = args.GetThisArg(); //actual input arg count int actualArgCount = args.ArgCount; SameArgMethodList foundMets; if (!sameArgNumMethodLists.TryGetValue(actualArgCount, out foundMets)) { //so if num of arg not match the return args.SetResultUndefined(); //? return; } //----------- //select best method by checking each vars //TODO: how to find hints ? //best match args object[] inputArgs = new object[actualArgCount]; Type[] inputArgsTypes = new Type[actualArgCount]; for (int i = 0; i < actualArgCount; ++i) { object arg_v = args.GetArgAsObject(i); inputArgs[i] = arg_v; if (arg_v == null) { //review here again inputArgsTypes[i] = null;//null value } else { inputArgsTypes[i] = arg_v.GetType(); } } JsMethodDefinition selectedMet = foundMets.SelectBestMethod(inputArgsTypes); if (selectedMet == null) { //if not found //TODO: review here , throw exception? args.SetResultUndefined(); //? return; } selectedMet.InvokeMethod(args); })); } }
public JsMethodGroup(string name, JsMethodDefinition firstMember) { this.Name = name; this.onlyOneMember = firstMember; }