From 4767b3ab2520ecab9921ccedbbbeb7459ee91875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20=C5=A0t=C3=A1gl?= Date: Sun, 18 Aug 2024 07:24:23 +0200 Subject: [PATCH] Fix throwing on accessing CLR FunctionDeclaration (#1949) --- Jint.Tests/Runtime/InteropTests.cs | 40 ++++++++++++++++++++++++++ Jint/Engine.cs | 4 +-- Jint/Native/Function/Function.cs | 4 +-- Jint/Native/Function/ScriptFunction.cs | 4 +-- 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/Jint.Tests/Runtime/InteropTests.cs b/Jint.Tests/Runtime/InteropTests.cs index 3b1593def..7054c1d0f 100644 --- a/Jint.Tests/Runtime/InteropTests.cs +++ b/Jint.Tests/Runtime/InteropTests.cs @@ -3,6 +3,7 @@ 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 @@ public void ShouldSeeClrMethods2() 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(); + } } diff --git a/Jint/Engine.cs b/Jint/Engine.cs index d33d13043..40bf799dd 100644 --- a/Jint/Engine.cs +++ b/Jint/Engine.cs @@ -1047,7 +1047,7 @@ private void GlobalDeclarationInstantiation( 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 EngineDebugView(Engine engine) public Environment VariableEnvironment => _engine.ExecutionContext.VariableEnvironment; public Environment LexicalEnvironment => _engine.ExecutionContext.LexicalEnvironment; } -} \ No newline at end of file +} diff --git a/Jint/Native/Function/Function.cs b/Jint/Native/Function/Function.cs index 734ce347a..8742342aa 100644 --- a/Jint/Native/Function/Function.cs +++ b/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 @@ internal Function( } // for example RavenDB wants to inspect this - public IFunction FunctionDeclaration => _functionDefinition.Function; + public IFunction? FunctionDeclaration => _functionDefinition?.Function; internal override bool IsCallable => true; diff --git a/Jint/Native/Function/ScriptFunction.cs b/Jint/Native/Function/ScriptFunction.cs index 421a59e0b..9c07c9891 100644 --- a/Jint/Native/Function/ScriptFunction.cs +++ b/Jint/Native/Function/ScriptFunction.cs @@ -58,7 +58,7 @@ internal ScriptFunction( /// 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 @@ ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget) 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.