public object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray parameters, ScriptBlockStatement blockStatement) { return(_customFunction(context, callerContext, parameters)); }
public virtual ValueTask <object> InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { return(new ValueTask <object>(Invoke(context, callerContext, arguments, blockStatement))); }
public override object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { var expectedNumberOfParameters = Parameters.Length; if (_hasTemplateContext) { expectedNumberOfParameters--; if (_hasSpan) { expectedNumberOfParameters--; } } var minimumRequiredParameters = expectedNumberOfParameters - _optionalParameterCount; // Check parameters if ((_hasObjectParams && arguments.Count < minimumRequiredParameters - 1) || (!_hasObjectParams && arguments.Count < minimumRequiredParameters)) { if (minimumRequiredParameters != expectedNumberOfParameters) { throw new ScriptRuntimeException(callerContext.Span, $"Invalid number of arguments `{arguments.Count}` passed to `{callerContext}` while expecting at least `{minimumRequiredParameters}` arguments"); } else { throw new ScriptRuntimeException(callerContext.Span, $"Invalid number of arguments `{arguments.Count}` passed to `{callerContext}` while expecting `{expectedNumberOfParameters}` arguments"); } } // Convert arguments object[] paramArguments = null; var argMask = 0; if (_hasObjectParams) { var objectParamsCount = arguments.Count - _lastParamsIndex; if (_hasTemplateContext) { objectParamsCount++; if (_hasSpan) { objectParamsCount++; } } paramArguments = new object[objectParamsCount]; _arguments[_lastParamsIndex] = paramArguments; argMask |= 1 << _lastParamsIndex; } // Copy TemplateContext/SourceSpan parameters int argOffset = 0; if (_hasTemplateContext) { _arguments[0] = context; argOffset++; argMask |= 1; if (_hasSpan) { _arguments[1] = callerContext.Span; argOffset++; argMask |= 2; } } var argOrderedIndex = argOffset; // Setup any default parameters if (_optionalParameterCount > 0) { for (int i = Parameters.Length - 1; i >= Parameters.Length - _optionalParameterCount; i--) { _arguments[i] = Parameters[i].DefaultValue; argMask |= 1 << i; } } int paramsIndex = 0; for (int i = 0; i < arguments.Count; i++) { Type argType = null; try { int argIndex; var arg = arguments[i]; var namedArg = arg as ScriptNamedArgument; if (namedArg != null) { var namedArgValue = GetValueFromNamedArgument(context, callerContext, namedArg); arg = namedArgValue.Value; argIndex = namedArgValue.Index; argType = namedArgValue.Type; if (_hasObjectParams && argIndex == _lastParamsIndex) { argType = _paramsElementType; argIndex = argIndex + paramsIndex; paramsIndex++; } } else { argIndex = argOrderedIndex; if (_hasObjectParams && argIndex == _lastParamsIndex) { argType = _paramsElementType; argIndex = argIndex + paramsIndex; paramsIndex++; } else { argType = Parameters[argIndex].ParameterType; argOrderedIndex++; } } var argValue = context.ToObject(callerContext.Span, arg, argType); if (paramArguments != null && argIndex >= _lastParamsIndex) { paramArguments[argIndex - _lastParamsIndex] = argValue; } else { _arguments[argIndex] = argValue; argMask |= 1 << argIndex; } } catch (Exception exception) { throw new ScriptRuntimeException(callerContext.Span, $"Unable to convert parameter #{i} of type `{arguments[i]?.GetType()}` to type `{argType}`", exception); } } // In case we have named arguments we need to verify that all arguments were set if (argMask != (1 << Parameters.Length) - 1) { if (minimumRequiredParameters != expectedNumberOfParameters) { throw new ScriptRuntimeException(callerContext.Span, $"Invalid number of arguments `{arguments.Count}` passed to `{callerContext}` while expecting at least `{minimumRequiredParameters}` arguments"); } else { throw new ScriptRuntimeException(callerContext.Span, $"Invalid number of arguments `{arguments.Count}` passed to `{callerContext}` while expecting `{expectedNumberOfParameters}` arguments"); } } // Call method try { var result = Method.Invoke(_target, _arguments); // NOTE: The following line should not be touch as it is being matched by ScribanAsyncCodeGen return(result); } catch (TargetInvocationException exception) { throw new ScriptRuntimeException(callerContext.Span, $"Unexpected exception when calling {callerContext}", exception.InnerException); } }
public object Evaluate(TemplateContext context, ScriptNode callerContext, ScriptArray parameters, ScriptBlockStatement blockStatement) { if (parameters.Count == 0) { throw new ScriptRuntimeException(callerContext.Span, "Expecting at least the name of the template to include for the <include> function"); } string templateName = null; try { templateName = ScriptValueConverter.ToString(callerContext.Span, parameters[0]); } catch (Exception ex) { throw new ScriptRuntimeException(callerContext.Span, $"Unexpected exception while converting first parameter for <include> function. Expecting a string", ex); } // If template name is empty, throw an exception if (templateName == null || string.IsNullOrEmpty(templateName = templateName.Trim())) { throw new ScriptRuntimeException(callerContext.Span, $"Include template name cannot be null or empty"); } // Compute a new parameters for the include var newParameters = new ScriptArray(parameters.Count - 1); for (int i = 1; i < parameters.Count; i++) { newParameters[i] = parameters[i]; } context.SetValue(ScriptVariable.Arguments, newParameters, true); Template template; if (!context.CachedTemplates.TryGetValue(templateName, out template)) { if (context.TemplateLoader == null) { throw new ScriptRuntimeException(callerContext.Span, $"Unable to include <{templateName}>. No TemplateLoader registered in TemplateContext.Options.TemplateLoader"); } string templateFilePath; var templateText = context.TemplateLoader.Load(context, callerContext.Span, templateName, out templateFilePath); if (templateText == null) { throw new ScriptRuntimeException(callerContext.Span, $"The result of including <{templateName}> cannot be null"); } // IF template file path is not defined, we use the template name instead templateFilePath = templateFilePath ?? templateName; // Clone parser options var parserOptions = context.TemplateLoaderParserOptions.Clone(); // Parse include in default modes (while top page can be using front matter) parserOptions.Mode = parserOptions.Mode == ScriptMode.ScriptOnly ? ScriptMode.ScriptOnly : ScriptMode.Default; template = Template.Parse(templateText, templateFilePath, parserOptions); // If the template has any errors, throw an exception if (template.HasErrors) { throw new ScriptParserRuntimeException(callerContext.Span, $"Error while parsing template <{templateName}> from [{templateFilePath}]", template.Messages); } context.CachedTemplates.Add(templateName, template); } // Query the pending includes stored in the context HashSet<string> pendingIncludes; object pendingIncludesObject; if (!context.Tags.TryGetValue(typeof(IncludeFunction), out pendingIncludesObject)) { pendingIncludesObject = pendingIncludes = new HashSet<string>(); context.Tags[typeof (IncludeFunction)] = pendingIncludesObject; } else { pendingIncludes = (HashSet<string>) pendingIncludesObject; } // Make sure that we cannot recursively include a template if (pendingIncludes.Contains(templateName)) { throw new ScriptRuntimeException(callerContext.Span, $"The include [{templateName}] cannot be used recursively"); } pendingIncludes.Add(templateName); context.PushOutput(); object result = null; try { template.Render(context); } finally { result = context.PopOutput(); pendingIncludes.Remove(templateName); } return result; }
public abstract object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement);
public object Evaluate(TemplateContext context, ScriptNode callerContext, ScriptArray parameters, ScriptBlockStatement blockStatement) { // Check parameters if ((hasObjectParams && parameters.Count < parametersInfo.Length - 1) || (!hasObjectParams && parameters.Count != parametersInfo.Length)) { throw new ScriptRuntimeException(callerContext.Span, $"Invalid number of arguments passed [{parameters.Count}] while expecting [{parametersInfo.Length}] for [{callerContext}]"); } // Convert arguments var arguments = new object[parametersInfo.Length]; object[] paramArguments = null; if (hasObjectParams) { paramArguments = new object[parameters.Count - lastParamsIndex]; arguments[lastParamsIndex] = paramArguments; } for (int i = 0; i < parameters.Count; i++) { var destType = hasObjectParams && i >= lastParamsIndex ? typeof(object) : parametersInfo[i].ParameterType; try { var argValue = ScriptValueConverter.ToObject(callerContext.Span, parameters[i], destType); if (hasObjectParams && i >= lastParamsIndex) { paramArguments[i - lastParamsIndex] = argValue; } else { arguments[i] = argValue; } } catch (Exception exception) { throw new ScriptRuntimeException(callerContext.Span, $"Unable to convert parameter #{i} of type [{parameters[i]?.GetType()}] to type [{destType}]", exception); } } // Call method try { var result = method.Invoke(target, arguments); return(result); } catch (Exception exception) { throw new ScriptRuntimeException(callerContext.Span, $"Unexpected exception when calling {callerContext}", exception); } }
public override async ValueTask <object> InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray scriptArguments, ScriptBlockStatement blockStatement) { Array paramArguments = null; var arguments = PrepareArguments(context, callerContext, scriptArguments, ref paramArguments); try { // Call the method via reflection var result = InvokeImpl(context, callerContext.Span, arguments); return(IsAwaitable ? await ConfigureAwait(result) : result); } catch (TargetInvocationException exception) { if (exception.InnerException != null) { throw exception.InnerException; } throw new ScriptRuntimeException(callerContext.Span, $"Unexpected exception when calling {callerContext}"); } finally { context.ReleaseReflectionArguments(arguments); } }
public object Evaluate(TemplateContext context, ScriptNode callerContext, ScriptArray parameters, ScriptBlockStatement blockStatement) { return customFunction(context, callerContext, parameters); }
public object Evaluate(TemplateContext context, ScriptNode callerContext, ScriptArray parameters, ScriptBlockStatement blockStatement) { // Check parameters if ((hasObjectParams && parameters.Count < parametersInfo.Length - 1) || (!hasObjectParams && parameters.Count != parametersInfo.Length)) { throw new ScriptRuntimeException(callerContext.Span, $"Invalid number of arguments passed [{parameters.Count}] while expecting [{parametersInfo.Length}] for [{callerContext}]"); } // Convert arguments var arguments = new object[parametersInfo.Length]; object[] paramArguments = null; if (hasObjectParams) { paramArguments = new object[parameters.Count - lastParamsIndex]; arguments[lastParamsIndex] = paramArguments; } for (int i = 0; i < parameters.Count; i++) { var destType = hasObjectParams && i >= lastParamsIndex ? typeof(object) : parametersInfo[i].ParameterType; try { var argValue = ScriptValueConverter.ToObject(callerContext.Span, parameters[i], destType); if (hasObjectParams && i >= lastParamsIndex) { paramArguments[i - lastParamsIndex] = argValue; } else { arguments[i] = argValue; } } catch (Exception exception) { throw new ScriptRuntimeException(callerContext.Span, $"Unable to convert parameter #{i} of type [{parameters[i]?.GetType()}] to type [{destType}]", exception); } } // Call method try { var result = method.Invoke(target, arguments); return result; } catch (Exception exception) { throw new ScriptRuntimeException(callerContext.Span, $"Unexpected exception when calling {callerContext}", exception); } }
public ValueTask <object> InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { return(new ValueTask <object>(_customFunction(context, callerContext, arguments))); }