mirror of
https://github.com/SSCLI/sscli_20021101
synced 2026-06-08 12:28:57 +00:00
9fa3874800
Moved the original file to the archive subfolder.
159 lines
5.8 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
}
|