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

  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.Reflection;
  20.     using System.Reflection.Emit;
  21.     using System.Globalization;
  22.    
  23.     public class ScriptBlock : AST
  24.     {
  25.         private Block statement_block;
  26.         private JSField[] fields;
  27.         private GlobalScope own_scope;
  28.        
  29.         internal ScriptBlock(Context context, Block statement_block) : base(context)
  30.         {
  31.             this.statement_block = statement_block;
  32.             this.own_scope = (GlobalScope)Engine.ScriptObjectStackTop();
  33.             this.fields = null;
  34.         }
  35.        
  36.         internal override object Evaluate()
  37.         {
  38.             if (this.fields == null)
  39.                 this.fields = this.own_scope.GetFields();
  40.             for (int i = 0int nf = this.fields.Length; i < nf; i++) {
  41.                 FieldInfo field = this.fields[i];
  42.                 if (field is JSExpandoField)
  43.                     continue;
  44.                 object val = field.GetValue(this.own_scope);
  45.                 if (val is FunctionObject) {
  46.                     ((FunctionObject)val).engine = this.Engine;
  47.                     this.own_scope.AddFieldOrUseExistingField(field.Name, new Closure((FunctionObject)val), field.Attributes);
  48.                 }
  49.                 else if (val is ClassScope)
  50.                     this.own_scope.AddFieldOrUseExistingField(field.Name, val, field.Attributes);
  51.                 else
  52.                     this.own_scope.AddFieldOrUseExistingField(field.Name, Missing.Value, field.Attributes);
  53.             }
  54.             object res = this.statement_block.Evaluate();
  55.             if (res is Completion)
  56.                 res = ((Completion)res).value;
  57.             return res;
  58.         }
  59.        
  60.         internal void ProcessAssemblyAttributeLists()
  61.         {
  62.             this.statement_block.ProcessAssemblyAttributeLists();
  63.         }
  64.        
  65.         internal override AST PartiallyEvaluate()
  66.         {
  67.             this.statement_block.PartiallyEvaluate();
  68.             if (this.Engine.PEFileKind == PEFileKinds.Dll && this.Engine.doSaveAfterCompile)
  69.                 this.statement_block.ComplainAboutAnythingOtherThanClassOrPackage();
  70.             this.fields = this.own_scope.GetFields();
  71.             return this;
  72.         }
  73.        
  74.         internal override void TranslateToIL(ILGenerator il, Type rtype)
  75.         {
  76.             Expression expr = this.statement_block.ToExpression();
  77.             if (expr != null)
  78.                 expr.TranslateToIL(il, rtype);
  79.             else {
  80.                 this.statement_block.TranslateToIL(il, Typeob.Void);
  81.                 (new ConstantWrapper(null, this.context)).TranslateToIL(il, rtype);
  82.             }
  83.         }
  84.        
  85.         internal TypeBuilder TranslateToILClass(CompilerGlobals compilerGlobals)
  86.         {
  87.             return TranslateToILClass(compilerGlobals, true);
  88.         }
  89.        
  90.         internal TypeBuilder TranslateToILClass(CompilerGlobals compilerGlobals, bool pushScope)
  91.         {
  92.             TypeBuilder classwriter = compilerGlobals.classwriter = compilerGlobals.module.DefineType("JScript " + (this.Engine.classCounter++).ToString(CultureInfo.InvariantCulture), TypeAttributes.Public, Typeob.GlobalScope, null);
  93.             compilerGlobals.classwriter.SetCustomAttribute(new CustomAttributeBuilder(CompilerGlobals.compilerGlobalScopeAttributeCtor, new object[0]));
  94.             if (null == compilerGlobals.globalScopeClassWriter)
  95.                 compilerGlobals.globalScopeClassWriter = classwriter;
  96.            
  97.             //Define a constructor that calls the appropriate constructor on GlobalScope
  98.             ConstructorBuilder cons = compilerGlobals.classwriter.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] {Typeob.GlobalScope});
  99.             ILGenerator il = cons.GetILGenerator();
  100.             il.Emit(OpCodes.Ldarg_0);
  101.             il.Emit(OpCodes.Ldarg_1);
  102.             il.Emit(OpCodes.Dup);
  103.             il.Emit(OpCodes.Ldfld, CompilerGlobals.engineField);
  104.             il.Emit(OpCodes.Call, CompilerGlobals.globalScopeConstructor);
  105.             il.Emit(OpCodes.Ret);
  106.            
  107.             //Define a method to contain the global code
  108.             MethodBuilder mw = classwriter.DefineMethod("Global Code", MethodAttributes.Public, Typeob.Object, null);
  109.             il = mw.GetILGenerator();
  110.            
  111.             if (this.Engine.GenerateDebugInfo) {
  112.                 ScriptObject ns = this.own_scope.GetParent();
  113.                 while (ns != null) {
  114.                     if (ns is WrappedNamespace && !((WrappedNamespace)ns).name.Equals(""))
  115.                         il.UsingNamespace(((WrappedNamespace)ns).name);
  116.                     ns = ns.GetParent();
  117.                 }
  118.             }
  119.            
  120.             int startLine = this.context.StartLine;
  121.             int startCol = this.context.StartColumn;
  122.             //this.context.document.EmitLineInfo(il, startLine, startCol, startLine, startCol + 1); // NOTE: make the debugger stop at line 1 in the jscript source instead of in prolog code
  123.             Context firstContext = this.GetFirstExecutableContext();
  124.             if (firstContext != null)
  125.                 firstContext.EmitFirstLineInfo(il);
  126.            
  127.             if (pushScope) {
  128.                 //Script block for VsaStaticScript doesn't need to push object onto
  129.                 //the stack because the constructors for are stashed into the GlobalScope
  130.                 //object when they are constructed.
  131.                
  132.                 //Emit code to push the scope onto the stack for use by eval...
  133.                 this.EmitILToLoadEngine(il);
  134.                 il.Emit(OpCodes.Ldarg_0);
  135.                 il.Emit(OpCodes.Call, CompilerGlobals.pushScriptObjectMethod);
  136.             }
  137.            
  138.             this.TranslateToILInitializer(il);
  139.             this.TranslateToIL(il, Typeob.Object);
  140.            
  141.             if (pushScope) {
  142.                 //... and corresponding code to pop it off.
  143.                 this.EmitILToLoadEngine(il);
  144.                 il.Emit(OpCodes.Call, CompilerGlobals.popScriptObjectMethod);
  145.                 il.Emit(OpCodes.Pop);
  146.             }
  147.            
  148.             il.Emit(OpCodes.Ret);
  149.            
  150.             return classwriter;
  151.         }
  152.        
  153.         internal override void TranslateToILInitializer(ILGenerator il)
  154.         {
  155.             int nf = this.fields.Length;
  156.             if (nf > 0) {
  157.                 for (int i = 0; i < nf; i++) {
  158.                     JSGlobalField field = this.fields[i] as JSGlobalField;
  159.                     if (field == null)
  160.                         continue;
  161.                     Type t = field.FieldType;
  162.                     if ((field.IsLiteral && t != Typeob.ScriptFunction && t != Typeob.Type) || field.metaData != null) {
  163.                         if ((t.IsPrimitive || t == Typeob.String || t.IsEnum) && field.metaData == null) {
  164.                             FieldBuilder b = compilerGlobals.classwriter.DefineField(field.Name, t, field.Attributes);
  165.                             b.SetConstant(field.value);
  166.                         }
  167.                         continue;
  168.                     }
  169.                     if (field.value is FunctionObject && ((FunctionObject)field.value).suppressIL)
  170.                         continue;
  171.                     FieldBuilder fb = compilerGlobals.classwriter.DefineField(field.Name, t, field.Attributes & (~(FieldAttributes.Literal | FieldAttributes.InitOnly)) | FieldAttributes.Static);
  172.                     field.metaData = fb;
  173.                     field.WriteCustomAttribute(this.Engine.doCRS);
  174.                     //There is no need to store Closure objects in the fields corresponding to functions, since the initializer code
  175.                     //for functions takes care of it. Likewise for Classes.
  176.                 }
  177.             }
  178.             this.statement_block.TranslateToILInitializer(il);
  179.         }
  180.        
  181.         internal override Context GetFirstExecutableContext()
  182.         {
  183.             return this.statement_block.GetFirstExecutableContext();
  184.         }
  185.     }
  186. }

Developer Fusion