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

  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.Diagnostics;
  22.     using System.Globalization;
  23.     using System.Reflection;
  24.     using System.Reflection.Emit;
  25.    
  26.     public sealed class FunctionObject : ScriptFunction
  27.     {
  28.         internal ParameterDeclaration[] parameter_declarations;
  29.         internal string[] formal_parameters;
  30.         internal TypeExpression return_type_expr;
  31.         private Block body;
  32.         private MethodInfo method;
  33.         private ParameterInfo[] parameterInfos;
  34.         internal Context funcContext;
  35.         private int argumentsSlotNumber;
  36.         internal JSLocalField[] fields;
  37.         internal FunctionScope own_scope;
  38.         internal ScriptObject enclosing_scope;
  39.         internal bool must_save_stack_locals;
  40.         //because it has a nested function (that accesses one of its locals) or an eval statement
  41.         internal bool hasArgumentsObject;
  42.         internal IReflect implementedIface;
  43.         internal MethodInfo implementedIfaceMethod;
  44.         internal bool isMethod;
  45.         internal bool isExpandoMethod;
  46.         internal bool isConstructor;
  47.         internal bool isImplicitCtor;
  48.         internal bool isStatic;
  49.         internal bool noVersionSafeAttributeSpecified;
  50.         internal bool suppressIL;
  51.         internal string text;
  52.         private MethodBuilder mb;
  53.         private ConstructorBuilder cb;
  54.         internal TypeBuilder classwriter;
  55.         internal MethodAttributes attributes;
  56.         internal Globals globals;
  57.         private ConstructorInfo superConstructor;
  58.         internal ConstructorCall superConstructorCall;
  59.         internal CustomAttributeList customAttributes;
  60.         // assigned from within the FunctionDeclaration constructor
  61.         private CLSComplianceSpec clsCompliance;
  62.         private LocalBuilder engineLocal;
  63.         private bool partiallyEvaluated;
  64.         internal Label returnLabel;
  65.        
  66.         internal FunctionObject(string name, ParameterDeclaration[] parameter_declarations, TypeExpression return_type_expr, Block body, FunctionScope own_scope, ScriptObject enclosing_scope, Context funcContext, MethodAttributes attributes) : this(name, parameter_declarations, return_type_expr, body, own_scope, enclosing_scope, funcContext, attributes, null, false
  67.         )
  68.         {
  69.         }
  70.        
  71.         internal FunctionObject(string name, ParameterDeclaration[] parameter_declarations, TypeExpression return_type_expr, Block body, FunctionScope own_scope, ScriptObject enclosing_scope, Context funcContext, MethodAttributes attributes, CustomAttributeList customAttributes, bool isMethod
  72.         ) : base(body.Globals.globalObject.originalFunction.originalPrototype, name, parameter_declarations.Length)
  73.         {
  74.             this.parameter_declarations = parameter_declarations;
  75.             int n = parameter_declarations.Length;
  76.             this.formal_parameters = new string[n];
  77.             for (int i = 0; i < n; i++)
  78.                 this.formal_parameters[i] = parameter_declarations[i].identifier;
  79.             this.argumentsSlotNumber = 0;
  80.             this.return_type_expr = return_type_expr;
  81.             if (this.return_type_expr != null)
  82.                 own_scope.AddReturnValueField();
  83.             this.body = body;
  84.             this.method = null;
  85.             this.parameterInfos = null;
  86.             this.funcContext = funcContext;
  87.             this.own_scope = own_scope;
  88.             this.own_scope.owner = this;
  89.             if ((!(enclosing_scope is ActivationObject) || !((ActivationObject)(enclosing_scope)).fast) && !isMethod) {
  90.                 this.argumentsSlotNumber = this.own_scope.GetNextSlotNumber();
  91.                 JSLocalField argsf = (JSLocalField)this.own_scope.AddNewField("arguments", null, (FieldAttributes)0);
  92.                 argsf.type = new TypeExpression(new ConstantWrapper(Typeob.Object, funcContext));
  93.                 argsf.isDefined = true;
  94.                 this.hasArgumentsObject = true;
  95.             }
  96.             else
  97.                 this.hasArgumentsObject = false;
  98.             this.implementedIface = null;
  99.             this.implementedIfaceMethod = null;
  100.             this.isMethod = isMethod;
  101.             this.isExpandoMethod = customAttributes == null ? false : customAttributes.ContainsExpandoAttribute();
  102.             this.isStatic = this.own_scope.isStatic = (attributes & MethodAttributes.Static) != (MethodAttributes)0;
  103.             this.suppressIL = false;
  104.             this.noVersionSafeAttributeSpecified = true;
  105.             // PartiallyEvaluate may change this value
  106.             this.fields = this.own_scope.GetLocalFields();
  107.             this.enclosing_scope = enclosing_scope;
  108.             this.must_save_stack_locals = false;
  109.             //This is set to true, if need be by PartiallyEvaluate.
  110.             this.text = null;
  111.             this.mb = null;
  112.             this.cb = null;
  113.             this.attributes = attributes;
  114.             if (!this.isStatic)
  115.                 this.attributes |= MethodAttributes.HideBySig;
  116.             this.globals = body.Globals;
  117.             this.superConstructor = null;
  118.             this.superConstructorCall = null;
  119.             this.customAttributes = customAttributes;
  120.             this.noExpando = false;
  121.             this.clsCompliance = CLSComplianceSpec.NotAttributed;
  122.             this.engineLocal = null;
  123.             this.partiallyEvaluated = false;
  124.         }
  125.        
  126.         internal FunctionObject(Type t, string name, string method_name, string[] formal_parameters, JSLocalField[] fields, bool must_save_stack_locals, bool hasArgumentsObject, string text, VsaEngine engine) : base(engine.Globals.globalObject.originalFunction.originalPrototype, name, formal_parameters.Length)
  127.         {
  128.             this.engine = engine;
  129.             this.formal_parameters = formal_parameters;
  130.             this.argumentsSlotNumber = 0;
  131.             this.body = null;
  132.             TypeReflector tr = TypeReflector.GetTypeReflectorFor(Globals.TypeRefs.ToReferenceContext(t));
  133.             this.method = tr.GetMethod(method_name, BindingFlags.Public | BindingFlags.Static);
  134.             this.parameterInfos = this.method.GetParameters();
  135.             if (!CustomAttribute.IsDefined(this.method, typeof(JSFunctionAttribute), false))
  136.                 this.isMethod = true;
  137.             else {
  138.                 object[] attrs = CustomAttribute.GetCustomAttributes(method, typeof(JSFunctionAttribute), false);
  139.                 JSFunctionAttributeEnum attr = ((JSFunctionAttribute)attrs[0]).attributeValue;
  140.                 this.isExpandoMethod = (attr & JSFunctionAttributeEnum.IsExpandoMethod) != 0;
  141.             }
  142.             this.funcContext = null;
  143.             this.own_scope = null;
  144.             this.fields = fields;
  145.             this.must_save_stack_locals = must_save_stack_locals;
  146.             this.hasArgumentsObject = hasArgumentsObject;
  147.             this.text = text;
  148.             this.attributes = MethodAttributes.Public;
  149.             this.globals = engine.Globals;
  150.             this.superConstructor = null;
  151.             this.superConstructorCall = null;
  152.             this.enclosing_scope = this.globals.ScopeStack.Peek();
  153.             this.noExpando = false;
  154.             this.clsCompliance = CLSComplianceSpec.NotAttributed;
  155.         }
  156.        
  157.         #if !DEBUG
  158.         [DebuggerStepThroughAttribute()]
  159.         [DebuggerHiddenAttribute()]
  160.         #endif
  161.         internal override object Call(object[] args, object thisob)
  162.         {
  163.             return this.Call(args, thisob, null, null);
  164.         }
  165.        
  166.         #if !DEBUG
  167.         [DebuggerStepThroughAttribute()]
  168.         [DebuggerHiddenAttribute()]
  169.         #endif
  170.         internal override object Call(object[] args, object thisob, Binder binder, CultureInfo culture)
  171.         {
  172.             if (this.body == null)
  173.                 //Calling a compiled function directly (not via a Closure). Happens when constructor property is used in new expression.
  174.                 return this.Call(args, thisob, this.enclosing_scope, new Closure(this), binder, culture);
  175.             //Get here from the Evaluator when in fast mode and the function is in the global scope.
  176.             StackFrame sf = new StackFrame(thisob is JSObject ? (JSObject)thisob : this.enclosing_scope, this.fields, new object[this.fields.Length], thisob);
  177.             if (this.isConstructor) {
  178.                 sf.closureInstance = thisob;
  179.                 if (this.superConstructor != null) {
  180.                     if (this.superConstructorCall == null) {
  181.                         if (this.superConstructor is JSConstructor)
  182.                             this.superConstructor.Invoke(thisob, new object[0]);
  183.                     }
  184.                     else {
  185.                         ASTList argASTs = this.superConstructorCall.arguments;
  186.                         int n = argASTs.count;
  187.                         object[] supArgs = new object[n];
  188.                         for (int i = 0; i < n; i++)
  189.                             supArgs[i] = argASTs[i].Evaluate();
  190.                         this.superConstructor.Invoke(thisob, (BindingFlags)0, binder, supArgs, culture);
  191.                     }
  192.                 }
  193.                 globals.ScopeStack.GuardedPush(thisob is JSObject ? (JSObject)thisob : this.enclosing_scope);
  194.                 try {
  195.                     ((ClassScope)this.enclosing_scope).owner.body.EvaluateInstanceVariableInitializers();
  196.                 }
  197.                 finally {
  198.                     globals.ScopeStack.Pop();
  199.                 }
  200.             }
  201.             else if (this.isMethod && !this.isStatic)
  202.                 if (((ClassScope)this.enclosing_scope).HasInstance(thisob))
  203.                     sf.closureInstance = thisob;
  204.                 else
  205.                     throw new JScriptException(JSError.TypeMismatch);
  206.             globals.ScopeStack.GuardedPush(sf);
  207.             try {
  208.                 this.own_scope.CloseNestedFunctions(sf);
  209.                 this.ConvertArguments(args, sf.localVars, 0, args.Length, this.formal_parameters.Length, binder, culture);
  210.                 Completion result = (Completion)(this.body.Evaluate());
  211.                 if (result.Return)
  212.                     return result.value;
  213.                 else
  214.                     return null;
  215.             }
  216.             finally {
  217.                 globals.ScopeStack.Pop();
  218.             }
  219.         }
  220.        
  221.         #if !DEBUG
  222.         [DebuggerStepThroughAttribute()]
  223.         [DebuggerHiddenAttribute()]
  224.         #endif
  225.         internal override object Call(object[] args, object thisob, ScriptObject enclosing_scope, Closure calleeClosure, Binder binder, CultureInfo culture)
  226.         {
  227.             if (this.body != null)
  228.                 return CallASTFunc(args, thisob, enclosing_scope, calleeClosure, binder, culture);
  229.            
  230.             object saved_caller = calleeClosure.caller;
  231.             calleeClosure.caller = this.globals.caller;
  232.             this.globals.caller = calleeClosure;
  233.             object saved_args = calleeClosure.arguments;
  234.             ScriptObject calling_scope = globals.ScopeStack.Peek();
  235.             ArgumentsObject caller_arguments = (calling_scope is StackFrame) ? ((StackFrame)calling_scope).caller_arguments : null;
  236.             StackFrame sf = new StackFrame(enclosing_scope, this.fields, this.must_save_stack_locals ? new object[this.fields.Length] : null, thisob);
  237.             globals.ScopeStack.GuardedPush(sf);
  238.             ArgumentsObject arguments = new ArgumentsObject(globals.globalObject.originalObjectPrototype, args, this, calleeClosure, sf, caller_arguments);
  239.             sf.caller_arguments = arguments;
  240.             calleeClosure.arguments = arguments;
  241.             try {
  242.                 try {
  243.                     int n = this.formal_parameters.Length;
  244.                     int m = args.Length;
  245.                     if (this.hasArgumentsObject) {
  246.                         object[] newargs = new object[n + 3];
  247.                         newargs[0] = thisob;
  248.                         newargs[1] = this.engine;
  249.                         newargs[2] = arguments;
  250.                         this.ConvertArguments(args, newargs, 3, m, n, binder, culture);
  251.                         return this.method.Invoke(thisob, BindingFlags.SuppressChangeType, null, newargs, null);
  252.                     }
  253.                     else if (!this.isMethod) {
  254.                         object[] newargs = new object[n + 2];
  255.                         newargs[0] = thisob;
  256.                         newargs[1] = this.engine;
  257.                         this.ConvertArguments(args, newargs, 2, m, n, binder, culture);
  258.                         return this.method.Invoke(thisob, BindingFlags.SuppressChangeType, null, newargs, null);
  259.                     }
  260.                     else if (n == m) {
  261.                         this.ConvertArguments(args, args, 0, m, n, binder, culture);
  262.                         return this.method.Invoke(thisob, BindingFlags.SuppressChangeType, null, args, null);
  263.                     }
  264.                     else {
  265.                         object[] newargs = new object[n];
  266.                         this.ConvertArguments(args, newargs, 0, m, n, binder, culture);
  267.                         return this.method.Invoke(thisob, BindingFlags.SuppressChangeType, null, newargs, null);
  268.                     }
  269.                 }
  270.                 catch (TargetInvocationException e) {
  271.                     throw e.InnerException;
  272.                 }
  273.             }
  274.             finally {
  275.                 globals.ScopeStack.Pop();
  276.                 calleeClosure.arguments = saved_args;
  277.                 this.globals.caller = calleeClosure.caller;
  278.                 calleeClosure.caller = saved_caller;
  279.             }
  280.         }
  281.        
  282.         private object CallASTFunc(object[] args, object thisob, ScriptObject enclosing_scope, Closure calleeClosure, Binder binder, CultureInfo culture)
  283.         {
  284.             object saved_caller = calleeClosure.caller;
  285.             calleeClosure.caller = this.globals.caller;
  286.             this.globals.caller = calleeClosure;
  287.             object saved_args = calleeClosure.arguments;
  288.             ScriptObject calling_scope = globals.ScopeStack.Peek();
  289.             ArgumentsObject caller_arguments = (calling_scope is StackFrame) ? ((StackFrame)calling_scope).caller_arguments : null;
  290.             StackFrame sf = new StackFrame(enclosing_scope, this.fields, new object[this.fields.Length], thisob);
  291.             if (this.isMethod && !this.isStatic)
  292.                 sf.closureInstance = thisob;
  293.             globals.ScopeStack.GuardedPush(sf);
  294.             try {
  295.                 this.own_scope.CloseNestedFunctions(sf);
  296.                 ArgumentsObject arguments = null;
  297.                 if (this.hasArgumentsObject) {
  298.                     arguments = new ArgumentsObject(this.globals.globalObject.originalObjectPrototype, args, this, calleeClosure, sf, caller_arguments);
  299.                     sf.localVars[this.argumentsSlotNumber] = arguments;
  300.                 }
  301.                 sf.caller_arguments = arguments;
  302.                 calleeClosure.arguments = arguments;
  303.                 this.ConvertArguments(args, sf.localVars, 0, args.Length, this.formal_parameters.Length, binder, culture);
  304.                 Completion result = (Completion)(this.body.Evaluate());
  305.                 if (result.Return)
  306.                     return result.value;
  307.                 else
  308.                     return null;
  309.             }
  310.             finally {
  311.                 this.globals.ScopeStack.Pop();
  312.                 calleeClosure.arguments = saved_args;
  313.                 this.globals.caller = calleeClosure.caller;
  314.                 calleeClosure.caller = saved_caller;
  315.             }
  316.         }
  317.        
  318.         //assume this code is called after PartiallyEvaluate
  319.         internal void CheckCLSCompliance(bool classIsCLSCompliant)
  320.         {
  321.             if (classIsCLSCompliant) {
  322.                 if (this.clsCompliance != CLSComplianceSpec.NonCLSCompliant) {
  323.                     for (int i = 0int length = this.parameter_declarations.Length; i < length; i++) {
  324.                         IReflect ir = this.parameter_declarations[i].ParameterIReflect;
  325.                         if (ir != null && !TypeExpression.TypeIsCLSCompliant(ir)) {
  326.                             this.clsCompliance = CLSComplianceSpec.NonCLSCompliant;
  327.                             this.funcContext.HandleError(JSError.NonCLSCompliantMember);
  328.                             return;
  329.                         }
  330.                     }
  331.                     if (this.return_type_expr != null && !this.return_type_expr.IsCLSCompliant()) {
  332.                         this.clsCompliance = CLSComplianceSpec.NonCLSCompliant;
  333.                         this.funcContext.HandleError(JSError.NonCLSCompliantMember);
  334.                     }
  335.                 }
  336.             }
  337.             else if (this.clsCompliance == CLSComplianceSpec.CLSCompliant)
  338.                 this.funcContext.HandleError(JSError.MemberTypeCLSCompliantMismatch);
  339.            
  340.         }
  341.        
  342.         #if !DEBUG
  343.         [DebuggerStepThroughAttribute()]
  344.         [DebuggerHiddenAttribute()]
  345.         #endif
  346.         internal object Construct(JSObject thisob, object[] args)
  347.         {
  348.             JSObject newob = new JSObject(null, false);
  349.             newob.SetParent(this.GetPrototypeForConstructedObject());
  350.             newob.outer_class_instance = thisob;
  351.             object result = this.Call(args, newob);
  352.             if (result is ScriptObject)
  353.                 return result;
  354.             return newob;
  355.         }
  356.        
  357.         private void ConvertArguments(object[] args, object[] newargs, int offset, int length, int n, Binder binder, CultureInfo culture)
  358.         {
  359.             ParameterInfo[] pars = this.parameterInfos;
  360.             if (pars != null) {
  361.                 for (int i = 0int j = offset; i < n; i++,j++) {
  362.                     Type t = pars[j].ParameterType;
  363.                     if (i == n - 1 && CustomAttribute.IsDefined(pars[j], typeof(ParamArrayAttribute), false)) {
  364.                         int k = length - i;
  365.                         if (k < 0)
  366.                             k = 0;
  367.                         newargs[j] = FunctionObject.CopyToNewParamArray(t.GetElementType(), k, args, i, binder, culture);
  368.                         return;
  369.                     }
  370.                     object argval = i < length ? args[i] : null;
  371.                     if (t == Typeob.Object)
  372.                         newargs[j] = argval;
  373.                     else if (binder != null)
  374.                         newargs[j] = binder.ChangeType(argval, t, culture);
  375.                     else
  376.                         newargs[j] = Convert.CoerceT(argval, t);
  377.                 }
  378.             }
  379.             else {
  380.                 ParameterDeclaration[] pds = this.parameter_declarations;
  381.                 for (int i = 0int j = offset; i < n; i++,j++) {
  382.                     IReflect ir = pds[i].ParameterIReflect;
  383.                     if (i == n - 1 && CustomAttribute.IsDefined(pds[j], typeof(ParamArrayAttribute), false)) {
  384.                         int k = length - i;
  385.                         if (k < 0)
  386.                             k = 0;
  387.                         newargs[j] = FunctionObject.CopyToNewParamArray(((TypedArray)ir).elementType, k, args, i);
  388.                         return;
  389.                     }
  390.                     object argval = i < length ? args[i] : null;
  391.                     if (ir == Typeob.Object) {
  392.                         newargs[j] = argval;
  393.                         continue;
  394.                     }
  395.                     if (ir is ClassScope)
  396.                         newargs[j] = Convert.Coerce(argval, ir);
  397.                     else if (binder != null)
  398.                         newargs[j] = binder.ChangeType(argval, Convert.ToType(ir), culture);
  399.                     else
  400.                         newargs[j] = Convert.CoerceT(argval, Convert.ToType(ir));
  401.                 }
  402.             }
  403.         }
  404.        
  405.         private static object[] CopyToNewParamArray(IReflect ir, int n, object[] args, int offset)
  406.         {
  407.             object[] paramArray = new object[n];
  408.             for (int i = 0; i < n; i++)
  409.                 paramArray[i] = Convert.Coerce(args[i + offset], ir);
  410.             return paramArray;
  411.         }
  412.        
  413.         private static System.Array CopyToNewParamArray(Type t, int n, object[] args, int offset, Binder binder, CultureInfo culture)
  414.         {
  415.             System.Array paramArray = System.Array.CreateInstance(t, n);
  416.             for (int i = 0; i < n; i++)
  417.                 paramArray.SetValue(binder.ChangeType(args[i + offset], t, culture), i);
  418.             return paramArray;
  419.         }
  420.        
  421.         internal void EmitLastLineInfo(ILGenerator il)
  422.         {
  423.             if (!this.isImplicitCtor) {
  424.                 // this is the only case so far where debug info does not go through Context and it's explicitely called here using DocumentContext
  425.                 int endLine = this.body.context.EndLine;
  426.                 int endColumn = this.body.context.EndColumn;
  427.                 this.body.context.document.EmitLineInfo(il, endLine, endColumn, endLine, endColumn + 1);
  428.             }
  429.         }
  430.        
  431.         internal string GetName()
  432.         {
  433.             return this.name;
  434.         }
  435.        
  436.         internal override int GetNumberOfFormalParameters()
  437.         {
  438.             return this.formal_parameters.Length;
  439.         }
  440.        
  441.         internal ConstructorInfo GetConstructorInfo(CompilerGlobals compilerGlobals)
  442.         {
  443.             return (ConstructorInfo)this.GetMethodBase(compilerGlobals);
  444.         }
  445.        
  446.         internal MethodInfo GetMethodInfo(CompilerGlobals compilerGlobals)
  447.         {
  448.             return (MethodInfo)this.GetMethodBase(compilerGlobals);
  449.         }
  450.        
  451.         internal MethodBase GetMethodBase(CompilerGlobals compilerGlobals)
  452.         {
  453.             if (this.mb != null)
  454.                 return this.mb;
  455.             if (this.cb != null)
  456.                 return this.cb;
  457.             JSFunctionAttributeEnum jsFunctionAttributes = 0;
  458.             int extras = 3;
  459.             if (this.isMethod) {
  460.                 if (this.isConstructor && ((ClassScope)this.enclosing_scope).outerClassField != null) {
  461.                     extras = 1;
  462.                     jsFunctionAttributes |= JSFunctionAttributeEnum.IsInstanceNestedClassConstructor;
  463.                 }
  464.                 else
  465.                     extras = 0;
  466.             }
  467.             else if (!this.hasArgumentsObject)
  468.                 extras = 2;
  469.             int np = this.formal_parameters.Length + extras;
  470.             Type[] ptypes = new Type[np];
  471.             Type rtype = Convert.ToType(this.ReturnType(null));
  472.             if (extras > 0) {
  473.                 if (this.isConstructor)
  474.                     ptypes[np - 1] = ((ClassScope)this.enclosing_scope).outerClassField.FieldType;
  475.                 else
  476.                     ptypes[0] = Typeob.Object;
  477.                 jsFunctionAttributes |= JSFunctionAttributeEnum.HasThisObject;
  478.             }
  479.             if (extras > 1) {
  480.                 ptypes[1] = Typeob.VsaEngine;
  481.                 jsFunctionAttributes |= JSFunctionAttributeEnum.HasEngine;
  482.             }
  483.             if (extras > 2) {
  484.                 ptypes[2] = Typeob.Object;
  485.                 jsFunctionAttributes |= JSFunctionAttributeEnum.HasArguments;
  486.             }
  487.             if (this.must_save_stack_locals)
  488.                 jsFunctionAttributes |= JSFunctionAttributeEnum.HasStackFrame;
  489.             if (this.isExpandoMethod)
  490.                 jsFunctionAttributes |= JSFunctionAttributeEnum.IsExpandoMethod;
  491.             if (this.isConstructor) {
  492.                 for (int i = 0; i < np - extras; i++)
  493.                     ptypes[i] = this.parameter_declarations[i].ParameterType;
  494.             }
  495.             else {
  496.                 for (int i = extras; i < np; i++)
  497.                     ptypes[i] = this.parameter_declarations[i - extras].ParameterType;
  498.             }
  499.             if (this.enclosing_scope is ClassScope)
  500.                 if (this.isConstructor) {
  501.                     this.cb = ((ClassScope)(this.enclosing_scope)).GetTypeBuilder().DefineConstructor(this.attributes & MethodAttributes.MemberAccessMask, CallingConventions.Standard, ptypes);
  502.                 }
  503.                 else {
  504.                     string name = this.name;
  505.                     if (this.implementedIfaceMethod != null) {
  506.                         JSMethod jsm = this.implementedIfaceMethod as JSMethod;
  507.                         if (jsm != null)
  508.                             this.implementedIfaceMethod = jsm.GetMethodInfo(compilerGlobals);
  509.                         name = this.implementedIfaceMethod.DeclaringType.FullName + "." + name;
  510.                     }
  511.                     TypeBuilder tb = ((ClassScope)(this.enclosing_scope)).GetTypeBuilder();
  512.                     if (this.mb != null)
  513.                         return this.mb;
  514.                     //Might have been defined as a result of the above call
  515.                     this.mb = tb.DefineMethod(name, this.attributes, rtype, ptypes);
  516.                     if (this.implementedIfaceMethod != null)
  517.                         ((ClassScope)(this.enclosing_scope)).GetTypeBuilder().DefineMethodOverride(this.mb, this.implementedIfaceMethod);
  518.                 }
  519.             else {
  520.                 if (enclosing_scope is FunctionScope) {
  521.                     //dealing with a nested function/function expression. Mangle the name.
  522.                     if (((FunctionScope)enclosing_scope).owner != null) {
  523.                         this.name = ((FunctionScope)enclosing_scope).owner.name + "." + this.name;
  524.                         jsFunctionAttributes |= JSFunctionAttributeEnum.IsNested;
  525.                     }
  526.                     else {
  527.                         //dealing with the dummy outer scope of a function expression
  528.                         ScriptObject escope = enclosing_scope;
  529.                         while (escope != null) {
  530.                             if (escope is FunctionScope && ((FunctionScope)escope).owner != null) {
  531.                                 this.name = ((FunctionScope)escope).owner.name + "." + this.name;
  532.                                 jsFunctionAttributes |= JSFunctionAttributeEnum.IsNested;
  533.                                 break;
  534.                             }
  535.                             escope = escope.GetParent();
  536.                         }
  537.                     }
  538.                 }
  539.                 //The name could still be a duplicate, so check against a table of names already used.
  540.                 if (compilerGlobals.usedNames[this.name] != null)
  541.                     this.name = this.name + ":" + (compilerGlobals.usedNames.count).ToString(CultureInfo.InvariantCulture);
  542.                 compilerGlobals.usedNames[this.name] = this;
  543.                
  544.                 // Use the class writer associated with the global scope if the function is a global
  545.                 // function or a nested function inside a global function. In these cases,
  546.                 // compilerGlobals.classwriter will be setup incorrectly if the function is called
  547.                 // from a code inside a class before it is declared.
  548.                 ScriptObject classScope = this.enclosing_scope;
  549.                 while (classScope != null && !(classScope is ClassScope))
  550.                     classScope = classScope.GetParent();
  551.                 this.classwriter = (classScope == null ? compilerGlobals.globalScopeClassWriter : compilerGlobals.classwriter);
  552.                
  553.                 this.mb = this.classwriter.DefineMethod(this.name, this.attributes, rtype, ptypes);
  554.             }
  555.             // the method is defined, we can now put debug info about the parameters
  556.             if (extras > 0) {
  557.                 if (this.mb != null)
  558.                     this.mb.DefineParameter(1, (ParameterAttributes)0, "this");
  559.                 else {
  560.                     ParameterBuilder pb = this.cb.DefineParameter(np, (ParameterAttributes)0, "this");
  561.                     pb.SetConstant(null);
  562.                     extras = 0;
  563.                     np--;
  564.                 }
  565.             }
  566.             if (extras > 1)
  567.                 this.mb.DefineParameter(2, (ParameterAttributes)0, "vsa Engine");
  568.             if (extras > 2)
  569.                 this.mb.DefineParameter(3, (ParameterAttributes)0, "arguments");
  570.             for (int i = extras; i < np; i++) {
  571.                 ParameterBuilder pb = this.mb != null ? this.mb.DefineParameter(i + 1, (ParameterAttributes)0, this.parameter_declarations[i - extras].identifier) : this.cb.DefineParameter(i + 1, (ParameterAttributes)0, this.parameter_declarations[i - extras].identifier);
  572.                 CustomAttributeList paramCustAttList = this.parameter_declarations[i - extras].customAttributes;
  573.                 if (paramCustAttList != null) {
  574.                     CustomAttributeBuilder[] paramCustomAttributes = paramCustAttList.GetCustomAttributeBuilders(false);
  575.                     for (int attIndex = 0; attIndex < paramCustomAttributes.Length; attIndex++)
  576.                         pb.SetCustomAttribute(paramCustomAttributes[attIndex]);
  577.                 }
  578.             }
  579.             if (jsFunctionAttributes > 0) {
  580.                 CustomAttributeBuilder cab = new CustomAttributeBuilder(CompilerGlobals.jsFunctionAttributeConstructor, new object[1] {jsFunctionAttributes});
  581.                 if (this.mb != null)
  582.                     this.mb.SetCustomAttribute(cab);
  583.                 else
  584.                     this.cb.SetCustomAttribute(cab);
  585.             }
  586.             // deal with custom attributes
  587.             if (this.customAttributes != null) {
  588.                 CustomAttributeBuilder[] custAtt = this.customAttributes.GetCustomAttributeBuilders(false);
  589.                 for (int j = 0; j < custAtt.Length; j++) {
  590.                     if (this.mb != null)
  591.                         this.mb.SetCustomAttribute(custAtt[j]);
  592.                     else
  593.                         this.cb.SetCustomAttribute(custAtt[j]);
  594.                 }
  595.             }
  596.             if (this.clsCompliance == CLSComplianceSpec.CLSCompliant)
  597.                 if (this.mb != null)
  598.                     this.mb.SetCustomAttribute(new CustomAttributeBuilder(CompilerGlobals.clsCompliantAttributeCtor, new object[] {true}));
  599.                 else
  600.                     this.cb.SetCustomAttribute(new CustomAttributeBuilder(CompilerGlobals.clsCompliantAttributeCtor, new object[] {true}));
  601.             else if (this.clsCompliance == CLSComplianceSpec.NonCLSCompliant)
  602.                 if (this.mb != null)
  603.                     this.mb.SetCustomAttribute(new CustomAttributeBuilder(CompilerGlobals.clsCompliantAttributeCtor, new object[] {false}));
  604.                 else
  605.                     this.cb.SetCustomAttribute(new CustomAttributeBuilder(CompilerGlobals.clsCompliantAttributeCtor, new object[] {false}));
  606.             if (this.mb != null) {
  607.                 this.mb.InitLocals = true;
  608.                 return this.mb;
  609.             }
  610.             else {
  611.                 this.cb.InitLocals = true;
  612.                 return this.cb;
  613.             }
  614.         }
  615.        
  616.         private static bool IsPresentIn(FieldInfo field, FieldInfo[] fields)
  617.         {
  618.             for (int i = 0int n = fields.Length; i < n; i++)
  619.                 if (field == fields[i])
  620.                     return true;
  621.             return false;
  622.         }
  623.        
  624.         internal bool Must_save_stack_locals {
  625.             get {
  626.                 if (!this.partiallyEvaluated)
  627.                     this.PartiallyEvaluate();
  628.                 return this.must_save_stack_locals;
  629.             }
  630.         }
  631.        
  632.         internal void PartiallyEvaluate()
  633.         {
  634.             if (this.partiallyEvaluated)
  635.                 return;
  636.            
  637.             // 49885 - Putting class definitions in a package makes class order dependent
  638.             // For methods, the logic in FunctionObject.PartiallyEvaluate must be called by
  639.             // Class.PartiallyEvaluate in order to ensure that the scope chain is set up correctly.
  640.             ClassScope classScope = this.enclosing_scope as ClassScope;
  641.             if (null != classScope)
  642.                 classScope.owner.PartiallyEvaluate();
  643.            
  644.             // In the case where the the caller is Class.PartiallyEvaluate, the call returns
  645.             // immediately since Class.partiallyEvaluated wil be set and this.partiallEvaluated
  646.             // will still be false to allow the partial evaluation to be computed. In the case where
  647.             // the caller isn't Class.PartiallyEvaluate, the call to Class.PartiallyEvaluate results
  648.             // in a call back to FunctionObject.PartiallyEvaluate. This call will set this.partiallyEvaluated
  649.             // and thus, we will not need to evaluate again.
  650.             if (this.partiallyEvaluated)
  651.                 return;
  652.            
  653.            
  654.             this.partiallyEvaluated = true;
  655.             // deal with custom attributes
  656.             this.clsCompliance = CLSComplianceSpec.NotAttributed;
  657.             if (this.customAttributes != null) {
  658.                 this.customAttributes.PartiallyEvaluate();
  659.                 CustomAttribute clsAttr = this.customAttributes.GetAttribute(Typeob.CLSCompliantAttribute);
  660.                 if (clsAttr != null) {
  661.                     this.clsCompliance = clsAttr.GetCLSComplianceValue();
  662.                     this.customAttributes.Remove(clsAttr);
  663.                 }
  664.                 clsAttr = this.customAttributes.GetAttribute(Typeob.Override);
  665.                 if (clsAttr != null) {
  666.                     if (this.isStatic)
  667.                         clsAttr.context.HandleError(JSError.StaticMethodsCannotOverride);
  668.                     else
  669.                         this.attributes &= ~MethodAttributes.NewSlot;
  670.                     this.noVersionSafeAttributeSpecified = false;
  671.                     this.customAttributes.Remove(clsAttr);
  672.                 }
  673.                 clsAttr = this.customAttributes.GetAttribute(Typeob.Hide);
  674.                 if (clsAttr != null) {
  675.                     if (!this.noVersionSafeAttributeSpecified) {
  676.                         clsAttr.context.HandleError(JSError.OverrideAndHideUsedTogether);
  677.                         this.attributes |= MethodAttributes.NewSlot;
  678.                         this.noVersionSafeAttributeSpecified = true;
  679.                     }
  680.                     else {
  681.                         if (this.isStatic)
  682.                             clsAttr.context.HandleError(JSError.StaticMethodsCannotHide);
  683.                         this.noVersionSafeAttributeSpecified = false;
  684.                     }
  685.                     this.customAttributes.Remove(clsAttr);
  686.                 }
  687.                 CustomAttribute expAttr = this.customAttributes.GetAttribute(Typeob.Expando);
  688.                 if (expAttr != null) {
  689.                     if (!this.noVersionSafeAttributeSpecified && (this.attributes & MethodAttributes.NewSlot) == 0) {
  690.                         expAttr.context.HandleError(JSError.ExpandoPrecludesOverride);
  691.                         this.attributes |= MethodAttributes.NewSlot;
  692.                         this.noVersionSafeAttributeSpecified = true;
  693.                     }
  694.                     if (this.isConstructor)
  695.                         expAttr.context.HandleError(JSError.NotValidForConstructor);
  696.                     else if ((this.attributes & MethodAttributes.Abstract) != 0)
  697.                         expAttr.context.HandleError(JSError.ExpandoPrecludesAbstract);
  698.                     else if ((this.attributes & MethodAttributes.Static) != 0)
  699.                         expAttr.context.HandleError(JSError.ExpandoPrecludesStatic);
  700.                     else if ((this.attributes & MethodAttributes.MemberAccessMask) != MethodAttributes.Public)
  701.                         expAttr.context.HandleError(JSError.ExpandoMustBePublic);
  702.                     else {
  703.                         this.own_scope.isMethod = false;
  704.                         this.isMethod = false;
  705.                         this.isExpandoMethod = true;
  706.                         this.isStatic = true;
  707.                         this.attributes &= ~MethodAttributes.Virtual;
  708.                         this.attributes &= ~MethodAttributes.NewSlot;
  709.                         this.attributes |= MethodAttributes.Static;
  710.                     }
  711.                 }
  712.             }
  713.             for (int i = 0int n = this.parameter_declarations.Length; i < n; i++) {
  714.                 this.parameter_declarations[i].PartiallyEvaluate();
  715.                 JSLocalField pfield = (JSLocalField)this.own_scope.name_table[this.formal_parameters[i]];
  716.                 pfield.type = this.parameter_declarations[i].type;
  717.                 if (pfield.type == null)
  718.                     pfield.type = new TypeExpression(new ConstantWrapper(Typeob.Object, this.parameter_declarations[i].context));
  719.                 pfield.isDefined = true;
  720.             }
  721.             if (this.return_type_expr != null) {
  722.                 this.return_type_expr.PartiallyEvaluate();
  723.                 this.own_scope.returnVar.type = this.return_type_expr;
  724.                 if (this.own_scope.returnVar.type.ToIReflect() == Typeob.Void) {
  725.                     this.own_scope.returnVar.type = null;
  726.                     this.own_scope.returnVar = null;
  727.                     //This does not completely get rid of the returnVar value, but acts as flag, hence the above.
  728.                 }
  729.             }
  730.             globals.ScopeStack.Push(this.own_scope);
  731.             if (!this.own_scope.isKnownAtCompileTime)
  732. //Function contains an eval. Type inference is impossible for local vars
  733.                 for (int i = 0int n = this.fields.Length; i < n; i++)
  734.                     this.fields[i].SetInferredType(Typeob.Object, null);
  735.             if (!this.isConstructor)
  736.                 this.body.PartiallyEvaluate();
  737.             else {
  738.                 this.body.MarkSuperOKIfIsFirstStatement();
  739.                 this.body.PartiallyEvaluate();
  740.                 //super constructor calls that have not been marked OK will generate errors
  741.                 ClassScope cscope = (ClassScope)this.enclosing_scope;
  742.                 int n = this.superConstructorCall == null ? 0 : this.superConstructorCall.arguments.count;
  743.                 Type[] argTypes = n == 0 ? Type.EmptyTypes : new Type[n];
  744.                 IReflect[] argIRs = new IReflect[n];
  745.                 for (int i = 0; i < n; i++)
  746.                     argIRs[i] = this.superConstructorCall.arguments[i].InferType(null);
  747.                 Context errorContext = this.superConstructorCall == null ? this.funcContext : this.superConstructorCall.context;
  748.                 try {
  749.                     if (this.superConstructorCall != null && !this.superConstructorCall.isSuperConstructorCall)
  750.                         this.superConstructor = JSBinder.SelectConstructor(cscope.constructors, argIRs);
  751.                     else
  752.                         this.superConstructor = cscope.owner.GetSuperConstructor(argIRs);
  753.                     if (this.superConstructor == null)
  754.                         errorContext.HandleError(JSError.SuperClassConstructorNotAccessible);
  755.                     else {
  756.                         ConstructorInfo cons = (ConstructorInfo)this.superConstructor;
  757.                         if (!cons.IsPublic && !cons.IsFamily && !cons.IsFamilyOrAssembly && !(this.superConstructor is JSConstructor && ((JSConstructor)this.superConstructor).IsAccessibleFrom(this.enclosing_scope))) {
  758.                             errorContext.HandleError(JSError.SuperClassConstructorNotAccessible);
  759.                             this.superConstructor = null;
  760.                         }
  761.                         else if (n > 0)
  762.                             if (!Binding.CheckParameters(cons.GetParameters(), argIRs, this.superConstructorCall.arguments, this.superConstructorCall.context))
  763.                                 this.superConstructor = null;
  764.                     }
  765.                 }
  766.                 catch (AmbiguousMatchException) {
  767.                     errorContext.HandleError(JSError.AmbiguousConstructorCall);
  768.                 }
  769.             }
  770.             this.own_scope.HandleUnitializedVariables();
  771.             globals.ScopeStack.Pop();
  772.             this.must_save_stack_locals = this.own_scope.mustSaveStackLocals;
  773.             this.fields = this.own_scope.GetLocalFields();
  774.         }
  775.        
  776.         internal IReflect ReturnType(JSField inference_target)
  777.         {
  778.             if (!this.partiallyEvaluated)
  779.                 this.PartiallyEvaluate();
  780.             if (this.own_scope.returnVar == null)
  781.                 return Typeob.Void;
  782.             else if (this.return_type_expr != null)
  783.                 return this.return_type_expr.ToIReflect();
  784.             else
  785.                 return this.own_scope.returnVar.GetInferredType(inference_target);
  786.         }
  787.        
  788.         public override string ToString()
  789.         {
  790.             if (this.text != null)
  791.                 return this.text;
  792.             else
  793.                 return this.funcContext.GetCode();
  794.         }
  795.        
  796.         internal void TranslateBodyToIL(ILGenerator il, CompilerGlobals compilerGlobals)
  797.         {
  798.             this.returnLabel = il.DefineLabel();
  799.             // Emit all the namespaces used by this function
  800.             if (this.body.Engine.GenerateDebugInfo) {
  801.                 ScriptObject ns = this.enclosing_scope.GetParent();
  802.                 while (ns != null) {
  803.                     if (ns is PackageScope)
  804.                         il.UsingNamespace(((PackageScope)ns).name);
  805.                     else if (ns is WrappedNamespace && !((WrappedNamespace)ns).name.Equals(""))
  806.                         il.UsingNamespace(((WrappedNamespace)ns).name);
  807.                     ns = ns.GetParent();
  808.                 }
  809.             }
  810.             int startLine = this.body.context.StartLine;
  811.             int startCol = this.body.context.StartColumn;
  812.             this.body.context.document.EmitLineInfo(il, startLine, startCol, startLine, startCol + 1);
  813.             if (this.body.context.document.debugOn)
  814.                 il.Emit(OpCodes.Nop);
  815.             //set up the compiler to emit direct accesses to the locals and pars.
  816.             int n = this.fields.Length;
  817.             for (int i = 0; i < n; i++) {
  818.                 if (!this.fields[i].IsLiteral || this.fields[i].value is FunctionObject) {
  819.                     Type t = this.fields[i].FieldType;
  820.                     LocalBuilder tok = il.DeclareLocal(t);
  821.                     if (this.fields[i].debugOn)
  822.                         tok.SetLocalSymInfo(this.fields[i].debuggerName);
  823.                     this.fields[i].metaData = tok;
  824.                 }
  825.             }
  826.             globals.ScopeStack.Push(this.own_scope);
  827.             try {
  828.                 if (this.must_save_stack_locals) {
  829.                     this.TranslateToMethodWithStackFrame(il, compilerGlobals, true);
  830.                     return;
  831.                 }
  832.                 this.body.TranslateToILInitializer(il);
  833.                 this.body.TranslateToIL(il, Typeob.Void);
  834.                 il.MarkLabel(this.returnLabel);
  835.             }
  836.             finally {
  837.                 globals.ScopeStack.Pop();
  838.             }
  839.         }
  840.        
  841.         internal void TranslateToIL(CompilerGlobals compilerGlobals)
  842.         {
  843.             if (this.suppressIL)
  844.                 return;
  845.             globals.ScopeStack.Push(this.own_scope);
  846.             try {
  847.                 if (this.mb == null && this.cb == null)
  848.                     this.GetMethodBase(compilerGlobals);
  849.                 int offset = (this.attributes & MethodAttributes.Static) == MethodAttributes.Static ? 0 : 1;
  850.                 int extras = 3;
  851.                 if (this.isMethod)
  852.                     extras = 0;
  853.                 else if (!this.hasArgumentsObject)
  854.                     extras = 2;
  855.                 ILGenerator il = this.mb != null ? this.mb.GetILGenerator() : this.cb.GetILGenerator();
  856.                 this.returnLabel = il.DefineLabel();
  857.                 // Emit all the namespaces used by this function
  858.                 if (this.body.Engine.GenerateDebugInfo) {
  859.                     ScriptObject ns = this.enclosing_scope.GetParent();
  860.                     while (ns != null) {
  861.                         if (ns is PackageScope)
  862.                             il.UsingNamespace(((PackageScope)ns).name);
  863.                         else if (ns is WrappedNamespace && !((WrappedNamespace)ns).name.Equals(""))
  864.                             il.UsingNamespace(((WrappedNamespace)ns).name);
  865.                         ns = ns.GetParent();
  866.                     }
  867.                 }
  868.                 if (!this.isImplicitCtor && this.body != null) {
  869.                     int startLine = this.body.context.StartLine;
  870.                     int startCol = this.body.context.StartColumn;
  871.                     this.body.context.document.EmitLineInfo(il, startLine, startCol, startLine, startCol + 1);
  872.                     if (this.body.context.document.debugOn)
  873.                         il.Emit(OpCodes.Nop);
  874.                 }
  875.                 //set up the compiler to emit direct accesses to the locals and pars.
  876.                 int n = this.fields.Length;
  877.                 for (int i = 0; i < n; i++) {
  878.                     // Use indexed lookup for the parameters. We must check to make sure the field
  879.                     // is not a nested function as they might have the same name as a parameter.
  880.                     int j = this.IsNestedFunctionField(this.fields[i]) ? -1 : System.Array.IndexOf(this.formal_parameters, this.fields[i].Name);
  881.                     if (j >= 0)
  882.                         this.fields[i].metaData = (short)(j + extras + offset);
  883.                     else if (this.hasArgumentsObject && this.fields[i].Name.Equals("arguments"))
  884.                         this.fields[i].metaData = (short)(2 + offset);
  885.                     else if (!this.fields[i].IsLiteral || this.fields[i].value is FunctionObject) {
  886.                         Type t = this.fields[i].FieldType;
  887.                         LocalBuilder tok = il.DeclareLocal(t);
  888.                         if (this.fields[i].debugOn)
  889.                             tok.SetLocalSymInfo(this.fields[i].debuggerName);
  890.                         this.fields[i].metaData = tok;
  891.                     }
  892.                     else if (this.own_scope.mustSaveStackLocals) {
  893.                         //Need to emit a field. FunctionDeclaration will initialize it with a closure
  894.                         LocalBuilder tok = il.DeclareLocal(this.fields[i].FieldType);
  895.                         this.fields[i].metaData = tok;
  896.                     }
  897.                 }
  898.                 if (this.isConstructor) {
  899.                     int pn = formal_parameters.Length + 1;
  900.                     ClassScope cscope = (ClassScope)this.enclosing_scope;
  901.                     //Call the default super constructor followed by the field initializers
  902.                     if (this.superConstructor == null)
  903.                         cscope.owner.EmitInitialCalls(il, null, null, null, 0);
  904.                     else {
  905.                         ParameterInfo[] pars = this.superConstructor.GetParameters();
  906.                         if (this.superConstructorCall != null)
  907.                             cscope.owner.EmitInitialCalls(il, this.superConstructor, pars, this.superConstructorCall.arguments, pn);
  908.                         else
  909.                             cscope.owner.EmitInitialCalls(il, this.superConstructor, pars, null, pn);
  910.                     }
  911.                 }
  912.                 if ((this.isMethod || this.isConstructor) && this.must_save_stack_locals) {
  913.                     this.TranslateToMethodWithStackFrame(il, compilerGlobals, false);
  914.                     return;
  915.                 }
  916.                 this.TranslateToILToCopyOuterScopeLocals(il, true, null);
  917.                
  918.                 bool savedInsideProtectedRegion = compilerGlobals.InsideProtectedRegion;
  919.                 compilerGlobals.InsideProtectedRegion = false;
  920.                 bool savedInsideFinally = compilerGlobals.InsideFinally;
  921.                 int savedFinallyStackTop = compilerGlobals.FinallyStackTop;
  922.                 compilerGlobals.InsideFinally = false;
  923.                 this.body.TranslateToILInitializer(il);
  924.                 this.body.TranslateToIL(il, Typeob.Void);
  925.                 compilerGlobals.InsideProtectedRegion = savedInsideProtectedRegion;
  926.                 compilerGlobals.InsideFinally = savedInsideFinally;
  927.                 compilerGlobals.FinallyStackTop = savedFinallyStackTop;
  928.                 il.MarkLabel(this.returnLabel);
  929.                 if (this.body.context.document.debugOn) {
  930.                     this.EmitLastLineInfo(il);
  931.                     il.Emit(OpCodes.Nop);
  932.                 }
  933.                 this.TranslateToILToSaveLocals(il);
  934.                 //put locals on heap so that nested functions can get to them
  935.                 if (this.own_scope.returnVar != null)
  936.                     il.Emit(OpCodes.Ldloc, (LocalBuilder)this.own_scope.returnVar.GetMetaData());
  937.                 il.Emit(OpCodes.Ret);
  938.             }
  939.             finally {
  940.                 globals.ScopeStack.Pop();
  941.             }
  942.         }
  943.        
  944.         private bool IsNestedFunctionField(JSLocalField field)
  945.         {
  946.             return field.value != null && field.value is FunctionObject;
  947.         }
  948.        
  949.         internal void TranslateToILToLoadEngine(ILGenerator il)
  950.         {
  951.             this.TranslateToILToLoadEngine(il, false);
  952.         }
  953.        
  954.         private void TranslateToILToLoadEngine(ILGenerator il, bool allocateLocal)
  955.         {
  956.             if (this.isMethod)
  957.                 if (this.isStatic)
  958.                     if (this.body.Engine.doCRS)
  959.                         il.Emit(OpCodes.Ldsfld, CompilerGlobals.contextEngineField);
  960.                     else {
  961.                         if (this.engineLocal == null) {
  962.                             if (allocateLocal)
  963.                                 this.engineLocal = il.DeclareLocal(Typeob.VsaEngine);
  964.                             if (this.body.Engine.PEFileKind == PEFileKinds.Dll) {
  965.                                 il.Emit(OpCodes.Ldtoken, ((ClassScope)this.own_scope.GetParent()).GetTypeBuilder());
  966.                                 il.Emit(OpCodes.Call, CompilerGlobals.createVsaEngineWithType);
  967.                             }
  968.                             else
  969.                                 il.Emit(OpCodes.Call, CompilerGlobals.createVsaEngine);
  970.                             if (allocateLocal)
  971.                                 il.Emit(OpCodes.Stloc, this.engineLocal);
  972.                             else
  973.                                 return;
  974.                         }
  975.                         il.Emit(OpCodes.Ldloc, this.engineLocal);
  976.                     }
  977.                 else {
  978.                     il.Emit(OpCodes.Ldarg_0);
  979.                     il.Emit(OpCodes.Callvirt, CompilerGlobals.getEngineMethod);
  980.                 }
  981.             else
  982.                 il.Emit(OpCodes.Ldarg_1);
  983.             //get it from a parameter when inside a non-method
  984.         }
  985.        
  986.         private void TranslateToMethodWithStackFrame(ILGenerator il, CompilerGlobals compilerGlobals, bool staticInitializer)
  987.         {
  988.             //Can get here if method contains a nested function or if method contains an eval
  989.             if (this.isStatic)
  990.                 il.Emit(OpCodes.Ldtoken, ((ClassScope)this.own_scope.GetParent()).GetTypeBuilder());
  991.             else
  992.                 il.Emit(OpCodes.Ldarg_0);
  993.             int n = this.fields.Length;
  994.             ConstantWrapper.TranslateToILInt(il, n);
  995.             il.Emit(OpCodes.Newarr, Typeob.JSLocalField);
  996.             for (int i = 0; i < n; i++) {
  997.                 JSLocalField field = this.fields[i];
  998.                 il.Emit(OpCodes.Dup);
  999.                 ConstantWrapper.TranslateToILInt(il, i);
  1000.                 il.Emit(OpCodes.Ldstr, field.Name);
  1001.                 il.Emit(OpCodes.Ldtoken, field.FieldType);
  1002.                 ConstantWrapper.TranslateToILInt(il, field.slotNumber);
  1003.                 il.Emit(OpCodes.Newobj, CompilerGlobals.jsLocalFieldConstructor);
  1004.                 il.Emit(OpCodes.Stelem_Ref);
  1005.             }
  1006.             this.TranslateToILToLoadEngine(il, true);
  1007.             if (this.isStatic)
  1008.                 il.Emit(OpCodes.Call, CompilerGlobals.pushStackFrameForStaticMethod);
  1009.             else
  1010.                 il.Emit(OpCodes.Call, CompilerGlobals.pushStackFrameForMethod);
  1011.             bool savedInsideProtectedRegion = compilerGlobals.InsideProtectedRegion;
  1012.             compilerGlobals.InsideProtectedRegion = true;
  1013.             il.BeginExceptionBlock();
  1014.             this.body.TranslateToILInitializer(il);
  1015.             this.body.TranslateToIL(il, Typeob.Void);
  1016.             il.MarkLabel(this.returnLabel);
  1017.             this.TranslateToILToSaveLocals(il);
  1018.             //put locals on heap so that nested functions can get to them
  1019.             Label retLabel = il.DefineLabel();
  1020.             il.Emit(OpCodes.Leave, retLabel);
  1021.             il.BeginFinallyBlock();
  1022.             this.TranslateToILToLoadEngine(il);
  1023.             il.Emit(OpCodes.Call, CompilerGlobals.popScriptObjectMethod);
  1024.             il.Emit(OpCodes.Pop);
  1025.             il.EndExceptionBlock();
  1026.             il.MarkLabel(retLabel);
  1027.             if (!staticInitializer) {
  1028.                 if (this.body.context.document.debugOn) {
  1029.                     this.EmitLastLineInfo(il);
  1030.                     il.Emit(OpCodes.Nop);
  1031.                 }
  1032.                 if (this.own_scope.returnVar != null)
  1033.                     il.Emit(OpCodes.Ldloc, (LocalBuilder)this.own_scope.returnVar.GetMetaData());
  1034.                 il.Emit(OpCodes.Ret);
  1035.             }
  1036.             compilerGlobals.InsideProtectedRegion = savedInsideProtectedRegion;
  1037.         }
  1038.        
  1039.         //Parameters and local variables might be accessed from eval or from nested functions.
  1040.         //These cannot get to the locals via IL, so the locals are saved to an array of Objects before every eval or call out of the function.
  1041.         //Upon return, they are restored from the array to the locals.
  1042.        
  1043.         internal void TranslateToILToRestoreLocals(ILGenerator il)
  1044.         {
  1045.             this.TranslateToILToRestoreLocals(il, null);
  1046.         }
  1047.        
  1048.         internal void TranslateToILToRestoreLocals(ILGenerator il, JSLocalField[] notToBeRestored)
  1049.         {
  1050.             this.TranslateToILToCopyOuterScopeLocals(il, true, notToBeRestored);
  1051.             if (!this.must_save_stack_locals)
  1052.                 return;
  1053.             int offset = (this.attributes & MethodAttributes.Static) == MethodAttributes.Static ? 0 : 1;
  1054.             int extras = 3;
  1055.             if (this.isMethod)
  1056.                 extras = 0;
  1057.             else if (!this.hasArgumentsObject)
  1058.                 extras = 2;
  1059.             int n = this.fields.Length;
  1060.             this.TranslateToILToLoadEngine(il);
  1061.             il.Emit(OpCodes.Call, CompilerGlobals.scriptObjectStackTopMethod);
  1062.             ScriptObject scope = globals.ScopeStack.Peek();
  1063.             while (scope is WithObject || scope is BlockScope) {
  1064.                 il.Emit(OpCodes.Call, CompilerGlobals.getParentMethod);
  1065.                 scope = scope.GetParent();
  1066.             }
  1067.             il.Emit(OpCodes.Castclass, Typeob.StackFrame);
  1068.             il.Emit(OpCodes.Ldfld, CompilerGlobals.localVarsField);
  1069.             for (int i = 0; i < n; i++) {
  1070.                 if (notToBeRestored != null && IsPresentIn(this.fields[i], notToBeRestored))
  1071.                     continue;
  1072.                 if (this.fields[i].IsLiteral)
  1073.                     continue;
  1074.                 il.Emit(OpCodes.Dup);
  1075.                 int j = System.Array.IndexOf(this.formal_parameters, this.fields[i].Name);
  1076.                 ConstantWrapper.TranslateToILInt(il, this.fields[i].slotNumber);
  1077.                 il.Emit(OpCodes.Ldelem_Ref);
  1078.                 Convert.Emit(this.body, il, Typeob.Object, this.fields[i].FieldType);
  1079.                 if (j >= 0 || (this.fields[i].Name.Equals("arguments") && this.hasArgumentsObject)) {
  1080.                     il.Emit(OpCodes.Starg, (short)(j + extras + offset));
  1081.                 }
  1082.                 else {
  1083.                     il.Emit(OpCodes.Stloc, (LocalBuilder)this.fields[i].metaData);
  1084.                 }
  1085.             }
  1086.             il.Emit(OpCodes.Pop);
  1087.         }
  1088.        
  1089.         internal void TranslateToILToSaveLocals(ILGenerator il)
  1090.         {
  1091.             this.TranslateToILToCopyOuterScopeLocals(il, false, null);
  1092.             if (!this.must_save_stack_locals)
  1093.                 return;
  1094.             int offset = (this.attributes & MethodAttributes.Static) == MethodAttributes.Static ? 0 : 1;
  1095.             int extras = 3;
  1096.             if (this.isMethod)
  1097.                 extras = 0;
  1098.             else if (!this.hasArgumentsObject)
  1099.                 extras = 2;
  1100.             int n = this.fields.Length;
  1101.             this.TranslateToILToLoadEngine(il);
  1102.             il.Emit(OpCodes.Call, CompilerGlobals.scriptObjectStackTopMethod);
  1103.             ScriptObject scope = globals.ScopeStack.Peek();
  1104.             while (scope is WithObject || scope is BlockScope) {
  1105.                 il.Emit(OpCodes.Call, CompilerGlobals.getParentMethod);
  1106.                 scope = scope.GetParent();
  1107.             }
  1108.             il.Emit(OpCodes.Castclass, Typeob.StackFrame);
  1109.             il.Emit(OpCodes.Ldfld, CompilerGlobals.localVarsField);
  1110.             for (int i = 0; i < n; i++) {
  1111.                 JSLocalField f = this.fields[i];
  1112.                 if (f.IsLiteral && !(f.value is FunctionObject))
  1113.                     continue;
  1114.                 il.Emit(OpCodes.Dup);
  1115.                 ConstantWrapper.TranslateToILInt(il, f.slotNumber);
  1116.                 int j = System.Array.IndexOf(this.formal_parameters, f.Name);
  1117.                 if (j >= 0 || (f.Name.Equals("arguments") && this.hasArgumentsObject)) {
  1118.                     Convert.EmitLdarg(il, (short)(j + extras + offset));
  1119.                 }
  1120.                 else {
  1121.                     il.Emit(OpCodes.Ldloc, (LocalBuilder)f.metaData);
  1122.                 }
  1123.                 Convert.Emit(this.body, il, f.FieldType, Typeob.Object);
  1124.                 il.Emit(OpCodes.Stelem_Ref);
  1125.             }
  1126.             il.Emit(OpCodes.Pop);
  1127.            
  1128.         }
  1129.        
  1130.         //Nested functions can access the locals of their containing functions. There is no way to do this in IL.
  1131.         //The work around is to copy the values of the outer scope locals to true locals at function entry and
  1132.         //then to copy the modified values back at function exit.
  1133.         //The outer scopes save their locals in an array before making calls, hence they are accessible.
  1134.        
  1135.         private void TranslateToILToCopyOuterScopeLocals(ILGenerator il, bool copyToNested, JSLocalField[] notToBeRestored)
  1136.         {
  1137.             if (this.own_scope.ProvidesOuterScopeLocals == null || this.own_scope.ProvidesOuterScopeLocals.count == 0)
  1138.                 return;
  1139.             this.TranslateToILToLoadEngine(il);
  1140.             il.Emit(OpCodes.Call, CompilerGlobals.scriptObjectStackTopMethod);
  1141.             ScriptObject scope = globals.ScopeStack.Peek();
  1142.             while (scope is WithObject || scope is BlockScope) {
  1143.                 il.Emit(OpCodes.Call, CompilerGlobals.getParentMethod);
  1144.                 scope = scope.GetParent();
  1145.             }
  1146.             scope = this.enclosing_scope;
  1147.             while (scope != null) {
  1148.                 //Run through the scope chain, copying locals from outer scopes that provide them.
  1149.                 il.Emit(OpCodes.Call, CompilerGlobals.getParentMethod);
  1150.                 if (scope is FunctionScope && ((FunctionScope)scope).owner != null && this.own_scope.ProvidesOuterScopeLocals[scope] != null) {
  1151.                     il.Emit(OpCodes.Dup);
  1152.                     il.Emit(OpCodes.Castclass, Typeob.StackFrame);
  1153.                     il.Emit(OpCodes.Ldfld, CompilerGlobals.localVarsField);
  1154.                     if (copyToNested)
  1155.                         ((FunctionScope)scope).owner.TranslateToILToCopyLocalsToNestedScope(il, this.own_scope, notToBeRestored);
  1156.                     else
  1157.                         ((FunctionScope)scope).owner.TranslateToILToCopyLocalsFromNestedScope(il, this.own_scope);
  1158.                 }
  1159.                 else if (scope is GlobalScope || scope is ClassScope)
  1160.                     break;
  1161.                 scope = scope.GetParent();
  1162.             }
  1163.             il.Emit(OpCodes.Pop);
  1164.         }
  1165.        
  1166.         private void TranslateToILToCopyLocalsToNestedScope(ILGenerator il, FunctionScope nestedScope, JSLocalField[] notToBeRestored)
  1167.         {
  1168.             int offset = (this.attributes & MethodAttributes.Static) == MethodAttributes.Static ? 0 : 1;
  1169.             int n = this.fields.Length;
  1170.             for (int i = 0; i < n; i++) {
  1171.                 JSLocalField field = nestedScope.GetOuterLocalField(this.fields[i].Name);
  1172.                 if (field == null || field.outerField != this.fields[i] || (notToBeRestored != null && IsPresentIn(field, notToBeRestored)))
  1173.                     continue;
  1174.                 il.Emit(OpCodes.Dup);
  1175.                 ConstantWrapper.TranslateToILInt(il, this.fields[i].slotNumber);
  1176.                 il.Emit(OpCodes.Ldelem_Ref);
  1177.                 Convert.Emit(this.body, il, Typeob.Object, this.fields[i].FieldType);
  1178.                 il.Emit(OpCodes.Stloc, (LocalBuilder)field.metaData);
  1179.             }
  1180.             il.Emit(OpCodes.Pop);
  1181.         }
  1182.        
  1183.         private void TranslateToILToCopyLocalsFromNestedScope(ILGenerator il, FunctionScope nestedScope)
  1184.         {
  1185.             int offset = (this.attributes & MethodAttributes.Static) == MethodAttributes.Static ? 0 : 1;
  1186.             int n = this.fields.Length;
  1187.             for (int i = 0; i < n; i++) {
  1188.                 JSLocalField field = nestedScope.GetOuterLocalField(this.fields[i].Name);
  1189.                 if (field == null || field.outerField != this.fields[i])
  1190.                     continue;
  1191.                 il.Emit(OpCodes.Dup);
  1192.                 ConstantWrapper.TranslateToILInt(il, this.fields[i].slotNumber);
  1193.                 il.Emit(OpCodes.Ldloc, (LocalBuilder)field.metaData);
  1194.                 Convert.Emit(this.body, il, this.fields[i].FieldType, Typeob.Object);
  1195.                 il.Emit(OpCodes.Stelem_Ref);
  1196.             }
  1197.             il.Emit(OpCodes.Pop);
  1198.         }
  1199.     }
  1200. }

Developer Fusion