Files
yallie 9fa3874800 Added the contents of the archive.
Moved the original file to the archive subfolder.
2017-11-20 16:11:42 +03:00

159 lines
5.8 KiB
C#

// ==++==
//
//
// Copyright (c) 2002 Microsoft Corporation. All rights reserved.
//
// The use and distribution terms for this software are contained in the file
// named license.txt, which can be found in the root of this distribution.
// By using this software in any fashion, you are agreeing to be bound by the
// terms of this license.
//
// You must not remove this notice, or any other, from this software.
//
//
// ==--==
namespace Microsoft.JScript
{
using Microsoft.JScript.Vsa;
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Globalization;
using System.Diagnostics;
internal sealed class JSNativeMethod : JSMethod{
private MethodInfo method;
private ParameterInfo[] formalParams;
private bool hasThis;
private bool hasVarargs;
private bool hasEngine;
private VsaEngine engine;
internal JSNativeMethod(MethodInfo method, Object obj, VsaEngine engine)
: base(obj){
this.method = method;
this.formalParams = method.GetParameters();
Object[] attrs = method.GetCustomAttributes(Typeob.JSFunctionAttribute, false);
JSFunctionAttribute attr = attrs.Length > 0 ? (JSFunctionAttribute)attrs[0] : new JSFunctionAttribute((JSFunctionAttributeEnum)0);
JSFunctionAttributeEnum attrVal = attr.attributeValue;
if ((attrVal & JSFunctionAttributeEnum.HasThisObject) != 0)
this.hasThis = true;
if ((attrVal & JSFunctionAttributeEnum.HasEngine) != 0)
this.hasEngine = true;
if ((attrVal & JSFunctionAttributeEnum.HasVarArgs) != 0)
this.hasVarargs = true;
this.engine = engine;
}
internal override Object Construct(Object[] args){
throw new JScriptException(JSError.NoConstructor);
}
public override MethodAttributes Attributes{
get{
return this.method.Attributes;
}
}
public override Type DeclaringType{
get{
return this.method.DeclaringType;
}
}
public override ParameterInfo[] GetParameters(){
return this.formalParams;
}
internal override MethodInfo GetMethodInfo(CompilerGlobals compilerGlobals){
return this.method;
}
#if !DEBUG
[DebuggerStepThroughAttribute]
[DebuggerHiddenAttribute]
#endif
internal override Object Invoke(Object obj, Object thisob, BindingFlags options, Binder binder, Object[] parameters, CultureInfo culture){
int n = this.formalParams.Length;
int pn = (parameters != null ? parameters.Length : 0);
if (!this.hasThis && !this.hasVarargs && n == pn)
if (binder != null)
return this.method.Invoke(this.obj, BindingFlags.SuppressChangeType, null, this.ConvertParams(0, parameters, binder, culture), null);
else
return this.method.Invoke(this.obj, options, binder, parameters, culture);
int offset = (this.hasThis ? 1 : 0) + (this.hasEngine ? 1 : 0);
Object[] arguments = new Object[n];
if (this.hasThis){
arguments[0] = thisob;
if (this.hasEngine)
arguments[1] = this.engine;
}else if (this.hasEngine)
arguments[0] = this.engine;
if (this.hasVarargs){
if (n == offset+1) //No params other than the vararg array
arguments[offset] = parameters;
else{
//Some of the values in parameters must be passed separately from the vararg array
int argsToCopy = n - 1 - offset; //The number of separate arguments
if (pn > argsToCopy){
ArrayObject.Copy(parameters, 0, arguments, offset, argsToCopy);
int vn = pn-argsToCopy;
Object[] varargs = new Object[vn];
ArrayObject.Copy(parameters, argsToCopy, varargs, 0, vn);
arguments[n - 1] = varargs;
}else{
ArrayObject.Copy(parameters, 0, arguments, offset, pn);
for (int i = pn; i < argsToCopy; i++)
arguments[i+offset] = Missing.Value;
arguments[n - 1] = new Object[0];
}
}
}else{
if(parameters != null){
if (n-offset < pn)
ArrayObject.Copy(parameters, 0, arguments, offset, n-offset);
else
ArrayObject.Copy(parameters, 0, arguments, offset, pn);
}
if(n-offset > pn){
for (int i = pn+offset; i < n; i++)
if (i == n-1 && this.formalParams[i].ParameterType.IsArray && this.formalParams[i].IsDefined(Typeob.ParamArrayAttribute, true))
arguments[i] = System.Array.CreateInstance(this.formalParams[i].ParameterType.GetElementType(), 0);
else
arguments[i] = Missing.Value;
}
}
if (binder != null)
return this.method.Invoke(this.obj, BindingFlags.SuppressChangeType, null, this.ConvertParams(offset, arguments, binder, culture), null);
else
return this.method.Invoke(this.obj, options, binder, arguments, culture);
}
private Object[] ConvertParams(int offset, Object[] parameters, Binder binder, CultureInfo culture){
int n = this.formalParams.Length;
if (this.hasVarargs) n--;
for (int i = offset; i < n; i++){
Type fpt = this.formalParams[i].ParameterType;
if (fpt != Typeob.Object)
parameters[i] = binder.ChangeType(parameters[i], fpt, culture);
}
return parameters;
}
public override String Name{
get{
return this.method.Name;
}
}
public override Type ReturnType{
get{
return this.method.ReturnType;
}
}
}
}