using System.Runtime.ExceptionServices;
using Jint.Native;
using Jint.Native.Function;
using Jint.Runtime.Descriptors;
namespace Jint.Runtime.Interop
{
///
/// Wraps a Clr method into a FunctionInstance
///
public sealed class ClrFunctionInstance : FunctionInstance, IEquatable
{
private readonly string? _name;
internal readonly Func _func;
public ClrFunctionInstance(
Engine engine,
string name,
Func func,
int length = 0,
PropertyFlag lengthFlags = PropertyFlag.AllForbidden)
: base(engine, engine.Realm, name != null ? new JsString(name) : null)
{
_name = name;
_func = func;
_prototype = engine._originalIntrinsics.Function.PrototypeObject;
_length = lengthFlags == PropertyFlag.AllForbidden
? PropertyDescriptor.AllForbiddenDescriptor.ForNumber(length)
: new PropertyDescriptor(JsNumber.Create(length), lengthFlags);
}
protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments)
{
try
{
return _func(thisObject, arguments);
}
catch (Exception e) when (e is not JavaScriptException)
{
if (_engine.Options.Interop.ExceptionHandler(e))
{
ExceptionHelper.ThrowJavaScriptException(_realm.Intrinsics.Error, e.Message);
}
else
{
ExceptionDispatchInfo.Capture(e).Throw();
}
return Undefined;
}
}
public override bool Equals(JsValue? obj)
{
return Equals(obj as ClrFunctionInstance);
}
public bool Equals(ClrFunctionInstance? other)
{
if (ReferenceEquals(null, other))
{
return false;
}
if (ReferenceEquals(this, other))
{
return true;
}
if (_func == other._func)
{
return true;
}
return false;
}
public override string ToString() => "function " + _name + "() { [native code] }";
}
}