forked from ServiceStack/ServiceStack
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathScriptBlock.cs
More file actions
101 lines (85 loc) · 3.86 KB
/
ScriptBlock.cs
File metadata and controls
101 lines (85 loc) · 3.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
using System;
using System.Threading;
using System.Threading.Tasks;
using ServiceStack.Script;
using ServiceStack.Text;
namespace ServiceStack.Script
{
public abstract class ScriptBlock
{
public ScriptContext Context { get; set; }
public ISharpPages Pages { get; set; }
public abstract string Name { get; }
protected virtual string GetCallTrace(PageBlockFragment fragment) => "Block: " + Name +
(fragment.Argument.IsNullOrEmpty() ? "" : " (" + fragment.Argument + ")");
protected virtual string GetElseCallTrace(PageElseBlock fragment) => "Block: " + Name + " > Else" +
(fragment.Argument.IsNullOrEmpty() ? "" : " (" + fragment.Argument + ")");
public abstract Task WriteAsync(ScriptScopeContext scope, PageBlockFragment block, CancellationToken token);
protected virtual async Task WriteAsync(ScriptScopeContext scope, PageFragment[] body, string callTrace, CancellationToken cancel)
{
await scope.PageResult.WriteFragmentsAsync(scope, body, callTrace, cancel);
}
protected virtual async Task WriteBodyAsync(ScriptScopeContext scope, PageBlockFragment fragment, CancellationToken token)
{
await WriteAsync(scope, fragment.Body, GetCallTrace(fragment), token);
}
protected virtual async Task WriteElseAsync(ScriptScopeContext scope, PageElseBlock fragment, CancellationToken token)
{
await WriteAsync(scope, fragment.Body, GetElseCallTrace(fragment), token);
}
protected async Task WriteElseAsync(ScriptScopeContext scope, PageElseBlock[] elseBlocks, CancellationToken cancel)
{
foreach (var elseBlock in elseBlocks)
{
if (elseBlock.Argument.IsNullOrEmpty())
{
await WriteElseAsync(scope, elseBlock, cancel);
return;
}
var argument = elseBlock.Argument;
if (argument.StartsWith("if "))
argument = argument.Advance(3);
var result = await argument.GetJsExpressionAndEvaluateToBoolAsync(scope,
ifNone: () => throw new NotSupportedException("'else if' block does not have a valid expression"));
if (result)
{
await WriteElseAsync(scope, elseBlock, cancel);
return;
}
}
}
protected bool CanExportScopeArgs(object element) =>
element != null && !(element is string) && (element.GetType().IsClass || element.GetType().Name == "KeyValuePair`2");
protected int AssertWithinMaxQuota(int value)
{
var maxQuota = (int)Context.Args[nameof(ScriptConfig.MaxQuota)];
if (value > maxQuota)
throw new NotSupportedException($"{value} exceeds Max Quota of {maxQuota}. \nMaxQuota can be changed in `Context.Args[nameof(TemplateConfig.MaxQuota)]` or globally in `TemplateConfig.MaxQuota`.");
return value;
}
}
public class DefaultScriptBlocks : IScriptPlugin
{
public void Register(ScriptContext context)
{
context.ScriptBlocks.AddRange(new ScriptBlock[] {
new IfScriptBlock(),
new EachScriptBlock(),
new RawScriptBlock(),
new CaptureScriptBlock(),
new PartialScriptBlock(),
new WithScriptBlock(),
new NoopScriptBlock(),
});
}
}
public class ProtectedScriptBlocks : IScriptPlugin
{
public void Register(ScriptContext context)
{
context.ScriptBlocks.AddRange(new ScriptBlock[] {
new EvalScriptBlock(), // evalTemplate filter has same functionality and is registered by default
});
}
}
}