From 1b7288df5eb91031747f2d0b1487127e871df7c2 Mon Sep 17 00:00:00 2001 From: Thrasha <112633551+Thrasha@users.noreply.github.com> Date: Wed, 17 Jul 2024 21:52:45 +0400 Subject: [PATCH] Make EsprimaExtensions.TryGetKey[ more resilient to missing execution context --- Jint.Tests/Runtime/EvaluationContextTests.cs | 14 ++++++++++++++ Jint/AstExtensions.cs | 10 +++++----- Jint/Engine.cs | 6 +++--- Jint/Native/Function/EvalFunction.cs | 5 ++++- .../Interpreter/Expressions/JintExpression.cs | 2 +- 5 files changed, 27 insertions(+), 10 deletions(-) create mode 100644 Jint.Tests/Runtime/EvaluationContextTests.cs diff --git a/Jint.Tests/Runtime/EvaluationContextTests.cs b/Jint.Tests/Runtime/EvaluationContextTests.cs new file mode 100644 index 0000000000..1cdb4f3f97 --- /dev/null +++ b/Jint.Tests/Runtime/EvaluationContextTests.cs @@ -0,0 +1,14 @@ +namespace Jint.Tests.Runtime; + +public class EvaluationContextTests +{ + [Fact] + public void ShouldThrowJavaScriptException() + { + var mockedEngine = new Engine(); + + Expression expression = new Identifier(NodeType.MemberExpression.ToString()); + + Assert.Throws(() => AstExtensions.TryGetComputedPropertyKey(expression, mockedEngine)); + } +} diff --git a/Jint/AstExtensions.cs b/Jint/AstExtensions.cs index 3cab91dde5..a5583f1e3e 100644 --- a/Jint/AstExtensions.cs +++ b/Jint/AstExtensions.cs @@ -62,7 +62,7 @@ internal static JsValue TryGetKey(this T expression, Engine engine, bool reso return key; } - private static JsValue TryGetComputedPropertyKey(T expression, Engine engine) + internal static JsValue TryGetComputedPropertyKey(T expression, Engine engine) where T : Expression { if (expression.Type is NodeType.Identifier @@ -79,8 +79,8 @@ or NodeType.FunctionExpression or NodeType.YieldExpression or NodeType.TemplateLiteral) { - var context = engine._activeEvaluationContext; - return JintExpression.Build(expression).GetValue(context!); + var context = engine._activeEvaluationContext ?? new EvaluationContext(engine); + return JintExpression.Build(expression).GetValue(context); } return JsValue.Undefined; @@ -152,7 +152,7 @@ internal static bool IsAnonymousFunctionDefinition(this T node) where T : Nod internal static bool IsOptional(this T node) where T : Expression { return node is IChainElement { Optional: true }; - } + } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static string LiteralKeyToString(Literal literal) @@ -318,7 +318,7 @@ internal static Record DefineMethod(this T m, ObjectInstance obj, ObjectInsta var runningExecutionContext = engine.ExecutionContext; var env = runningExecutionContext.LexicalEnvironment; - var privateEnv= runningExecutionContext.PrivateEnvironment; + var privateEnv = runningExecutionContext.PrivateEnvironment; var prototype = functionPrototype ?? intrinsics.Function.PrototypeObject; var function = m.Value as IFunction; diff --git a/Jint/Engine.cs b/Jint/Engine.cs index 3c50a94e85..2ba6a12429 100644 --- a/Jint/Engine.cs +++ b/Jint/Engine.cs @@ -62,7 +62,7 @@ public sealed partial class Engine : IDisposable internal readonly Dictionary TypeCache = new(StringComparer.Ordinal); // we use registered type reference as prototype if it's known - internal Dictionary? _typeReferences; + internal Dictionary? _typeReferences; // cache for already wrapped CLR objects to keep object identity internal ConditionalWeakTable? _objectWrapperCache; @@ -459,7 +459,7 @@ private Engine ScriptEvaluation(ScriptRecord scriptRecord, ParserOptions parserO // TODO what about callstack and thrown exceptions? RunAvailableContinuations(); - return this; + return this; } finally { @@ -1243,7 +1243,7 @@ internal void EvalDeclarationInstantiation( { foreach (var name in pointer.Names) { - privateIdentifiers??= new HashSet(PrivateIdentifierNameComparer._instance); + privateIdentifiers ??= new HashSet(PrivateIdentifierNameComparer._instance); privateIdentifiers.Add(name.Key); } diff --git a/Jint/Native/Function/EvalFunction.cs b/Jint/Native/Function/EvalFunction.cs index 4aa9af4baf..099067c488 100644 --- a/Jint/Native/Function/EvalFunction.cs +++ b/Jint/Native/Function/EvalFunction.cs @@ -1,6 +1,7 @@ using Jint.Runtime; using Jint.Runtime.Descriptors; using Jint.Runtime.Environments; +using Jint.Runtime.Interpreter; using Jint.Runtime.Interpreter.Statements; using Environment = Jint.Runtime.Environments.Environment; @@ -178,7 +179,9 @@ internal JsValue PerformEval(JsValue x, Realm callerRealm, bool strictCaller, bo Engine.EvalDeclarationInstantiation(script, varEnv, lexEnv, privateEnv, strictEval); var statement = new JintScript(script); - var result = statement.Execute(_engine._activeEvaluationContext!); + var context = _engine._activeEvaluationContext ?? new EvaluationContext(_engine); + var result = statement.Execute(context); + var value = result.GetValueOrDefault(); if (result.Type == CompletionType.Throw) diff --git a/Jint/Runtime/Interpreter/Expressions/JintExpression.cs b/Jint/Runtime/Interpreter/Expressions/JintExpression.cs index 4a5f0f9feb..2767688dd6 100644 --- a/Jint/Runtime/Interpreter/Expressions/JintExpression.cs +++ b/Jint/Runtime/Interpreter/Expressions/JintExpression.cs @@ -132,7 +132,7 @@ protected internal static JintExpression Build(Expression expression) : new JintMemberExpression((MemberExpression) ((ChainExpression) expression).Expression), NodeType.AwaitExpression => new JintAwaitExpression((AwaitExpression) expression), NodeType.YieldExpression => new JintYieldExpression((YieldExpression) expression), - _ => null + _ => null }; if (result is null)