Skip to content

Commit

Permalink
Merge pull request #1692 from riganti/fix-translation-collection-repe…
Browse files Browse the repository at this point in the history
…ated-init

Fix repeated initialization of JS translator collection
  • Loading branch information
tomasherceg authored Aug 26, 2023
2 parents 7ed29e3 + e66d353 commit dfc0706
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,12 @@ public StaticCommandBindingCompiler(IOptions<JavascriptTranslatorConfiguration>
JavascriptTranslator CreateTranslator(DataContextStack dataContext)
{
var staticCommandTranslator = ActivatorUtilities.CreateInstance<StaticCommandMethodTranslator>(services, dataContext);
var configForStaticCommands = new JavascriptTranslatorConfiguration();
configForStaticCommands.Translators.Add(this.translatorConfiguration);
configForStaticCommands.Translators.Add(staticCommandTranslator);
var configForStaticCommands = new CompositeJavascriptTranslator {
Translators = {
this.translatorConfiguration,
staticCommandTranslator
}
};

return new JavascriptTranslator(configForStaticCommands, serializationMapper);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Linq.Expressions;
using System.Net;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using DotVVM.Framework.Binding;
using DotVVM.Framework.Binding.HelperNamespace;
Expand Down Expand Up @@ -38,14 +39,24 @@ public class DelegateInvokeMethodTranslator : IJavascriptMethodTranslator
}
}

public partial class JavascriptTranslatableMethodCollection : IJavascriptMethodTranslator
public partial class JavascriptTranslatableMethodCollection : IJavascriptMethodTranslator, ICloneable
{
public readonly Dictionary<MethodInfo, IJavascriptMethodTranslator> MethodTranslators = new Dictionary<MethodInfo, IJavascriptMethodTranslator>();
public readonly HashSet<Type> Interfaces = new HashSet<Type>();

public JavascriptTranslatableMethodCollection()
private JavascriptTranslatableMethodCollection() { }

public static JavascriptTranslatableMethodCollection CreateEmpty() => new();
private static JavascriptTranslatableMethodCollection? premadeDefault;
public static JavascriptTranslatableMethodCollection CreateDefault()
{
AddDefaultMethodTranslators();
if (premadeDefault is null)
{
var result = CreateEmpty();
result.AddDefaultMethodTranslators();
Interlocked.CompareExchange(ref premadeDefault, result, null);
}
return premadeDefault.Clone();
}

public void AddMethodTranslator(Type declaringType, string methodName, IJavascriptMethodTranslator translator, Type[]? parameters = null, bool allowGeneric = true, bool allowMultipleMethods = false)
Expand Down Expand Up @@ -820,5 +831,19 @@ JsExpression wrapInRound(JsExpression a) =>
if (baseMethod != null && baseMethod != method) return TryTranslateCall(context, args, baseMethod);
else return null;
}

public JavascriptTranslatableMethodCollection Clone()
{
var clone = new JavascriptTranslatableMethodCollection();
foreach (var i in Interfaces)
clone.Interfaces.Add(i);
foreach (var item in MethodTranslators)
{
var translator = item.Value is ICloneable cloneable ? (IJavascriptMethodTranslator)cloneable.Clone() : item.Value;
clone.MethodTranslators.Add(item.Key, translator);
}
return clone;
}
object ICloneable.Clone() => Clone();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using DotVVM.Framework.Binding.HelperNamespace;
using DotVVM.Framework.Compilation.ControlTree;
using DotVVM.Framework.Compilation.Javascript.Ast;
using DotVVM.Framework.Configuration;
using DotVVM.Framework.Controls;
using DotVVM.Framework.Utils;
using DotVVM.Framework.ViewModel;
Expand Down Expand Up @@ -239,19 +240,35 @@ public static VMPropertyInfoAnnotation FromDotvvmProperty(DotvvmProperty p) =>
: new VMPropertyInfoAnnotation(p.PropertyInfo, p.PropertyType);
}

public class JavascriptTranslatorConfiguration: IJavascriptMethodTranslator
public class CompositeJavascriptTranslator: IJavascriptMethodTranslator
{
private readonly FreezableList<IJavascriptMethodTranslator> _translators = new();
public IList<IJavascriptMethodTranslator> Translators => _translators;
public JsExpression? TryTranslateCall(LazyTranslatedExpression? context, LazyTranslatedExpression[] arguments, MethodInfo method)
{
foreach (var t in this._translators)
{
if (t.TryTranslateCall(context, arguments, method) is {} result)
return result;
}
return null;
}

public void Freeze()
{
_translators.Freeze();
}
}

public class JavascriptTranslatorConfiguration: CompositeJavascriptTranslator
{
public List<IJavascriptMethodTranslator> Translators { get; } = new List<IJavascriptMethodTranslator>();
public JavascriptTranslatableMethodCollection MethodCollection { get; }

public JavascriptTranslatorConfiguration()
{
Translators.Add(MethodCollection = new JavascriptTranslatableMethodCollection());
Translators.Add(MethodCollection = JavascriptTranslatableMethodCollection.CreateDefault());
Translators.Add(new DelegateInvokeMethodTranslator());
Translators.Add(new CustomPrimitiveTypesConversionTranslator());
}

public JsExpression? TryTranslateCall(LazyTranslatedExpression? context, LazyTranslatedExpression[] arguments, MethodInfo method) =>
Translators.Select(t => t.TryTranslateCall(context, arguments, method)).FirstOrDefault(d => d != null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ public void Freeze()
foreach (var t in this.HtmlAttributeTransforms)
t.Value.Freeze();
_defaultDirectives.Freeze();

JavascriptTranslator.Freeze();
}
}
}
3 changes: 2 additions & 1 deletion src/Framework/Framework/Configuration/FreezableList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public void Clear()
}
public bool Contains(T item) => list.Contains(item);
public void CopyTo(T[] array, int arrayIndex) => list.CopyTo(array, arrayIndex);
public IEnumerator<T> GetEnumerator() => list.GetEnumerator();
public List<T>.Enumerator GetEnumerator() => list.GetEnumerator();
public int IndexOf(T item) => list.IndexOf(item);
public void Insert(int index, T item)
{
Expand All @@ -87,6 +87,7 @@ public void RemoveAt(int index)
ThrowIfFrozen();
list.RemoveAt(index);
}
IEnumerator<T> IEnumerable<T>.GetEnumerator() => list.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => list.GetEnumerator();
public void CopyTo(Array array, int index) => ((ICollection)list).CopyTo(array, index);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public static ValidationResult CreateValidationResult<T>(this T vm, string error


private static JavascriptTranslator defaultJavaScriptTranslator = new JavascriptTranslator(
Options.Create(new JavascriptTranslatorConfiguration()),
new JavascriptTranslatorConfiguration(),
new ViewModelSerializationMapper(new ViewModelValidationRuleTranslator(), new AttributeViewModelValidationMetadataProvider(), new DefaultPropertySerialization(), DotvvmConfiguration.CreateDefault()));

public static ValidationResult CreateValidationResult<T>(ValidationContext validationContext, string error, params Expression<Func<T, object>>[] expressions)
Expand Down

0 comments on commit dfc0706

Please sign in to comment.