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

  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 Microsoft.Vsa;
  23.    
  24.     internal sealed class VsaHostObject : VsaItem, IVsaGlobalItem
  25.     {
  26.         private object hostObject;
  27.         internal bool exposeMembers;
  28.         internal bool isVisible;
  29.         private bool exposed;
  30.         private bool compiled;
  31.         private VsaScriptScope scope;
  32.         private FieldInfo field;
  33.         private string typeString;
  34.        
  35.         internal VsaHostObject(VsaEngine engine, string itemName, VsaItemType type) : this(engine, itemName, type, null)
  36.         {
  37.         }
  38.        
  39.         internal VsaHostObject(VsaEngine engine, string itemName, VsaItemType type, VsaScriptScope scope) : base(engine, itemName, type, VsaItemFlag.None)
  40.         {
  41.             this.hostObject = null;
  42.             this.exposeMembers = false;
  43.             this.isVisible = false;
  44.             this.exposed = false;
  45.             this.compiled = false;
  46.             this.scope = scope;
  47.             // non-null only when the VsaHostObject is added to a VsaScriptScope (rather than being added directly to the engine)
  48.             this.field = null;
  49.             this.typeString = "System.Object";
  50.         }
  51.        
  52.         public bool ExposeMembers {
  53.             get {
  54.                 if (this.engine == null)
  55.                     throw new VsaException(VsaError.EngineClosed);
  56.                 return this.exposeMembers;
  57.             }
  58.             set {
  59.                 if (this.engine == null)
  60.                     throw new VsaException(VsaError.EngineClosed);
  61.                 this.exposeMembers = value;
  62.             }
  63.         }
  64.        
  65.         internal FieldInfo Field {
  66.             get {
  67.                 JSVariableField jsField = this.field as JSVariableField;
  68.                 if (jsField != null)
  69.                     return (FieldInfo)jsField.GetMetaData();
  70.                 return this.field;
  71.             }
  72.         }
  73.        
  74.         public object GetObject()
  75.         {
  76.             if (this.engine == null)
  77.                 throw new VsaException(VsaError.EngineClosed);
  78.             if (this.hostObject == null) {
  79.                 if (this.engine.Site == null)
  80.                     throw new VsaException(VsaError.SiteNotSet);
  81.                
  82.                 this.hostObject = this.engine.Site.GetGlobalInstance(this.name);
  83.             }
  84.             return this.hostObject;
  85.         }
  86.        
  87.         private void AddNamedItemNamespace()
  88.         {
  89.             // create an outer scope comprising all the members in the named item
  90.             GlobalScope current = (GlobalScope)this.Scope.GetObject();
  91.             //get the global scope object
  92.             if (current.isComponentScope)
  93.                 current = (GlobalScope)current.GetParent();
  94.             ScriptObject parent = current.GetParent();
  95.             //this can be non null if the current scope is nested inside another
  96.             VsaNamedItemScope namedItemNamespace = new VsaNamedItemScope(this.GetObject(), parent, this.engine);
  97.             // insert into the prototype chain of the global scope object
  98.             current.SetParent(namedItemNamespace);
  99.             namedItemNamespace.SetParent(parent);
  100.         }
  101.        
  102.         private void RemoveNamedItemNamespace()
  103.         {
  104.             ScriptObject current = (ScriptObject)this.Scope.GetObject();
  105.             ScriptObject parent = current.GetParent();
  106.             while (parent != null) {
  107.                 if (parent is VsaNamedItemScope) {
  108.                     if (((VsaNamedItemScope)parent).namedItem == this.hostObject) {
  109.                         // take this item out of the parent chain
  110.                         current.SetParent(parent.GetParent());
  111.                         break;
  112.                     }
  113.                 }
  114.                 current = parent;
  115.                 parent = parent.GetParent();
  116.             }
  117.         }
  118.        
  119.         internal override void Remove()
  120.         {
  121.             base.Remove();
  122.             if (this.exposed) {
  123.                 if (this.exposeMembers)
  124.                     RemoveNamedItemNamespace();
  125.                 if (this.isVisible)
  126.                     ((ScriptObject)this.Scope.GetObject()).DeleteMember(this.name);
  127.                 this.hostObject = null;
  128.                 this.exposed = false;
  129.             }
  130.         }
  131.        
  132.         internal override void CheckForErrors()
  133.         {
  134.             this.Compile();
  135.         }
  136.        
  137.         internal override void Compile()
  138.         {
  139.             // if it is a named item and it has a type push the type into the field so the compiler knows about it
  140.             if (!this.compiled) {
  141.                 if (this.isVisible) {
  142.                     ActivationObject obj = (ActivationObject)this.Scope.GetObject();
  143.                     JSVariableField field = (JSVariableField)obj.AddFieldOrUseExistingField(this.name, null, FieldAttributes.Public | FieldAttributes.Static);
  144.                     Type type = this.engine.GetType(this.typeString);
  145.                     if (type != null)
  146.                         field.type = new TypeExpression(new ConstantWrapper(type, null));
  147.                     this.field = field;
  148.                 }
  149.             }
  150.         }
  151.        
  152.         internal override void Run()
  153.         {
  154.             if (!this.exposed) {
  155.                 // expose the named item
  156.                 if (this.isVisible) {
  157.                     ActivationObject obj = (ActivationObject)this.Scope.GetObject();
  158.                     this.field = obj.AddFieldOrUseExistingField(this.name, this.GetObject(), FieldAttributes.Public | FieldAttributes.Static);
  159.                 }
  160.                 if (this.exposeMembers)
  161.                     this.AddNamedItemNamespace();
  162.                 this.exposed = true;
  163.             }
  164.         }
  165.        
  166.         internal void ReRun(GlobalScope scope)
  167.         {
  168.             if (this.field is JSGlobalField) {
  169.                 ((JSGlobalField)this.field).ILField = scope.GetField(this.name, BindingFlags.Public | BindingFlags.Static);
  170.                 this.field.SetValue(scope, this.GetObject());
  171.                 this.field = null;
  172.             }
  173.         }
  174.        
  175.         internal override void Reset()
  176.         {
  177.             base.Reset();
  178.             this.hostObject = null;
  179.             this.exposed = false;
  180.             this.compiled = false;
  181.             this.scope = null;
  182.         }
  183.        
  184.         private VsaScriptScope Scope {
  185.             get {
  186.                 if (this.scope == null)
  187.                     this.scope = (VsaScriptScope)this.engine.GetGlobalScope();
  188.                 return this.scope;
  189.             }
  190.         }
  191.        
  192.         internal override void Close()
  193.         {
  194.             this.Remove();
  195.             base.Close();
  196.             this.hostObject = null;
  197.             this.scope = null;
  198.         }
  199.        
  200.         public string TypeString {
  201.             get {
  202.                 if (this.engine == null)
  203.                     throw new VsaException(VsaError.EngineClosed);
  204.                 return this.typeString;
  205.             }
  206.             set {
  207.                 if (this.engine == null)
  208.                     throw new VsaException(VsaError.EngineClosed);
  209.                 this.typeString = value;
  210.                 this.isDirty = true;
  211.                 this.engine.IsDirty = true;
  212.             }
  213.         }
  214.     }
  215.    
  216. }

Developer Fusion