JintAssignmentExpression.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. using Esprima.Ast;
  2. using Jint.Native;
  3. using Jint.Native.Function;
  4. using Jint.Runtime.Environments;
  5. using Jint.Runtime.References;
  6. namespace Jint.Runtime.Interpreter.Expressions
  7. {
  8. internal sealed class JintAssignmentExpression : JintExpression
  9. {
  10. private readonly JintExpression _left;
  11. private readonly JintExpression _right;
  12. private readonly AssignmentOperator _operator;
  13. private JintAssignmentExpression(Engine engine, AssignmentExpression expression) : base(engine, expression)
  14. {
  15. _left = Build(engine, expression.Left);
  16. _right = Build(engine, expression.Right);
  17. _operator = expression.Operator;
  18. }
  19. internal static JintExpression Build(Engine engine, AssignmentExpression expression)
  20. {
  21. if (expression.Operator == AssignmentOperator.Assign)
  22. {
  23. if (expression.Left is BindingPattern)
  24. {
  25. return new BindingPatternAssignmentExpression(engine, expression);
  26. }
  27. return new SimpleAssignmentExpression(engine, expression);
  28. }
  29. return new JintAssignmentExpression(engine, expression);
  30. }
  31. protected override object EvaluateInternal()
  32. {
  33. var lref = _left.Evaluate() as Reference ?? ExceptionHelper.ThrowReferenceError<Reference>(_engine);
  34. var rval = _right.GetValue();
  35. var lval = _engine.GetValue(lref, false);
  36. switch (_operator)
  37. {
  38. case AssignmentOperator.PlusAssign:
  39. if (AreIntegerOperands(lval, rval))
  40. {
  41. lval = (long) lval.AsInteger() + rval.AsInteger();
  42. }
  43. else
  44. {
  45. var lprim = TypeConverter.ToPrimitive(lval);
  46. var rprim = TypeConverter.ToPrimitive(rval);
  47. if (lprim.IsString() || rprim.IsString())
  48. {
  49. if (!(lprim is JsString jsString))
  50. {
  51. jsString = new JsString.ConcatenatedString(TypeConverter.ToString(lprim));
  52. }
  53. lval = jsString.Append(rprim);
  54. }
  55. else
  56. {
  57. lval = TypeConverter.ToNumber(lprim) + TypeConverter.ToNumber(rprim);
  58. }
  59. }
  60. break;
  61. case AssignmentOperator.MinusAssign:
  62. lval = AreIntegerOperands(lval, rval)
  63. ? JsNumber.Create(lval.AsInteger() - rval.AsInteger())
  64. : JsNumber.Create(TypeConverter.ToNumber(lval) - TypeConverter.ToNumber(rval));
  65. break;
  66. case AssignmentOperator.TimesAssign:
  67. if (AreIntegerOperands(lval, rval))
  68. {
  69. lval = (long) lval.AsInteger() * rval.AsInteger();
  70. }
  71. else if (lval.IsUndefined() || rval.IsUndefined())
  72. {
  73. lval = Undefined.Instance;
  74. }
  75. else
  76. {
  77. lval = TypeConverter.ToNumber(lval) * TypeConverter.ToNumber(rval);
  78. }
  79. break;
  80. case AssignmentOperator.DivideAssign:
  81. lval = Divide(lval, rval);
  82. break;
  83. case AssignmentOperator.ModuloAssign:
  84. if (lval.IsUndefined() || rval.IsUndefined())
  85. {
  86. lval = Undefined.Instance;
  87. }
  88. else
  89. {
  90. lval = TypeConverter.ToNumber(lval) % TypeConverter.ToNumber(rval);
  91. }
  92. break;
  93. case AssignmentOperator.BitwiseAndAssign:
  94. lval = TypeConverter.ToInt32(lval) & TypeConverter.ToInt32(rval);
  95. break;
  96. case AssignmentOperator.BitwiseOrAssign:
  97. lval = TypeConverter.ToInt32(lval) | TypeConverter.ToInt32(rval);
  98. break;
  99. case AssignmentOperator.BitwiseXOrAssign:
  100. lval = TypeConverter.ToInt32(lval) ^ TypeConverter.ToInt32(rval);
  101. break;
  102. case AssignmentOperator.LeftShiftAssign:
  103. lval = TypeConverter.ToInt32(lval) << (int) (TypeConverter.ToUint32(rval) & 0x1F);
  104. break;
  105. case AssignmentOperator.RightShiftAssign:
  106. lval = TypeConverter.ToInt32(lval) >> (int) (TypeConverter.ToUint32(rval) & 0x1F);
  107. break;
  108. case AssignmentOperator.UnsignedRightShiftAssign:
  109. lval = (uint) TypeConverter.ToInt32(lval) >> (int) (TypeConverter.ToUint32(rval) & 0x1F);
  110. break;
  111. default:
  112. return ExceptionHelper.ThrowNotImplementedException<object>();
  113. }
  114. _engine.PutValue(lref, lval);
  115. _engine._referencePool.Return(lref);
  116. return lval;
  117. }
  118. internal sealed class SimpleAssignmentExpression : JintExpression
  119. {
  120. private JintExpression _left;
  121. private JintExpression _right;
  122. private JintIdentifierExpression _leftIdentifier;
  123. private bool _evalOrArguments;
  124. public SimpleAssignmentExpression(Engine engine, AssignmentExpression expression) : base(engine, expression)
  125. {
  126. _initialized = false;
  127. }
  128. protected override void Initialize()
  129. {
  130. var assignmentExpression = ((AssignmentExpression) _expression);
  131. _left = Build(_engine, assignmentExpression.Left);
  132. _leftIdentifier = _left as JintIdentifierExpression;
  133. _evalOrArguments = _leftIdentifier?.HasEvalOrArguments == true;
  134. _right = Build(_engine, assignmentExpression.Right);
  135. }
  136. protected override object EvaluateInternal()
  137. {
  138. JsValue rval = null;
  139. if (_leftIdentifier != null)
  140. {
  141. rval = AssignToIdentifier(_engine, _leftIdentifier, _right, _evalOrArguments);
  142. }
  143. return rval ?? SetValue();
  144. }
  145. private JsValue SetValue()
  146. {
  147. // slower version
  148. var lref = _left.Evaluate() as Reference ?? ExceptionHelper.ThrowReferenceError<Reference>(_engine);
  149. lref.AssertValid(_engine);
  150. var rval = _right.GetValue();
  151. _engine.PutValue(lref, rval);
  152. _engine._referencePool.Return(lref);
  153. return rval;
  154. }
  155. internal static JsValue AssignToIdentifier(
  156. Engine engine,
  157. JintIdentifierExpression left,
  158. JintExpression right,
  159. bool hasEvalOrArguments)
  160. {
  161. var env = engine.ExecutionContext.LexicalEnvironment;
  162. var strict = StrictModeScope.IsStrictModeCode;
  163. if (LexicalEnvironment.TryGetIdentifierEnvironmentWithBindingValue(
  164. env,
  165. left._expressionName,
  166. strict,
  167. out var environmentRecord,
  168. out _))
  169. {
  170. if (strict && hasEvalOrArguments)
  171. {
  172. ExceptionHelper.ThrowSyntaxError(engine);
  173. }
  174. var rval = right.GetValue().Clone();
  175. if (right._expression.IsFunctionWithName())
  176. {
  177. ((FunctionInstance) rval).SetFunctionName(left._expressionName.StringValue);
  178. }
  179. environmentRecord.SetMutableBinding(left._expressionName, rval, strict);
  180. return rval;
  181. }
  182. return null;
  183. }
  184. }
  185. }
  186. }