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

  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.Reflection;
  22.     using System.Runtime.InteropServices.Expando;
  23.    
  24.     [System.Runtime.InteropServices.ComVisible(true)]
  25.     public class GlobalScope : ActivationObject, IExpando
  26.     {
  27.         private ArrayList componentScopes;
  28.         //List of script blocks that collectively form a global or module scope. Script blocks have no component scopes.
  29.         internal GlobalObject globalObject;
  30.         //null for script blocks and module scopes.
  31.         private bool recursive;
  32.         //Set this while busy with a lookup, in case the object to which the lookup has been delegated returns the favor.
  33.         internal bool evilScript;
  34.         //Indicates that script contains an eval, or that it may be followed by separately compiled script blocks
  35.         internal object thisObject;
  36.         //Late bound uses of the this literal use this value. Only happens in calls to eval from global code.
  37.         internal bool isComponentScope;
  38.         private TypeReflector globalObjectTR;
  39.         private TypeReflector typeReflector;
  40.        
  41.         public GlobalScope(GlobalScope parent, VsaEngine engine) : this(parent, engine, parent != null)
  42.         {
  43.         }
  44.        
  45.         internal GlobalScope(GlobalScope parent, VsaEngine engine, bool isComponentScope) : base(parent)
  46.         {
  47.             this.componentScopes = null;
  48.             this.recursive = false;
  49.             this.isComponentScope = isComponentScope;
  50.             if (parent == null) {
  51.                 this.globalObject = engine.Globals.globalObject;
  52.                 this.globalObjectTR = TypeReflector.GetTypeReflectorFor(Globals.TypeRefs.ToReferenceContext(this.globalObject.GetType()));
  53.                 this.fast = !(this.globalObject is LenientGlobalObject);
  54.             }
  55.             else {
  56.                 this.globalObject = null;
  57.                 this.globalObjectTR = null;
  58.                 this.fast = parent.fast;
  59.                 if (isComponentScope)
  60.                     ((GlobalScope)this.parent).AddComponentScope(this);
  61.             }
  62.             this.engine = engine;
  63.             this.isKnownAtCompileTime = this.fast;
  64.             this.evilScript = true;
  65.             //True by default. Set it false when a single script block is being compiled.
  66.             this.thisObject = this;
  67.             this.typeReflector = TypeReflector.GetTypeReflectorFor(Globals.TypeRefs.ToReferenceContext(this.GetType()));
  68.             if (isComponentScope)
  69.                 engine.Scopes.Add(this);
  70.         }
  71.        
  72.        
  73.         internal void AddComponentScope(GlobalScope component)
  74.         {
  75.             if (this.componentScopes == null)
  76.                 this.componentScopes = new ArrayList();
  77.             this.componentScopes.Add(component);
  78.             component.thisObject = this.thisObject;
  79.             //Component scopes pretend they are one and the same as their parent scope.
  80.         }
  81.        
  82.         public FieldInfo AddField(string name)
  83.         {
  84.             if (this.fast)
  85.                 return null;
  86.             if (this.isComponentScope)
  87.                 return ((GlobalScope)this.parent).AddField(name);
  88.             FieldInfo field = (FieldInfo)this.name_table[name];
  89.             if (field == null) {
  90.                 field = new JSExpandoField(name);
  91.                 this.name_table[name] = field;
  92.                 this.field_table.Add(field);
  93.             }
  94.             return field;
  95.         }
  96.        
  97.         MethodInfo IExpando.AddMethod(string name, Delegate method)
  98.         {
  99.             return null;
  100.         }
  101.        
  102.         internal override JSVariableField AddNewField(string name, object value, FieldAttributes attributeFlags)
  103.         {
  104.             if (!this.isComponentScope)
  105.                 return base.AddNewField(name, value, attributeFlags);
  106.             //Could get here from eval
  107.             return ((GlobalScope)this.parent).AddNewField(name, value, attributeFlags);
  108.         }
  109.        
  110.         PropertyInfo IExpando.AddProperty(string name)
  111.         {
  112.             return null;
  113.         }
  114.        
  115.         internal override bool DeleteMember(string name)
  116.         {
  117.             if (this.isComponentScope)
  118.                 return this.parent.DeleteMember(name);
  119.             FieldInfo field = (FieldInfo)this.name_table[name];
  120.             if (field != null) {
  121.                 if (field is JSExpandoField) {
  122.                     field.SetValue(this, Missing.Value);
  123.                     this.name_table.Remove(name);
  124.                     this.field_table.Remove(field);
  125.                     return true;
  126.                 }
  127.                 else
  128.                     return false;
  129.             }
  130.             else
  131.                 return false;
  132.         }
  133.        
  134.         public override object GetDefaultThisObject()
  135.         {
  136.             return this;
  137.         }
  138.        
  139.         internal override object GetDefaultValue(PreferredType preferred_type)
  140.         {
  141.             if (preferred_type == PreferredType.String || preferred_type == PreferredType.LocaleString)
  142.                 return "";
  143.             else
  144.                 return Double.NaN;
  145.         }
  146.        
  147.         public override FieldInfo GetField(string name, int lexLevel)
  148.         {
  149.             return this.GetField(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly);
  150.         }
  151.        
  152.         internal JSField[] GetFields()
  153.         {
  154.             int n = this.field_table.Count;
  155.             JSField[] result = new JSField[n];
  156.             for (int i = 0; i < n; i++)
  157.                 result[i] = (JSField)this.field_table[i];
  158.             return result;
  159.         }
  160.        
  161.         public override FieldInfo[] GetFields(BindingFlags bindingAttr)
  162.         {
  163.             return base.GetFields(bindingAttr | BindingFlags.DeclaredOnly);
  164.         }
  165.        
  166.         public override GlobalScope GetGlobalScope()
  167.         {
  168.             return this;
  169.         }
  170.        
  171.         public override FieldInfo GetLocalField(string name)
  172.         {
  173.             return this.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly);
  174.         }
  175.        
  176.         public override MemberInfo[] GetMember(string name, BindingFlags bindingAttr)
  177.         {
  178.             return this.GetMember(name, bindingAttr, false);
  179.         }
  180.        
  181.         private MemberInfo[] GetMember(string name, BindingFlags bindingAttr, bool calledFromParent)
  182.         {
  183.             if (this.recursive)
  184.                 return new MemberInfo[0];
  185.             MemberInfo[] result = null;
  186.             if (!this.isComponentScope) {
  187.                 //Look for an expando
  188.                 MemberInfo[] members = base.GetMember(name, bindingAttr | BindingFlags.DeclaredOnly);
  189.                 if (members.Length > 0)
  190.                     return members;
  191.                 if (this.componentScopes != null)
  192.                     for (int i = 0int n = this.componentScopes.Count; i < n; i++) {
  193.                         GlobalScope sc = (GlobalScope)this.componentScopes[i];
  194.                         result = sc.GetMember(name, bindingAttr | BindingFlags.DeclaredOnly, true);
  195.                         if (result.Length > 0)
  196.                             return result;
  197.                     }
  198.                 if (this.globalObject != null)
  199.                     result = this.globalObjectTR.GetMember(name, bindingAttr & ~BindingFlags.NonPublic | BindingFlags.Static);
  200.                 if (result != null && result.Length > 0)
  201.                     return ScriptObject.WrapMembers(result, this.globalObject);
  202.             }
  203.             else {
  204.                 //Look for global variables represented as static fields on subclass of GlobalScope. I.e. the script block case.
  205.                 result = this.typeReflector.GetMember(name, bindingAttr & ~BindingFlags.NonPublic | BindingFlags.Static);
  206.                 int n = result.Length;
  207.                 if (n > 0) {
  208.                     int toBeHidden = 0;
  209.                     MemberInfo[] newResult = new MemberInfo[n];
  210.                     for (int i = 0; i < n; i++) {
  211.                         MemberInfo mem = newResult[i] = result[i];
  212.                         if (mem.DeclaringType.IsAssignableFrom(Typeob.GlobalScope)) {
  213.                             newResult[i] = null;
  214.                             toBeHidden++;
  215.                         }
  216.                         else if (mem is FieldInfo) {
  217.                             FieldInfo field = (FieldInfo)mem;
  218.                             if (field.IsStatic && field.FieldType == Typeob.Type) {
  219.                                 Type t = (Type)field.GetValue(null);
  220.                                 if (t != null)
  221.                                     newResult[i] = t;
  222.                             }
  223.                         }
  224.                     }
  225.                     if (toBeHidden == 0)
  226.                         return result;
  227.                     if (toBeHidden == n)
  228.                         return new MemberInfo[0];
  229.                     MemberInfo[] remainingMembers = new MemberInfo[n - toBeHidden];
  230.                     int j = 0;
  231.                     foreach (MemberInfo mem in newResult)
  232.                         if (mem != null)
  233.                             remainingMembers[j++] = mem;
  234.                     return remainingMembers;
  235.                 }
  236.             }
  237.             if (this.parent != null && !calledFromParent && ((bindingAttr & BindingFlags.DeclaredOnly) == 0 || this.isComponentScope)) {
  238.                 this.recursive = true;
  239.                 try {
  240.                     result = ((ScriptObject)this.parent).GetMember(name, bindingAttr);
  241.                 }
  242.                 finally {
  243.                     this.recursive = false;
  244.                 }
  245.                 if (result != null && result.Length > 0)
  246.                     return result;
  247.             }
  248.             return new MemberInfo[0];
  249.         }
  250.        
  251.         public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
  252.         {
  253.             if (this.recursive)
  254.                 return new MemberInfo[0];
  255.             MemberInfoList result = new MemberInfoList();
  256.             if (this.isComponentScope) {
  257.                 MemberInfo[] mems = Globals.TypeRefs.ToReferenceContext(this.GetType()).GetMembers(bindingAttr | BindingFlags.DeclaredOnly);
  258.                 if (mems != null)
  259.                     foreach (MemberInfo mem in mems)
  260.                         result.Add(mem);
  261.             }
  262.             else {
  263.                 if (this.componentScopes != null) {
  264.                     for (int i = 0int n = this.componentScopes.Count; i < n; i++) {
  265.                         GlobalScope sc = (GlobalScope)this.componentScopes[i];
  266.                         this.recursive = true;
  267.                         MemberInfo[] mems = null;
  268.                         try {
  269.                             mems = sc.GetMembers(bindingAttr);
  270.                         }
  271.                         finally {
  272.                             this.recursive = false;
  273.                         }
  274.                         if (mems != null)
  275.                             foreach (MemberInfo mem in mems)
  276.                                 result.Add(mem);
  277.                     }
  278.                 }
  279.                 IEnumerator enu = this.field_table.GetEnumerator();
  280.                 while (enu.MoveNext()) {
  281.                     FieldInfo field = (FieldInfo)enu.Current;
  282.                     result.Add(field);
  283.                 }
  284.             }
  285.             if (this.parent != null && (this.isComponentScope || ((bindingAttr & BindingFlags.DeclaredOnly) == 0))) {
  286.                 this.recursive = true;
  287.                 MemberInfo[] mems = null;
  288.                 try {
  289.                     mems = ((ScriptObject)this.parent).GetMembers(bindingAttr);
  290.                 }
  291.                 finally {
  292.                     this.recursive = false;
  293.                 }
  294.                 if (mems != null)
  295.                     foreach (MemberInfo mem in mems)
  296.                         result.Add(mem);
  297.             }
  298.             return result.ToArray();
  299.         }
  300.        
  301.         public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
  302.         {
  303.             return base.GetMethods(bindingAttr | BindingFlags.DeclaredOnly);
  304.         }
  305.        
  306.         public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
  307.         {
  308.             return base.GetProperties(bindingAttr | BindingFlags.DeclaredOnly);
  309.         }
  310.        
  311.         internal override void GetPropertyEnumerator(ArrayList enums, ArrayList objects)
  312.         {
  313.             FieldInfo[] fields = this.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
  314.             if (fields.Length > 0) {
  315.                 enums.Add(fields.GetEnumerator());
  316.                 objects.Add(this);
  317.             }
  318.             ScriptObject parent = this.GetParent();
  319.             if (parent != null)
  320.                 parent.GetPropertyEnumerator(enums, objects);
  321.         }
  322.        
  323.         internal void SetFast()
  324.         {
  325.             this.fast = true;
  326.             this.isKnownAtCompileTime = true;
  327.             if (this.globalObject != null) {
  328.                 this.globalObject = GlobalObject.commonInstance;
  329.                 this.globalObjectTR = TypeReflector.GetTypeReflectorFor(Globals.TypeRefs.ToReferenceContext(this.globalObject.GetType()));
  330.             }
  331.         }
  332.        
  333.         void IExpando.RemoveMember(MemberInfo m)
  334.         {
  335.             this.DeleteMember(m.Name);
  336.         }
  337.        
  338.         internal override void SetMemberValue(string name, object value)
  339.         {
  340.             MemberInfo[] members = this.GetMember(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
  341.             if (members.Length == 0) {
  342.                 // We do not want to create expando fields on the global object when assigning to an undefined
  343.                 // variable in the debugger.
  344.                 if (VsaEngine.executeForJSEE)
  345.                     throw new JScriptException(JSError.UndefinedIdentifier, new Context(new DocumentContext("", null), name));
  346.                 FieldInfo field = this.AddField(name);
  347.                 if (field != null)
  348.                     field.SetValue(this, value);
  349.                 return;
  350.             }
  351.             MemberInfo m = LateBinding.SelectMember(members);
  352.             if (m == null)
  353.                 throw new JScriptException(JSError.AssignmentToReadOnly);
  354.             LateBinding.SetMemberValue(this, name, value, m, members);
  355.         }
  356.        
  357.     }
  358. }

Developer Fusion