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

  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. /*
  16. This class keeps track of the members of classes for compile-time purposes.
  17. It is also used at run-time, by the Evaluator, to store field instance values.
  18. expandoValue and Clone have to do with the latter usage.
  19. */
  20. namespace Microsoft.JScript
  21. {
  22.     using System;
  23.     using System.Collections;
  24.     using System.Globalization;
  25.     using System.Reflection;
  26.    
  27.     internal sealed class JSMemberField : JSVariableField
  28.     {
  29.         private object expandoValue;
  30.         internal JSMemberField nextOverload;
  31.        
  32.         internal JSMemberField(ClassScope obj, string name, object value, FieldAttributes attributeFlags) : base(name, obj, attributeFlags)
  33.         {
  34.             this.value = value;
  35.             this.nextOverload = null;
  36.         }
  37.        
  38.         internal JSMemberField AddOverload(FunctionObject func, FieldAttributes attributeFlags)
  39.         {
  40.             JSMemberField last = this;
  41.             while (last.nextOverload != null)
  42.                 last = last.nextOverload;
  43.             JSMemberField f = last.nextOverload = new JSMemberField((ClassScope)this.obj, this.Name, func, attributeFlags);
  44.             f.type = this.type;
  45.             return f;
  46.         }
  47.        
  48.         internal void AddOverloadedMembers(MemberInfoList mems, ClassScope scope, BindingFlags attrs)
  49.         {
  50.             JSMemberField field = this;
  51.             while (field != null) {
  52.                 MethodInfo meth = ((JSMemberField)field).GetAsMethod(scope);
  53.                 if (meth.IsStatic) {
  54.                     if ((attrs & BindingFlags.Static) == 0)
  55.                         goto next;
  56.                 }
  57.                 else {
  58.                     if ((attrs & BindingFlags.Instance) == 0)
  59.                         goto next;
  60.                 }
  61.                 if (meth.IsPublic) {
  62.                     if ((attrs & BindingFlags.Public) == 0)
  63.                         goto next;
  64.                 }
  65.                 else {
  66.                     if ((attrs & BindingFlags.NonPublic) == 0)
  67.                         goto next;
  68.                 }
  69.                 mems.Add(meth);
  70.                 next:
  71.                 field = field.nextOverload;
  72.             }
  73.             if ((attrs & BindingFlags.DeclaredOnly) != 0 && (attrs & BindingFlags.FlattenHierarchy) == 0)
  74.                 return;
  75.             IReflect superClass = scope.GetSuperType();
  76.             MemberInfo[] supMembers = superClass.GetMember(this.Name, attrs & ~BindingFlags.DeclaredOnly);
  77.             foreach (MemberInfo supMember in supMembers)
  78.                 if (supMember.MemberType == MemberTypes.Method)
  79.                     mems.Add(supMember);
  80.         }
  81.        
  82.         public override FieldAttributes Attributes {
  83.             get {
  84.                 if ((this.attributeFlags & FieldAttributes.Literal) != 0) {
  85.                     if (this.value is FunctionObject && !((FunctionObject)this.value).isStatic)
  86.                         return this.attributeFlags;
  87.                     else if (this.value is JSProperty) {
  88.                         JSProperty prop = (JSProperty)value;
  89.                         if (prop.getter != null && !(prop.getter.IsStatic))
  90.                             return this.attributeFlags;
  91.                         if (prop.setter != null && !(prop.setter.IsStatic))
  92.                             return this.attributeFlags;
  93.                     }
  94.                     else
  95.                         return this.attributeFlags;
  96.                     return this.attributeFlags | FieldAttributes.Static;
  97.                 }
  98.                 return this.attributeFlags;
  99.             }
  100.         }
  101.        
  102.         internal void CheckOverloadsForDuplicates()
  103.         {
  104.             JSMemberField current = this;
  105.             while (current != null) {
  106.                 FunctionObject func = current.value as FunctionObject;
  107.                 if (func == null)
  108.                     return;
  109.                 for (JSMemberField next = current.nextOverload; next != null; next = next.nextOverload) {
  110.                     FunctionObject f = (FunctionObject)next.value;
  111.                     if (f.implementedIface != func.implementedIface)
  112.                         continue;
  113.                     if (Class.ParametersMatch(f.parameter_declarations, func.parameter_declarations)) {
  114.                         func.funcContext.HandleError(JSError.DuplicateMethod);
  115.                         f.funcContext.HandleError(JSError.DuplicateMethod);
  116.                         break;
  117.                     }
  118.                 }
  119.                 current = current.nextOverload;
  120.             }
  121.         }
  122.        
  123.         internal override object GetMetaData()
  124.         {
  125.             if (this.metaData == null)
  126.                 ((ClassScope)this.obj).GetTypeBuilderOrEnumBuilder();
  127.             return this.metaData;
  128.         }
  129.        
  130.         public override object GetValue(object obj)
  131.         {
  132.             if (obj is StackFrame)
  133.                 return this.GetValue(((StackFrame)obj).closureInstance, (StackFrame)obj);
  134.             if (obj is ScriptObject)
  135.                 return this.GetValue(obj, (ScriptObject)obj);
  136.             return this.GetValue(obj, null);
  137.         }
  138.        
  139.         private object GetValue(object obj, ScriptObject scope)
  140.         {
  141.             if (this.IsStatic || this.IsLiteral)
  142.                 return this.value;
  143.             if (this.obj != obj) {
  144.                 JSObject jsob = obj as JSObject;
  145.                 if (jsob != null) {
  146.                     FieldInfo field = jsob.GetField(this.Name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
  147.                     if (field != null)
  148.                         return field.GetValue(obj);
  149.                     else if (jsob.outer_class_instance != null)
  150.                         return GetValue(jsob.outer_class_instance, null);
  151.                 }
  152.                 throw new TargetException();
  153.             }
  154.             if (!this.IsPublic && (scope == null || !this.IsAccessibleFrom(scope)))
  155.                 if (((JSObject)this.obj).noExpando)
  156.                     throw new JScriptException(JSError.NotAccessible, new Context(new DocumentContext("", null), this.Name));
  157.                 else
  158.                     return this.expandoValue;
  159.             return this.value;
  160.         }
  161.        
  162.         internal bool IsAccessibleFrom(ScriptObject scope)
  163.         {
  164.             //Never call this if the member is public
  165.             while (scope != null && !(scope is ClassScope))
  166.                 scope = scope.GetParent();
  167.             ClassScope objType = null;
  168.             if (this.obj is ClassScope)
  169.                 objType = (ClassScope)this.obj;
  170.             else
  171.                 objType = (ClassScope)((ScriptObject)this.obj).GetParent();
  172.             if (this.IsPrivate)
  173.                 if (scope == null)
  174.                     return false;
  175.                 else
  176.                     return scope == objType || ((ClassScope)scope).IsNestedIn(objType, this.IsStatic);
  177.             else if (this.IsFamily)
  178.                 if (scope == null)
  179.                     return false;
  180.                 else
  181.                     return ((ClassScope)scope).IsSameOrDerivedFrom(objType) || ((ClassScope)scope).IsNestedIn(objType, this.IsStatic);
  182.             else {
  183.                 //if (this.IsAssembly || this.IsFamilyOrAssembly)
  184.                 if (this.IsFamilyOrAssembly && scope != null && (((ClassScope)scope).IsSameOrDerivedFrom(objType) || ((ClassScope)scope).IsNestedIn(objType, this.IsStatic)))
  185.                     return true;
  186.                 else if (scope == null)
  187.                     return objType.GetPackage() == null;
  188.                 else
  189.                     //Code is not in a class and hence it is in the default package
  190.                     //null indicates default package
  191.                     return objType.GetPackage() == ((ClassScope)scope).GetPackage();
  192.             }
  193.         }
  194.        
  195.         internal ConstructorInfo[] GetAsConstructors(object proto)
  196.         {
  197.             JSMemberField field = this;
  198.             int n = 0;
  199.             while (field != null) {
  200.                 field = field.nextOverload;
  201.                 n++;
  202.             }
  203.             ConstructorInfo[] result = new ConstructorInfo[n];
  204.             field = this;
  205.             n = 0;
  206.             while (field != null) {
  207.                 Debug.Assert(field.IsLiteral);
  208.                 FunctionObject func = (FunctionObject)field.value;
  209.                 func.isConstructor = true;
  210.                 func.proto = proto;
  211.                 result[n++] = new JSConstructor(func);
  212.                 field = field.nextOverload;
  213.             }
  214.             return result;
  215.         }
  216.        
  217.         public override void SetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, CultureInfo locale)
  218.         {
  219.             if (obj is StackFrame)
  220.                 this.SetValue(((StackFrame)obj).closureInstance, value, invokeAttr, binder, locale, (StackFrame)obj);
  221.             else if (obj is ScriptObject)
  222.                 this.SetValue(obj, value, invokeAttr, binder, locale, (ScriptObject)obj);
  223.             else
  224.                 this.SetValue(obj, value, invokeAttr, binder, locale, null);
  225.         }
  226.        
  227.         private void SetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, CultureInfo locale, ScriptObject scope)
  228.         {
  229.             if (this.IsStatic || this.IsLiteral) {
  230.                 if ((this.IsLiteral || this.IsInitOnly) && !(this.value is Missing))
  231.                     throw new JScriptException(JSError.AssignmentToReadOnly);
  232.                 goto setValue;
  233.             }
  234.             if (this.obj != obj) {
  235.                 if (obj is JSObject) {
  236.                     FieldInfo field = ((JSObject)obj).GetField(this.Name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
  237.                     if (field != null) {
  238.                         field.SetValue(obj, value, invokeAttr, binder, locale);
  239.                         return;
  240.                     }
  241.                 }
  242.                 throw new TargetException();
  243.             }
  244.             if (!this.IsPublic && (scope == null || !this.IsAccessibleFrom(scope))) {
  245.                 if (((JSObject)this.obj).noExpando)
  246.                     throw new JScriptException(JSError.NotAccessible, new Context(new DocumentContext("", null), this.Name));
  247.                 else
  248.                     this.expandoValue = value;
  249.                 return;
  250.             }
  251.             setValue:
  252.             if (this.type != null)
  253.                 this.value = Convert.Coerce(value, this.type);
  254.             else
  255.                 this.value = value;
  256.         }
  257.     }
  258. }

Developer Fusion