The Labs \ Source Viewer \ SSCLI \ Microsoft.JScript \ Binding

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace Microsoft.JScript
  16. {
  17.    
  18.     using System;
  19.     using System.Collections;
  20.     using System.Globalization;
  21.     using System.Reflection;
  22.     using System.Reflection.Emit;
  23.    
  24.     public abstract class Binding : AST
  25.     {
  26.         private IReflect[] argIRs;
  27.         protected MemberInfo defaultMember;
  28.         private IReflect defaultMemberReturnIR;
  29.         private bool isArrayElementAccess;
  30.         private bool isArrayConstructor;
  31.         protected bool isAssignmentToDefaultIndexedProperty;
  32.         protected bool isFullyResolved;
  33.         protected bool isNonVirtual;
  34.         internal MemberInfo[] members;
  35.         internal MemberInfo member;
  36.         protected string name;
  37.         private bool giveErrors;
  38.        
  39.         static internal ConstantWrapper ReflectionMissingCW = new ConstantWrapper(System.Reflection.Missing.Value, null);
  40.         private static ConstantWrapper JScriptMissingCW = new ConstantWrapper(Missing.Value, null);
  41.        
  42.         internal Binding(Context context, string name) : base(context)
  43.         {
  44.             this.argIRs = null;
  45.             this.defaultMember = null;
  46.             this.defaultMemberReturnIR = null;
  47.             this.isArrayElementAccess = false;
  48.             this.isArrayConstructor = false;
  49.             this.isAssignmentToDefaultIndexedProperty = false;
  50.             this.isFullyResolved = true;
  51.             this.isNonVirtual = false;
  52.             this.members = null;
  53.             this.member = null;
  54.             this.name = name;
  55.             this.giveErrors = true;
  56.         }
  57.        
  58.         private bool Accessible(bool checkSetter)
  59.         {
  60.             if (this.member == null)
  61.                 return false;
  62.             switch (this.member.MemberType) {
  63.                 case MemberTypes.Constructor:
  64.                     return AccessibleConstructor();
  65.                 case MemberTypes.Event:
  66.                     return false;
  67.                 case MemberTypes.Field:
  68.                     return AccessibleField(checkSetter);
  69.                 case MemberTypes.Method:
  70.                     return AccessibleMethod();
  71.                 case MemberTypes.NestedType:
  72.                     if (!((Type)this.member).IsNestedPublic) {
  73.                         if (this.giveErrors)
  74.                             this.context.HandleError(JSError.NotAccessible, this.isFullyResolved);
  75.                         return false;
  76.                     }
  77.                     if (checkSetter)
  78.                         return false;
  79.                     return true;
  80.                 case MemberTypes.TypeInfo:
  81.                     if (!((Type)this.member).IsPublic) {
  82.                         if (this.giveErrors)
  83.                             this.context.HandleError(JSError.NotAccessible, this.isFullyResolved);
  84.                         return false;
  85.                     }
  86.                     if (checkSetter)
  87.                         return false;
  88.                     return true;
  89.                 case MemberTypes.Property:
  90.                     return AccessibleProperty(checkSetter);
  91.             }
  92.             return false;
  93.         }
  94.        
  95.         private bool AccessibleConstructor()
  96.         {
  97.             ConstructorInfo cons = (ConstructorInfo)this.member;
  98.             if ((cons is JSConstructor && ((JSConstructor)member).GetClassScope().owner.isAbstract) || (!(cons is JSConstructor) && cons.DeclaringType.IsAbstract)) {
  99.                 this.context.HandleError(JSError.CannotInstantiateAbstractClass);
  100.                 return false;
  101.             }
  102.             if (cons.IsPublic)
  103.                 return true;
  104.             if (cons is JSConstructor) {
  105.                 if (((JSConstructor)cons).IsAccessibleFrom(Globals.ScopeStack.Peek()))
  106.                     return true;
  107.             }
  108.             if (this.giveErrors)
  109.                 this.context.HandleError(JSError.NotAccessible, this.isFullyResolved);
  110.             return false;
  111.         }
  112.        
  113.         private bool AccessibleField(bool checkWritable)
  114.         {
  115.             FieldInfo field = (FieldInfo)this.member;
  116.             if (checkWritable && (field.IsInitOnly || field.IsLiteral))
  117.                 return false;
  118.             if (!field.IsPublic) {
  119.                 JSWrappedField wfield = field as JSWrappedField;
  120.                 if (wfield != null)
  121.                     this.member = field = wfield.wrappedField;
  122.                 JSClosureField cfield = field as JSClosureField;
  123.                 JSMemberField mfield = (cfield != null ? cfield.field : field) as JSMemberField;
  124.                 if (mfield == null) {
  125.                     if ((!field.IsFamily && !field.IsFamilyOrAssembly) || !Binding.InsideClassThatExtends(Globals.ScopeStack.Peek(), field.ReflectedType)) {
  126.                         if (this.giveErrors)
  127.                             this.context.HandleError(JSError.NotAccessible, this.isFullyResolved);
  128.                         return false;
  129.                     }
  130.                 }
  131.                 else if (!mfield.IsAccessibleFrom(Globals.ScopeStack.Peek())) {
  132.                     if (this.giveErrors)
  133.                         this.context.HandleError(JSError.NotAccessible, this.isFullyResolved);
  134.                     return false;
  135.                 }
  136.             }
  137.             if (field.IsLiteral && field is JSVariableField) {
  138.                 ClassScope csc = ((JSVariableField)field).value as ClassScope;
  139.                 if (csc != null && !csc.owner.IsStatic) {
  140.                     Lookup lookup = this as Lookup;
  141.                     if (lookup == null || !lookup.InStaticCode() || lookup.InFunctionNestedInsideInstanceMethod())
  142.                         return true;
  143.                     if (this.giveErrors)
  144.                         this.context.HandleError(JSError.InstanceNotAccessibleFromStatic, this.isFullyResolved);
  145.                     return true;
  146.                 }
  147.             }
  148.             if (field.IsStatic || field.IsLiteral || this.defaultMember != null || !(this is Lookup) || !((Lookup)this).InStaticCode())
  149.                 return true;
  150.             if (field is JSWrappedField && field.DeclaringType == Typeob.LenientGlobalObject)
  151.                 return true;
  152.             if (this.giveErrors) {
  153.                 if (!field.IsStatic && this is Lookup && ((Lookup)this).InStaticCode())
  154.                     this.context.HandleError(JSError.InstanceNotAccessibleFromStatic, this.isFullyResolved);
  155.                 else
  156.                     this.context.HandleError(JSError.NotAccessible, this.isFullyResolved);
  157.             }
  158.             return false;
  159.         }
  160.        
  161.         private bool AccessibleMethod()
  162.         {
  163.             MethodInfo meth = (MethodInfo)this.member;
  164.             return this.AccessibleMethod(meth);
  165.         }
  166.        
  167.         private bool AccessibleMethod(MethodInfo meth)
  168.         {
  169.             if (meth == null)
  170.                 return false;
  171.             if (this.isNonVirtual && meth.IsAbstract) {
  172.                 this.context.HandleError(JSError.InvalidCall);
  173.                 return false;
  174.             }
  175.             if (!meth.IsPublic) {
  176.                 JSWrappedMethod wmeth = meth as JSWrappedMethod;
  177.                 if (wmeth != null)
  178.                     meth = wmeth.method;
  179.                 JSClosureMethod cmeth = meth as JSClosureMethod;
  180.                 JSFieldMethod fmeth = (cmeth != null ? cmeth.method : meth) as JSFieldMethod;
  181.                 if (fmeth == null) {
  182.                     if ((meth.IsFamily || meth.IsFamilyOrAssembly) && Binding.InsideClassThatExtends(Globals.ScopeStack.Peek(), meth.ReflectedType))
  183.                         return true;
  184.                     if (this.giveErrors)
  185.                         this.context.HandleError(JSError.NotAccessible, this.isFullyResolved);
  186.                     return false;
  187.                 }
  188.                 else if (!fmeth.IsAccessibleFrom(Globals.ScopeStack.Peek())) {
  189.                     if (this.giveErrors)
  190.                         this.context.HandleError(JSError.NotAccessible, this.isFullyResolved);
  191.                     return false;
  192.                 }
  193.             }
  194.             if (meth.IsStatic || this.defaultMember != null || !(this is Lookup) || !((Lookup)this).InStaticCode())
  195.                 return true;
  196.             if (meth is JSWrappedMethod && ((Lookup)this).CanPlaceAppropriateObjectOnStack(((JSWrappedMethod)meth).obj))
  197.                 return true;
  198.             if (this.giveErrors) {
  199.                 if (!meth.IsStatic && this is Lookup && ((Lookup)this).InStaticCode())
  200.                     this.context.HandleError(JSError.InstanceNotAccessibleFromStatic, this.isFullyResolved);
  201.                 else
  202.                     this.context.HandleError(JSError.NotAccessible, this.isFullyResolved);
  203.             }
  204.             return false;
  205.         }
  206.        
  207.         private bool AccessibleProperty(bool checkSetter)
  208.         {
  209.             PropertyInfo prop = (PropertyInfo)this.member;
  210.             if (this.AccessibleMethod(checkSetter ? JSProperty.GetSetMethod(prop, true) : JSProperty.GetGetMethod(prop, true)))
  211.                 return true;
  212.             if (this.giveErrors && !checkSetter)
  213.                 this.context.HandleError(JSError.WriteOnlyProperty);
  214.             return false;
  215.         }
  216.        
  217.         static internal bool AssignmentCompatible(IReflect lhir, AST rhexpr, IReflect rhir, bool reportError)
  218.         {
  219.             if (rhexpr is ConstantWrapper) {
  220.                 object rhval = rhexpr.Evaluate();
  221.                 if (rhval is ClassScope) {
  222.                     if (lhir == Typeob.Type || lhir == Typeob.Object || lhir == Typeob.String)
  223.                         return true;
  224.                     else {
  225.                         if (reportError)
  226.                             rhexpr.context.HandleError(JSError.TypeMismatch);
  227.                         return false;
  228.                     }
  229.                 }
  230.                 ClassScope csc = lhir as ClassScope;
  231.                 if (csc != null) {
  232.                     EnumDeclaration ed = csc.owner as EnumDeclaration;
  233.                     if (ed != null) {
  234.                         ConstantWrapper cw = rhexpr as ConstantWrapper;
  235.                         if (cw != null && cw.value is string) {
  236.                             FieldInfo field = csc.GetField((string)cw.value, BindingFlags.Public | BindingFlags.Static);
  237.                             if (field == null)
  238.                                 return false;
  239.                             ed.PartiallyEvaluate();
  240.                             cw.value = new DeclaredEnumValue(((JSMemberField)field).value, field.Name, csc);
  241.                         }
  242.                         if (rhir == Typeob.String)
  243.                             return true;
  244.                         lhir = ed.baseType.ToType();
  245.                     }
  246.                 }
  247.                 else if (lhir is Type) {
  248.                     Type type = lhir as Type;
  249.                     if (type.IsEnum) {
  250.                         ConstantWrapper cw = rhexpr as ConstantWrapper;
  251.                         if (cw != null && cw.value is string) {
  252.                             FieldInfo field = type.GetField((string)cw.value, BindingFlags.Public | BindingFlags.Static);
  253.                             if (field == null)
  254.                                 return false;
  255.                             cw.value = MetadataEnumValue.GetEnumValue(field.FieldType, field.GetRawConstantValue());
  256.                         }
  257.                         if (rhir == Typeob.String)
  258.                             return true;
  259.                         lhir = Enum.GetUnderlyingType(type);
  260.                     }
  261.                 }
  262.                
  263.                 if (lhir is Type) {
  264.                     try {
  265.                         Convert.CoerceT(rhval, (Type)lhir);
  266.                         return true;
  267.                     }
  268.                     catch {
  269.                         if (lhir == Typeob.Single && rhval is double) {
  270.                             if (((ConstantWrapper)rhexpr).isNumericLiteral)
  271.                                 return true;
  272.                             double d = (double)rhval;
  273.                             float s = (float)d;
  274.                             if (d.ToString(CultureInfo.InvariantCulture).Equals(s.ToString(CultureInfo.InvariantCulture))) {
  275.                                 ((ConstantWrapper)rhexpr).value = s;
  276.                                 return true;
  277.                             }
  278.                         }
  279.                         if (lhir == Typeob.Decimal) {
  280.                             ConstantWrapper cw = rhexpr as ConstantWrapper;
  281.                             if (cw != null && cw.isNumericLiteral) {
  282.                                 try {
  283.                                     Convert.CoerceT(cw.context.GetCode(), Typeob.Decimal);
  284.                                     return true;
  285.                                 }
  286.                                 catch {
  287.                                 }
  288.                             }
  289.                         }
  290.                         if (reportError)
  291.                             rhexpr.context.HandleError(JSError.TypeMismatch);
  292.                     }
  293.                     return false;
  294.                 }
  295.             }
  296.             else if (rhexpr is ArrayLiteral)
  297.                 return ((ArrayLiteral)rhexpr).AssignmentCompatible(lhir, reportError);
  298.             if (rhir == Typeob.Object)
  299.                 return true;
  300.             //Too little is known about the expression to complain at compile time
  301.             if (rhir == Typeob.Double && Convert.IsPrimitiveNumericType(lhir))
  302.                 return true;
  303.             //Arithmetic expressions infer to Double, but might have the right result.
  304.             if (lhir is Type && Typeob.Delegate.IsAssignableFrom((Type)lhir) && rhir == Typeob.ScriptFunction && rhexpr is Binding && ((Binding)rhexpr).IsCompatibleWithDelegate((Type)lhir))
  305.                 return true;
  306.             if (Convert.IsPromotableTo(rhir, lhir))
  307.                 return true;
  308.             //rhexpr delivers a value that can be converted to something expected by the assignment target
  309.             if (Convert.IsJScriptArray(rhir) && Binding.ArrayAssignmentCompatible(rhexpr, lhir))
  310.                 return true;
  311.             if (lhir == Typeob.String)
  312.                 return true;
  313.             // Everything is assignment-compatible to string.
  314.             if (rhir == Typeob.String && (lhir == Typeob.Boolean || Convert.IsPrimitiveNumericType(lhir))) {
  315.                 if (reportError)
  316.                     rhexpr.context.HandleError(JSError.PossibleBadConversionFromString);
  317.                 return true;
  318.             }
  319.             if ((lhir == Typeob.Char && rhir == Typeob.String) || Convert.IsPromotableTo(lhir, rhir) || (Convert.IsPrimitiveNumericType(lhir) && Convert.IsPrimitiveNumericType(rhir))) {
  320.                 if (reportError)
  321.                     rhexpr.context.HandleError(JSError.PossibleBadConversion);
  322.                 return true;
  323.             }
  324.            
  325.             if (reportError)
  326.                 rhexpr.context.HandleError(JSError.TypeMismatch);
  327.             return false;
  328.         }
  329.        
  330.         private static bool ArrayAssignmentCompatible(AST ast, IReflect lhir)
  331.         {
  332.             // If we've made it here then we already know that lhir is not Object or String
  333.             // and that a JScript array is not promotable to lhir. There are cases where
  334.             // a JScript array is not promotable but is assignable with a warning. A
  335.             // JScript array is assignable to a System.Array or to a rank-one typed array.
  336.             if (!Convert.IsArray(lhir))
  337.                 return false;
  338.             else if (lhir == Typeob.Array) {
  339.                 ast.context.HandleError(JSError.ArrayMayBeCopied);
  340.                 return true;
  341.             }
  342.             else if (Convert.GetArrayRank(lhir) == 1) {
  343.                 ast.context.HandleError(JSError.ArrayMayBeCopied);
  344.                 return true;
  345.             }
  346.             else
  347.                 return false;
  348.         }
  349.        
  350.         internal void CheckIfDeletable()
  351.         {
  352.             if (this.member != null || this.defaultMember != null)
  353.                 this.context.HandleError(JSError.NotDeletable);
  354.             this.member = null;
  355.             this.defaultMember = null;
  356.         }
  357.        
  358.         internal void CheckIfUseless()
  359.         {
  360.             // This is called for expression statements. There are no cases where an
  361.             // expression which just retrieves a property should not give a warning.
  362.             // We don't bother giving a warning if members is empty because more than
  363.             // likely an warning or error was already issued.
  364.             if (this.members == null || this.members.Length == 0)
  365.                 return;
  366.             this.context.HandleError(JSError.UselessExpression);
  367.         }
  368.        
  369.         static internal bool CheckParameters(ParameterInfo[] pars, IReflect[] argIRs, ASTList argAST, Context ctx)
  370.         {
  371.             return Binding.CheckParameters(pars, argIRs, argAST, ctx, 0, false, true);
  372.         }
  373.        
  374.         static internal bool CheckParameters(ParameterInfo[] pars, IReflect[] argIRs, ASTList argAST, Context ctx, int offset, bool defaultIsUndefined, bool reportError)
  375.         {
  376.             int n = argIRs.Length;
  377.             int m = pars.Length;
  378.             bool tooManyParams = false;
  379.             if (n > m - offset) {
  380.                 n = m - offset;
  381.                 tooManyParams = true;
  382.             }
  383.             for (int i = 0; i < n; i++) {
  384.                 IReflect formalIR = (pars[i + offset] is ParameterDeclaration) ? ((ParameterDeclaration)pars[i + offset]).ParameterIReflect : pars[i + offset].ParameterType;
  385.                 IReflect actualIR = argIRs[i];
  386.                 if (i == n - 1 && ((formalIR is Type && Typeob.Array.IsAssignableFrom((Type)formalIR)) || formalIR is TypedArray) && CustomAttribute.IsDefined(pars[i + offset], typeof(ParamArrayAttribute), false)) {
  387.                     tooManyParams = false;
  388.                     int k = argIRs.Length;
  389.                     if (i == k - 1) {
  390.                         if (Binding.AssignmentCompatible(formalIR, argAST[i], argIRs[i], false))
  391.                             return true;
  392.                     }
  393.                     IReflect elemIR = formalIR is Type ? ((Type)formalIR).GetElementType() : ((TypedArray)formalIR).elementType;
  394.                     for (int j = i; j < k; j++)
  395.                         if (!Binding.AssignmentCompatible(elemIR, argAST[j], argIRs[j], reportError))
  396.                             return false;
  397.                     return true;
  398.                 }
  399.                 if (!Binding.AssignmentCompatible(formalIR, argAST[i], actualIR, reportError))
  400.                     return false;
  401.             }
  402.             if (tooManyParams && reportError)
  403.                 ctx.HandleError(JSError.TooManyParameters);
  404.             if (offset == 0 && n < m && !defaultIsUndefined)
  405. //Fewer actual parameters than formal parameters
  406.                 for (int j = n; j < m; j++)
  407.                     if (TypeReferences.GetDefaultParameterValue(pars[j]) == System.Convert.DBNull) {
  408.                         //No default value specified
  409.                         //Ensure that custom attribute has been resolved before checking
  410.                         ParameterDeclaration pardecl = pars[j] as ParameterDeclaration;
  411.                         if (pardecl != null)
  412.                             pardecl.PartiallyEvaluate();
  413.                         if (j < m - 1 || !CustomAttribute.IsDefined(pars[j], typeof(ParamArrayAttribute), false)) {
  414.                             if (reportError)
  415.                                 ctx.HandleError(JSError.TooFewParameters);
  416.                             IReflect formalIR = (pars[j + offset] is ParameterDeclaration) ? ((ParameterDeclaration)pars[j + offset]).ParameterIReflect : pars[j + offset].ParameterType;
  417.                             Type formalType = formalIR as Type;
  418.                             if (formalType != null && formalType.IsValueType && !formalType.IsPrimitive && !formalType.IsEnum)
  419.                                 return false;
  420.                             //Can't generate valid code for this since there is no general mapping from undefined to value types
  421.                         }
  422.                     }
  423.             return true;
  424.         }
  425.        
  426.         internal override bool Delete()
  427.         {
  428.             return this.EvaluateAsLateBinding().Delete();
  429.         }
  430.        
  431.         internal override object Evaluate()
  432.         {
  433.             object ob = this.GetObject();
  434.             MemberInfo member = this.member;
  435.             if (member != null)
  436.                 switch (member.MemberType) {
  437.                     case MemberTypes.Field:
  438.                         return ((FieldInfo)member).GetValue(ob);
  439.                     case MemberTypes.Property:
  440.                         MemberInfo[] members = new MemberInfo[] {JSProperty.GetGetMethod((PropertyInfo)member, false)};
  441.                         return LateBinding.CallOneOfTheMembers(members, new object[0], false, ob, null, null, null, this.Engine);
  442.                     case MemberTypes.Event:
  443.                         return null;
  444.                     case MemberTypes.NestedType:
  445.                         return member;
  446.                 }
  447.             if (this.members != null && this.members.Length > 0) {
  448.                 //Special case check for methods on builtin objects
  449.                 if (this.members.Length == 1 && this.members[0].MemberType == MemberTypes.Method) {
  450.                     MethodInfo meth = (MethodInfo)members[0];
  451.                     Type dt = meth is JSMethod ? null : meth.DeclaringType;
  452.                    
  453.                     if (dt == Typeob.GlobalObject || (dt != null && dt != Typeob.StringObject && dt != Typeob.NumberObject && dt != Typeob.BooleanObject && dt.IsSubclassOf(Typeob.JSObject))) {
  454.                         //This only happens in fast mode. We could add InitOnly fields to the fast predefined objects and initialize them
  455.                         //with instances of BuiltinFunction objects, in which case we would never get here, but we would like to avoid
  456.                         //the start up cost of allocating these objects, particularly if they end up never being used (the expected common case).
  457.                         return Globals.BuiltinFunctionFor(ob, TypeReferences.ToExecutionContext(meth));
  458.                         //Note that meth is not wrapped because it is static
  459.                     }
  460.                 }
  461.                
  462.                 return new FunctionWrapper(this.name, ob, this.members);
  463.             }
  464.             return this.EvaluateAsLateBinding().GetValue();
  465.         }
  466.        
  467.         //Returns a list of member infos that are sorted by declaring type. Superclass members always follow derived class members.
  468.         private MemberInfoList GetAllKnownInstanceBindingsForThisName()
  469.         {
  470.             IReflect[] classes = this.GetAllEligibleClasses();
  471.             MemberInfoList result = new MemberInfoList();
  472.             foreach (IReflect c in classes) {
  473.                 if (c is ClassScope) {
  474.                     if (((ClassScope)c).ParentIsInSamePackage())
  475.                         result.AddRange(c.GetMember(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
  476.                     else
  477.                         result.AddRange(c.GetMember(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance));
  478.                 }
  479.                 else
  480.                     result.AddRange(c.GetMember(name, BindingFlags.Public | BindingFlags.Instance));
  481.             }
  482.             return result;
  483.         }
  484.        
  485.         //Returns a list of the classes visible from the current scope.
  486.         //Currently, classes are returned only if they are ancestors of the current class, or reside in the same package.
  487.         private IReflect[] GetAllEligibleClasses()
  488.         {
  489.             ArrayList classes = new ArrayList(16);
  490.             ClassScope currentClass = null;
  491.             PackageScope currentPackage = null;
  492.             ScriptObject scope = Globals.ScopeStack.Peek();
  493.             while (scope is WithObject || scope is BlockScope)
  494.                 scope = scope.GetParent();
  495.             if (scope is FunctionScope)
  496.                 scope = ((FunctionScope)scope).owner.enclosing_scope;
  497.             if (scope is ClassScope) {
  498.                 currentClass = (ClassScope)scope;
  499.                 currentPackage = currentClass.package;
  500.             }
  501.             if (currentClass != null)
  502.                 currentClass.AddClassesFromInheritanceChain(this.name, classes);
  503.             if (currentPackage != null)
  504.                 currentPackage.AddClassesExcluding(currentClass, this.name, classes);
  505.             else
  506.                 ((IActivationObject)scope).GetGlobalScope().AddClassesExcluding(currentClass, this.name, classes);
  507.             IReflect[] result = new IReflect[classes.Count];
  508.             classes.CopyTo(result);
  509.             return result;
  510.         }
  511.        
  512.         protected abstract object GetObject();
  513.        
  514.         protected abstract void HandleNoSuchMemberError();
  515.        
  516.         internal override IReflect InferType(JSField inference_target)
  517.         {
  518.             Debug.Assert(this.members != null);
  519.             //Have to call a PartiallyEvaluate routine before calling InferType
  520.             if (this.isArrayElementAccess) {
  521.                 IReflect ir = this.defaultMemberReturnIR;
  522.                 return ir is TypedArray ? ((TypedArray)ir).elementType : ((Type)ir).GetElementType();
  523.             }
  524.             if (this.isAssignmentToDefaultIndexedProperty) {
  525.                 if (this.member is PropertyInfo)
  526.                     //Could be null if no binding was found
  527.                     return ((PropertyInfo)this.member).PropertyType;
  528.                 return Typeob.Object;
  529.             }
  530.             MemberInfo member = this.member;
  531.             if (member is FieldInfo) {
  532.                 JSWrappedField wf = member as JSWrappedField;
  533.                 if (wf != null)
  534.                     member = wf.wrappedField;
  535.                 if (member is JSVariableField)
  536.                     return ((JSVariableField)member).GetInferredType(inference_target);
  537.                 else
  538.                     return ((FieldInfo)member).FieldType;
  539.             }
  540.             if (member is PropertyInfo) {
  541.                 JSWrappedProperty wp = member as JSWrappedProperty;
  542.                 if (wp != null)
  543.                     member = wp.property;
  544.                 if (member is JSProperty)
  545.                     return ((JSProperty)member).PropertyIR();
  546.                 else {
  547.                     PropertyInfo prop = (PropertyInfo)member;
  548.                     if (prop.DeclaringType == Typeob.GlobalObject)
  549.                         return (IReflect)prop.GetValue(this.Globals.globalObject, null);
  550.                     else
  551.                         return prop.PropertyType;
  552.                 }
  553.             }
  554.            
  555.             if (member is Type)
  556.                 return Typeob.Type;
  557.             if (member is EventInfo)
  558.                 return Typeob.EventInfo;
  559.             if (this.members.Length > 0 && this.Engine.doFast)
  560.                 return Typeob.ScriptFunction;
  561.             return Typeob.Object;
  562.         }
  563.        
  564.         internal virtual IReflect InferTypeOfCall(JSField inference_target, bool isConstructor)
  565.         {
  566.             Debug.Assert(this.members != null);
  567.             //Have to call a PartiallyEvaluate routine before calling InferTypeOfCall
  568.             if (!this.isFullyResolved)
  569.                 return Typeob.Object;
  570.             if (this.isArrayConstructor)
  571.                 return this.defaultMemberReturnIR;
  572.             if (this.isArrayElementAccess) {
  573.                 IReflect ir = this.defaultMemberReturnIR;
  574.                 return ir is TypedArray ? ((TypedArray)ir).elementType : ((Type)ir).GetElementType();
  575.             }
  576.             MemberInfo member = this.member;
  577.             if (member is JSFieldMethod)
  578.                 return isConstructor ? Typeob.Object : ((JSFieldMethod)member).ReturnIR();
  579.             if (member is MethodInfo)
  580.                 return ((MethodInfo)member).ReturnType;
  581.             if (member is JSConstructor)
  582.                 return ((JSConstructor)member).GetClassScope();
  583.             if (member is ConstructorInfo)
  584.                 return ((ConstructorInfo)member).DeclaringType;
  585.             if (member is Type)
  586.                 return (Type)member;
  587.             if (member is FieldInfo && ((FieldInfo)member).IsLiteral) {
  588.                 object val = member is JSVariableField ? ((JSVariableField)member).value : TypeReferences.GetConstantValue((FieldInfo)member);
  589.                 if (val is ClassScope || val is TypedArray)
  590.                     return (IReflect)val;
  591.             }
  592.             return Typeob.Object;
  593.         }
  594.        
  595.         private static bool InsideClassThatExtends(ScriptObject scope, Type type)
  596.         {
  597.             while (scope is WithObject || scope is BlockScope)
  598.                 scope = scope.GetParent();
  599.             if (scope is ClassScope)
  600.                 return type.IsAssignableFrom(((ClassScope)scope).GetBakedSuperType());
  601.             if (scope is FunctionScope)
  602.                 return Binding.InsideClassThatExtends(((FunctionScope)scope).owner.enclosing_scope, type);
  603.             //Eval does not see non public members, so don't worry about StackFrame
  604.             return false;
  605.         }
  606.        
  607.         internal void InvalidateBinding()
  608.         {
  609.             this.isAssignmentToDefaultIndexedProperty = false;
  610.             this.isArrayConstructor = false;
  611.             this.isArrayElementAccess = false;
  612.             this.defaultMember = null;
  613.             this.member = null;
  614.             this.members = new MemberInfo[0];
  615.         }
  616.        
  617.         internal bool IsCompatibleWithDelegate(Type delegateType)
  618.         {
  619.             Debug.Assert(this.members != null && this.members.Length > 0);
  620.             MethodInfo invoke = delegateType.GetMethod("Invoke");
  621.             ParameterInfo[] dparams = invoke.GetParameters();
  622.             Type drtype = invoke.ReturnType;
  623.             foreach (MemberInfo mem in this.members) {
  624.                 if (mem is MethodInfo) {
  625.                     MethodInfo meth = (MethodInfo)mem;
  626.                     Type returnType = null;
  627.                     if (meth is JSFieldMethod) {
  628.                         IReflect returnIR = ((JSFieldMethod)meth).ReturnIR();
  629.                         if (returnIR is ClassScope)
  630.                             returnType = ((ClassScope)returnIR).GetBakedSuperType();
  631.                         else if (returnIR is Type)
  632.                             returnType = (Type)returnIR;
  633.                         else
  634.                             //JScript cannot define delegates, so baked is OK.
  635.                             returnType = Convert.ToType(returnIR);
  636.                         if (((JSFieldMethod)meth).func.isExpandoMethod)
  637.                             return false;
  638.                     }
  639.                     else
  640.                         returnType = meth.ReturnType;
  641.                     if (returnType == drtype && Class.ParametersMatch(dparams, meth.GetParameters())) {
  642.                         this.member = meth;
  643.                         this.isFullyResolved = true;
  644.                         return true;
  645.                     }
  646.                 }
  647.             }
  648.             return false;
  649.         }
  650.        
  651.         public static bool IsMissing(object value)
  652.         {
  653.             return value is Missing;
  654.         }
  655.        
  656.         private MethodInfo LookForParameterlessPropertyGetter()
  657.         {
  658.             // We only get here as a result of an AmbiguousMatchException. If all the matches are parameterless
  659.             // property getters, we try selecting a match without providing arguments.
  660.             for (int i = 0int n = this.members.Length; i < n; i++) {
  661.                 PropertyInfo prop = this.members[i] as PropertyInfo;
  662.                 if (prop != null) {
  663.                     MethodInfo meth = prop.GetGetMethod(true);
  664.                     if (meth == null)
  665.                         continue;
  666.                     ParameterInfo[] parameters = meth.GetParameters();
  667.                     if (parameters == null || parameters.Length == 0)
  668.                         continue;
  669.                 }
  670.                 return null;
  671.             }
  672.             try {
  673.                 MethodInfo meth = JSBinder.SelectMethod(this.members, new IReflect[0]);
  674.                 //Returns property getters as well
  675.                 if (meth != null && meth.IsSpecialName) {
  676.                     //Property getter.
  677.                     return meth;
  678.                 }
  679.             }
  680.             catch (AmbiguousMatchException) {
  681.             }
  682.             return null;
  683.         }
  684.        
  685.         internal override bool OkToUseAsType()
  686.         {
  687.             MemberInfo member = this.member;
  688.             if (member is Type)
  689.                 return this.isFullyResolved = true;
  690.             if (member is FieldInfo) {
  691.                 FieldInfo field = (FieldInfo)member;
  692.                 if (field.IsLiteral) {
  693.                     if (field is JSMemberField && ((JSMemberField)field).value is ClassScope && !field.IsStatic)
  694.                         return false;
  695.                     return this.isFullyResolved = true;
  696.                 }
  697.                 if (!(member is JSField) && field.IsStatic && field.GetValue(null) is Type)
  698.                     return this.isFullyResolved = true;
  699.             }
  700.             return false;
  701.         }
  702.        
  703.         private int PlaceValuesForHiddenParametersOnStack(ILGenerator il, MethodInfo meth, ParameterInfo[] pars)
  704.         {
  705.             int offset = 0;
  706.             if (meth is JSFieldMethod) {
  707.                 FunctionObject func = ((JSFieldMethod)meth).func;
  708.                 if (func != null && func.isMethod)
  709.                     return 0;
  710.                 if (this is Lookup)
  711.                     ((Lookup)this).TranslateToILDefaultThisObject(il);
  712.                 else
  713.                     this.TranslateToILObject(il, Typeob.Object, false);
  714.                 this.EmitILToLoadEngine(il);
  715.                 return 0;
  716.             }
  717.             object[] attrs = CustomAttribute.GetCustomAttributes(meth, typeof(JSFunctionAttribute), false);
  718.             if (attrs == null || attrs.Length == 0)
  719.                 return 0;
  720.             JSFunctionAttributeEnum attr = ((JSFunctionAttribute)attrs[0]).attributeValue;
  721.             if ((attr & JSFunctionAttributeEnum.HasThisObject) != 0) {
  722.                 offset = 1;
  723.                 Type pt = pars[0].ParameterType;
  724.                 if (this is Lookup && pt == Typeob.Object)
  725.                     ((Lookup)this).TranslateToILDefaultThisObject(il);
  726.                 else {
  727.                     if (Typeob.ArrayObject.IsAssignableFrom(member.DeclaringType))
  728.                         this.TranslateToILObject(il, Typeob.ArrayObject, false);
  729.                     else
  730.                         this.TranslateToILObject(il, pt, false);
  731.                 }
  732.             }
  733.             if ((attr & JSFunctionAttributeEnum.HasEngine) != 0) {
  734.                 offset += 1;
  735.                 this.EmitILToLoadEngine(il);
  736.             }
  737.             return offset;
  738.         }
  739.        
  740.         private bool ParameterlessPropertyValueIsCallable(MethodInfo meth, ASTList args, IReflect[] argIRs, bool constructor, bool brackets)
  741.         {
  742.             ParameterInfo[] pars = meth.GetParameters();
  743.             if (pars == null || pars.Length == 0) {
  744.                 if ((meth is JSWrappedMethod && ((JSWrappedMethod)meth).GetWrappedObject() is GlobalObject) || argIRs.Length > 0 || (!(meth is JSMethod) && Typeob.ScriptFunction.IsAssignableFrom(meth.ReturnType))) {
  745.                     this.member = this.ResolveOtherKindOfCall(args, argIRs, constructor, brackets);
  746.                     return true;
  747.                 }
  748.                 IReflect mrt = meth is JSFieldMethod ? ((JSFieldMethod)meth).ReturnIR() : meth.ReturnType;
  749.                 if (mrt != Typeob.Object && mrt != Typeob.ScriptFunction)
  750.                     this.context.HandleError(JSError.InvalidCall);
  751.                 else {
  752.                     this.member = this.ResolveOtherKindOfCall(args, argIRs, constructor, brackets);
  753.                     return true;
  754.                 }
  755.             }
  756.             return false;
  757.         }
  758.        
  759.         static internal void PlaceArgumentsOnStack(ILGenerator il, ParameterInfo[] pars, ASTList args, int offset, int rhoffset, AST missing)
  760.         {
  761.             int k = args.count;
  762.             int n = k + offset;
  763.             int m = pars.Length - rhoffset;
  764.             bool varargs = m > 0 && CustomAttribute.IsDefined(pars[m - 1], typeof(ParamArrayAttribute), false) && !(k == m && Convert.IsArrayType(args[k - 1].InferType(null)));
  765.             Type varargElemType = varargs ? pars[--m].ParameterType.GetElementType() : null;
  766.             if (n > m)
  767.                 n = m;
  768.             for (int i = offset; i < n; i++) {
  769.                 Type ptype = pars[i].ParameterType;
  770.                 AST arg = args[i - offset];
  771.                 if (arg is ConstantWrapper && ((ConstantWrapper)arg).value == System.Reflection.Missing.Value) {
  772.                     object defVal = TypeReferences.GetDefaultParameterValue(pars[i]);
  773.                     ((ConstantWrapper)arg).value = defVal != System.Convert.DBNull ? defVal : null;
  774.                 }
  775.                 if (ptype.IsByRef)
  776.                     arg.TranslateToILReference(il, ptype.GetElementType());
  777.                 else
  778.                     arg.TranslateToIL(il, ptype);
  779.             }
  780.             if (n < m) {
  781.                 for (int i = n; i < m; i++) {
  782.                     Type ptype = pars[i].ParameterType;
  783.                     if (TypeReferences.GetDefaultParameterValue(pars[i]) == System.Convert.DBNull)
  784.                         if (ptype.IsByRef)
  785.                             missing.TranslateToILReference(il, ptype.GetElementType());
  786.                         else
  787.                             missing.TranslateToIL(il, ptype);
  788.                     else if (ptype.IsByRef)
  789.                         (new ConstantWrapper(TypeReferences.GetDefaultParameterValue(pars[i]), null)).TranslateToILReference(il, ptype.GetElementType());
  790.                     else
  791.                         //No default value was specified
  792.                         (new ConstantWrapper(TypeReferences.GetDefaultParameterValue(pars[i]), null)).TranslateToIL(il, ptype);
  793.                 }
  794.             }
  795.             if (varargs) {
  796.                 n -= offset;
  797.                 //The number of arguments in argList that are already on the stack
  798.                 m = k > n ? k - n : 0;
  799.                 //The number of arguments in argList that are to be placed in the vararg array
  800.                 ConstantWrapper.TranslateToILInt(il, m);
  801.                 il.Emit(OpCodes.Newarr, varargElemType);
  802.                 bool doLdelema = varargElemType.IsValueType && !varargElemType.IsPrimitive;
  803.                 for (int i = 0; i < m; i++) {
  804.                     il.Emit(OpCodes.Dup);
  805.                     ConstantWrapper.TranslateToILInt(il, i);
  806.                     if (doLdelema)
  807.                         il.Emit(OpCodes.Ldelema, varargElemType);
  808.                     args[i + n].TranslateToIL(il, varargElemType);
  809.                     Binding.TranslateToStelem(il, varargElemType);
  810.                 }
  811.             }
  812.         }
  813.        
  814.         internal bool RefersToMemoryLocation()
  815.         {
  816.             if (this.isFullyResolved) {
  817.                 if (this.isArrayElementAccess)
  818.                     return true;
  819.                 return this.member is FieldInfo;
  820.             }
  821.             return false;
  822.         }
  823.        
  824.         internal override void ResolveCall(ASTList args, IReflect[] argIRs, bool constructor, bool brackets)
  825.         {
  826.             this.argIRs = argIRs;
  827.             if (this.members == null || this.members.Length == 0) {
  828.                 if (constructor && this.isFullyResolved && this.Engine.doFast)
  829.                     if (this.member != null && (this.member is Type || (this.member is FieldInfo && ((FieldInfo)this.member).IsLiteral)))
  830.                         this.context.HandleError(JSError.NoConstructor);
  831.                     else
  832.                         this.HandleNoSuchMemberError();
  833.                 else
  834.                     this.HandleNoSuchMemberError();
  835.                 return;
  836.                 //Have to do a runtime lookup
  837.             }
  838.             MemberInfo member = null;
  839.             if (!(this is CallableExpression) && !(constructor && brackets))
  840.                 try {
  841.                     if (constructor)
  842.                         this.member = member = JSBinder.SelectConstructor(this.members, argIRs);
  843.                     else {
  844.                         MethodInfo meth;
  845.                         this.member = member = meth = JSBinder.SelectMethod(this.members, argIRs);
  846.                         //Returns property getters as well
  847.                         if (meth != null && meth.IsSpecialName) {
  848.                             //Property getter.
  849.                             if (this.name == meth.Name) {
  850.                                 if (this.name.StartsWith("get_", StringComparison.Ordinal) || this.name.StartsWith("set_", StringComparison.Ordinal)) {
  851.                                     this.context.HandleError(JSError.NotMeantToBeCalledDirectly);
  852.                                     this.member = null;
  853.                                     return;
  854.                                 }
  855.                             }
  856.                             else if (this.ParameterlessPropertyValueIsCallable(meth, args, argIRs, constructor, brackets))
  857.                                 return;
  858.                             // this.member was set by ParameterlessPropertyValueIsCallable
  859.                         }
  860.                     }
  861.                 }
  862.                 catch (AmbiguousMatchException) {
  863.                     if (constructor)
  864.                         this.context.HandleError(JSError.AmbiguousConstructorCall, this.isFullyResolved);
  865.                     else {
  866.                         MethodInfo meth = this.LookForParameterlessPropertyGetter();
  867.                         if (meth != null && this.ParameterlessPropertyValueIsCallable(meth, args, argIRs, constructor, brackets))
  868.                             return;
  869.                         // this.member was set by ParameterlessPropertyValueIsCallable
  870.                         this.context.HandleError(JSError.AmbiguousMatch, this.isFullyResolved);
  871.                         this.member = null;
  872.                     }
  873.                     return;
  874.                 }
  875.                 catch (JScriptException e) {
  876.                     this.context.HandleError((Microsoft.JScript.JSError)(e.ErrorNumber & 65535), e.Message, true);
  877.                     return;
  878.                 }
  879.             if (member == null)
  880.                 member = this.ResolveOtherKindOfCall(args, argIRs, constructor, brackets);
  881.             if (member == null)
  882.                 return;
  883.             //Already complained about it, if applicable. Do runtime lookup.
  884.             if (!this.Accessible(false)) {
  885.                 this.member = null;
  886.                 return;
  887.             }
  888.             WarnIfObsolete();
  889.             if (member is MethodBase) {
  890.                 if (CustomAttribute.IsDefined(member, typeof(JSFunctionAttribute), false) && !(this.defaultMember is PropertyInfo)) {
  891.                     int hidden = 0;
  892.                     object[] attrs = CustomAttribute.GetCustomAttributes(member, typeof(JSFunctionAttribute), false);
  893.                     JSFunctionAttributeEnum attr = ((JSFunctionAttribute)attrs[0]).attributeValue;
  894.                     if ((constructor && !(member is ConstructorInfo)) || (attr & JSFunctionAttributeEnum.HasArguments) != 0) {
  895.                         //Can only happen when doing an Eval from slow mode code
  896.                         //Cannot call such methods directly, so bind to the associated field instead
  897.                         this.member = LateBinding.SelectMember(this.members);
  898.                         this.defaultMember = null;
  899.                         return;
  900.                     }
  901.                     if ((attr & JSFunctionAttributeEnum.HasThisObject) != 0)
  902.                         hidden = 1;
  903.                     if ((attr & JSFunctionAttributeEnum.HasEngine) != 0)
  904.                         hidden += 1;
  905.                     if (!Binding.CheckParameters(((MethodBase)member).GetParameters(), argIRs, args, this.context, hidden, true, this.isFullyResolved)) {
  906.                         this.member = null;
  907.                         return;
  908.                     }
  909.                 }
  910.                 else if (constructor && member is JSFieldMethod) {
  911.                     //Do a late bound call so that the function as constructor semantics work out
  912.                     this.member = LateBinding.SelectMember(this.members);
  913.                     return;
  914.                 }
  915.                 else if (constructor && member is ConstructorInfo && !(member is JSConstructor) && Typeob.Delegate.IsAssignableFrom(member.DeclaringType)) {
  916.                     this.context.HandleError(JSError.DelegatesShouldNotBeExplicitlyConstructed);
  917.                     this.member = null;
  918.                     return;
  919.                 }
  920.                 else if (!Binding.CheckParameters(((MethodBase)member).GetParameters(), argIRs, args, this.context, 0, false, this.isFullyResolved)) {
  921.                     this.member = null;
  922.                     return;
  923.                 }
  924.             }
  925.             return;
  926.         }
  927.        
  928.         internal override object ResolveCustomAttribute(ASTList args, IReflect[] argIRs, AST target)
  929.         {
  930.             try {
  931.                 this.ResolveCall(args, argIRs, true, false);
  932.             }
  933.             catch (AmbiguousMatchException) {
  934.                 this.context.HandleError(JSError.AmbiguousConstructorCall);
  935.                 return null;
  936.             }
  937.             JSConstructor jscons = this.member as JSConstructor;
  938.             if (jscons != null) {
  939.                 ClassScope csc = jscons.GetClassScope();
  940.                 if (csc.owner.IsCustomAttribute())
  941.                     return csc;
  942.             }
  943.             else {
  944.                 ConstructorInfo cons = this.member as ConstructorInfo;
  945.                 if (cons != null) {
  946.                     Type attrType = cons.DeclaringType;
  947.                     if (Typeob.Attribute.IsAssignableFrom(attrType)) {
  948.                         object[] usageAttrs = CustomAttribute.GetCustomAttributes(attrType, typeof(AttributeUsageAttribute), false);
  949.                         if (usageAttrs.Length > 0)
  950.                             return attrType;
  951.                     }
  952.                 }
  953.             }
  954.             this.context.HandleError(JSError.InvalidCustomAttributeClassOrCtor);
  955.             return null;
  956.         }
  957.        
  958.         internal void ResolveLHValue()
  959.         {
  960.             MemberInfo member = this.member = LateBinding.SelectMember(this.members);
  961.             if ((member != null && !this.Accessible(true)) || (this.member == null && this.members.Length > 0)) {
  962.                 this.context.HandleError(JSError.AssignmentToReadOnly, this.isFullyResolved);
  963.                 this.member = null;
  964.                 //Recover by going late bound. The runtime routine will fail silently
  965.                 this.members = new MemberInfo[0];
  966.                 return;
  967.             }
  968.             if (member is JSPrototypeField) {
  969.                 //Go late bound
  970.                 this.member = null;
  971.                 this.members = new MemberInfo[0];
  972.                 return;
  973.             }
  974.             this.WarnIfNotFullyResolved();
  975.             this.WarnIfObsolete();
  976.             return;
  977.         }
  978.        
  979.         private MemberInfo ResolveOtherKindOfCall(ASTList argList, IReflect[] argIRs, bool constructor, bool brackets)
  980.         {
  981.             //There is no method or constructor corresponding to this binding. But there is something else.
  982.             MemberInfo member = this.member = LateBinding.SelectMember(this.members);
  983.             //Choose something
  984.             //If the chosen member is a read-only property on the global object of type Type, replace it with the type.
  985.             if (member is PropertyInfo && !(member is JSProperty) && member.DeclaringType == Typeob.GlobalObject) {
  986.                 PropertyInfo prop = (PropertyInfo)member;
  987.                 Type ptype = prop.PropertyType;
  988.                 if (ptype == Typeob.Type)
  989.                     member = (Type)prop.GetValue(null, null);
  990.                 else if (constructor && brackets) {
  991.                     //Map properties returning fast mode constructor functions to types
  992.                     MethodInfo meth = ptype.GetMethod("CreateInstance", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
  993.                     if (meth != null) {
  994.                         Type rtype = meth.ReturnType;
  995.                         if (rtype == Typeob.BooleanObject)
  996.                             member = Typeob.Boolean;
  997.                         else if (rtype == Typeob.StringObject)
  998.                             member = Typeob.String;
  999.                         else
  1000.                             member = rtype;
  1001.                     }
  1002.                 }
  1003.             }
  1004.            
  1005.             //Check for casts to type expressions, i.e. int[](x)
  1006.             CallableExpression ce = this as CallableExpression;
  1007.             if (ce != null) {
  1008.                 ConstantWrapper cw = ce.expression as ConstantWrapper;
  1009.                 if (cw != null && cw.InferType(null) is Type)
  1010.                     member = new JSGlobalField(null, null, cw.value, FieldAttributes.Literal | FieldAttributes.Public);
  1011.             }
  1012.            
  1013.             //If the chosen member is a literal field containing a class/function or a nested type, we replace members and try again.
  1014.             if (member is Type) {
  1015.                 if (constructor) {
  1016.                     if (brackets) {
  1017.                         this.isArrayConstructor = true;
  1018.                         this.defaultMember = member;
  1019.                         this.defaultMemberReturnIR = new TypedArray((Type)member, argIRs.Length);
  1020.                         for (int i = 0int n = argIRs.Length; i < n; i++) {
  1021.                             if (argIRs[i] != Typeob.Object && !Convert.IsPrimitiveNumericType(argIRs[i])) {
  1022.                                 argList[i].context.HandleError(JSError.TypeMismatch, this.isFullyResolved);
  1023.                                 break;
  1024.                             }
  1025.                         }
  1026.                         return this.member = member;
  1027.                     }
  1028.                     else {
  1029.                         ConstructorInfo[] constructors = ((Type)member).GetConstructors(BindingFlags.Instance | BindingFlags.Public);
  1030.                         if (constructors == null || constructors.Length == 0) {
  1031.                             this.context.HandleError(JSError.NoConstructor);
  1032.                             this.member = null;
  1033.                             return null;
  1034.                         }
  1035.                         this.members = constructors;
  1036.                         this.ResolveCall(argList, argIRs, true, brackets);
  1037.                         return this.member;
  1038.                     }
  1039.                 }
  1040.                 else {
  1041.                     if (!brackets && argIRs.Length == 1) {
  1042.                         //Dealing with a type cast
  1043.                         return member;
  1044.                     }
  1045.                     this.context.HandleError(JSError.InvalidCall);
  1046.                     return this.member = null;
  1047.                 }
  1048.             }
  1049.             if (member is JSPrototypeField)
  1050.                 //Have to go late-bound
  1051.                 return this.member = null;
  1052.             if (member is FieldInfo && ((FieldInfo)member).IsLiteral) {
  1053.                 if (!this.AccessibleField(false))
  1054.                     return this.member = null;
  1055.                 object val = member is JSVariableField ? ((JSVariableField)member).value : TypeReferences.GetConstantValue((FieldInfo)member);
  1056.                 if ((val is ClassScope || val is Type)) {
  1057.                     if (constructor) {
  1058.                         if (brackets) {
  1059.                             this.isArrayConstructor = true;
  1060.                             this.defaultMember = member;
  1061.                             this.defaultMemberReturnIR = new TypedArray((val is ClassScope ? (IReflect)val : (IReflect)val), argIRs.Length);
  1062.                             for (int i = 0int n = argIRs.Length; i < n; i++) {
  1063.                                 if (argIRs[i] != Typeob.Object && !Convert.IsPrimitiveNumericType(argIRs[i])) {
  1064.                                     argList[i].context.HandleError(JSError.TypeMismatch, this.isFullyResolved);
  1065.                                     break;
  1066.                                 }
  1067.                             }
  1068.                             return this.member = member;
  1069.                         }
  1070.                         else {
  1071.                             if (val is ClassScope && !((ClassScope)val).owner.isStatic) {
  1072.                                 ConstantWrapper cw = null;
  1073.                                 if (this is Member && (cw = ((Member)this).rootObject as ConstantWrapper) != null && !(cw.Evaluate() is Namespace)) {
  1074.                                     ((Member)this).rootObject.context.HandleError(JSError.NeedInstance);
  1075.                                     return null;
  1076.                                 }
  1077.                             }
  1078.                             this.members = val is ClassScope ? ((ClassScope)val).constructors : ((Type)val).GetConstructors(BindingFlags.Instance | BindingFlags.Public);
  1079.                             if (this.members == null || this.members.Length == 0) {
  1080.                                 this.context.HandleError(JSError.NoConstructor);
  1081.                                 this.member = null;
  1082.                                 return null;
  1083.                             }
  1084.                             this.ResolveCall(argList, argIRs, true, brackets);
  1085.                             return this.member;
  1086.                         }
  1087.                     }
  1088.                     else {
  1089.                         if (!brackets && argIRs.Length == 1) {
  1090.                             Type ty = val as Type;
  1091.                             return this.member = (ty != null ? ty : member);
  1092.                         }
  1093.                         this.context.HandleError(JSError.InvalidCall);
  1094.                         return this.member = null;
  1095.                     }
  1096.                 }
  1097.                 if (val is TypedArray) {
  1098.                     if (!constructor) {
  1099.                         //Casting a value to an array type
  1100.                         if (argIRs.Length != 1 || brackets)
  1101.                             goto ReportError;
  1102.                         return this.member = member;
  1103.                     }
  1104.                     if (!brackets)
  1105.                         goto ReportError;
  1106.                     //new T(...) where T is an array type.
  1107.                     if (argIRs.Length == 0)
  1108.                         goto ReportError;
  1109.                     //new T[] where T is an array type.
  1110.                     this.isArrayConstructor = true;
  1111.                     this.defaultMember = member;
  1112.                     this.defaultMemberReturnIR = new TypedArray((IReflect)val, argIRs.Length);
  1113.                     for (int i = 0int n = argIRs.Length; i < n; i++) {
  1114.                         if (argIRs[i] != Typeob.Object && !Convert.IsPrimitiveNumericType(argIRs[i])) {
  1115.                             argList[i].context.HandleError(JSError.TypeMismatch, this.isFullyResolved);
  1116.                             break;
  1117.                         }
  1118.                     }
  1119.                     return this.member = member;
  1120.                 }
  1121.                 if (val is FunctionObject) {
  1122.                     FunctionObject func = (FunctionObject)val;
  1123.                     if (!func.isExpandoMethod && !func.Must_save_stack_locals && (func.own_scope.ProvidesOuterScopeLocals == null || func.own_scope.ProvidesOuterScopeLocals.count == 0))
  1124.                         return this.member = ((JSVariableField)this.member).GetAsMethod(func.own_scope);
  1125.                     return this.member;
  1126.                     //Have to call via the field so that the stack frame is set up correctly
  1127.                 }
  1128.             }
  1129.            
  1130.             //Check the type of this binding for more information
  1131.             IReflect ir = this.InferType(null);
  1132.             Type t = ir as Type;
  1133.             if (!brackets && ((t != null && Typeob.ScriptFunction.IsAssignableFrom(t)) || ir is ScriptFunction)) {
  1134.                 this.defaultMember = member;
  1135.                 if (t == null) {
  1136.                     this.defaultMemberReturnIR = Globals.TypeRefs.ToReferenceContext(ir.GetType());
  1137.                     //The appropriate subtype of ScriptFunction
  1138.                     this.member = this.defaultMemberReturnIR.GetMethod(constructor ? "CreateInstance" : "Invoke", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);
  1139.                     if (this.member == null) {
  1140.                         this.defaultMemberReturnIR = Typeob.ScriptFunction;
  1141.                         this.member = this.defaultMemberReturnIR.GetMethod(constructor ? "CreateInstance" : "Invoke", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);
  1142.                     }
  1143.                     return this.member;
  1144.                 }
  1145.                 else {
  1146.                     // We have a script function but it might not be an "expando" function.
  1147.                     if (constructor && this.members.Length != 0 && this.members[0] is JSFieldMethod) {
  1148.                         JSFieldMethod fieldmethod = (JSFieldMethod)this.members[0];
  1149.                         fieldmethod.func.PartiallyEvaluate();
  1150.                         if (!fieldmethod.func.isExpandoMethod)
  1151.                             this.context.HandleError(JSError.NotAnExpandoFunction, this.isFullyResolved);
  1152.                     }
  1153.                     this.defaultMemberReturnIR = t;
  1154.                     return this.member = t.GetMethod(constructor ? "CreateInstance" : "Invoke", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);
  1155.                 }
  1156.             }
  1157.             if (ir == Typeob.Type) {
  1158.                 //Type cast to type only known at runtime
  1159.                 //Have to go late-bound
  1160.                 this.member = null;
  1161.                 return null;
  1162.             }
  1163.             if (ir == Typeob.Object || (ir is ScriptObject && brackets && !(ir is ClassScope)))
  1164.                 //The result of evaluating this binding could be a callable/constructable thing or a thing with a default indexed property.
  1165.                 //Or it could not, but we don't know enough at compile time to moan about it.
  1166.                 return member;
  1167.            
  1168.             //Perhaps this is an array element access
  1169.             if (ir is TypedArray || (ir is Type && ((Type)ir).IsArray)) {
  1170.                 int n = argIRs.Length;
  1171.                 int m = ir is TypedArray ? ((TypedArray)ir).rank : ((Type)ir).GetArrayRank();
  1172.                 if (n != m)
  1173.                     this.context.HandleError(JSError.IncorrectNumberOfIndices, this.isFullyResolved);
  1174.                 else {
  1175.                     for (int i = 0; i < m; i++) {
  1176.                         if (argIRs[i] != Typeob.Object && (!Convert.IsPrimitiveNumericType(argIRs[i]) || Convert.IsBadIndex(argList[i]))) {
  1177.                             argList[i].context.HandleError(JSError.TypeMismatch, this.isFullyResolved);
  1178.                             break;
  1179.                         }
  1180.                     }
  1181.                 }
  1182.                 if (constructor) {
  1183.                     if (!brackets)
  1184.                         goto ReportError;
  1185.                     //dealing with new Arr[...]. Give an error if the array element type is not Object, Type, or ScriptFunction
  1186.                     IReflect elemIR = ir is TypedArray ? ((TypedArray)ir).elementType : ((Type)ir).GetElementType();
  1187.                     if (ir != Typeob.Object && !(ir is ClassScope) && !(ir is Type && !Typeob.Type.IsAssignableFrom((Type)ir) && !Typeob.ScriptFunction.IsAssignableFrom((Type)ir)))
  1188.                         goto ReportError;
  1189.                 }
  1190.                 this.isArrayElementAccess = true;
  1191.                 this.defaultMember = member;
  1192.                 this.defaultMemberReturnIR = ir;
  1193.                 return null;
  1194.                 //Delay looking up the method to call until code gen time.
  1195.             }
  1196.            
  1197.             //Perhaps The result of evaluating this binding is an object that has a default indexed property/method that can be called
  1198.             if (constructor)
  1199.                 goto ReportError;
  1200.             //new binding(....) does not make sense for a default indexed property or method
  1201.             //Check for a default indexed property or default method
  1202.             if (brackets && ir == Typeob.String && (this.argIRs.Length != 1 || !Convert.IsPrimitiveNumericType(argIRs[0])))
  1203.                 ir = Typeob.StringObject;
  1204.             MemberInfo[] defaultMembers = brackets || !(ir is ScriptObject) ? JSBinder.GetDefaultMembers(ir) : null;
  1205.             if (defaultMembers != null && defaultMembers.Length > 0) {
  1206.                 try {
  1207.                     this.defaultMember = member;
  1208.                     this.defaultMemberReturnIR = ir;
  1209.                     return this.member = JSBinder.SelectMethod(this.members = defaultMembers, argIRs);
  1210.                     //Returns property getters as well
  1211.                 }
  1212.                 catch (AmbiguousMatchException) {
  1213.                     this.context.HandleError(JSError.AmbiguousMatch, this.isFullyResolved);
  1214.                     return this.member = null;
  1215.                 }
  1216.             }
  1217.            
  1218.             //Perhaps this is calling a delegate
  1219.             if (!brackets && ir is Type && Typeob.Delegate.IsAssignableFrom((Type)ir)) {
  1220.                 this.defaultMember = member;
  1221.                 this.defaultMemberReturnIR = ir;
  1222.                 return this.member = ((Type)ir).GetMethod("Invoke");
  1223.             }
  1224.             ReportError:
  1225.            
  1226.             //We now know enough to say that this binding really is not callable/constructable. Say so.
  1227.             if (constructor)
  1228.                 this.context.HandleError(JSError.NeedType, this.isFullyResolved);
  1229.             else if (brackets)
  1230.                 this.context.HandleError(JSError.NotIndexable, this.isFullyResolved);
  1231.             else
  1232.                 this.context.HandleError(JSError.FunctionExpected, this.isFullyResolved);
  1233.             return this.member = null;
  1234.         }
  1235.        
  1236.         protected void ResolveRHValue()
  1237.         {
  1238.             MemberInfo member = this.member = LateBinding.SelectMember(this.members);
  1239.             JSLocalField lfield = this.member as JSLocalField;
  1240.             if (lfield != null) {
  1241.                 FunctionObject funcOb = lfield.value as FunctionObject;
  1242.                 if (funcOb != null) {
  1243.                     FunctionScope enclosingScope = funcOb.enclosing_scope as FunctionScope;
  1244.                     if (enclosingScope != null)
  1245.                         enclosingScope.closuresMightEscape = true;
  1246.                 }
  1247.             }
  1248.             if (member is JSPrototypeField) {
  1249.                 //Have to go late bound
  1250.                 this.member = null;
  1251.                 return;
  1252.             }
  1253.             if (!this.Accessible(false)) {
  1254.                 this.member = null;
  1255.                 return;
  1256.             }
  1257.             WarnIfObsolete();
  1258.             this.WarnIfNotFullyResolved();
  1259.         }
  1260.        
  1261.         internal override void SetPartialValue(AST partial_value)
  1262.         {
  1263.             Binding.AssignmentCompatible(this.InferType(null), partial_value, partial_value.InferType(null), this.isFullyResolved);
  1264.         }
  1265.        
  1266.         internal void SetPartialValue(ASTList argList, IReflect[] argIRs, AST partial_value, bool inBrackets)
  1267.         {
  1268.             if (this.members == null || this.members.Length == 0) {
  1269.                 this.HandleNoSuchMemberError();
  1270.                 this.isAssignmentToDefaultIndexedProperty = true;
  1271.                 return;
  1272.                 //Have to do a runtime lookup
  1273.             }
  1274.            
  1275.             this.PartiallyEvaluate();
  1276.             //The rhside value of the binding delivers the object with the default indexed property we are assigning to
  1277.             IReflect ir = this.InferType(null);
  1278.             this.isAssignmentToDefaultIndexedProperty = true;
  1279.             if (ir == Typeob.Object) {
  1280.                 JSVariableField jsvf = this.member as JSVariableField;
  1281.                 if (jsvf == null || !jsvf.IsLiteral || !(jsvf.value is ClassScope))
  1282.                     return;
  1283.                 //Not enough is known at compile time to give an error
  1284.                 ir = Typeob.Type;
  1285.                 goto giveError;
  1286.             }
  1287.            
  1288.             //Might be an assignment to an array element
  1289.             if ((ir is TypedArray || (ir is Type && ((Type)ir).IsArray))) {
  1290.                 bool gaveAnError = false;
  1291.                 //Check dimension
  1292.                 int n = argIRs.Length;
  1293.                 int m = ir is TypedArray ? ((TypedArray)ir).rank : ((Type)ir).GetArrayRank();
  1294.                 if (n != m) {
  1295.                     this.context.HandleError(JSError.IncorrectNumberOfIndices, this.isFullyResolved);
  1296.                     gaveAnError = true;
  1297.                 }
  1298.                 //Check type of indices
  1299.                 for (int i = 0; i < m; i++) {
  1300.                     if (!gaveAnError && i < n && argIRs[i] != Typeob.Object && (!Convert.IsPrimitiveNumericType(argIRs[i]) || Convert.IsBadIndex(argList[i]))) {
  1301.                         argList[i].context.HandleError(JSError.TypeMismatch, this.isFullyResolved);
  1302.                         gaveAnError = true;
  1303.                     }
  1304.                 }
  1305.                 this.isArrayElementAccess = true;
  1306.                 this.isAssignmentToDefaultIndexedProperty = false;
  1307.                 this.defaultMember = member;
  1308.                 this.defaultMemberReturnIR = ir;
  1309.                
  1310.                 //Check type of rhside
  1311.                 IReflect elemIR = ir is TypedArray ? ((TypedArray)ir).elementType : ((Type)ir).GetElementType();
  1312.                 Binding.AssignmentCompatible(elemIR, partial_value, partial_value.InferType(null), this.isFullyResolved);
  1313.                 return;
  1314.             }
  1315.            
  1316.             //Might be an assignment to a default indexed property
  1317.             MemberInfo[] defaultMembers = JSBinder.GetDefaultMembers(ir);
  1318.             if (defaultMembers != null && defaultMembers.Length > 0 && this.member != null) {
  1319.                 try {
  1320.                     PropertyInfo prop = JSBinder.SelectProperty(defaultMembers, argIRs);
  1321.                     if (prop == null) {
  1322.                         this.context.HandleError(JSError.NotIndexable, Convert.ToTypeName(ir));
  1323.                         return;
  1324.                     }
  1325.                     if (JSProperty.GetSetMethod(prop, true) == null) {
  1326.                         if (ir == Typeob.String)
  1327.                             this.context.HandleError(JSError.UselessAssignment);
  1328.                         else
  1329.                             this.context.HandleError(JSError.AssignmentToReadOnly, this.isFullyResolved && this.Engine.doFast);
  1330.                         return;
  1331.                     }
  1332.                     if (!Binding.CheckParameters(prop.GetIndexParameters(), argIRs, argList, this.context, 0, false, true)) {
  1333.                         return;
  1334.                     }
  1335.                     this.defaultMember = this.member;
  1336.                     this.defaultMemberReturnIR = ir;
  1337.                     this.members = defaultMembers;
  1338.                     this.member = prop;
  1339.                 }
  1340.                 catch (AmbiguousMatchException) {
  1341.                     this.context.HandleError(JSError.AmbiguousMatch, this.isFullyResolved);
  1342.                     this.member = null;
  1343.                 }
  1344.                 return;
  1345.             }
  1346.             giveError:
  1347.            
  1348.             this.member = null;
  1349.             if (!inBrackets)
  1350.                 this.context.HandleError(JSError.IllegalAssignment);
  1351.             else
  1352.                 this.context.HandleError(JSError.NotIndexable, Convert.ToTypeName(ir));
  1353.         }
  1354.        
  1355.         internal override void SetValue(object value)
  1356.         {
  1357.             MemberInfo member = this.member;
  1358.             object ob = this.GetObject();
  1359.             if (member is FieldInfo) {
  1360.                 FieldInfo field = (FieldInfo)member;
  1361.                 if (field.IsLiteral || field.IsInitOnly)
  1362.                     return;
  1363.                 if (!(field is JSField) || field is JSWrappedField)
  1364.                     value = Convert.CoerceT(value, field.FieldType, false);
  1365.                 field.SetValue(ob, value, BindingFlags.SuppressChangeType, null, null);
  1366.                 return;
  1367.             }
  1368.             if (member is PropertyInfo) {
  1369.                 PropertyInfo prop = (PropertyInfo)member;
  1370.                 if (ob is ClassScope && !(prop is JSProperty)) {
  1371.                     JSProperty.SetValue(prop, ((WithObject)((ClassScope)ob).GetParent()).contained_object, value, null);
  1372.                     return;
  1373.                 }
  1374.                 if (!(prop is JSProperty))
  1375.                     value = Convert.CoerceT(value, prop.PropertyType, false);
  1376.                 JSProperty.SetValue(prop, ob, value, null);
  1377.                 return;
  1378.             }
  1379.             if (this.members == null || this.members.Length == 0) {
  1380.                 this.EvaluateAsLateBinding().SetValue(value);
  1381.                 return;
  1382.             }
  1383.             //The name has been bound to something and that something is not a valid assignment target.
  1384.             throw new JScriptException(JSError.IllegalAssignment);
  1385.         }
  1386.        
  1387.         internal override void TranslateToIL(ILGenerator il, Type rtype)
  1388.         {
  1389.             this.TranslateToIL(il, rtype, false, false);
  1390.         }
  1391.        
  1392.         internal void TranslateToIL(ILGenerator il, Type rtype, bool calledFromDelete)
  1393.         {
  1394.             this.TranslateToIL(il, rtype, false, false, calledFromDelete);
  1395.         }
  1396.        
  1397.         private void TranslateToIL(ILGenerator il, Type rtype, bool preSet, bool preSetPlusGet)
  1398.         {
  1399.             this.TranslateToIL(il, rtype, preSet, preSetPlusGet, false);
  1400.         }
  1401.        
  1402.         private void TranslateToIL(ILGenerator il, Type rtype, bool preSet, bool preSetPlusGet, bool calledFromDelete)
  1403.         {
  1404.             if (this.member is FieldInfo) {
  1405.                 FieldInfo field = (FieldInfo)this.member;
  1406.                 bool isStatic = field.IsStatic || field.IsLiteral;
  1407.                 if (field.IsLiteral && field is JSMemberField) {
  1408.                     object val = ((JSMemberField)field).value;
  1409.                     FunctionObject func = val as FunctionObject;
  1410.                     isStatic = func == null || !func.isExpandoMethod;
  1411.                 }
  1412.                 if (!isStatic || field is JSClosureField) {
  1413.                     this.TranslateToILObject(il, field.DeclaringType, true);
  1414.                     if (preSetPlusGet)
  1415.                         il.Emit(OpCodes.Dup);
  1416.                     isStatic = false;
  1417.                 }
  1418.                 if (!preSet) {
  1419.                     object tok = field is JSField ? ((JSField)field).GetMetaData() : field is JSFieldInfo ? ((JSFieldInfo)field).field : field;
  1420.                     if (tok is FieldInfo && !((FieldInfo)tok).IsLiteral)
  1421.                         il.Emit(isStatic ? OpCodes.Ldsfld : OpCodes.Ldfld, (FieldInfo)tok);
  1422.                     else if (tok is LocalBuilder)
  1423.                         il.Emit(OpCodes.Ldloc, (LocalBuilder)tok);
  1424.                     else if (field.IsLiteral) {
  1425.                         (new ConstantWrapper(TypeReferences.GetConstantValue(field), this.context)).TranslateToIL(il, rtype);
  1426.                         return;
  1427.                     }
  1428.                     else
  1429.                         Convert.EmitLdarg(il, (short)tok);
  1430.                     Convert.Emit(this, il, field.FieldType, rtype);
  1431.                 }
  1432.                 return;
  1433.             }
  1434.             if (this.member is PropertyInfo) {
  1435.                 PropertyInfo prop = (PropertyInfo)this.member;
  1436.                 MethodInfo meth = preSet ? JSProperty.GetSetMethod(prop, true) : JSProperty.GetGetMethod(prop, true);
  1437.                 if (meth == null) {
  1438.                     if (preSet)
  1439.                         return;
  1440.                     if (this is Lookup) {
  1441.                         il.Emit(OpCodes.Ldc_I4, (int)JSError.WriteOnlyProperty);
  1442.                         il.Emit(OpCodes.Newobj, CompilerGlobals.scriptExceptionConstructor);
  1443.                         il.Emit(OpCodes.Throw);
  1444.                     }
  1445.                     else
  1446.                         il.Emit(OpCodes.Ldnull);
  1447.                     return;
  1448.                 }
  1449.                 bool isStatic = meth.IsStatic && !(meth is JSClosureMethod);
  1450.                 if (!isStatic) {
  1451.                     Type obType = meth.DeclaringType;
  1452.                     if (obType == Typeob.StringObject && meth.Name.Equals("get_length")) {
  1453.                         this.TranslateToILObject(il, Typeob.String, false);
  1454.                         meth = CompilerGlobals.stringLengthMethod;
  1455.                     }
  1456.                     else
  1457.                         this.TranslateToILObject(il, obType, true);
  1458.                 }
  1459.                 if (!preSet) {
  1460.                     Debug.Assert(meth.GetParameters().Length == 0);
  1461.                     meth = this.GetMethodInfoMetadata(meth);
  1462.                     if (isStatic) {
  1463.                         il.Emit(OpCodes.Call, meth);
  1464.                     }
  1465.                     else {
  1466.                         if (preSetPlusGet)
  1467.                             il.Emit(OpCodes.Dup);
  1468.                         if (!this.isNonVirtual && meth.IsVirtual && !meth.IsFinal && (!meth.ReflectedType.IsSealed || !meth.ReflectedType.IsValueType))
  1469.                             il.Emit(OpCodes.Callvirt, meth);
  1470.                         else
  1471.                             il.Emit(OpCodes.Call, meth);
  1472.                     }
  1473.                     Convert.Emit(this, il, meth.ReturnType, rtype);
  1474.                 }
  1475.                 return;
  1476.             }
  1477.             if (this.member is MethodInfo) {
  1478.                 MethodInfo meth = this.GetMethodInfoMetadata((MethodInfo)this.member);
  1479.                 if (Typeob.Delegate.IsAssignableFrom(rtype)) {
  1480.                     if (!meth.IsStatic) {
  1481.                         Type obType = meth.DeclaringType;
  1482.                         this.TranslateToILObject(il, obType, false);
  1483.                         if (obType.IsValueType)
  1484.                             il.Emit(OpCodes.Box, obType);
  1485.                     }
  1486.                     else
  1487.                         il.Emit(OpCodes.Ldnull);
  1488.                     if (meth.IsVirtual && !meth.IsFinal && (!meth.ReflectedType.IsSealed || !meth.ReflectedType.IsValueType)) {
  1489.                         il.Emit(OpCodes.Dup);
  1490.                         il.Emit(OpCodes.Ldvirtftn, meth);
  1491.                     }
  1492.                     else
  1493.                         il.Emit(OpCodes.Ldftn, meth);
  1494.                     ConstructorInfo cons = rtype.GetConstructor(new Type[] {Typeob.Object, Typeob.UIntPtr});
  1495.                     if (cons == null)
  1496.                         cons = rtype.GetConstructor(new Type[] {Typeob.Object, Typeob.IntPtr});
  1497.                     il.Emit(OpCodes.Newobj, cons);
  1498.                     return;
  1499.                 }
  1500.                 //ResolveRHValue will never set this.member to a MethodInfo. The above case only happens
  1501.                 //because IsCompatibleWithDelegate sets this.member to the method that matches the delegate type.
  1502.                 if (member is JSExpandoIndexerMethod) {
  1503.                     //Need to put the expando class instance on the stack as the this object in expressions such as exInstance["foo"]90
  1504.                     MemberInfo mem = this.member;
  1505.                     this.member = this.defaultMember;
  1506.                     this.TranslateToIL(il, Typeob.Object);
  1507.                     this.member = mem;
  1508.                     return;
  1509.                 }
  1510.                 il.Emit(OpCodes.Ldnull);
  1511.                 //get something on the stack, in case we DO get here
  1512.                 Convert.Emit(this, il, Typeob.Object, rtype);
  1513.                 return;
  1514.             }
  1515.             object done = null;
  1516.             if (this is Lookup)
  1517.                 ((Lookup)this).TranslateToLateBinding(il);
  1518.             else {
  1519.                 if (!this.isFullyResolved && !preSet && !preSetPlusGet)
  1520.                     done = this.TranslateToSpeculativeEarlyBindings(il, rtype, false);
  1521.                 ((Member)this).TranslateToLateBinding(il, done != null);
  1522.                 if (!this.isFullyResolved && preSetPlusGet)
  1523.                     done = this.TranslateToSpeculativeEarlyBindings(il, rtype, true);
  1524.             }
  1525.             if (preSetPlusGet)
  1526.                 il.Emit(OpCodes.Dup);
  1527.             if (!preSet) {
  1528.                 if (this is Lookup && !calledFromDelete)
  1529.                     il.Emit(OpCodes.Call, CompilerGlobals.getValue2Method);
  1530.                 else
  1531.                     il.Emit(OpCodes.Call, CompilerGlobals.getNonMissingValueMethod);
  1532.                 Convert.Emit(this, il, Typeob.Object, rtype);
  1533.                 if (done != null)
  1534.                     il.MarkLabel((Label)done);
  1535.             }
  1536.         }
  1537.        
  1538.         internal override void TranslateToILCall(ILGenerator il, Type rtype, ASTList argList, bool construct, bool brackets)
  1539.         {
  1540.             MemberInfo member = this.member;
  1541.             if (this.defaultMember != null) {
  1542.                 if (this.isArrayConstructor) {
  1543.                     TypedArray tArr = (TypedArray)this.defaultMemberReturnIR;
  1544.                     Type eType = Convert.ToType(tArr.elementType);
  1545.                     Debug.Assert(tArr.rank == argList.count);
  1546.                     int r = tArr.rank;
  1547.                     if (r == 1) {
  1548.                         argList[0].TranslateToIL(il, Typeob.Int32);
  1549.                         il.Emit(OpCodes.Newarr, eType);
  1550.                     }
  1551.                     else {
  1552.                         Type aType = tArr.ToType();
  1553.                         Type[] dTypes = new Type[r];
  1554.                         for (int i = 0; i < r; i++)
  1555.                             dTypes[i] = Typeob.Int32;
  1556.                         for (int i = 0int n = argList.count; i < n; i++)
  1557.                             argList[i].TranslateToIL(il, Typeob.Int32);
  1558.                         TypeBuilder eTypeB = eType as TypeBuilder;
  1559.                         if (eTypeB != null) {
  1560.                             MethodInfo cons = ((ModuleBuilder)aType.Module).GetArrayMethod(aType, ".ctor", CallingConventions.HasThis, Typeob.Void, dTypes);
  1561.                             il.Emit(OpCodes.Newobj, cons);
  1562.                         }
  1563.                         else {
  1564.                             ConstructorInfo cons = aType.GetConstructor(dTypes);
  1565.                             il.Emit(OpCodes.Newobj, cons);
  1566.                         }
  1567.                     }
  1568.                     Convert.Emit(this, il, tArr.ToType(), rtype);
  1569.                     return;
  1570.                 }
  1571.                 this.member = this.defaultMember;
  1572.                 IReflect defIR = this.defaultMemberReturnIR;
  1573.                 Type defType = defIR is Type ? (Type)defIR : Convert.ToType(defIR);
  1574.                 this.TranslateToIL(il, defType);
  1575.                 if (this.isArrayElementAccess) {
  1576.                     Debug.Assert(defType.IsArray);
  1577.                     for (int i = 0int m = argList.count; i < m; i++)
  1578.                         argList[i].TranslateToIL(il, Typeob.Int32);
  1579.                     Type etype = defType.GetElementType();
  1580.                     int n = defType.GetArrayRank();
  1581.                     if (n == 1) {
  1582.                         Binding.TranslateToLdelem(il, etype);
  1583.                     }
  1584.                     else {
  1585.                         Type[] indexTypes = new Type[n];
  1586.                         for (int i = 0; i < n; i++)
  1587.                             indexTypes[i] = Typeob.Int32;
  1588.                         MethodInfo getter = compilerGlobals.module.GetArrayMethod(defType, "Get", CallingConventions.HasThis, etype, indexTypes);
  1589.                         il.Emit(OpCodes.Call, getter);
  1590.                     }
  1591.                     Convert.Emit(this, il, etype, rtype);
  1592.                     return;
  1593.                 }
  1594.                 this.member = member;
  1595.             }
  1596.             if (member is MethodInfo) {
  1597.                 MethodInfo meth = (MethodInfo)member;
  1598.                 Type dt = meth.DeclaringType;
  1599.                 Type rt = meth.ReflectedType;
  1600.                 ParameterInfo[] pars = meth.GetParameters();
  1601.                 bool isStatic = meth.IsStatic;
  1602.                 if (!isStatic && this.defaultMember == null)
  1603.                     this.TranslateToILObject(il, dt, true);
  1604.                 if (meth is JSClosureMethod)
  1605.                     this.TranslateToILObject(il, dt, false);
  1606.                 ConstantWrapper missing = null;
  1607.                 int offset = 0;
  1608.                 if (meth is JSFieldMethod || CustomAttribute.IsDefined(meth, typeof(JSFunctionAttribute), false)) {
  1609.                     offset = this.PlaceValuesForHiddenParametersOnStack(il, meth, pars);
  1610.                     missing = Binding.JScriptMissingCW;
  1611.                 }
  1612.                 else
  1613.                     missing = Binding.ReflectionMissingCW;
  1614.                 if (argList.count == 1 && missing == Binding.JScriptMissingCW && this.defaultMember is PropertyInfo) {
  1615.                     //Dealing with the CreateInstance method of a constructor function
  1616.                     Debug.Assert(meth.Name == "CreateInstance" || meth.Name == "Invoke");
  1617.                     il.Emit(OpCodes.Ldc_I4_1);
  1618.                     il.Emit(OpCodes.Newarr, Typeob.Object);
  1619.                     il.Emit(OpCodes.Dup);
  1620.                     il.Emit(OpCodes.Ldc_I4_0);
  1621.                     argList[0].TranslateToIL(il, Typeob.Object);
  1622.                     il.Emit(OpCodes.Stelem_Ref);
  1623.                 }
  1624.                 else
  1625.                     Binding.PlaceArgumentsOnStack(il, pars, argList, offset, 0, missing);
  1626.                 meth = this.GetMethodInfoMetadata(meth);
  1627.                 if (!this.isNonVirtual && meth.IsVirtual && !meth.IsFinal && (!rt.IsSealed || !rt.IsValueType))
  1628.                     il.Emit(OpCodes.Callvirt, meth);
  1629.                 else
  1630.                     il.Emit(OpCodes.Call, meth);
  1631.                 Convert.Emit(this, il, meth.ReturnType, rtype);
  1632.                 return;
  1633.             }
  1634.             if (member is ConstructorInfo) {
  1635.                 Debug.Assert(construct);
  1636.                 ConstructorInfo cons = (ConstructorInfo)member;
  1637.                 ParameterInfo[] pars = cons.GetParameters();
  1638.                 bool instanceNestedClassConstructor = false;
  1639.                 if (CustomAttribute.IsDefined(cons, typeof(JSFunctionAttribute), false)) {
  1640.                     object[] attrs = CustomAttribute.GetCustomAttributes(cons, typeof(JSFunctionAttribute), false);
  1641.                     instanceNestedClassConstructor = (((JSFunctionAttribute)attrs[0]).attributeValue & JSFunctionAttributeEnum.IsInstanceNestedClassConstructor) != 0;
  1642.                 }
  1643.                 if (instanceNestedClassConstructor) {
  1644.                     Binding.PlaceArgumentsOnStack(il, pars, argList, 0, 1, Binding.ReflectionMissingCW);
  1645.                     this.TranslateToILObject(il, pars[pars.Length - 1].ParameterType, false);
  1646.                 }
  1647.                 else
  1648.                     Binding.PlaceArgumentsOnStack(il, pars, argList, 0, 0, Binding.ReflectionMissingCW);
  1649.                 Type outerClass = null;
  1650.                 if (member is JSConstructor && (outerClass = ((JSConstructor)member).OuterClassType()) != null)
  1651.                     this.TranslateToILObject(il, outerClass, false);
  1652.                 bool needEngine = false;
  1653.                 Type t = cons.DeclaringType;
  1654.                 if (cons is JSConstructor) {
  1655.                     cons = ((JSConstructor)cons).GetConstructorInfo(compilerGlobals);
  1656.                     needEngine = true;
  1657.                 }
  1658.                 else
  1659.                     needEngine = Typeob.INeedEngine.IsAssignableFrom(t);
  1660.                 il.Emit(OpCodes.Newobj, cons);
  1661.                 if (needEngine) {
  1662.                     il.Emit(OpCodes.Dup);
  1663.                     this.EmitILToLoadEngine(il);
  1664.                     il.Emit(OpCodes.Callvirt, CompilerGlobals.setEngineMethod);
  1665.                 }
  1666.                 Convert.Emit(this, il, t, rtype);
  1667.                 return;
  1668.             }
  1669.             Type mt = member as Type;
  1670.             if (mt != null) {
  1671.                 Debug.Assert(!construct && !brackets);
  1672.                 Debug.Assert(argList.count == 1);
  1673.                 AST arg0 = argList[0];
  1674.                 if (arg0 is NullLiteral) {
  1675.                     //Skip the double conversion path below that involves runtime helper
  1676.                     arg0.TranslateToIL(il, mt);
  1677.                     Convert.Emit(this, il, mt, rtype);
  1678.                     return;
  1679.                 }
  1680.                 IReflect arg0ir = arg0.InferType(null);
  1681.                 if (arg0ir == Typeob.ScriptFunction && Typeob.Delegate.IsAssignableFrom(mt))
  1682.                     arg0.TranslateToIL(il, mt);
  1683.                 else {
  1684.                     Type argType = Convert.ToType(arg0ir);
  1685.                     arg0.TranslateToIL(il, argType);
  1686.                     Convert.Emit(this, il, argType, mt, true);
  1687.                 }
  1688.                 Convert.Emit(this, il, mt, rtype);
  1689.                 return;
  1690.             }
  1691.             if (member is FieldInfo && ((FieldInfo)member).IsLiteral) {
  1692.                 object val = member is JSVariableField ? ((JSVariableField)member).value : TypeReferences.GetConstantValue((FieldInfo)member);
  1693.                 if (val is Type || val is ClassScope || val is TypedArray) {
  1694.                     Debug.Assert(argList.count == 1);
  1695.                     AST arg0 = argList[0];
  1696.                     if (arg0 is NullLiteral) {
  1697.                         il.Emit(OpCodes.Ldnull);
  1698.                         return;
  1699.                     }
  1700.                     ClassScope csc = val as ClassScope;
  1701.                     if (csc != null) {
  1702.                         EnumDeclaration ed = csc.owner as EnumDeclaration;
  1703.                         if (ed != null)
  1704.                             val = ed.baseType.ToType();
  1705.                     }
  1706.                     Type argType = Convert.ToType(arg0.InferType(null));
  1707.                     arg0.TranslateToIL(il, argType);
  1708.                     Type t = val is Type ? (Type)val : val is ClassScope ? Convert.ToType((ClassScope)val) : ((TypedArray)val).ToType();
  1709.                     Convert.Emit(this, il, argType, t, true);
  1710.                     if (!rtype.IsEnum)
  1711.                         Convert.Emit(this, il, t, rtype);
  1712.                     return;
  1713.                 }
  1714.             }
  1715.             LocalBuilder loc = null;
  1716.             for (int i = 0int n = argList.count; i < n; i++) {
  1717.                 if (argList[i] is AddressOf) {
  1718.                     loc = il.DeclareLocal(Typeob.ArrayOfObject);
  1719.                     break;
  1720.                 }
  1721.             }
  1722.             object done = null;
  1723.             if (member == null && (this.members == null || this.members.Length == 0)) {
  1724.                 if (this is Lookup)
  1725.                     ((Lookup)this).TranslateToLateBinding(il);
  1726.                 else {
  1727.                     done = this.TranslateToSpeculativeEarlyBoundCalls(il, rtype, argList, construct, brackets);
  1728.                     ((Member)this).TranslateToLateBinding(il, done != null);
  1729.                 }
  1730.                 argList.TranslateToIL(il, Typeob.ArrayOfObject);
  1731.                 if (loc != null) {
  1732.                     il.Emit(OpCodes.Dup);
  1733.                     il.Emit(OpCodes.Stloc, loc);
  1734.                 }
  1735.                 if (construct)
  1736.                     il.Emit(OpCodes.Ldc_I4_1);
  1737.                 else
  1738.                     il.Emit(OpCodes.Ldc_I4_0);
  1739.                 if (brackets)
  1740.                     il.Emit(OpCodes.Ldc_I4_1);
  1741.                 else
  1742.                     il.Emit(OpCodes.Ldc_I4_0);
  1743.                 this.EmitILToLoadEngine(il);
  1744.                 il.Emit(OpCodes.Call, CompilerGlobals.callMethod);
  1745.                 Convert.Emit(this, il, Typeob.Object, rtype);
  1746.                 if (loc != null) {
  1747.                     for (int i = 0int n = argList.count; i < n; i++) {
  1748.                         AddressOf addr = argList[i] as AddressOf;
  1749.                         if (addr != null) {
  1750.                             addr.TranslateToILPreSet(il);
  1751.                             il.Emit(OpCodes.Ldloc, loc);
  1752.                             ConstantWrapper.TranslateToILInt(il, i);
  1753.                             il.Emit(OpCodes.Ldelem_Ref);
  1754.                             Convert.Emit(this, il, Typeob.Object, Convert.ToType(addr.InferType(null)));
  1755.                             addr.TranslateToILSet(il, null);
  1756.                         }
  1757.                     }
  1758.                 }
  1759.                 if (done != null)
  1760.                     il.MarkLabel((Label)done);
  1761.                 return;
  1762.             }
  1763.             this.TranslateToILWithDupOfThisOb(il);
  1764.             argList.TranslateToIL(il, Typeob.ArrayOfObject);
  1765.             if (loc != null) {
  1766.                 il.Emit(OpCodes.Dup);
  1767.                 il.Emit(OpCodes.Stloc, loc);
  1768.             }
  1769.             if (construct)
  1770.                 il.Emit(OpCodes.Ldc_I4_1);
  1771.             else
  1772.                 il.Emit(OpCodes.Ldc_I4_0);
  1773.             if (brackets)
  1774.                 il.Emit(OpCodes.Ldc_I4_1);
  1775.             else
  1776.                 il.Emit(OpCodes.Ldc_I4_0);
  1777.             this.EmitILToLoadEngine(il);
  1778.             il.Emit(OpCodes.Call, CompilerGlobals.callValueMethod);
  1779.             Convert.Emit(this, il, Typeob.Object, rtype);
  1780.             if (loc != null) {
  1781.                 for (int i = 0int n = argList.count; i < n; i++) {
  1782.                     AddressOf addr = argList[i] as AddressOf;
  1783.                     if (addr != null) {
  1784.                         addr.TranslateToILPreSet(il);
  1785.                         il.Emit(OpCodes.Ldloc, loc);
  1786.                         ConstantWrapper.TranslateToILInt(il, i);
  1787.                         il.Emit(OpCodes.Ldelem_Ref);
  1788.                         Convert.Emit(this, il, Typeob.Object, Convert.ToType(addr.InferType(null)));
  1789.                         addr.TranslateToILSet(il, null);
  1790.                     }
  1791.                 }
  1792.             }
  1793.         }
  1794.        
  1795.         internal override void TranslateToILDelete(ILGenerator il, Type rtype)
  1796.         {
  1797.             if (this is Lookup)
  1798.                 ((Lookup)this).TranslateToLateBinding(il);
  1799.             else
  1800.                 ((Member)this).TranslateToLateBinding(il, false);
  1801.             il.Emit(OpCodes.Call, CompilerGlobals.deleteMethod);
  1802.             Convert.Emit(this, il, Typeob.Boolean, rtype);
  1803.         }
  1804.        
  1805.         protected abstract void TranslateToILObject(ILGenerator il, Type obtype, bool noValue);
  1806.        
  1807.         internal override void TranslateToILPreSet(ILGenerator il)
  1808.         {
  1809.             this.TranslateToIL(il, null, true, false);
  1810.         }
  1811.        
  1812.         internal override void TranslateToILPreSet(ILGenerator il, ASTList argList)
  1813.         {
  1814.             if (this.isArrayElementAccess) {
  1815.                 this.member = this.defaultMember;
  1816.                 IReflect defIR = this.defaultMemberReturnIR;
  1817.                 Type defType = defIR is Type ? (Type)defIR : Convert.ToType(defIR);
  1818.                 this.TranslateToIL(il, defType);
  1819.                 Debug.Assert(defType.IsArray);
  1820.                 for (int i = 0int m = argList.count; i < m; i++)
  1821.                     argList[i].TranslateToIL(il, Typeob.Int32);
  1822.                 if (defType.GetArrayRank() == 1) {
  1823.                     Type etype = defType.GetElementType();
  1824.                     if (etype.IsValueType && !etype.IsPrimitive && !etype.IsEnum)
  1825.                         il.Emit(OpCodes.Ldelema, etype);
  1826.                 }
  1827.                 return;
  1828.             }
  1829.             Debug.Assert(this.isAssignmentToDefaultIndexedProperty);
  1830.             if (this.member is PropertyInfo && this.defaultMember != null) {
  1831.                 //early bound to default indexed property
  1832.                 PropertyInfo prop = (PropertyInfo)this.member;
  1833.                 this.member = this.defaultMember;
  1834.                 this.TranslateToIL(il, Convert.ToType(this.defaultMemberReturnIR));
  1835.                 this.member = prop;
  1836.                 Binding.PlaceArgumentsOnStack(il, prop.GetIndexParameters(), argList, 0, 0, Binding.ReflectionMissingCW);
  1837.                 return;
  1838.             }
  1839.             base.TranslateToILPreSet(il, argList);
  1840.         }
  1841.        
  1842.         internal override void TranslateToILPreSetPlusGet(ILGenerator il)
  1843.         {
  1844.             this.TranslateToIL(il, Convert.ToType(this.InferType(null)), false, true);
  1845.         }
  1846.        
  1847.         internal override void TranslateToILPreSetPlusGet(ILGenerator il, ASTList argList, bool inBrackets)
  1848.         {
  1849.             if (this.isArrayElementAccess) {
  1850.                 this.member = this.defaultMember;
  1851.                 IReflect defIR = this.defaultMemberReturnIR;
  1852.                 Type defType = defIR is Type ? (Type)defIR : Convert.ToType(defIR);
  1853.                 Debug.Assert(defType.IsArray);
  1854.                 this.TranslateToIL(il, defType);
  1855.                 il.Emit(OpCodes.Dup);
  1856.                 int n = defType.GetArrayRank();
  1857.                 LocalBuilder[] iTemp = new LocalBuilder[n];
  1858.                 for (int i = 0int m = argList.count; i < m; i++) {
  1859.                     argList[i].TranslateToIL(il, Typeob.Int32);
  1860.                     iTemp[i] = il.DeclareLocal(Typeob.Int32);
  1861.                     il.Emit(OpCodes.Dup);
  1862.                     il.Emit(OpCodes.Stloc, iTemp[i]);
  1863.                 }
  1864.                 Type etype = defType.GetElementType();
  1865.                 if (n == 1) {
  1866.                     Binding.TranslateToLdelem(il, etype);
  1867.                 }
  1868.                 else {
  1869.                     Type[] indexTypes = new Type[n];
  1870.                     for (int i = 0; i < n; i++)
  1871.                         indexTypes[i] = Typeob.Int32;
  1872.                     MethodInfo getter = defType.GetMethod("Get", indexTypes);
  1873.                     il.Emit(OpCodes.Call, getter);
  1874.                 }
  1875.                 LocalBuilder eTemp = il.DeclareLocal(etype);
  1876.                 il.Emit(OpCodes.Stloc, eTemp);
  1877.                 for (int i = 0; i < n; i++)
  1878.                     il.Emit(OpCodes.Ldloc, iTemp[i]);
  1879.                 if (n == 1 && etype.IsValueType && !etype.IsPrimitive)
  1880.                     il.Emit(OpCodes.Ldelema, etype);
  1881.                 il.Emit(OpCodes.Ldloc, eTemp);
  1882.                 return;
  1883.             }
  1884.             Debug.Assert(this.isAssignmentToDefaultIndexedProperty);
  1885.             if (this.member != null) {
  1886.                 //Go late bound. It is too much work, for too little gain, to do this early bound
  1887.                 if (this.defaultMember != null) {
  1888.                     this.member = this.defaultMember;
  1889.                     this.defaultMember = null;
  1890.                 }
  1891.             }
  1892.             base.TranslateToILPreSetPlusGet(il, argList, inBrackets);
  1893.         }
  1894.        
  1895.         internal override object TranslateToILReference(ILGenerator il, Type rtype)
  1896.         {
  1897.             if (this.member is FieldInfo) {
  1898.                 FieldInfo field = (FieldInfo)this.member;
  1899.                 Type ftype = field.FieldType;
  1900.                 if (rtype == ftype) {
  1901.                     bool isStatic = field.IsStatic;
  1902.                     if (!isStatic)
  1903.                         this.TranslateToILObject(il, field.DeclaringType, true);
  1904.                     object tok = field is JSField ? ((JSField)field).GetMetaData() : field is JSFieldInfo ? ((JSFieldInfo)field).field : field;
  1905.                     if (tok is FieldInfo)
  1906.                         if (field.IsInitOnly) {
  1907.                             LocalBuilder loc = il.DeclareLocal(ftype);
  1908.                             il.Emit(isStatic ? OpCodes.Ldsfld : OpCodes.Ldfld, (FieldInfo)tok);
  1909.                             il.Emit(OpCodes.Stloc, loc);
  1910.                             il.Emit(OpCodes.Ldloca, loc);
  1911.                         }
  1912.                         else
  1913.                             il.Emit(isStatic ? OpCodes.Ldsflda : OpCodes.Ldflda, (FieldInfo)tok);
  1914.                     else if (tok is LocalBuilder)
  1915.                         il.Emit(OpCodes.Ldloca, (LocalBuilder)tok);
  1916.                     else
  1917.                         il.Emit(OpCodes.Ldarga, (short)tok);
  1918.                     return null;
  1919.                 }
  1920.             }
  1921.             return base.TranslateToILReference(il, rtype);
  1922.         }
  1923.        
  1924.         internal override void TranslateToILSet(ILGenerator il, AST rhvalue)
  1925.         {
  1926.             if (this.isArrayElementAccess) {
  1927.                 IReflect defIR = this.defaultMemberReturnIR;
  1928.                 Type defType = defIR is Type ? (Type)defIR : Convert.ToType(defIR);
  1929.                 Debug.Assert(defType.IsArray);
  1930.                 int n = defType.GetArrayRank();
  1931.                 Type etype = defType.GetElementType();
  1932.                 if (rhvalue != null)
  1933.                     rhvalue.TranslateToIL(il, etype);
  1934.                 if (n == 1) {
  1935.                     Binding.TranslateToStelem(il, etype);
  1936.                 }
  1937.                 else {
  1938.                     Type[] indexTypes = new Type[n + 1];
  1939.                     for (int i = 0; i < n; i++)
  1940.                         indexTypes[i] = Typeob.Int32;
  1941.                     indexTypes[n] = etype;
  1942.                     MethodInfo setter = compilerGlobals.module.GetArrayMethod(defType, "Set", CallingConventions.HasThis, Typeob.Void, indexTypes);
  1943.                     il.Emit(OpCodes.Call, setter);
  1944.                 }
  1945.                 return;
  1946.             }
  1947.             if (this.isAssignmentToDefaultIndexedProperty) {
  1948.                 if (this.member is PropertyInfo && this.defaultMember != null) {
  1949.                     //early bound to default indexed property
  1950.                     PropertyInfo prop = (PropertyInfo)this.member;
  1951.                     MethodInfo meth = JSProperty.GetSetMethod(prop, false);
  1952.                     //Guard against trying to assign to properties on the Global object
  1953.                     JSWrappedMethod wmeth = meth as JSWrappedMethod;
  1954.                     if (wmeth == null || !(wmeth.GetWrappedObject() is GlobalObject)) {
  1955.                         meth = this.GetMethodInfoMetadata(meth);
  1956.                         if (rhvalue != null)
  1957.                             rhvalue.TranslateToIL(il, prop.PropertyType);
  1958.                         if (meth.IsVirtual && !meth.IsFinal && (!meth.ReflectedType.IsSealed || !meth.ReflectedType.IsValueType))
  1959.                             il.Emit(OpCodes.Callvirt, meth);
  1960.                         else
  1961.                             il.Emit(OpCodes.Call, meth);
  1962.                         return;
  1963.                     }
  1964.                 }
  1965.                 base.TranslateToILSet(il, rhvalue);
  1966.                 return;
  1967.             }
  1968.             if (this.member is FieldInfo) {
  1969.                 FieldInfo field = (FieldInfo)this.member;
  1970.                 if (rhvalue != null)
  1971.                     rhvalue.TranslateToIL(il, field.FieldType);
  1972.                 if (field.IsLiteral || field.IsInitOnly) {
  1973.                     il.Emit(OpCodes.Pop);
  1974.                     return;
  1975.                 }
  1976.                 object tok = field is JSField ? ((JSField)field).GetMetaData() : field is JSFieldInfo ? ((JSFieldInfo)field).field : field;
  1977.                 FieldInfo f = tok as FieldInfo;
  1978.                 if (f != null)
  1979.                     il.Emit(f.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, f);
  1980.                 else if (tok is LocalBuilder)
  1981.                     il.Emit(OpCodes.Stloc, (LocalBuilder)tok);
  1982.                 else
  1983.                     il.Emit(OpCodes.Starg, (short)tok);
  1984.                 return;
  1985.             }
  1986.             if (this.member is PropertyInfo) {
  1987.                 PropertyInfo prop = (PropertyInfo)this.member;
  1988.                 if (rhvalue != null)
  1989.                     rhvalue.TranslateToIL(il, prop.PropertyType);
  1990.                 MethodInfo meth = JSProperty.GetSetMethod(prop, true);
  1991.                 if (meth == null) {
  1992.                     il.Emit(OpCodes.Pop);
  1993.                     return;
  1994.                 }
  1995.                 meth = this.GetMethodInfoMetadata(meth);
  1996.                 if (meth.IsStatic && !(meth is JSClosureMethod))
  1997.                     il.Emit(OpCodes.Call, meth);
  1998.                 else {
  1999.                     if (!this.isNonVirtual && meth.IsVirtual && !meth.IsFinal && (!meth.ReflectedType.IsSealed || !meth.ReflectedType.IsValueType))
  2000.                         il.Emit(OpCodes.Callvirt, meth);
  2001.                     else
  2002.                         il.Emit(OpCodes.Call, meth);
  2003.                 }
  2004.                 return;
  2005.             }
  2006.             //do speculative early bound assignments
  2007.             object done = this.TranslateToSpeculativeEarlyBoundSet(il, rhvalue);
  2008.             if (rhvalue != null)
  2009.                 rhvalue.TranslateToIL(il, Typeob.Object);
  2010.             il.Emit(OpCodes.Call, CompilerGlobals.setValueMethod);
  2011.             if (done != null)
  2012.                 il.MarkLabel((Label)done);
  2013.         }
  2014.        
  2015.         protected abstract void TranslateToILWithDupOfThisOb(ILGenerator il);
  2016.        
  2017.         private static void TranslateToLdelem(ILGenerator il, Type etype)
  2018.         {
  2019.             switch (Type.GetTypeCode(etype)) {
  2020.                 case TypeCode.SByte:
  2021.                     il.Emit(OpCodes.Ldelem_I1);
  2022.                     break;
  2023.                 case TypeCode.Boolean:
  2024.                 case TypeCode.Byte:
  2025.                     il.Emit(OpCodes.Ldelem_U1);
  2026.                     break;
  2027.                 case TypeCode.Int16:
  2028.                     il.Emit(OpCodes.Ldelem_I2);
  2029.                     break;
  2030.                 case TypeCode.Char:
  2031.                 case TypeCode.UInt16:
  2032.                     il.Emit(OpCodes.Ldelem_U2);
  2033.                     break;
  2034.                 case TypeCode.Int32:
  2035.                     il.Emit(OpCodes.Ldelem_I4);
  2036.                     break;
  2037.                 case TypeCode.UInt32:
  2038.                     il.Emit(OpCodes.Ldelem_U4);
  2039.                     break;
  2040.                 case TypeCode.Int64:
  2041.                 case TypeCode.UInt64:
  2042.                     il.Emit(OpCodes.Ldelem_I8);
  2043.                     break;
  2044.                 case TypeCode.Single:
  2045.                     il.Emit(OpCodes.Ldelem_R4);
  2046.                     break;
  2047.                 case TypeCode.Double:
  2048.                     il.Emit(OpCodes.Ldelem_R8);
  2049.                     break;
  2050.                 case TypeCode.Decimal:
  2051.                 case TypeCode.DateTime:
  2052.                 case TypeCode.String:
  2053.                 case TypeCode.Object:
  2054.                     if (etype.IsValueType) {
  2055.                         il.Emit(OpCodes.Ldelema, etype);
  2056.                         il.Emit(OpCodes.Ldobj, etype);
  2057.                     }
  2058.                     else
  2059.                         il.Emit(OpCodes.Ldelem_Ref);
  2060.                     break;
  2061.             }
  2062.         }
  2063.        
  2064.         private object TranslateToSpeculativeEarlyBoundSet(ILGenerator il, AST rhvalue)
  2065.         {
  2066.             this.giveErrors = false;
  2067.             object done = null;
  2068.             bool needObject = true;
  2069.             LocalBuilder objectLocal = null;
  2070.             LocalBuilder valueLocal = null;
  2071.             Label next = il.DefineLabel();
  2072.             MemberInfoList members = this.GetAllKnownInstanceBindingsForThisName();
  2073.             for (int i = 0int n = members.count; i < n; i++) {
  2074.                 MemberInfo member = members[i];
  2075.                 FieldInfo field = null;
  2076.                 MethodInfo setter = null;
  2077.                 PropertyInfo prop = null;
  2078.                 if (member is FieldInfo) {
  2079.                     field = (FieldInfo)member;
  2080.                     if (field.IsLiteral || field.IsInitOnly)
  2081.                         continue;
  2082.                 }
  2083.                 else if (member is PropertyInfo) {
  2084.                     prop = (PropertyInfo)member;
  2085.                     if (prop.GetIndexParameters().Length > 0 || (setter = JSProperty.GetSetMethod(prop, true)) == null)
  2086.                         continue;
  2087.                 }
  2088.                 else
  2089.                     continue;
  2090.                 this.member = member;
  2091.                 if (!this.Accessible(true))
  2092.                     continue;
  2093.                 if (needObject) {
  2094.                     needObject = false;
  2095.                     if (rhvalue == null) {
  2096.                         valueLocal = il.DeclareLocal(Typeob.Object);
  2097.                         il.Emit(OpCodes.Stloc, valueLocal);
  2098.                     }
  2099.                     il.Emit(OpCodes.Dup);
  2100.                     il.Emit(OpCodes.Ldfld, CompilerGlobals.objectField);
  2101.                     objectLocal = il.DeclareLocal(Typeob.Object);
  2102.                     il.Emit(OpCodes.Stloc, objectLocal);
  2103.                     done = il.DefineLabel();
  2104.                 }
  2105.                 Type t = member.DeclaringType;
  2106.                 il.Emit(OpCodes.Ldloc, objectLocal);
  2107.                 il.Emit(OpCodes.Isinst, t);
  2108.                 LocalBuilder objectTemp = il.DeclareLocal(t);
  2109.                 il.Emit(OpCodes.Dup);
  2110.                 il.Emit(OpCodes.Stloc, objectTemp);
  2111.                 il.Emit(OpCodes.Brfalse, next);
  2112.                 il.Emit(OpCodes.Ldloc, objectTemp);
  2113.                 if (rhvalue == null)
  2114.                     il.Emit(OpCodes.Ldloc, valueLocal);
  2115.                 if (field != null) {
  2116.                     if (rhvalue == null)
  2117.                         Convert.Emit(this, il, Typeob.Object, field.FieldType);
  2118.                     else
  2119.                         rhvalue.TranslateToIL(il, field.FieldType);
  2120.                     if (field is JSField)
  2121.                         il.Emit(OpCodes.Stfld, (FieldInfo)((JSField)field).GetMetaData());
  2122.                     else if (field is JSFieldInfo)
  2123.                         il.Emit(OpCodes.Stfld, ((JSFieldInfo)field).field);
  2124.                     else
  2125.                         il.Emit(OpCodes.Stfld, field);
  2126.                 }
  2127.                 else {
  2128.                     if (rhvalue == null)
  2129.                         Convert.Emit(this, il, Typeob.Object, prop.PropertyType);
  2130.                     else
  2131.                         rhvalue.TranslateToIL(il, prop.PropertyType);
  2132.                     setter = this.GetMethodInfoMetadata(setter);
  2133.                     if (setter.IsVirtual && !setter.IsFinal && (!t.IsSealed || !t.IsValueType))
  2134.                         il.Emit(OpCodes.Callvirt, setter);
  2135.                     else
  2136.                         il.Emit(OpCodes.Call, setter);
  2137.                 }
  2138.                 il.Emit(OpCodes.Pop);
  2139.                 //Get rid of the LateBound instance
  2140.                 il.Emit(OpCodes.Br, (Label)done);
  2141.                 il.MarkLabel(next);
  2142.                 next = il.DefineLabel();
  2143.             }
  2144.             if (valueLocal != null)
  2145.                 il.Emit(OpCodes.Ldloc, valueLocal);
  2146.             this.member = null;
  2147.             return done;
  2148.         }
  2149.        
  2150.         private object TranslateToSpeculativeEarlyBindings(ILGenerator il, Type rtype, bool getObjectFromLateBindingInstance)
  2151.         {
  2152.             //Find all members named this.name to which the current context might have access to.
  2153.             //Generate early bound access to these, guarded by runtime type checks.
  2154.             this.giveErrors = false;
  2155.             object done = null;
  2156.             bool needObject = true;
  2157.             LocalBuilder objectLocal = null;
  2158.             Label next = il.DefineLabel();
  2159.             MemberInfoList members = this.GetAllKnownInstanceBindingsForThisName();
  2160.             for (int i = 0int n = members.count; i < n; i++) {
  2161.                 MemberInfo member = members[i];
  2162.                 if (!(member is FieldInfo) && (!(member is PropertyInfo) || ((PropertyInfo)member).GetIndexParameters().Length > 0 || JSProperty.GetGetMethod((PropertyInfo)member, true) == null))
  2163.                     continue;
  2164.                 this.member = member;
  2165.                 if (!this.Accessible(false))
  2166.                     continue;
  2167.                 if (needObject) {
  2168.                     needObject = false;
  2169.                     if (getObjectFromLateBindingInstance) {
  2170.                         il.Emit(OpCodes.Dup);
  2171.                         il.Emit(OpCodes.Ldfld, CompilerGlobals.objectField);
  2172.                     }
  2173.                     else
  2174.                         this.TranslateToILObject(il, Typeob.Object, false);
  2175.                     objectLocal = il.DeclareLocal(Typeob.Object);
  2176.                     il.Emit(OpCodes.Stloc, objectLocal);
  2177.                     done = il.DefineLabel();
  2178.                 }
  2179.                 Type t = member.DeclaringType;
  2180.                 il.Emit(OpCodes.Ldloc, objectLocal);
  2181.                 il.Emit(OpCodes.Isinst, t);
  2182.                 LocalBuilder objectTemp = il.DeclareLocal(t);
  2183.                 il.Emit(OpCodes.Dup);
  2184.                 il.Emit(OpCodes.Stloc, objectTemp);
  2185.                 il.Emit(OpCodes.Brfalse_S, next);
  2186.                 il.Emit(OpCodes.Ldloc, objectTemp);
  2187.                 if (member is FieldInfo) {
  2188.                     FieldInfo field = (FieldInfo)member;
  2189.                     if (field.IsLiteral) {
  2190.                         il.Emit(OpCodes.Pop);
  2191.                         continue;
  2192.                         //instance nested class, bail out.
  2193.                     }
  2194.                     if (field is JSField)
  2195.                         il.Emit(OpCodes.Ldfld, (FieldInfo)((JSField)field).GetMetaData());
  2196.                     else if (field is JSFieldInfo)
  2197.                         il.Emit(OpCodes.Ldfld, ((JSFieldInfo)field).field);
  2198.                     else
  2199.                         il.Emit(OpCodes.Ldfld, (FieldInfo)field);
  2200.                     Convert.Emit(this, il, field.FieldType, rtype);
  2201.                 }
  2202.                 else if (member is PropertyInfo) {
  2203.                     MethodInfo getter = JSProperty.GetGetMethod((PropertyInfo)member, true);
  2204.                     getter = this.GetMethodInfoMetadata(getter);
  2205.                     if (getter.IsVirtual && !getter.IsFinal && (!t.IsSealed || t.IsValueType))
  2206.                         il.Emit(OpCodes.Callvirt, getter);
  2207.                     else
  2208.                         il.Emit(OpCodes.Call, getter);
  2209.                     Convert.Emit(this, il, getter.ReturnType, rtype);
  2210.                 }
  2211.                 il.Emit(OpCodes.Br, (Label)done);
  2212.                 il.MarkLabel(next);
  2213.                 next = il.DefineLabel();
  2214.             }
  2215.             il.MarkLabel(next);
  2216.             if (!needObject && !getObjectFromLateBindingInstance)
  2217.                 il.Emit(OpCodes.Ldloc, objectLocal);
  2218.             this.member = null;
  2219.             return done;
  2220.         }
  2221.        
  2222.         private object TranslateToSpeculativeEarlyBoundCalls(ILGenerator il, Type rtype, ASTList argList, bool construct, bool brackets)
  2223.         {
  2224.             this.giveErrors = false;
  2225.             object done = null;
  2226.             bool needObject = true;
  2227.             LocalBuilder objectLocal = null;
  2228.             Label next = il.DefineLabel();
  2229.             IReflect[] classes = this.GetAllEligibleClasses();
  2230.             if (construct) {
  2231.                 //dealing with "new ob.foo(...)" or "new ob.foo[...]".
  2232.                 //Early binding only makes sense if foo is a nested type marked as protected or package
  2233.                 //But nested types are static and hence will not show up late bound via the object.
  2234.                 //There is the possibility that a programmer can declare a static field and initialize it to a type.
  2235.                 //In that case late bound access works if the field is public, but not otherwise.
  2236.                 //This does not seem like a core scenario that justifies a lot of code inside this if statement.
  2237.                 return done;
  2238.             }
  2239.             Debug.Assert(argList.count == 0 || this.argIRs.Length == argList.count);
  2240.             foreach (IReflect c in classes) {
  2241.                 MemberInfo[] members = c.GetMember(this.name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
  2242.                 try {
  2243.                     // This code generation does not account for the case ob.foo(...) where ob.foo is a property
  2244.                     // with zero arguments. The code should get the property followed by a call on the
  2245.                     // returned object. For this case, we don't emit the speculative IL and let the late bound
  2246.                     // code handle it.
  2247.                     MethodInfo meth;
  2248.                     MemberInfo mem = JSBinder.SelectCallableMember(members, this.argIRs);
  2249.                     if (mem != null && mem.MemberType == MemberTypes.Property) {
  2250.                         ParameterInfo[] parameters;
  2251.                         meth = ((PropertyInfo)mem).GetGetMethod(true);
  2252.                         if (meth == null || (parameters = meth.GetParameters()) == null || parameters.Length == 0)
  2253.                             continue;
  2254.                     }
  2255.                     else
  2256.                         meth = mem as MethodInfo;
  2257.                    
  2258.                     if (meth != null) {
  2259.                         if (!Binding.CheckParameters(meth.GetParameters(), this.argIRs, argList, this.context, 0, true, false))
  2260.                             continue;
  2261.                         //If meth is a base class method or if meth is an override of a base class method and the base class is in the same package as c
  2262.                         //there is no need to have an instance check for c
  2263.                         if (meth is JSFieldMethod) {
  2264.                             FunctionObject func = ((JSFieldMethod)meth).func;
  2265.                             if (func != null && (func.attributes & MethodAttributes.NewSlot) == 0 && ((ClassScope)c).ParentIsInSamePackage())
  2266.                                 continue;
  2267.                         }
  2268.                         else if (meth is JSWrappedMethod && ((JSWrappedMethod)meth).obj is ClassScope && ((JSWrappedMethod)meth).GetPackage() == ((ClassScope)c).package)
  2269.                             continue;
  2270.                         this.member = meth;
  2271.                         if (!this.Accessible(false))
  2272.                             continue;
  2273.                         if (needObject) {
  2274.                             needObject = false;
  2275.                             this.TranslateToILObject(il, Typeob.Object, false);
  2276.                             objectLocal = il.DeclareLocal(Typeob.Object);
  2277.                             il.Emit(OpCodes.Stloc, objectLocal);
  2278.                             done = il.DefineLabel();
  2279.                         }
  2280.                         Type t = meth.DeclaringType;
  2281.                         il.Emit(OpCodes.Ldloc, objectLocal);
  2282.                         il.Emit(OpCodes.Isinst, t);
  2283.                         LocalBuilder objectTemp = il.DeclareLocal(t);
  2284.                         il.Emit(OpCodes.Dup);
  2285.                         il.Emit(OpCodes.Stloc, objectTemp);
  2286.                         il.Emit(OpCodes.Brfalse, next);
  2287.                         il.Emit(OpCodes.Ldloc, objectTemp);
  2288.                         Binding.PlaceArgumentsOnStack(il, meth.GetParameters(), argList, 0, 0, Binding.ReflectionMissingCW);
  2289.                         meth = this.GetMethodInfoMetadata(meth);
  2290.                         if (meth.IsVirtual && !meth.IsFinal && (!t.IsSealed || t.IsValueType))
  2291.                             il.Emit(OpCodes.Callvirt, meth);
  2292.                         else
  2293.                             il.Emit(OpCodes.Call, meth);
  2294.                         Convert.Emit(this, il, meth.ReturnType, rtype);
  2295.                         il.Emit(OpCodes.Br, (Label)done);
  2296.                         il.MarkLabel(next);
  2297.                         next = il.DefineLabel();
  2298.                     }
  2299.                 }
  2300.                 catch (AmbiguousMatchException) {
  2301.                 }
  2302.             }
  2303.             il.MarkLabel(next);
  2304.             if (!needObject)
  2305.                 il.Emit(OpCodes.Ldloc, objectLocal);
  2306.             this.member = null;
  2307.             return done;
  2308.         }
  2309.        
  2310.         static internal void TranslateToStelem(ILGenerator il, Type etype)
  2311.         {
  2312.             switch (Type.GetTypeCode(etype)) {
  2313.                 case TypeCode.SByte:
  2314.                 case TypeCode.Boolean:
  2315.                 case TypeCode.Byte:
  2316.                     il.Emit(OpCodes.Stelem_I1);
  2317.                     break;
  2318.                 case TypeCode.Int16:
  2319.                 case TypeCode.Char:
  2320.                 case TypeCode.UInt16:
  2321.                     il.Emit(OpCodes.Stelem_I2);
  2322.                     break;
  2323.                 case TypeCode.Int32:
  2324.                 case TypeCode.UInt32:
  2325.                     il.Emit(OpCodes.Stelem_I4);
  2326.                     break;
  2327.                 case TypeCode.Int64:
  2328.                 case TypeCode.UInt64:
  2329.                     il.Emit(OpCodes.Stelem_I8);
  2330.                     break;
  2331.                 case TypeCode.Single:
  2332.                     il.Emit(OpCodes.Stelem_R4);
  2333.                     break;
  2334.                 case TypeCode.Double:
  2335.                     il.Emit(OpCodes.Stelem_R8);
  2336.                     break;
  2337.                 case TypeCode.Decimal:
  2338.                 case TypeCode.DateTime:
  2339.                 case TypeCode.String:
  2340.                 case TypeCode.Object:
  2341.                     if (etype.IsValueType) {
  2342.                         il.Emit(OpCodes.Stobj, etype);
  2343.                     }
  2344.                     else
  2345.                         il.Emit(OpCodes.Stelem_Ref);
  2346.                     break;
  2347.             }
  2348.         }
  2349.        
  2350.         private void WarnIfNotFullyResolved()
  2351.         {
  2352.             if (this.isFullyResolved || this.member == null)
  2353.                 return;
  2354.             if (this.member is JSVariableField && ((JSVariableField)this.member).type == null)
  2355.                 return;
  2356.             if (!this.Engine.doFast && this.member is IWrappedMember)
  2357.                 return;
  2358.             ScriptObject scope = Globals.ScopeStack.Peek();
  2359.             while (scope != null) {
  2360.                 if (scope is WithObject && !((WithObject)scope).isKnownAtCompileTime) {
  2361.                     this.context.HandleError(JSError.AmbiguousBindingBecauseOfWith);
  2362.                     return;
  2363.                 }
  2364.                 else if (scope is ActivationObject && !((ActivationObject)scope).isKnownAtCompileTime) {
  2365.                     this.context.HandleError(JSError.AmbiguousBindingBecauseOfEval);
  2366.                     return;
  2367.                 }
  2368.                 scope = scope.GetParent();
  2369.             }
  2370.         }
  2371.        
  2372.         private void WarnIfObsolete()
  2373.         {
  2374.             Binding.WarnIfObsolete(this.member, this.context);
  2375.         }
  2376.        
  2377.         static internal void WarnIfObsolete(MemberInfo member, Context context)
  2378.         {
  2379.             if (member == null)
  2380.                 return;
  2381.             string message = null;
  2382.             bool isError = false;
  2383.             object[] custAttribs = CustomAttribute.GetCustomAttributes(member, typeof(ObsoleteAttribute), false);
  2384.             if (custAttribs != null && custAttribs.Length > 0) {
  2385.                 ObsoleteAttribute attr = (ObsoleteAttribute)custAttribs[0];
  2386.                 message = attr.Message;
  2387.                 isError = attr.IsError;
  2388.             }
  2389.             else {
  2390.                 custAttribs = CustomAttribute.GetCustomAttributes(member, typeof(NotRecommended), false);
  2391.                 if (custAttribs != null && custAttribs.Length > 0) {
  2392.                     NotRecommended attr = (NotRecommended)custAttribs[0];
  2393.                     message = ": " + attr.Message;
  2394.                     isError = false;
  2395.                 }
  2396.                 else
  2397.                     return;
  2398.             }
  2399.             context.HandleError(JSError.Deprecated, message, isError);
  2400.            
  2401.         }
  2402.        
  2403.         private MethodInfo GetMethodInfoMetadata(MethodInfo method)
  2404.         {
  2405.             if (method is JSMethod)
  2406.                 return ((JSMethod)method).GetMethodInfo(this.compilerGlobals);
  2407.             if (method is JSMethodInfo)
  2408.                 return ((JSMethodInfo)method).method;
  2409.             return method;
  2410.         }
  2411.     }
  2412. }

Developer Fusion