diff --git a/Jint/Options.cs b/Jint/Options.cs
index 56f7b4d236..74a477434e 100644
--- a/Jint/Options.cs
+++ b/Jint/Options.cs
@@ -295,7 +295,7 @@ public class InteropOptions
/// to the CLR host and interrupt the script execution. If handler returns true these exceptions are converted
/// to JS errors that can be caught by the script.
///
- public ExceptionHandlerDelegate ExceptionHandler { get; set; } = static exception => false;
+ public ExceptionHandlerDelegate ExceptionHandler { get; set; } = _defaultExceptionHandler;
///
/// Assemblies to allow scripts to call CLR types directly like System.IO.File.
@@ -328,6 +328,8 @@ public class InteropOptions
///
public Func CreateTypeReferenceObject = (_, _, _) => null;
+ internal static readonly ExceptionHandlerDelegate _defaultExceptionHandler = static exception => false;
+
///
/// When not null, is used to serialize any CLR object in an
/// passing through 'JSON.stringify'.
diff --git a/Jint/Runtime/Interop/ClrFunctionInstance.cs b/Jint/Runtime/Interop/ClrFunctionInstance.cs
index d777dc5a05..674baf3c4e 100644
--- a/Jint/Runtime/Interop/ClrFunctionInstance.cs
+++ b/Jint/Runtime/Interop/ClrFunctionInstance.cs
@@ -1,78 +1,81 @@
+using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using Jint.Native;
using Jint.Native.Function;
using Jint.Runtime.Descriptors;
-namespace Jint.Runtime.Interop
+namespace Jint.Runtime.Interop;
+
+///
+/// Wraps a Clr method into a FunctionInstance
+///
+public sealed class ClrFunctionInstance : FunctionInstance, IEquatable
{
- ///
- /// Wraps a Clr method into a FunctionInstance
- ///
- public sealed class ClrFunctionInstance : FunctionInstance, IEquatable
+ internal readonly Func _func;
+ private readonly bool _bubbleExceptions;
+
+ public ClrFunctionInstance(
+ Engine engine,
+ string name,
+ Func func,
+ int length = 0,
+ PropertyFlag lengthFlags = PropertyFlag.AllForbidden)
+ : base(engine, engine.Realm, new JsString(name))
{
- internal readonly Func _func;
+ _func = func;
- public ClrFunctionInstance(
- Engine engine,
- string name,
- Func func,
- int length = 0,
- PropertyFlag lengthFlags = PropertyFlag.AllForbidden)
- : base(engine, engine.Realm, new JsString(name))
- {
- _func = func;
+ _prototype = engine._originalIntrinsics.Function.PrototypeObject;
- _prototype = engine._originalIntrinsics.Function.PrototypeObject;
+ _length = lengthFlags == PropertyFlag.AllForbidden
+ ? PropertyDescriptor.AllForbiddenDescriptor.ForNumber(length)
+ : new PropertyDescriptor(JsNumber.Create(length), lengthFlags);
- _length = lengthFlags == PropertyFlag.AllForbidden
- ? PropertyDescriptor.AllForbiddenDescriptor.ForNumber(length)
- : new PropertyDescriptor(JsNumber.Create(length), lengthFlags);
- }
+ _bubbleExceptions = _engine.Options.Interop.ExceptionHandler == InteropOptions._defaultExceptionHandler;
+ }
+
+ protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments) => _bubbleExceptions ? _func(thisObject, arguments) : CallSlow(thisObject, arguments);
- protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments)
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private JsValue CallSlow(JsValue thisObject, JsValue[] arguments)
+ {
+ try
{
- try
+ return _func(thisObject, arguments);
+ }
+ catch (Exception e) when (e is not JavaScriptException)
+ {
+ if (_engine.Options.Interop.ExceptionHandler(e))
{
- return _func(thisObject, arguments);
+ ExceptionHelper.ThrowJavaScriptException(_realm.Intrinsics.Error, e.Message);
}
- catch (Exception e) when (e is not JavaScriptException)
+ else
{
- if (_engine.Options.Interop.ExceptionHandler(e))
- {
- ExceptionHelper.ThrowJavaScriptException(_realm.Intrinsics.Error, e.Message);
- }
- else
- {
- ExceptionDispatchInfo.Capture(e).Throw();
- }
-
- return Undefined;
+ ExceptionDispatchInfo.Capture(e).Throw();
}
+
+ return Undefined;
}
+ }
+
+ public override bool Equals(JsValue? obj) => Equals(obj as ClrFunctionInstance);
- public override bool Equals(JsValue? obj)
+ public bool Equals(ClrFunctionInstance? other)
+ {
+ if (ReferenceEquals(null, other))
{
- return Equals(obj as ClrFunctionInstance);
+ return false;
}
- public bool Equals(ClrFunctionInstance? other)
+ if (ReferenceEquals(this, other))
{
- if (ReferenceEquals(null, other))
- {
- return false;
- }
-
- if (ReferenceEquals(this, other))
- {
- return true;
- }
-
- if (_func == other._func)
- {
- return true;
- }
+ return true;
+ }
- return false;
+ if (_func == other._func)
+ {
+ return true;
}
+
+ return false;
}
}