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

  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.Globalization;
  21.     using System.Diagnostics;
  22.    
  23.     public abstract class ScriptFunction : JSObject
  24.     {
  25.         protected int ilength;
  26.         internal string name;
  27.        
  28.         internal object proto;
  29.        
  30.         internal ScriptFunction(ScriptObject parent) : base(parent)
  31.         {
  32.             this.ilength = 0;
  33.             this.name = "Function.prototype";
  34.             this.proto = Missing.Value;
  35.         }
  36.        
  37.         protected ScriptFunction(ScriptObject parent, string name) : base(parent, typeof(ScriptFunction))
  38.         {
  39.             this.ilength = 0;
  40.             this.name = name;
  41.             this.proto = new JSPrototypeObject(parent.GetParent(), this);
  42.         }
  43.        
  44.         internal ScriptFunction(ScriptObject parent, string name, int length) : base(parent)
  45.         {
  46.             this.ilength = length;
  47.             this.name = name;
  48.             this.proto = new JSPrototypeObject(parent.GetParent(), this);
  49.         }
  50.        
  51.         #if !DEBUG
  52.         [DebuggerStepThroughAttribute()]
  53.         [DebuggerHiddenAttribute()]
  54.         #endif
  55.         internal abstract object Call(object[] args, object thisob);
  56.        
  57.         internal virtual object Call(object[] args, object thisob, Binder binder, CultureInfo culture)
  58.         {
  59.             return this.Call(args, thisob);
  60.         }
  61.        
  62.         internal virtual object Call(object[] args, object thisob, ScriptObject enclosing_scope, Closure calleeClosure, Binder binder, CultureInfo culture)
  63.         {
  64.             return this.Call(args, thisob);
  65.         }
  66.        
  67.         #if !DEBUG
  68.         [DebuggerStepThroughAttribute()]
  69.         [DebuggerHiddenAttribute()]
  70.         #endif
  71.         internal virtual object Construct(object[] args)
  72.         {
  73.             JSObject newob = new JSObject(null, false);
  74.             newob.SetParent(this.GetPrototypeForConstructedObject());
  75.             object result = this.Call(args, newob);
  76.             if (result is ScriptObject || (this is BuiltinFunction && ((BuiltinFunction)this).method.Name.Equals("CreateInstance")))
  77.                 return result;
  78.             return newob;
  79.         }
  80.        
  81.         #if !DEBUG
  82.         [DebuggerStepThroughAttribute()]
  83.         [DebuggerHiddenAttribute()]
  84.         #endif
  85.         [JSFunctionAttribute(JSFunctionAttributeEnum.HasVarArgs)]
  86.         public object CreateInstance(params object[] args)
  87.         {
  88.             return this.Construct(args);
  89.         }
  90.        
  91.         internal override string GetClassName()
  92.         {
  93.             return "Function";
  94.         }
  95.        
  96.         internal virtual int GetNumberOfFormalParameters()
  97.         {
  98.             return this.ilength;
  99.         }
  100.        
  101.         protected ScriptObject GetPrototypeForConstructedObject()
  102.         {
  103.             object ob = this.proto;
  104.             if (ob is JSObject)
  105.                 return (JSObject)ob;
  106.             else if (ob is ClassScope)
  107.                 return (ClassScope)ob;
  108.             else
  109.                 return (ObjectPrototype)(this.GetParent().GetParent());
  110.             //The prototype of function is FunctionPrototype, its Prototype is ObjectPrototype
  111.         }
  112.        
  113.         internal virtual bool HasInstance(object ob)
  114.         {
  115.             if (!(ob is JSObject))
  116.                 return false;
  117.             object proto = this.proto;
  118.             if (!(proto is ScriptObject))
  119.                 throw new JScriptException(JSError.InvalidPrototype);
  120.             ScriptObject parent = ((JSObject)ob).GetParent();
  121.             ScriptObject prot = (ScriptObject)proto;
  122.             while (parent != null) {
  123.                 if (parent == prot)
  124.                     return true;
  125.                 else if (parent is WithObject) {
  126.                     object wob = ((WithObject)parent).contained_object;
  127.                     if (wob == prot && wob is ClassScope)
  128.                         return true;
  129.                 }
  130.                 parent = parent.GetParent();
  131.             }
  132.             return false;
  133.         }
  134.        
  135.         #if !DEBUG
  136.         [DebuggerStepThroughAttribute()]
  137.         [DebuggerHiddenAttribute()]
  138.         #endif
  139.         [JSFunctionAttribute(JSFunctionAttributeEnum.HasThisObject | JSFunctionAttributeEnum.HasVarArgs)]
  140.         public object Invoke(object thisob, params object[] args)
  141.         {
  142.             return this.Call(args, thisob);
  143.         }
  144.        
  145.         #if !DEBUG
  146.         [DebuggerStepThroughAttribute()]
  147.         [DebuggerHiddenAttribute()]
  148.         #endif
  149.         public override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters)
  150.         {
  151.             if (target != this)
  152.                 throw new TargetException();
  153.            
  154.             string thisName = "this";
  155.            
  156.             if (name == null || name == String.Empty) {
  157.                 if ((invokeAttr & BindingFlags.CreateInstance) != 0) {
  158.                     if ((invokeAttr & (BindingFlags.InvokeMethod | BindingFlags.GetField | BindingFlags.GetProperty | BindingFlags.SetField | BindingFlags.SetProperty | BindingFlags.PutDispProperty)) != 0)
  159.                         throw new ArgumentException();
  160.                     return this.Construct(args);
  161.                 }
  162.                
  163.                 if ((invokeAttr & BindingFlags.InvokeMethod) != 0) {
  164.                     //Get the this object
  165.                     object thisob = null;
  166.                     if (namedParameters != null) {
  167.                         int i = Array.IndexOf(namedParameters, thisName);
  168.                         if (i == 0) {
  169.                             thisob = args[0];
  170.                             int n = args.Length - 1;
  171.                             object[] args2 = new object[n];
  172.                             ArrayObject.Copy(args, 1, args2, 0, n);
  173.                             args = args2;
  174.                         }
  175.                         if (i != 0 || namedParameters.Length != 1)
  176.                             throw new ArgumentException();
  177.                     }
  178.                    
  179.                     //Prefer call only if there GetXXX is not set, or there is one or more args.
  180.                     if (args.Length > 0 || (invokeAttr & (BindingFlags.GetField | BindingFlags.GetProperty)) == 0)
  181.                         return this.Call(args, thisob, binder, culture);
  182.                 }
  183.             }
  184.             return base.InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters);
  185.         }
  186.        
  187.         public virtual int length {
  188.             get { return this.ilength; }
  189.             set { }
  190.         }
  191.        
  192.         public override string ToString()
  193.         {
  194.             return "function " + this.name + "() {\n [native code]\n}";
  195.         }
  196.        
  197.         public object prototype {
  198.             get { return this.proto; }
  199.             set {
  200.                 if (!this.noExpando)
  201.                     this.proto = value;
  202.             }
  203.         }
  204.     }
  205. }

Developer Fusion