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

  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.Collections.Generic;
  21.     using System.Configuration.Assemblies;
  22.     using System.Globalization;
  23.     using System.Reflection;
  24.     using System.Reflection.Emit;
  25.     using System.Security.Permissions;
  26.    
  27.     internal sealed class CustomAttribute : AST
  28.     {
  29.         private AST ctor;
  30.         private ASTList args;
  31.         private AST target;
  32.         //indicates what kind of member the custom attribute is being applied to
  33.         internal object type;
  34.         // will contain either the Type or ClassScope for the custom attribute type
  35.         private ArrayList positionalArgValues;
  36.         private ArrayList namedArgFields;
  37.         private ArrayList namedArgFieldValues;
  38.         private ArrayList namedArgProperties;
  39.         private ArrayList namedArgPropertyValues;
  40.         internal bool raiseToPropertyLevel;
  41.        
  42.         internal CustomAttribute(Context context, AST func, ASTList args) : base(context)
  43.         {
  44.             this.ctor = func;
  45.             this.args = args;
  46.             this.target = null;
  47.             this.type = null;
  48.             this.positionalArgValues = new ArrayList();
  49.             this.namedArgFields = new ArrayList();
  50.             this.namedArgFieldValues = new ArrayList();
  51.             this.namedArgProperties = new ArrayList();
  52.             this.namedArgPropertyValues = new ArrayList();
  53.             this.raiseToPropertyLevel = false;
  54.         }
  55.        
  56.         //Check that custom attribute is applicable to its target
  57.         private bool CheckIfTargetOK(object caType)
  58.         {
  59.             if (caType == null)
  60.                 return false;
  61.             AttributeTargets validOn = (AttributeTargets)0;
  62.             Type caTypeT = caType as Type;
  63.             if (caTypeT != null) {
  64.                 object[] usage = CustomAttribute.GetCustomAttributes(caTypeT, typeof(AttributeUsageAttribute), true);
  65.                 validOn = ((AttributeUsageAttribute)usage[0]).ValidOn;
  66.             }
  67.             else
  68.                 validOn = ((ClassScope)caType).owner.validOn;
  69.             object target = this.target;
  70.             Class c = target as Class;
  71.             if (c != null) {
  72.                 if (c.isInterface) {
  73.                     if ((validOn & AttributeTargets.Interface) != 0)
  74.                         return true;
  75.                 }
  76.                 else if (c is EnumDeclaration) {
  77.                     if ((validOn & AttributeTargets.Enum) != 0)
  78.                         return true;
  79.                 }
  80.                 else if ((validOn & AttributeTargets.Class) != 0) {
  81.                     if (caTypeT == typeof(AttributeUsageAttribute)) {
  82.                         //This is an attribute that describes a new attribute class
  83.                         //Set the validOn field of Class so that it becomes easier to check the usage of the new attribute
  84.                         if (this.positionalArgValues.Count > 0) {
  85.                             object par0 = this.positionalArgValues[0];
  86.                             if (par0 is AttributeTargets)
  87.                                 c.validOn = (AttributeTargets)par0;
  88.                         }
  89.                         for (int i = 0int n = this.namedArgProperties.Count; i < n; i++) {
  90.                             PropertyInfo prop = this.namedArgProperties[i] as PropertyInfo;
  91.                             if (prop.Name == "AllowMultiple")
  92.                                 c.allowMultiple = (bool)this.namedArgPropertyValues[i];
  93.                         }
  94.                     }
  95.                     return true;
  96.                 }
  97.                 else if (caTypeT.FullName == "System.NonSerializedAttribute") {
  98.                     c.attributes &= ~TypeAttributes.Serializable;
  99.                     return false;
  100.                 }
  101.                 this.context.HandleError(JSError.InvalidCustomAttributeTarget, CustomAttribute.GetTypeName(caType));
  102.                 return false;
  103.             }
  104.             FunctionDeclaration fDecl = target as FunctionDeclaration;
  105.             if (fDecl != null) {
  106.                 if ((validOn & AttributeTargets.Property) != 0 && fDecl.enclosingProperty != null) {
  107.                     if (fDecl.enclosingProperty.getter == null || ((JSFieldMethod)fDecl.enclosingProperty.getter).func == fDecl.func) {
  108.                         this.raiseToPropertyLevel = true;
  109.                         return true;
  110.                     }
  111.                     else {
  112.                         this.context.HandleError(JSError.PropertyLevelAttributesMustBeOnGetter);
  113.                         return false;
  114.                     }
  115.                 }
  116.                 if ((validOn & AttributeTargets.Method) != 0 && fDecl.isMethod)
  117.                     return true;
  118.                 if ((validOn & AttributeTargets.Constructor) != 0 && fDecl.func.isConstructor)
  119.                     return true;
  120.                 this.context.HandleError(JSError.InvalidCustomAttributeTarget, CustomAttribute.GetTypeName(caType));
  121.                 return false;
  122.             }
  123.             if (target is VariableDeclaration || target is Constant) {
  124.                 if ((validOn & AttributeTargets.Field) != 0)
  125.                     return true;
  126.                 this.context.HandleError(JSError.InvalidCustomAttributeTarget, CustomAttribute.GetTypeName(caType));
  127.                 return false;
  128.             }
  129.             if (target is AssemblyCustomAttributeList && (validOn & AttributeTargets.Assembly) != 0)
  130.                 return true;
  131.             if (target == null && (validOn & AttributeTargets.Parameter) != 0)
  132.                 return true;
  133.             this.context.HandleError(JSError.InvalidCustomAttributeTarget, CustomAttribute.GetTypeName(caType));
  134.             return false;
  135.         }
  136.        
  137.         private static ushort DaysSince2000()
  138.         {
  139.             return (ushort)(DateTime.Now - new DateTime(2000, 1, 1)).Days;
  140.         }
  141.        
  142.         internal override object Evaluate()
  143.         {
  144.             ConstructorInfo c = (ConstructorInfo)((Binding)this.ctor).member;
  145.             ParameterInfo[] pars = c.GetParameters();
  146.             int pn = pars.Length;
  147.             for (int i = positionalArgValues.Count; i < pn; i++)
  148.                 positionalArgValues.Add(Convert.CoerceT(null, pars[i].ParameterType));
  149.             object[] pArgVals = new object[pn];
  150.             positionalArgValues.CopyTo(0, pArgVals, 0, pn);
  151.             object ca = c.Invoke(BindingFlags.ExactBinding, null, pArgVals, null);
  152.             for (int i = 0int n = this.namedArgProperties.Count; i < n; i++) {
  153.                 JSProperty prop = this.namedArgProperties[i] as JSProperty;
  154.                 if (prop != null)
  155.                     prop.SetValue(ca, Convert.Coerce(this.namedArgPropertyValues[i], prop.PropertyIR()), null);
  156.                 else
  157.                     ((PropertyInfo)this.namedArgProperties[i]).SetValue(ca, this.namedArgPropertyValues[i], null);
  158.             }
  159.             for (int i = 0int n = this.namedArgFields.Count; i < n; i++) {
  160.                 JSVariableField field = this.namedArgFields[i] as JSVariableField;
  161.                 if (field != null)
  162.                     field.SetValue(ca, Convert.Coerce(this.namedArgFieldValues[i], field.GetInferredType(null)));
  163.                 else
  164.                     ((FieldInfo)this.namedArgFields[i]).SetValue(ca, this.namedArgFieldValues[i]);
  165.             }
  166.             return ca;
  167.         }
  168.        
  169.         internal CLSComplianceSpec GetCLSComplianceValue()
  170.         {
  171.             Debug.Assert(this.type == Typeob.CLSCompliantAttribute);
  172.             return ((bool)this.positionalArgValues[0]) ? CLSComplianceSpec.CLSCompliant : CLSComplianceSpec.NonCLSCompliant;
  173.         }
  174.        
  175.         private void ConvertClassScopesAndEnumWrappers(ArrayList vals)
  176.         {
  177.             for (int i = 0int n = vals.Count; i < n; i++) {
  178.                 ClassScope csc = vals[i] as ClassScope;
  179.                 if (csc != null) {
  180.                     vals[i] = csc.GetTypeBuilder();
  181.                     continue;
  182.                 }
  183.                 EnumWrapper wrapper = vals[i] as EnumWrapper;
  184.                 if (wrapper != null)
  185.                     vals[i] = wrapper.ToNumericValue();
  186.             }
  187.         }
  188.        
  189.         private void ConvertFieldAndPropertyInfos(ArrayList vals)
  190.         {
  191.             for (int i = 0int n = vals.Count; i < n; i++) {
  192.                 JSField jsfld = vals[i] as JSField;
  193.                 if (jsfld != null) {
  194.                     vals[i] = jsfld.GetMetaData();
  195.                     continue;
  196.                 }
  197.                 JSProperty jsprop = vals[i] as JSProperty;
  198.                 if (jsprop != null) {
  199.                     vals[i] = jsprop.metaData;
  200.                     continue;
  201.                 }
  202.             }
  203.         }
  204.        
  205.         internal CustomAttributeBuilder GetCustomAttribute()
  206.         {
  207.             ConstructorInfo c = (ConstructorInfo)((Binding)this.ctor).member;
  208.             ParameterInfo[] pars = c.GetParameters();
  209.             int pn = pars.Length;
  210.             if (c is JSConstructor)
  211.                 c = ((JSConstructor)c).GetConstructorInfo(compilerGlobals);
  212.             this.ConvertClassScopesAndEnumWrappers(this.positionalArgValues);
  213.             this.ConvertClassScopesAndEnumWrappers(this.namedArgPropertyValues);
  214.             this.ConvertClassScopesAndEnumWrappers(this.namedArgFieldValues);
  215.             this.ConvertFieldAndPropertyInfos(this.namedArgProperties);
  216.             this.ConvertFieldAndPropertyInfos(this.namedArgFields);
  217.             for (int i = positionalArgValues.Count; i < pn; i++)
  218.                 positionalArgValues.Add(Convert.CoerceT(null, pars[i].ParameterType));
  219.             object[] pArgVals = new object[pn];
  220.             positionalArgValues.CopyTo(0, pArgVals, 0, pn);
  221.             PropertyInfo[] nArgProps = new PropertyInfo[namedArgProperties.Count];
  222.             namedArgProperties.CopyTo(nArgProps);
  223.             object[] nArgPVals = new object[namedArgPropertyValues.Count];
  224.             namedArgPropertyValues.CopyTo(nArgPVals);
  225.             FieldInfo[] nArgFields = new FieldInfo[namedArgFields.Count];
  226.             namedArgFields.CopyTo(nArgFields);
  227.             object[] nArgFVals = new object[namedArgFieldValues.Count];
  228.             namedArgFieldValues.CopyTo(nArgFVals);
  229.             return new CustomAttributeBuilder(c, pArgVals, nArgProps, nArgPVals, nArgFields, nArgFVals);
  230.         }
  231.        
  232.         internal object GetTypeIfAttributeHasToBeUnique()
  233.         {
  234.             Type t = this.type as Type;
  235.             if (t != null) {
  236.                 object[] custAttrs = CustomAttribute.GetCustomAttributes(t, typeof(AttributeUsageAttribute), false);
  237.                 if (custAttrs.Length > 0 && !((AttributeUsageAttribute)custAttrs[0]).AllowMultiple)
  238.                     return t;
  239.                 return null;
  240.             }
  241.             if (!((ClassScope)this.type).owner.allowMultiple)
  242.                 return this.type;
  243.             return null;
  244.         }
  245.        
  246.         private static string GetTypeName(object t)
  247.         {
  248.             Type ty = t as Type;
  249.             if (ty != null)
  250.                 return ty.FullName;
  251.             return ((ClassScope)t).GetFullName();
  252.         }
  253.        
  254.         internal bool IsExpandoAttribute()
  255.         {
  256.             //Use only before partial evaluation has been done
  257.             Lookup id = this.ctor as Lookup;
  258.             return id != null && id.Name == "expando";
  259.         }
  260.         internal override AST PartiallyEvaluate()
  261.         {
  262.             this.ctor = this.ctor.PartiallyEvaluateAsCallable();
  263.            
  264.             //first weed out assignment expressions and use them as property initializers
  265.             ASTList positionalArgs = new ASTList(this.args.context);
  266.             ASTList namedArgs = new ASTList(this.args.context);
  267.             for (int i = 0int m = this.args.count; i < m; i++) {
  268.                 AST arg = this.args[i];
  269.                 Assign assign = arg as Assign;
  270.                 if (assign != null) {
  271.                     assign.rhside = assign.rhside.PartiallyEvaluate();
  272.                     namedArgs.Append(assign);
  273.                 }
  274.                 else
  275.                     positionalArgs.Append(arg.PartiallyEvaluate());
  276.             }
  277.            
  278.             int n = positionalArgs.count;
  279.             IReflect[] argIRs = new IReflect[n];
  280.             for (int i = 0; i < n; i++) {
  281.                 AST arg = positionalArgs[i];
  282.                 // only accept ConstantWrappers
  283.                 if (arg is ConstantWrapper) {
  284.                     object argument = arg.Evaluate();
  285.                     if ((argIRs[i] = CustomAttribute.TypeOfArgument(argument)) != null) {
  286.                         this.positionalArgValues.Add(argument);
  287.                         continue;
  288.                     }
  289.                 }
  290.                 else if (arg is ArrayLiteral && ((ArrayLiteral)arg).IsOkToUseInCustomAttribute()) {
  291.                     argIRs[i] = Typeob.ArrayObject;
  292.                     this.positionalArgValues.Add(arg.Evaluate());
  293.                     continue;
  294.                 }
  295.                 arg.context.HandleError(JSError.InvalidCustomAttributeArgument);
  296.                 return null;
  297.                 // the custom attribute is not good and it will be ignored
  298.             }
  299.            
  300.             //Get the custom attribute and the appropriate constructor (under the covers)
  301.             this.type = this.ctor.ResolveCustomAttribute(positionalArgs, argIRs, this.target);
  302.             if (this.type == null)
  303.                 return null;
  304.             if (Convert.IsPromotableTo((IReflect)this.type, Typeob.CodeAccessSecurityAttribute)) {
  305.                 this.context.HandleError(JSError.CannotUseStaticSecurityAttribute);
  306.                 return null;
  307.             }
  308.            
  309.            
  310.             //Coerce the positional arguments to the right type and supply default values for optional parameters
  311.             ConstructorInfo c = (ConstructorInfo)((Binding)this.ctor).member;
  312.             ParameterInfo[] parameters = c.GetParameters();
  313.             int j = 0;
  314.             int len = this.positionalArgValues.Count;
  315.             foreach (ParameterInfo p in parameters) {
  316.                 IReflect ir = p is ParameterDeclaration ? ((ParameterDeclaration)p).ParameterIReflect : p.ParameterType;
  317.                 if (j < len) {
  318.                     object value = this.positionalArgValues[j];
  319.                     this.positionalArgValues[j] = Convert.Coerce(value, ir, value is ArrayObject);
  320.                     j++;
  321.                 }
  322.                 else {
  323.                     object value;
  324.                     if (TypeReferences.GetDefaultParameterValue(p) == System.Convert.DBNull) {
  325.                         value = Convert.Coerce(null, ir);
  326.                     }
  327.                     else
  328.                         value = TypeReferences.GetDefaultParameterValue(p);
  329.                     this.positionalArgValues.Add(value);
  330.                 }
  331.             }
  332.            
  333.             //Check validity of property/field initializers
  334.             for (int i = 0int m = namedArgs.count; i < m; i++) {
  335.                 Assign assign = (Assign)namedArgs[i];
  336.                 if (assign.lhside is Lookup && (assign.rhside is ConstantWrapper || (assign.rhside is ArrayLiteral && ((ArrayLiteral)assign.rhside).IsOkToUseInCustomAttribute()))) {
  337.                     object value = assign.rhside.Evaluate();
  338.                     IReflect argType = null;
  339.                     if (value is ArrayObject || ((argType = CustomAttribute.TypeOfArgument(value)) != null && argType != Typeob.Object)) {
  340.                         string name = ((Lookup)assign.lhside).Name;
  341.                         MemberInfo[] members = ((IReflect)this.type).GetMember(name, BindingFlags.Public | BindingFlags.Instance);
  342.                         if (members == null || members.Length == 0) {
  343.                             assign.context.HandleError(JSError.NoSuchMember);
  344.                             return null;
  345.                         }
  346.                         if (members.Length == 1) {
  347.                             MemberInfo member = members[0];
  348.                             if (member is FieldInfo) {
  349.                                 FieldInfo fieldInfo = (FieldInfo)member;
  350.                                 if (!fieldInfo.IsLiteral && !fieldInfo.IsInitOnly) {
  351.                                     try {
  352.                                         IReflect ir = fieldInfo is JSVariableField ? ((JSVariableField)fieldInfo).GetInferredType(null) : fieldInfo.FieldType;
  353.                                         value = Convert.Coerce(value, ir, value is ArrayObject);
  354.                                         this.namedArgFields.Add(member);
  355.                                         this.namedArgFieldValues.Add(value);
  356.                                         continue;
  357.                                     }
  358.                                     catch (JScriptException) {
  359.                                         assign.rhside.context.HandleError(JSError.TypeMismatch);
  360.                                         return null;
  361.                                         // the custom attribute is not good and it will be ignored
  362.                                     }
  363.                                 }
  364.                             }
  365.                             else if (member is PropertyInfo) {
  366.                                 PropertyInfo propertyInfo = (PropertyInfo)member;
  367.                                 MethodInfo setMethodInfo = JSProperty.GetSetMethod(propertyInfo, false);
  368.                                 if (setMethodInfo != null) {
  369.                                     ParameterInfo[] paramInfo = setMethodInfo.GetParameters();
  370.                                     if (paramInfo != null && paramInfo.Length == 1) {
  371.                                         try {
  372.                                             IReflect ir = paramInfo[0] is ParameterDeclaration ? ((ParameterDeclaration)paramInfo[0]).ParameterIReflect : paramInfo[0].ParameterType;
  373.                                             value = Convert.Coerce(value, ir, value is ArrayObject);
  374.                                             this.namedArgProperties.Add(member);
  375.                                             this.namedArgPropertyValues.Add(value);
  376.                                         }
  377.                                         catch (JScriptException) {
  378.                                             assign.rhside.context.HandleError(JSError.TypeMismatch);
  379.                                             return null;
  380.                                             // the custom attribute is not good and it will be ignored
  381.                                         }
  382.                                         continue;
  383.                                     }
  384.                                 }
  385.                             }
  386.                         }
  387.                     }
  388.                 }
  389.                 assign.context.HandleError(JSError.InvalidCustomAttributeArgument);
  390.                 return null;
  391.             }
  392.            
  393.             if (!this.CheckIfTargetOK(this.type))
  394.                 return null;
  395.             //Ignore attribute
  396.             //Consume and discard assembly name attributes
  397.             try {
  398.                 Type ty = this.type as Type;
  399.                 if (ty != null && this.target is AssemblyCustomAttributeList) {
  400.                     if (ty.FullName == "System.Reflection.AssemblyAlgorithmIdAttribute") {
  401.                         if (this.positionalArgValues.Count > 0)
  402.                             this.Engine.Globals.assemblyHashAlgorithm = (AssemblyHashAlgorithm)Convert.CoerceT(this.positionalArgValues[0], typeof(AssemblyHashAlgorithm));
  403.                         return null;
  404.                     }
  405.                     if (ty.FullName == "System.Reflection.AssemblyCultureAttribute") {
  406.                         if (this.positionalArgValues.Count > 0) {
  407.                             string cultureId = Convert.ToString(this.positionalArgValues[0]);
  408.                             if (this.Engine.PEFileKind != PEFileKinds.Dll && cultureId.Length > 0) {
  409.                                 this.context.HandleError(JSError.ExecutablesCannotBeLocalized);
  410.                                 return null;
  411.                             }
  412.                             this.Engine.Globals.assemblyCulture = new CultureInfo(cultureId);
  413.                         }
  414.                         return null;
  415.                     }
  416.                     if (ty.FullName == "System.Reflection.AssemblyDelaySignAttribute") {
  417.                         if (this.positionalArgValues.Count > 0)
  418.                             this.Engine.Globals.assemblyDelaySign = Convert.ToBoolean(this.positionalArgValues[0], false);
  419.                         return null;
  420.                     }
  421.                     if (ty.FullName == "System.Reflection.AssemblyFlagsAttribute") {
  422.                         if (this.positionalArgValues.Count > 0)
  423.                             this.Engine.Globals.assemblyFlags = (AssemblyFlags)(uint)Convert.CoerceT(this.positionalArgValues[0], typeof(uint));
  424.                         return null;
  425.                     }
  426.                     if (ty.FullName == "System.Reflection.AssemblyKeyFileAttribute") {
  427.                         if (this.positionalArgValues.Count > 0) {
  428.                             this.Engine.Globals.assemblyKeyFileName = Convert.ToString(this.positionalArgValues[0]);
  429.                             this.Engine.Globals.assemblyKeyFileNameContext = this.context;
  430.                             if (this.Engine.Globals.assemblyKeyFileName != null && this.Engine.Globals.assemblyKeyFileName.Length == 0) {
  431.                                 this.Engine.Globals.assemblyKeyFileName = null;
  432.                                 this.Engine.Globals.assemblyKeyFileNameContext = null;
  433.                             }
  434.                         }
  435.                         return null;
  436.                     }
  437.                     if (ty.FullName == "System.Reflection.AssemblyKeyNameAttribute") {
  438.                         if (this.positionalArgValues.Count > 0) {
  439.                             this.Engine.Globals.assemblyKeyName = Convert.ToString(this.positionalArgValues[0]);
  440.                             this.Engine.Globals.assemblyKeyNameContext = this.context;
  441.                             if (this.Engine.Globals.assemblyKeyName != null && this.Engine.Globals.assemblyKeyName.Length == 0) {
  442.                                 this.Engine.Globals.assemblyKeyName = null;
  443.                                 this.Engine.Globals.assemblyKeyNameContext = null;
  444.                             }
  445.                         }
  446.                         return null;
  447.                     }
  448.                     if (ty.FullName == "System.Reflection.AssemblyVersionAttribute") {
  449.                         if (this.positionalArgValues.Count > 0)
  450.                             this.Engine.Globals.assemblyVersion = this.ParseVersion(Convert.ToString(this.positionalArgValues[0]));
  451.                         return null;
  452.                     }
  453.                     if (ty.FullName == "System.CLSCompliantAttribute") {
  454.                         this.Engine.isCLSCompliant = this.args == null || this.args.count == 0 || Convert.ToBoolean(this.positionalArgValues[0], false);
  455.                         return this;
  456.                     }
  457.                 }
  458.             }
  459.             catch (ArgumentException) {
  460.                 this.context.HandleError(JSError.InvalidCall);
  461.             }
  462.            
  463.             return this;
  464.         }
  465.        
  466.         private Version ParseVersion(string vString)
  467.         {
  468.             ushort major = 1;
  469.             ushort minor = 0;
  470.             ushort build = 0;
  471.             ushort revision = 0;
  472.             try {
  473.                 int n = vString.Length;
  474.                 int i = vString.IndexOf('.', 0);
  475.                 if (i < 0)
  476.                     throw new Exception();
  477.                 major = UInt16.Parse(vString.Substring(0, i), CultureInfo.InvariantCulture);
  478.                 int j = vString.IndexOf('.', i + 1);
  479.                 if (j < i + 1)
  480.                     minor = UInt16.Parse(vString.Substring(i + 1, n - i - 1), CultureInfo.InvariantCulture);
  481.                 else {
  482.                     minor = UInt16.Parse(vString.Substring(i + 1, j - i - 1), CultureInfo.InvariantCulture);
  483.                     if (vString[j + 1] == '*') {
  484.                         build = CustomAttribute.DaysSince2000();
  485.                         revision = CustomAttribute.SecondsSinceMidnight();
  486.                     }
  487.                     else {
  488.                         int k = vString.IndexOf('.', j + 1);
  489.                         if (k < j + 1)
  490.                             build = UInt16.Parse(vString.Substring(j + 1, n - j - 1), CultureInfo.InvariantCulture);
  491.                         else {
  492.                             build = UInt16.Parse(vString.Substring(j + 1, k - j - 1), CultureInfo.InvariantCulture);
  493.                             if (vString[k + 1] == '*')
  494.                                 revision = CustomAttribute.SecondsSinceMidnight();
  495.                             else
  496.                                 revision = UInt16.Parse(vString.Substring(k + 1, n - k - 1), CultureInfo.InvariantCulture);
  497.                         }
  498.                     }
  499.                 }
  500.             }
  501.             catch {
  502.                 this.args[0].context.HandleError(JSError.NotValidVersionString);
  503.             }
  504.             return new Version(major, minor, build, revision);
  505.         }
  506.        
  507.         private static ushort SecondsSinceMidnight()
  508.         {
  509.             TimeSpan sinceMidnight = DateTime.Now - DateTime.Today;
  510.             return (ushort)((sinceMidnight.Hours * 60 * 60 + sinceMidnight.Minutes * 60 + sinceMidnight.Seconds) / 2);
  511.         }
  512.        
  513.         internal void SetTarget(AST target)
  514.         {
  515.             this.target = target;
  516.         }
  517.        
  518.         internal override void TranslateToIL(ILGenerator il, Type rtype)
  519.         {
  520.         }
  521.        
  522.         internal override void TranslateToILInitializer(ILGenerator il)
  523.         {
  524.         }
  525.        
  526.         static internal IReflect TypeOfArgument(object argument)
  527.         {
  528.             if (argument is Enum)
  529.                 return argument.GetType();
  530.             else if (argument is EnumWrapper)
  531.                 return ((EnumWrapper)argument).classScopeOrType;
  532.             else {
  533.                 switch (Convert.GetTypeCode(argument)) {
  534.                     case TypeCode.Empty:
  535.                     case TypeCode.DBNull:
  536.                         return Typeob.Object;
  537.                     case TypeCode.Boolean:
  538.                         return Typeob.Boolean;
  539.                     case TypeCode.Char:
  540.                         return Typeob.Char;
  541.                     case TypeCode.Byte:
  542.                         return Typeob.Byte;
  543.                     case TypeCode.UInt16:
  544.                         return Typeob.UInt16;
  545.                     case TypeCode.UInt32:
  546.                         return Typeob.UInt32;
  547.                     case TypeCode.UInt64:
  548.                         return Typeob.UInt64;
  549.                     case TypeCode.SByte:
  550.                         return Typeob.SByte;
  551.                     case TypeCode.Int16:
  552.                         return Typeob.Int16;
  553.                     case TypeCode.Int32:
  554.                         return Typeob.Int32;
  555.                     case TypeCode.Int64:
  556.                         return Typeob.Int64;
  557.                     case TypeCode.Single:
  558.                         return Typeob.Single;
  559.                     case TypeCode.Double:
  560.                         return Typeob.Double;
  561.                     case TypeCode.Object:
  562.                         if (argument is Type)
  563.                             return Typeob.Type;
  564.                         if (argument is ClassScope)
  565.                             return Typeob.Type;
  566.                         break;
  567.                     case TypeCode.String:
  568.                         return Typeob.String;
  569.                 }
  570.                 return null;
  571.             }
  572.         }
  573.        
  574.         // These APIs are to detect and support ReflectionOnlyLoadFrom which is used at compile time.
  575.         // If it isn't the reflection only case, then the normal API to get attributes is used.
  576.         //
  577.         // At compile time, the only custom attributes which we extract using GetCustomAttributes are:
  578.         // Microsoft.JScript.JSFunctionAttribute
  579.         // Microsoft.JScript.NotRecommended
  580.         // Microsoft.JScript.ReferenceAttribute
  581.         // System.AttributeUsageAttribute
  582.         // System.CLSCompliantAttribute
  583.         // System.ObsoleteAttribute
  584.         // System.Runtime.InteropServices.CoClassAttribute
  585.         // System.Security.AllowPartiallyTrustedCallersAttribute
  586.         //
  587.         // The only ones we check for using IsDefined are:
  588.         // Microsoft.JScript.Expando
  589.         // Microsoft.JScript.JSFunctionAttribute
  590.         // System.ParamArrayAttribute
  591.         // System.Runtime.CompilerServices.RequiredAttributeAttribute
  592.         //
  593.         // None of these are Inherited attibutes and so the ReflectionOnly code path can ignore the
  594.         // inherit flag. The System.* attributes are sealed. The Microsoft.JScript ones are not,
  595.         // though they should be and the compiler will not respect subtypes of these attributes.
  596.         //
  597.         private static object GetCustomAttributeValue(CustomAttributeTypedArgument arg)
  598.         {
  599.             Type reflectionOnlyArgType = arg.ArgumentType;
  600.            
  601.             // If it's an enumerated type, the value is the boxed underlying value and must be converted.
  602.             if (reflectionOnlyArgType.IsEnum)
  603.                 return Enum.ToObject(Type.GetType(reflectionOnlyArgType.FullName), arg.Value);
  604.            
  605.             return arg.Value;
  606.         }
  607.        
  608.         static internal object[] GetCustomAttributes(Assembly target, Type caType, bool inherit)
  609.         {
  610.             if (!target.ReflectionOnly)
  611.                 return target.GetCustomAttributes(caType, inherit);
  612.             return CustomAttribute.ExtractCustomAttribute(CustomAttributeData.GetCustomAttributes(target), caType);
  613.         }
  614.        
  615.         static internal object[] GetCustomAttributes(Module target, Type caType, bool inherit)
  616.         {
  617.             if (!target.Assembly.ReflectionOnly)
  618.                 return target.GetCustomAttributes(caType, inherit);
  619.             return CustomAttribute.ExtractCustomAttribute(CustomAttributeData.GetCustomAttributes(target), caType);
  620.         }
  621.        
  622.         static internal object[] GetCustomAttributes(MemberInfo target, Type caType, bool inherit)
  623.         {
  624.             // JScript implements subclasses of MemberInfo which throw an exception when Module is
  625.             // accessed. We know that none of these are from a ReflectionOnly assembly.
  626.             Type t = target.GetType();
  627.             if (t.Assembly == typeof(CustomAttribute).Assembly || !target.Module.Assembly.ReflectionOnly)
  628.                 return target.GetCustomAttributes(caType, inherit);
  629.             return CustomAttribute.ExtractCustomAttribute(CustomAttributeData.GetCustomAttributes(target), caType);
  630.         }
  631.        
  632.         static internal object[] GetCustomAttributes(ParameterInfo target, Type caType, bool inherit)
  633.         {
  634.             // JScript implements subclasses of ParameterInfo which throw an exception when Module is
  635.             // accessed. We know that none of these are from a ReflectionOnly assembly.
  636.             Type t = target.GetType();
  637.             if (t.Assembly == typeof(CustomAttribute).Assembly || !target.Member.Module.Assembly.ReflectionOnly)
  638.                 return target.GetCustomAttributes(caType, inherit);
  639.             return CustomAttribute.ExtractCustomAttribute(CustomAttributeData.GetCustomAttributes(target), caType);
  640.         }
  641.        
  642.         // This is the common processing code to extract the attributes from the list returned
  643.         // by the custom attribute data reflector.
  644.         private static object[] ExtractCustomAttribute(IList<CustomAttributeData> attributes, Type caType)
  645.         {
  646.             // None of the custom attributes we check for have AllowMultiple == true
  647.             Debug.Assert(caType == typeof(Microsoft.JScript.JSFunctionAttribute) || caType == typeof(Microsoft.JScript.NotRecommended) || caType == typeof(Microsoft.JScript.ReferenceAttribute) || caType == typeof(System.AttributeUsageAttribute) || caType == typeof(System.CLSCompliantAttribute) || caType == typeof(System.ObsoleteAttribute) || caType == typeof(System.Security.AllowPartiallyTrustedCallersAttribute) || caType == typeof(System.ParamArrayAttribute));
  648.            
  649.             Type caReflectionOnlyType = Globals.TypeRefs.ToReferenceContext(caType);
  650.             foreach (CustomAttributeData caData in attributes) {
  651.                 if (caData.Constructor.DeclaringType == caReflectionOnlyType) {
  652.                     // Build up the constructor argument list and create an instance.
  653.                     ArrayList args = new ArrayList();
  654.                     foreach (CustomAttributeTypedArgument arg in caData.ConstructorArguments) {
  655.                         args.Add(CustomAttribute.GetCustomAttributeValue(arg));
  656.                     }
  657.                     object instance = Activator.CreateInstance(caType, args.ToArray());
  658.                    
  659.                     // Populate the public fields.
  660.                     foreach (CustomAttributeNamedArgument namedArg in caData.NamedArguments) {
  661.                         caType.InvokeMember(namedArg.MemberInfo.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetField | BindingFlags.SetProperty, null, instance, new object[1] {CustomAttribute.GetCustomAttributeValue(namedArg.TypedValue)}, null, CultureInfo.InvariantCulture, null);
  662.                     }
  663.                     return new object[1] {instance};
  664.                 }
  665.             }
  666.             return new object[0];
  667.         }
  668.        
  669.        
  670.         static internal bool IsDefined(MemberInfo target, Type caType, bool inherit)
  671.         {
  672.             // JScript implements subclasses of MemberInfo which throw an exception when Module is
  673.             // accessed. We know that none of these are from a ReflectionOnly assembly.
  674.             Type t = target.GetType();
  675.             if (t.Assembly == typeof(CustomAttribute).Assembly || !target.Module.Assembly.ReflectionOnly)
  676.                 return target.IsDefined(caType, inherit);
  677.             return CustomAttribute.CheckForCustomAttribute(CustomAttributeData.GetCustomAttributes(target), caType);
  678.         }
  679.        
  680.         static internal bool IsDefined(ParameterInfo target, Type caType, bool inherit)
  681.         {
  682.             // JScript implements subclasses of ParameterInfo which throw an exception when Module is
  683.             // accessed. We know that none of these are from a ReflectionOnly assembly.
  684.             Type t = target.GetType();
  685.             if (t.Assembly == typeof(CustomAttribute).Assembly || !target.Member.Module.Assembly.ReflectionOnly)
  686.                 return target.IsDefined(caType, inherit);
  687.             return CustomAttribute.CheckForCustomAttribute(CustomAttributeData.GetCustomAttributes(target), caType);
  688.         }
  689.        
  690.         private static bool CheckForCustomAttribute(IList<CustomAttributeData> attributes, Type caType)
  691.         {
  692.             Debug.Assert(caType == typeof(Microsoft.JScript.Expando) || caType == typeof(Microsoft.JScript.JSFunctionAttribute) || caType == typeof(System.ParamArrayAttribute) || caType == typeof(System.Runtime.CompilerServices.RequiredAttributeAttribute));
  693.            
  694.             Type caReflectionOnlyType = Globals.TypeRefs.ToReferenceContext(caType);
  695.             foreach (CustomAttributeData caData in attributes) {
  696.                 if (caData.Constructor.DeclaringType == caReflectionOnlyType)
  697.                     return true;
  698.             }
  699.             return false;
  700.         }
  701.        
  702.     }
  703. }

Developer Fusion