Browse Source

Fix throwing on accessing CLR FunctionDeclaration (#1949)

Matěj Štágl 1 year ago
parent
commit
4767b3ab25

+ 40 - 0
Jint.Tests/Runtime/InteropTests.cs

@@ -3,6 +3,7 @@ using System.Globalization;
 using System.Reflection;
 using System.Runtime.CompilerServices;
 using Jint.Native;
+using Jint.Native.Function;
 using Jint.Runtime;
 using Jint.Runtime.Interop;
 using Jint.Tests.Runtime.Converters;
@@ -3545,4 +3546,43 @@ try {
          
         props.Should().BeEquivalentTo(["Get_A"]);
     }
+    
+    [Fact]
+    public void ShouldNotThrowOnInspectingClrFunction()
+    {
+        var engine = new Engine();
+        
+        engine.SetValue("clrDelegate", () => 4);
+        
+        var val = engine.GetValue("clrDelegate");
+
+        var fn = val as Function;
+        var decl = fn!.FunctionDeclaration;
+
+        decl.Should().BeNull();
+    }
+    
+    private class ShouldNotThrowOnInspectingClrFunctionTestClass
+    {
+        public int MyInt()
+        {
+            return 4;
+        }
+    }
+    
+    [Fact]
+    public void ShouldNotThrowOnInspectingClrClassFunction()
+    {
+        var engine = new Engine();
+        
+        engine.SetValue("clrCls", new ShouldNotThrowOnInspectingClrFunctionTestClass());
+        
+        var val = engine.GetValue("clrCls");
+        var clrFn = val.Get("MyInt");
+        
+        var fn = clrFn as Function;
+        var decl = fn!.FunctionDeclaration;
+        
+        decl.Should().BeNull();
+    }
 }

+ 2 - 2
Jint/Engine.cs

@@ -1047,7 +1047,7 @@ public sealed partial class Engine : IDisposable
         var env = (FunctionEnvironment) ExecutionContext.LexicalEnvironment;
         var strict = _isStrict || StrictModeScope.IsStrictModeCode;
 
-        var configuration = func.Initialize();
+        var configuration = func!.Initialize();
         var parameterNames = configuration.ParameterNames;
         var hasDuplicates = configuration.HasDuplicates;
         var simpleParameterList = configuration.IsSimpleParameterList;
@@ -1618,4 +1618,4 @@ public sealed partial class Engine : IDisposable
         public Environment VariableEnvironment => _engine.ExecutionContext.VariableEnvironment;
         public Environment LexicalEnvironment => _engine.ExecutionContext.LexicalEnvironment;
     }
-}
+}

+ 2 - 2
Jint/Native/Function/Function.cs

@@ -20,7 +20,7 @@ public abstract partial class Function : ObjectInstance, ICallable
     internal PropertyDescriptor? _nameDescriptor;
 
     internal Environment? _environment;
-    internal readonly JintFunctionDefinition _functionDefinition = null!;
+    internal readonly JintFunctionDefinition? _functionDefinition;
     internal readonly FunctionThisMode _thisMode;
     internal JsValue _homeObject = Undefined;
     internal ConstructorKind _constructorKind = ConstructorKind.Base;
@@ -71,7 +71,7 @@ public abstract partial class Function : ObjectInstance, ICallable
     }
 
     // for example RavenDB wants to inspect this
-    public IFunction FunctionDeclaration => _functionDefinition.Function;
+    public IFunction? FunctionDeclaration => _functionDefinition?.Function;
 
     internal override bool IsCallable => true;
 

+ 2 - 2
Jint/Native/Function/ScriptFunction.cs

@@ -58,7 +58,7 @@ public sealed class ScriptFunction : Function, IConstructor
     /// </summary>
     protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments)
     {
-        var strict = _functionDefinition.Strict || _thisMode == FunctionThisMode.Strict;
+        var strict = _functionDefinition!.Strict || _thisMode == FunctionThisMode.Strict;
         using (new StrictModeScope(strict, true))
         {
             try
@@ -158,7 +158,7 @@ public sealed class ScriptFunction : Function, IConstructor
 
                 var context = _engine._activeEvaluationContext ?? new EvaluationContext(_engine);
 
-                var result = _functionDefinition.EvaluateBody(context, this, arguments);
+                var result = _functionDefinition!.EvaluateBody(context, this, arguments);
 
                 // The DebugHandler needs the current execution context before the return for stepping through the return point
                 // We exclude the empty constructor generated for classes without an explicit constructor.