public JsExpression CompileToJavascript(DataContextStack dataContext, Expression expression) { var currentContextVariable = new JsTemporaryVariableParameter(new JsIdentifierExpression("ko").Member("contextFor").Invoke(new JsSymbolicParameter(CommandBindingExpression.SenderElementParameter))); var resultPromiseVariable = new JsTemporaryVariableParameter(new JsNewExpression("DotvvmPromise")); var senderVariable = new JsTemporaryVariableParameter(new JsSymbolicParameter(CommandBindingExpression.SenderElementParameter)); var visitor = new ExtractExpressionVisitor(ex => ex.NodeType == ExpressionType.Call && ex is MethodCallExpression methodCall && javascriptTranslator.TryTranslateMethodCall(methodCall.Object, methodCall.Arguments.ToArray(), methodCall.Method, dataContext) == null); var rootCallback = visitor.Visit(expression); var js = SouldCompileCallback(rootCallback) ? new JsSymbolicParameter(resultPromiseVariable).Member("resolve").Invoke(javascriptTranslator.CompileToJavascript(rootCallback, dataContext)) : null; foreach (var param in visitor.ParameterOrder.Reverse <ParameterExpression>()) { js = js ?? new JsSymbolicParameter(resultPromiseVariable).Member("resolve").Invoke(new JsIdentifierExpression(param.Name)); var callback = new JsFunctionExpression(new[] { new JsIdentifier(param.Name) }, new JsBlockStatement(new JsExpressionStatement(js))); var method = visitor.Replaced[param] as MethodCallExpression; js = CompileMethodCall(method, dataContext, callback); } foreach (var sp in js.Descendants.OfType <JsSymbolicParameter>()) { if (sp.Symbol == JavascriptTranslator.KnockoutContextParameter) { sp.Symbol = currentContextVariable; } else if (sp.Symbol == JavascriptTranslator.KnockoutViewModelParameter) { sp.ReplaceWith(new JsSymbolicParameter(currentContextVariable).Member("$data")); } else if (sp.Symbol == CommandBindingExpression.SenderElementParameter) { sp.Symbol = senderVariable; } } return(new JsBinaryExpression(js, BinaryOperatorType.Sequence, new JsSymbolicParameter(resultPromiseVariable))); }
public JsExpression GetArgsScript(MethodCallExpression expression, DataContextStack dataContext) { var arguments = (expression.Object == null ? new Expression[0] : new[] { expression.Object }) .Concat(expression.Arguments).Select(a => JavascriptTranslator.CompileToJavascript(a, dataContext, vmMapper)); return(new JsArrayExpression(arguments)); }
public static string GetArgsScript(MethodCallExpression expression, DataContextStack dataContext) { var target = expression.Object == null ? "null" : JavascriptTranslator.CompileToJavascript(expression.Object, dataContext); var arguments = new[] { target }.Concat(expression.Arguments.Select(a => JavascriptTranslator.CompileToJavascript(a, dataContext))); return("[" + String.Join(", ", arguments) + "]"); }
/// <summary> /// Builds a <see cref="ViewModelValidationError.PropertyPath"/> from a LINQ expression /// </summary> public static string BuildPath <TValidationTarget>(Expression <Func <TValidationTarget, object> > propertyAccessor, DotvvmConfiguration configuration) { var context = DataContextStack.Create(typeof(TValidationTarget)); var js = JavascriptTranslator.CompileToJavascript(propertyAccessor, context, configuration.ServiceLocator.GetService <IViewModelSerializationMapper>()); js.AcceptVisitor(new KnockoutObservableHandlingVisitor(true)); var propertyPathExtractingVisitor = new PropertyPathExtractingVisitor(); js.AcceptVisitor(propertyPathExtractingVisitor); return(propertyPathExtractingVisitor.ExtractedPropertyPath); }
public string CompileBinding(string expression, Type[] contexts, Type expectedType) { var context = new DataContextStack(contexts.FirstOrDefault() ?? typeof(object), rootControlType: typeof(DotvvmControl)); for (int i = 1; i < contexts.Length; i++) { context = new DataContextStack(contexts[i], context); } var parser = new BindingExpressionBuilder(); var expressionTree = TypeConversion.ImplicitConversion(parser.Parse(expression, context, BindingParserOptions.Create <ValueBindingExpression>()), expectedType, true, true); return(JavascriptTranslator.CompileToJavascript(expressionTree, context)); }
public override string CompileToJs(ResolvedBinding binding, CompiledBindingExpression compiledExpression) { var expression = binding.GetExpression(); var visitor = new ExtractExpressionVisitor(ex => ex.NodeType == ExpressionType.Call); var rootCallback = visitor.Visit(expression); var js = SouldCompileCallback(rootCallback) ? JavascriptTranslator.CompileToJavascript(rootCallback, binding.DataContextTypeStack) : null; foreach (var param in visitor.ParameterOrder) { var callback = js == null ? null : $"function({param.Name}){{{js}}}"; var method = visitor.Replaced[param] as MethodCallExpression; js = CompileMethodCall(method, binding.DataContextTypeStack, callback); } return("var $context = ko.contextFor(this);var sender = this;(function(i_pageArea){with($context){" + js + "}})"); }
public string CompileBinding(Func <Dictionary <string, Expression>, Expression> expr, Type[] contexts) { var context = DataContextStack.Create(contexts.FirstOrDefault() ?? typeof(object), extensionParameters: new BindingExtensionParameter[] { new BindingPageInfoExtensionParameter() }); for (int i = 1; i < contexts.Length; i++) { context = DataContextStack.Create(contexts[i], context); } var expressionTree = expr(BindingExpressionBuilder.GetParameters(context).ToDictionary(e => e.Name, e => (Expression)e)); var jsExpression = new JsParenthesizedExpression(JavascriptTranslator.CompileToJavascript(expressionTree, context, DotvvmConfiguration.CreateDefault().ServiceLocator.GetService <IViewModelSerializationMapper>())); jsExpression.AcceptVisitor(new KnockoutObservableHandlingVisitor(true)); JsTemporaryVariableResolver.ResolveVariables(jsExpression); return(JavascriptTranslator.FormatKnockoutScript(jsExpression.Expression)); }
public string CompileBinding(string expression, Type[] contexts, Type expectedType) { var context = DataContextStack.Create(contexts.FirstOrDefault() ?? typeof(object), extenstionParameters: new BindingExtensionParameter[] { new BindingPageInfoExtensionParameter() }); for (int i = 1; i < contexts.Length; i++) { context = DataContextStack.Create(contexts[i], context); } var parser = new BindingExpressionBuilder(); var expressionTree = TypeConversion.ImplicitConversion(parser.Parse(expression, context, BindingParserOptions.Create <ValueBindingExpression>()), expectedType, true, true); var jsExpression = new JsParenthesizedExpression(JavascriptTranslator.CompileToJavascript(expressionTree, context, DotvvmConfiguration.CreateDefault().ServiceLocator.GetService <IViewModelSerializationMapper>())); jsExpression.AcceptVisitor(new KnockoutObservableHandlingVisitor(true)); JsTemporaryVariableResolver.ResolveVariables(jsExpression); return(JavascriptTranslator.FormatKnockoutScript(jsExpression.Expression)); }
public virtual string CompileToJavascript(ResolvedBinding binding, CompiledBindingExpression expression) { var javascript = JavascriptTranslator.CompileToJavascript(binding.GetExpression(), binding.DataContextTypeStack); if (javascript == "$data") { javascript = "$rawData"; } else if (javascript.StartsWith("$data.", StringComparison.Ordinal)) { javascript = javascript.Substring("$data.".Length); } // do not produce try/eval on single properties if (javascript.Contains(".") || javascript.Contains("(")) { return("dotvvm.evaluator.tryEval(function(){return " + javascript + "})"); } else { return(javascript); } }
public KnockoutJsExpressionBindingProperty CompileToJavascript(CastedExpressionBindingProperty expression, DataContextStack dataContext) { return(new KnockoutJsExpressionBindingProperty( javascriptTranslator.CompileToJavascript(expression.Expression, dataContext).ApplyAction(a => a.Freeze()))); }
public static string GetArgsScript(MethodCallExpression expression, DataContextStack dataContext, IViewModelSerializationMapper vmMapper) { var target = expression.Object == null ? null : JavascriptTranslator.FormatKnockoutScript(JavascriptTranslator.CompileToJavascript(expression.Object, dataContext, vmMapper), allowDataGlobal: false); var arguments = (target == null ? new string[0] : new[] { target }) .Concat(expression.Arguments.Select(a => JavascriptTranslator.FormatKnockoutScript(JavascriptTranslator.CompileToJavascript(a, dataContext, vmMapper), allowDataGlobal: true))); return("[" + String.Join(", ", arguments) + "]"); }
public new string CompileToJavascript(ResolvedBinding binding, CompiledBindingExpression compiledExpression, DotvvmConfiguration config) { var vmMapper = config.ServiceLocator.GetService <IViewModelSerializationMapper>(); var expression = binding.GetExpression(); var visitor = new ExtractExpressionVisitor(ex => ex.NodeType == ExpressionType.Call); var rootCallback = visitor.Visit(expression); var js = SouldCompileCallback(rootCallback) ? "resultPromise.resolve(" + JavascriptTranslator.FormatKnockoutScript(JavascriptTranslator.CompileToJavascript(rootCallback, binding.DataContextTypeStack, vmMapper), allowDataGlobal: false) + ")" : null; foreach (var param in visitor.ParameterOrder.Reverse <ParameterExpression>()) { if (js == null) { js = $"resultPromise.resolve({param.Name})"; } var callback = $"function({param.Name}){{{js}}}"; var method = visitor.Replaced[param] as MethodCallExpression; js = CompileMethodCall(method, binding.DataContextTypeStack, vmMapper, callback); } return("var $context = ko.contextFor(this);var sender = this;var resultPromise = new DotvvmPromise();(function(i_pageArea){with($context){" + js + "}})"); }
public JsExpression CompileToJavascript(DataContextStack dataContext, Expression expression) { var currentContextVariable = new JsTemporaryVariableParameter(new JsIdentifierExpression("ko").Member("contextFor").Invoke(new JsSymbolicParameter(CommandBindingExpression.SenderElementParameter))); // var resultPromiseVariable = new JsNewExpression("DotvvmPromise")); var senderVariable = new JsTemporaryVariableParameter(new JsSymbolicParameter(CommandBindingExpression.SenderElementParameter)); var visitor = new ExtractExpressionVisitor(ex => { if (ex.NodeType == ExpressionType.Call && ex is MethodCallExpression methodCall) { if (javascriptTranslator.TryTranslateMethodCall(methodCall.Object, methodCall.Arguments.ToArray(), methodCall.Method, dataContext) is JsExpression jsTranslation) { if (jsTranslation.Annotation <ResultIsPromiseAnnotation>() is ResultIsPromiseAnnotation promiseAnnotation) { return(p => new BindingParameterAnnotation(extensionParameter: new JavascriptTranslationVisitor.FakeExtensionParameter(_ => new JsIdentifierExpression(p.Name).WithAnnotations(promiseAnnotation.ResultAnnotations), p.Name, new ResolvedTypeDescriptor(p.Type)))); } else { return(null); } } return(p => new BindingParameterAnnotation(extensionParameter: new JavascriptTranslationVisitor.FakeExtensionParameter(_ => new JsIdentifierExpression(p.Name).WithAnnotation(new ViewModelInfoAnnotation(p.Type)), p.Name, new ResolvedTypeDescriptor(p.Type)))); } return(null); }); var rootCallback = visitor.Visit(expression); var js = SouldCompileCallback(rootCallback) ? new JsIdentifierExpression("resolve").Invoke(javascriptTranslator.CompileToJavascript(rootCallback, dataContext)) : null; foreach (var param in visitor.ParameterOrder.Reverse <ParameterExpression>()) { js = js ?? new JsIdentifierExpression("resolve").Invoke(new JsIdentifierExpression(param.Name)); var callback = new JsFunctionExpression(new[] { new JsIdentifier(param.Name) }, new JsBlockStatement(new JsExpressionStatement(js))); var method = visitor.Replaced[param] as MethodCallExpression; js = CompileMethodCall(method, dataContext, callback); } foreach (var sp in js.Descendants.OfType <JsSymbolicParameter>()) { if (sp.Symbol == JavascriptTranslator.KnockoutContextParameter) { sp.Symbol = currentContextVariable; } else if (sp.Symbol == JavascriptTranslator.KnockoutViewModelParameter) { sp.ReplaceWith(new JsSymbolicParameter(currentContextVariable).Member("$data")); } else if (sp.Symbol == CommandBindingExpression.SenderElementParameter) { sp.Symbol = senderVariable; } } if (js is JsInvocationExpression invocation && invocation.Target is JsIdentifierExpression identifier && identifier.Identifier == "resolve") { // optimize `new Promise(function (resolve) { resolve(x) })` to `Promise.resolve(x)` identifier.ReplaceWith(new JsIdentifierExpression("Promise").Member("resolve")); return(js); }