forked from ServiceStack/ServiceStack
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJsAssignmentExpression.cs
More file actions
112 lines (97 loc) · 4.1 KB
/
Copy pathJsAssignmentExpression.cs
File metadata and controls
112 lines (97 loc) · 4.1 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
102
103
104
105
106
107
108
109
110
111
112
using System;
using System.Collections.Generic;
namespace ServiceStack.Script
{
public class JsAssignmentExpression : JsExpression
{
public JsAssignmentExpression(JsToken left, JsAssignment @operator, JsToken right)
{
Left = left ?? throw new SyntaxErrorException($"Left Expression missing in Binary Expression");
Operator = @operator ?? throw new SyntaxErrorException($"Operator missing in Binary Expression");
Right = right ?? throw new SyntaxErrorException($"Right Expression missing in Binary Expression");
}
public JsAssignment Operator { get; set; }
public JsToken Left { get; set; }
public JsToken Right { get; set; }
public override string ToRawString() => "(" + JsonValue(Left) + Operator.Token + JsonValue(Right) + ")";
protected bool Equals(JsAssignmentExpression other) =>
Equals(Operator, other.Operator) && Equals(Left, other.Left) && Equals(Right, other.Right);
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((JsAssignmentExpression) obj);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = (Operator != null ? Operator.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (Left != null ? Left.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (Right != null ? Right.GetHashCode() : 0);
return hashCode;
}
}
private Action<ScriptScopeContext, object, object> assignFn;
private string EvalProperty(JsToken token, ScriptScopeContext scope)
{
switch (token)
{
case JsIdentifier id:
return id.Name;
default:
return JsonValue(token.Evaluate(scope));
}
}
public override object Evaluate(ScriptScopeContext scope)
{
var rhs = Right.Evaluate(scope);
if (Left is JsIdentifier id)
{
if (scope.ScopedParams.ContainsKey(id.Name))
{
scope.ScopedParams[id.Name] = rhs;
}
else
{
scope.PageResult.Args[id.Name] = rhs;
}
return rhs;
}
else if (Left is JsMemberExpression memberExpr)
{
var target = memberExpr.Object.Evaluate(scope);
if (target == null)
throw new ArgumentNullException(memberExpr.Object.ToRawString());
// Evaluate target then reduce to simple expression then compile assign expression using expression trees
var assignTargetExpr = memberExpr.Computed
? "obj[" + EvalProperty(memberExpr.Property, scope) + "]"
: "obj." + EvalProperty(memberExpr.Property, scope);
if (assignFn == null)
{
assignFn = scope.Context.GetAssignExpression(target.GetType(), assignTargetExpr.AsMemory());
if (assignFn == null)
throw new NotSupportedException($"Could not create assignment expression for '{memberExpr.ToRawString()}'");
}
if (assignFn != null)
{
assignFn(scope, target, rhs);
return rhs;
}
}
throw new NotSupportedException("Assignment Expression not supported: " + Left.ToRawString());
}
public override Dictionary<string, object> ToJsAst()
{
var to = new Dictionary<string, object>
{
["type"] = ToJsAstType(),
["operator"] = Operator.Token,
["left"] = Left.ToJsAst(),
["right"] = Right.ToJsAst(),
};
return to;
}
}
}