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

  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 Microsoft.JScript.Vsa;
  19.     using System;
  20.     using System.Collections;
  21.     using System.Diagnostics;
  22.     using System.Globalization;
  23.     using System.Reflection;
  24.    
  25.     [System.Runtime.InteropServices.ComVisible(true)]
  26.     public abstract class ScriptObject : IReflect
  27.     {
  28.         protected ScriptObject parent;
  29.        
  30.         //Used by JSObject.GetMembers to cache members that must be delegated to other objects
  31.         internal SimpleHashtable wrappedMemberCache;
  32.        
  33.         public VsaEngine engine;
  34.         //This is only really useful for ScriptFunctions, IActivation objects and prototype objects. It lives here for the sake of simplicity.
  35.         //Prototype objects do not need the scope stack, so in fast mode, all prototype objects can share a common engine.
  36.         internal ScriptObject(ScriptObject parent)
  37.         {
  38.             this.parent = parent;
  39.             this.wrappedMemberCache = null;
  40.             if (this.parent != null)
  41.                 this.engine = parent.engine;
  42.             else
  43.                 this.engine = null;
  44.         }
  45.        
  46.         internal virtual bool DeleteMember(string name)
  47.         {
  48.             return false;
  49.         }
  50.        
  51.         internal virtual object GetDefaultValue(PreferredType preferred_type)
  52.         {
  53.             throw new JScriptException(JSError.InternalError);
  54.         }
  55.        
  56.         public FieldInfo GetField(string name, BindingFlags bindingAttr)
  57.         {
  58.             foreach (MemberInfo member in this.GetMember(name, bindingAttr))
  59.                 if (member.MemberType == MemberTypes.Field)
  60.                     return (FieldInfo)member;
  61.             return null;
  62.         }
  63.        
  64.         public virtual FieldInfo[] GetFields(BindingFlags bindingAttr)
  65.         {
  66.             ArrayObject arr = this as ArrayObject;
  67.             if (arr != null && arr.denseArrayLength > 0) {
  68.                 //Interop fails to see elements unless they are returned in a GetXXXs call. An element in
  69.                 //the sparse portion of the array is returned as a FieldInfo. When interop asks for these
  70.                 //migrate the elements stored in the dense portion of the array to the sparse portion so that
  71.                 //they will be accessible.
  72.                 uint i;
  73.                 uint length;
  74.                 length = arr.denseArrayLength;
  75.                 if (length > arr.len)
  76.                     length = arr.len;
  77.                 for (i = 0; i < length; i++) {
  78.                     object element = arr.denseArray[i];
  79.                     if (element != Missing.Value)
  80.                         arr.SetMemberValue2(i.ToString(CultureInfo.InvariantCulture), element);
  81.                     //Implemented on JSObject and bypasses length checking
  82.                 }
  83.                 arr.denseArrayLength = 0;
  84.                 arr.denseArray = null;
  85.             }
  86.            
  87.             MemberInfo[] members = this.GetMembers(bindingAttr);
  88.             if (members == null)
  89.                 return new FieldInfo[0];
  90.             int fieldCount = 0;
  91.             foreach (MemberInfo member in members)
  92.                 if (member.MemberType == MemberTypes.Field)
  93.                     fieldCount++;
  94.             FieldInfo[] fields = new FieldInfo[fieldCount];
  95.             fieldCount = 0;
  96.             foreach (MemberInfo member in members)
  97.                 if (member.MemberType == MemberTypes.Field)
  98.                     fields[fieldCount++] = (FieldInfo)member;
  99.             return fields;
  100.         }
  101.        
  102.         public abstract MemberInfo[] GetMember(string name, BindingFlags bindingAttr);
  103.        
  104.         internal virtual object GetMemberValue(string name)
  105.         {
  106.             MemberInfo[] members = this.GetMember(name, BindingFlags.Instance | BindingFlags.Public);
  107.             if (members.Length == 0)
  108.                 return Missing.Value;
  109.             return LateBinding.GetMemberValue(this, name, LateBinding.SelectMember(members), members);
  110.         }
  111.        
  112.         public abstract MemberInfo[] GetMembers(BindingFlags bindingAttr);
  113.        
  114.         public MethodInfo GetMethod(string name, BindingFlags bindingAttr)
  115.         {
  116.             return this.GetMethod(name, bindingAttr, JSBinder.ob, Type.EmptyTypes, null);
  117.         }
  118.        
  119.         public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)
  120.         {
  121.             MemberInfo[] members = this.GetMember(name, bindingAttr);
  122.             if (members.Length == 1)
  123.                 return members[0] as MethodInfo;
  124.             int methodCount = 0;
  125.             foreach (MemberInfo member in members)
  126.                 if (member.MemberType == MemberTypes.Method)
  127.                     methodCount++;
  128.             if (methodCount == 0)
  129.                 return null;
  130.             MethodInfo[] methods = new MethodInfo[methodCount];
  131.             methodCount = 0;
  132.             foreach (MemberInfo member in members)
  133.                 if (member.MemberType == MemberTypes.Method)
  134.                     methods[methodCount++] = (MethodInfo)member;
  135.             if (binder == null)
  136.                 binder = JSBinder.ob;
  137.             return (MethodInfo)binder.SelectMethod(bindingAttr, methods, types, modifiers);
  138.         }
  139.        
  140.         public virtual MethodInfo[] GetMethods(BindingFlags bindingAttr)
  141.         {
  142.             MemberInfo[] members = this.GetMembers(bindingAttr);
  143.             if (members == null)
  144.                 return new MethodInfo[0];
  145.             int methodCount = 0;
  146.             foreach (MemberInfo member in members)
  147.                 if (member.MemberType == MemberTypes.Method)
  148.                     methodCount++;
  149.             MethodInfo[] methods = new MethodInfo[methodCount];
  150.             methodCount = 0;
  151.             foreach (MemberInfo member in members)
  152.                 if (member.MemberType == MemberTypes.Method)
  153.                     methods[methodCount++] = (MethodInfo)member;
  154.             return methods;
  155.         }
  156.        
  157.         //Returns the parent object (the object to which the script object delegates requests for properties/methods it does not implement itself).
  158.         public ScriptObject GetParent()
  159.         {
  160.             return this.parent;
  161.         }
  162.        
  163.         internal virtual void GetPropertyEnumerator(ArrayList enums, ArrayList objects)
  164.         {
  165.             MemberInfo[] members = this.GetMembers(BindingFlags.Instance | BindingFlags.Public);
  166.             if (members.Length > 0) {
  167.                 enums.Add(members.GetEnumerator());
  168.                 objects.Add(this);
  169.             }
  170.             ScriptObject parent = this.GetParent();
  171.             if (parent != null)
  172.                 parent.GetPropertyEnumerator(enums, objects);
  173.         }
  174.        
  175.         public PropertyInfo GetProperty(string name, BindingFlags bindingAttr)
  176.         {
  177.             return this.GetProperty(name, bindingAttr, JSBinder.ob, null, Type.EmptyTypes, null);
  178.         }
  179.        
  180.         public PropertyInfo GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
  181.         {
  182.             MemberInfo[] members = this.GetMember(name, bindingAttr);
  183.             if (members.Length == 1)
  184.                 return members[0] as PropertyInfo;
  185.             int propertyCount = 0;
  186.             foreach (MemberInfo member in members)
  187.                 if (member.MemberType == MemberTypes.Property)
  188.                     propertyCount++;
  189.             if (propertyCount == 0)
  190.                 return null;
  191.             PropertyInfo[] properties = new PropertyInfo[propertyCount];
  192.             propertyCount = 0;
  193.             foreach (MemberInfo member in members)
  194.                 if (member.MemberType == MemberTypes.Property)
  195.                     properties[propertyCount++] = (PropertyInfo)member;
  196.             if (binder == null)
  197.                 binder = JSBinder.ob;
  198.             return (PropertyInfo)binder.SelectProperty(bindingAttr, properties, returnType, types, modifiers);
  199.         }
  200.        
  201.         public virtual PropertyInfo[] GetProperties(BindingFlags bindingAttr)
  202.         {
  203.             MemberInfo[] members = this.GetMembers(bindingAttr);
  204.             if (members == null)
  205.                 return new PropertyInfo[0];
  206.             int propertyCount = 0;
  207.             foreach (MemberInfo member in members)
  208.                 if (member.MemberType == MemberTypes.Property)
  209.                     propertyCount++;
  210.             PropertyInfo[] properties = new PropertyInfo[propertyCount];
  211.             propertyCount = 0;
  212.             foreach (MemberInfo member in members)
  213.                 if (member.MemberType == MemberTypes.Property)
  214.                     properties[propertyCount++] = (PropertyInfo)member;
  215.             return properties;
  216.         }
  217.        
  218.         internal virtual object GetValueAtIndex(uint index)
  219.         {
  220.             return this.GetMemberValue(index.ToString(CultureInfo.CurrentUICulture));
  221.         }
  222.        
  223.         #if !DEBUG
  224.         [DebuggerStepThroughAttribute()]
  225.         [DebuggerHiddenAttribute()]
  226.         #endif
  227.         public virtual object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo locale, string[] namedParameters)
  228.         {
  229.             if (target != this)
  230.                 throw new TargetException();
  231.            
  232.             bool preferredTypeSpecified = name.StartsWith("< JScript-", StringComparison.Ordinal);
  233.             bool dispid0 = (name == null || name == String.Empty || name.Equals("[DISPID=0]") || preferredTypeSpecified);
  234.            
  235.             if ((invokeAttr & BindingFlags.CreateInstance) != 0) {
  236.                 if ((invokeAttr & (BindingFlags.InvokeMethod | BindingFlags.GetField | BindingFlags.GetProperty | BindingFlags.SetField | BindingFlags.SetProperty | BindingFlags.PutDispProperty)) != 0)
  237.                     throw new ArgumentException(JScriptException.Localize("Bad binding flags", locale));
  238.                 //js: x = new foo() --> dispid0, create
  239.                 if (dispid0)
  240.                     throw new MissingMethodException();
  241.                
  242.                 //js: x = new foo.name() --> dispid0, create
  243.                 LateBinding lb = new LateBinding(name, this);
  244.                 return lb.Call(binder, args, modifiers, locale, namedParameters, true, false, this.engine);
  245.             }
  246.            
  247.             //According to docs, name == null is only valid for CreateInstance
  248.             if (name == null)
  249.                 throw new ArgumentException(JScriptException.Localize("Bad name", locale));
  250.            
  251.             if ((invokeAttr & (BindingFlags.InvokeMethod | BindingFlags.GetField | BindingFlags.GetProperty)) != 0) {
  252.                 if ((invokeAttr & (BindingFlags.SetField | BindingFlags.SetProperty | BindingFlags.PutDispProperty)) != 0)
  253.                     throw new ArgumentException(JScriptException.Localize("Bad binding flags", locale));
  254.                
  255.                 if (dispid0) {
  256.                     //All callable functions inherit from ScriptFunction which overrides this method to handle
  257.                     //the InvokeMethod case.
  258.                    
  259.                     //js,vbs: x = foo() --> dispid0, invoke
  260.                     if ((invokeAttr & (BindingFlags.GetField | BindingFlags.GetProperty)) == 0)
  261.                         throw new MissingMethodException();
  262.                    
  263.                     //js: x = foo --> dispid0, propget; vbs: x = foo --> dispid0, invoke|propget
  264.                     if (args == null || args.Length == 0) {
  265.                         if (this is JSObject || this is GlobalScope || this is ClassScope) {
  266.                             PreferredType preferredType = PreferredType.Either;
  267.                             if (preferredTypeSpecified) {
  268.                                 if (name.StartsWith("< JScript-Number", StringComparison.Ordinal))
  269.                                     preferredType = PreferredType.Number;
  270.                                 else if (name.StartsWith("< JScript-String", StringComparison.Ordinal))
  271.                                     preferredType = PreferredType.String;
  272.                                 else if (name.StartsWith("< JScript-LocaleString", StringComparison.Ordinal))
  273.                                     preferredType = PreferredType.LocaleString;
  274.                             }
  275.                             return this.GetDefaultValue(preferredType);
  276.                         }
  277.                         throw new MissingFieldException();
  278.                     }
  279.                    
  280.                     //We support indexed properties with exactly one index on all script objects.
  281.                    
  282.                     //js,vbs: x = foo(1,2) --> dispid0, invoke|propget
  283.                     if (args.Length > 1)
  284.                         throw new ArgumentException(JScriptException.Localize("Too many arguments", locale));
  285.                    
  286.                     //js,vbs: x = foo(1) --> dispid0, invoke|propget
  287.                     object val = args[0];
  288.                     if (val is Int32)
  289.                         return this[(int)val];
  290.                     IConvertible ic = Convert.GetIConvertible(val);
  291.                     if (ic != null && Convert.IsPrimitiveNumericTypeCode(ic.GetTypeCode())) {
  292.                         double d = ic.ToDouble(null);
  293.                         if (d >= 0 && d <= Int32.MaxValue && d == System.Math.Round(d))
  294.                             return this[(int)d];
  295.                     }
  296.                     return this[Convert.ToString(val)];
  297.                 }
  298.                
  299.                 //If no arguments are supplied, prefer GetXXXX rather than Invoke.
  300.                 //js: x = foo.bar --> name="bar", propget; vbs: x = foo.bar --> name="bar", propget|invoke
  301.                 if ((args == null || args.Length == 0) && (invokeAttr & (BindingFlags.GetField | BindingFlags.GetProperty)) != 0) {
  302.                     object member = this.GetMemberValue(name);
  303.                     if (member != Missing.Value)
  304.                         return member;
  305.                    
  306.                     //js: x = foo.bar --> name="bar", propget
  307.                     if ((invokeAttr & BindingFlags.InvokeMethod) == 0)
  308.                         throw new MissingFieldException();
  309.                 }
  310.                
  311.                 //Use LateBinding to call because arguments have been supplied.
  312.                 //vbs: x = foo.bar --> name="bar", propget|invoke
  313.                 //js,vbs: x = foo.bar() --> name="bar", invoke
  314.                 //js,vbs: x = foo.bar(1) --> name="bar", invoke|propget
  315.                 LateBinding lb = new LateBinding(name, this);
  316.                 return lb.Call(binder, args, modifiers, locale, namedParameters, false, false, this.engine);
  317.             }
  318.            
  319.             if ((invokeAttr & (BindingFlags.SetField | BindingFlags.SetProperty | BindingFlags.PutDispProperty)) != 0) {
  320.                 if (dispid0) {
  321.                     if (args == null || args.Length < 2)
  322.                         throw new ArgumentException(JScriptException.Localize("Too few arguments", locale));
  323.                     else if (args.Length > 2)
  324.                         throw new ArgumentException(JScriptException.Localize("Too many arguments", locale));
  325.                     object val = args[0];
  326.                     if (val is Int32) {
  327.                         this[(int)val] = args[1];
  328.                         return null;
  329.                     }
  330.                     IConvertible ic = Convert.GetIConvertible(val);
  331.                     if (ic != null && Convert.IsPrimitiveNumericTypeCode(ic.GetTypeCode())) {
  332.                         double d = ic.ToDouble(null);
  333.                         if (d >= 0 && d <= Int32.MaxValue && d == System.Math.Round(d)) {
  334.                             this[(int)d] = args[1];
  335.                             return null;
  336.                         }
  337.                     }
  338.                     this[Convert.ToString(val)] = args[1];
  339.                     return null;
  340.                 }
  341.                 if (args == null || args.Length < 1)
  342.                     throw new ArgumentException(JScriptException.Localize("Too few arguments", locale));
  343.                 else if (args.Length > 1)
  344.                     throw new ArgumentException(JScriptException.Localize("Too many arguments", locale));
  345.                 this.SetMemberValue(name, args[0]);
  346.                 return null;
  347.             }
  348.            
  349.             throw new ArgumentException(JScriptException.Localize("Bad binding flags", locale));
  350.         }
  351.        
  352.         //This routine combines a GetField/GetProperty (with expando) and a subsequent SetValue operation.
  353.         //It is used when the Field/Property cannot be cached. It is overridden by JSObject and GlobalScope to provide expando
  354.         internal virtual void SetMemberValue(string name, object value)
  355.         {
  356.             MemberInfo[] members = this.GetMember(name, BindingFlags.Instance | BindingFlags.Public);
  357.             LateBinding.SetMemberValue(this, name, value, LateBinding.SelectMember(members), members);
  358.         }
  359.        
  360.         internal void SetParent(ScriptObject parent)
  361.         {
  362.             this.parent = parent;
  363.             if (parent != null)
  364.                 this.engine = parent.engine;
  365.         }
  366.        
  367.         //This routine combines a GetField/GetProperty and a subsequent SetValue operation.
  368.         //It is used when the Field/Property cannot be cached.
  369.         //It has the advantage that Arrays need never create a JSField object to access array elements.
  370.         //Also, it avoids the need to convert the index into a string.
  371.         internal virtual void SetValueAtIndex(uint index, object value)
  372.         {
  373.             this.SetMemberValue(index.ToString(CultureInfo.InvariantCulture), value);
  374.         }
  375.        
  376.         public object this[double index]
  377.         {
  378.             get {
  379.                 if (this == null)
  380.                     throw new JScriptException(JSError.ObjectExpected);
  381.                 object result;
  382.                 if (index >= 0 && index <= UInt32.MaxValue && index == System.Math.Round(index))
  383.                     result = this.GetValueAtIndex((uint)index);
  384.                 else
  385.                     result = this.GetMemberValue(Convert.ToString(index));
  386.                 return result is Missing ? null : result;
  387.             }
  388.             set {
  389.                 if (index >= 0 && index <= UInt32.MaxValue && index == System.Math.Round(index))
  390.                     this.SetValueAtIndex((uint)index, value);
  391.                 else
  392.                     this.SetMemberValue(Convert.ToString(index), value);
  393.             }
  394.         }
  395.        
  396.         public object this[int index]
  397.         {
  398.             get {
  399.                 if (this == null)
  400.                     throw new JScriptException(JSError.ObjectExpected);
  401.                 object result;
  402.                 if (index >= 0)
  403.                     result = this.GetValueAtIndex((uint)index);
  404.                 else
  405.                     result = this.GetMemberValue(Convert.ToString(index));
  406.                 return result is Missing ? null : result;
  407.             }
  408.             set {
  409.                 if (this == null)
  410.                     throw new JScriptException(JSError.ObjectExpected);
  411.                 if (index >= 0)
  412.                     this.SetValueAtIndex((uint)index, value);
  413.                 else
  414.                     this.SetMemberValue(Convert.ToString(index), value);
  415.             }
  416.         }
  417.        
  418.         public object this[string name]
  419.         {
  420.             get {
  421.                 if (this == null)
  422.                     throw new JScriptException(JSError.ObjectExpected);
  423.                 object result = this.GetMemberValue(name);
  424.                 return result is Missing ? null : result;
  425.             }
  426.             set {
  427.                 if (this == null)
  428.                     throw new JScriptException(JSError.ObjectExpected);
  429.                 this.SetMemberValue(name, value);
  430.             }
  431.         }
  432.        
  433.         public object this[params object[] pars]
  434.         {
  435.             get {
  436.                 int n = pars.Length;
  437.                 if (n == 0)
  438.                     if (this is ScriptFunction || this == null)
  439.                         throw new JScriptException(JSError.FunctionExpected);
  440.                     else
  441.                         throw new JScriptException(JSError.TooFewParameters);
  442.                 if (this == null)
  443.                     throw new JScriptException(JSError.ObjectExpected);
  444.                 object val = pars[n - 1];
  445.                 if (val is Int32)
  446.                     return this[(int)val];
  447.                 IConvertible ic = Convert.GetIConvertible(val);
  448.                 if (ic != null && Convert.IsPrimitiveNumericTypeCode(ic.GetTypeCode())) {
  449.                     double d = ic.ToDouble(null);
  450.                     if (d >= 0 && d <= Int32.MaxValue && d == System.Math.Round(d))
  451.                         return this[(int)d];
  452.                 }
  453.                 return this[Convert.ToString(val)];
  454.             }
  455.             set {
  456.                 int n = pars.Length;
  457.                 if (n == 0)
  458.                     if (this == null)
  459.                         throw new JScriptException(JSError.FunctionExpected);
  460.                     else if (this is ScriptFunction)
  461.                         throw new JScriptException(JSError.CannotAssignToFunctionResult);
  462.                     else
  463.                         throw new JScriptException(JSError.TooFewParameters);
  464.                 if (this == null)
  465.                     throw new JScriptException(JSError.ObjectExpected);
  466.                 object val = pars[n - 1];
  467.                 if (val is Int32) {
  468.                     this[(int)val] = value;
  469.                     return;
  470.                 }
  471.                 IConvertible ic = Convert.GetIConvertible(val);
  472.                 if (ic != null && Convert.IsPrimitiveNumericTypeCode(ic.GetTypeCode())) {
  473.                     double d = ic.ToDouble(null);
  474.                     if (d >= 0 && d <= Int32.MaxValue && d == System.Math.Round(d)) {
  475.                         this[(int)d] = value;
  476.                         return;
  477.                     }
  478.                 }
  479.                 this[Convert.ToString(val)] = value;
  480.             }
  481.         }
  482.        
  483.         public virtual Type UnderlyingSystemType {
  484.             get { return this.GetType(); }
  485.         }
  486.        
  487.         protected static MemberInfo[] WrapMembers(MemberInfo[] members, object obj)
  488.         {
  489.             if (members == null)
  490.                 return null;
  491.             int n = members.Length;
  492.             if (n == 0)
  493.                 return members;
  494.             MemberInfo[] result = new MemberInfo[n];
  495.             for (int i = 0; i < n; i++)
  496.                 result[i] = ScriptObject.WrapMember(members[i], obj);
  497.             return result;
  498.         }
  499.        
  500.         protected static MemberInfo[] WrapMembers(MemberInfo member, object obj)
  501.         {
  502.             MemberInfo[] result = new MemberInfo[1];
  503.             result[0] = ScriptObject.WrapMember(member, obj);
  504.             return result;
  505.         }
  506.        
  507.         protected static MemberInfo[] WrapMembers(MemberInfo[] members, object obj, SimpleHashtable cache)
  508.         {
  509.             if (members == null)
  510.                 return null;
  511.             int n = members.Length;
  512.             if (n == 0)
  513.                 return members;
  514.             MemberInfo[] result = new MemberInfo[n];
  515.             for (int i = 0; i < n; i++) {
  516.                 MemberInfo wrappedMember = (MemberInfo)cache[members[i]];
  517.                 if (null == wrappedMember) {
  518.                     wrappedMember = ScriptObject.WrapMember(members[i], obj);
  519.                     cache[members[i]] = wrappedMember;
  520.                 }
  521.                 result[i] = wrappedMember;
  522.             }
  523.             return result;
  524.         }
  525.        
  526.         static internal MemberInfo WrapMember(MemberInfo member, object obj)
  527.         {
  528.             switch (member.MemberType) {
  529.                 case MemberTypes.Field:
  530.                     FieldInfo field = (FieldInfo)member;
  531.                     if (field.IsStatic || field.IsLiteral)
  532.                         return field;
  533.                     else if (!(field is JSWrappedField))
  534.                         return new JSWrappedField(field, obj);
  535.                     else
  536.                         return field;
  537.                     break;
  538.                 case MemberTypes.Method:
  539.                     MethodInfo method = (MethodInfo)member;
  540.                     if (method.IsStatic)
  541.                         return method;
  542.                     else if (!(method is JSWrappedMethod))
  543.                         return new JSWrappedMethod(method, obj);
  544.                     else
  545.                         return method;
  546.                     break;
  547.                 case MemberTypes.Property:
  548.                     PropertyInfo property = (PropertyInfo)member;
  549.                     if (property is JSWrappedProperty)
  550.                         return property;
  551.                     MethodInfo getMethod = JSProperty.GetGetMethod(property, true);
  552.                     MethodInfo setMethod = JSProperty.GetSetMethod(property, true);
  553.                     if ((getMethod == null || getMethod.IsStatic) && (setMethod == null || setMethod.IsStatic))
  554.                         return property;
  555.                     else
  556.                         return new JSWrappedProperty(property, obj);
  557.                     break;
  558.                 default:
  559.                     return member;
  560.             }
  561.         }
  562.     }
  563. }

Developer Fusion