From a6f11c4864646c010ca3d455c4b499e2ba9360a5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Apr 2026 09:38:56 +0000 Subject: [PATCH 1/3] Initial plan From f9c99c5e7adce46cf655397e71d774b9e3481f4e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Apr 2026 10:02:40 +0000 Subject: [PATCH 2/3] Fix frozen JsBinaryExpression error in string.IsNullOrEmpty binding translation Agent-Logs-Url: https://github.com/riganti/dotvvm/sessions/13a597db-6d37-4df2-99f1-73f83128f1c8 Co-authored-by: tomasherceg <5599524+tomasherceg@users.noreply.github.com> --- .../Compilation/Javascript/Ast/JsAstHelpers.cs | 2 ++ .../Binding/JavascriptCompilationTests.cs | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/Framework/Framework/Compilation/Javascript/Ast/JsAstHelpers.cs b/src/Framework/Framework/Compilation/Javascript/Ast/JsAstHelpers.cs index 11bdce52b8..98c7de01b5 100644 --- a/src/Framework/Framework/Compilation/Javascript/Ast/JsAstHelpers.cs +++ b/src/Framework/Framework/Compilation/Javascript/Ast/JsAstHelpers.cs @@ -73,6 +73,8 @@ public static ParametrizedCode FormatParametrizedScript(this JsNode node, bool n { if (node is null) throw new ArgumentNullException(nameof(node)); + // FixParenthesis modifies the tree in-place; if the node is frozen we must clone it first + if (node.IsFrozen) node = node.Clone(); node = node.FixParenthesis(); var visitor = new JsFormattingVisitor(niceMode, indent); node.AcceptVisitor(visitor); diff --git a/src/Tests/Binding/JavascriptCompilationTests.cs b/src/Tests/Binding/JavascriptCompilationTests.cs index 1b480c61cf..1805d872bf 100644 --- a/src/Tests/Binding/JavascriptCompilationTests.cs +++ b/src/Tests/Binding/JavascriptCompilationTests.cs @@ -1,4 +1,6 @@ using DotVVM.Framework.Binding; +using DotVVM.Framework.Binding.Expressions; +using DotVVM.Framework.Binding.Properties; using DotVVM.Framework.Controls; using DotVVM.Framework.Runtime; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -1511,6 +1513,22 @@ public void JavascriptCompilation_StringFunctions(string input, string expected) Assert.AreEqual(expected, result); } + [TestMethod] + [DataRow("VmArray.Where(v => string.IsNullOrEmpty(v.SomeString)).ToList()")] + [DataRow("VmArray.Where(v => string.IsNullOrWhiteSpace(v.SomeString)).ToList()")] + // Regression test: FormatParametrizedScript was called on a frozen JsBinaryExpression (from string.IsNullOrEmpty/IsNullOrWhiteSpace + // translation) causing ObjectIsFrozenException when computing SimplePathExpressionBindingProperty. + public void JavascriptCompilation_IsNullOrEmpty_InWhereLambda_DoesNotThrowOnSimplePathExpression(string expression) + { + var binding = bindingHelper.ValueBinding>( + expression, + new[] { typeof(TestViewModel) }); + // Getting SimplePathExpressionBindingProperty should not throw + var simplePath = binding.GetProperty(typeof(SimplePathExpressionBindingProperty), ErrorHandlingMode.ReturnException); + Assert.IsNotInstanceOfType(simplePath, typeof(Exception), + $"Getting SimplePathExpressionBindingProperty threw an exception: {simplePath}"); + } + [TestMethod] public void JavascriptCompilation_CustomPrimitiveToString() { From 4854507f4101d8c1f6c2e9bf9e9f9fb1f0cc20ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Herceg?= Date: Thu, 2 Apr 2026 12:47:39 +0200 Subject: [PATCH 3/3] Test simplified --- .../Binding/JavascriptCompilationTests.cs | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/Tests/Binding/JavascriptCompilationTests.cs b/src/Tests/Binding/JavascriptCompilationTests.cs index 1805d872bf..84a524c127 100644 --- a/src/Tests/Binding/JavascriptCompilationTests.cs +++ b/src/Tests/Binding/JavascriptCompilationTests.cs @@ -1,25 +1,26 @@ -using DotVVM.Framework.Binding; -using DotVVM.Framework.Binding.Expressions; -using DotVVM.Framework.Binding.Properties; -using DotVVM.Framework.Controls; -using DotVVM.Framework.Runtime; -using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; +using System.Text.Json.Serialization; using System.Threading.Tasks; +using DotVVM.Framework.Binding; +using DotVVM.Framework.Binding.Expressions; +using DotVVM.Framework.Binding.Properties; using DotVVM.Framework.Compilation; using DotVVM.Framework.Compilation.Binding; using DotVVM.Framework.Compilation.ControlTree; using DotVVM.Framework.Compilation.Javascript; using DotVVM.Framework.Compilation.Javascript.Ast; -using DotVVM.Framework.Testing; using DotVVM.Framework.Configuration; -using System.Linq.Expressions; -using Microsoft.Extensions.DependencyInjection; +using DotVVM.Framework.Controls; +using DotVVM.Framework.Runtime; +using DotVVM.Framework.Testing; using DotVVM.Framework.Utils; using DotVVM.Framework.ViewModel; -using System.Text.Json.Serialization; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using static DotVVM.Framework.Configuration.FreezableUtils; namespace DotVVM.Framework.Tests.Binding { @@ -1523,10 +1524,7 @@ public void JavascriptCompilation_IsNullOrEmpty_InWhereLambda_DoesNotThrowOnSimp var binding = bindingHelper.ValueBinding>( expression, new[] { typeof(TestViewModel) }); - // Getting SimplePathExpressionBindingProperty should not throw - var simplePath = binding.GetProperty(typeof(SimplePathExpressionBindingProperty), ErrorHandlingMode.ReturnException); - Assert.IsNotInstanceOfType(simplePath, typeof(Exception), - $"Getting SimplePathExpressionBindingProperty threw an exception: {simplePath}"); + var simplePath = binding.GetProperty(typeof(SimplePathExpressionBindingProperty), ErrorHandlingMode.ThrowException); } [TestMethod]