123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- using Esprima.Ast;
- using Jint.Native;
- using Jint.Runtime.References;
- namespace Jint.Runtime.Interpreter.Expressions
- {
- internal sealed class JintUpdateExpression : JintExpression
- {
- private JintExpression _argument;
- private int _change;
- private bool _prefix;
- private JintIdentifierExpression _leftIdentifier;
- private bool _evalOrArguments;
- public JintUpdateExpression(Engine engine, UpdateExpression expression) : base(engine, expression)
- {
- _initialized = false;
- }
- protected override void Initialize()
- {
- var expression = (UpdateExpression) _expression;
- _prefix = expression.Prefix;
- _argument = Build(_engine, expression.Argument);
- if (expression.Operator == UnaryOperator.Increment)
- {
- _change = 1;
- }
- else if (expression.Operator == UnaryOperator.Decrement)
- {
- _change = - 1;
- }
- else
- {
- ExceptionHelper.ThrowArgumentException();
- }
- _leftIdentifier = _argument as JintIdentifierExpression;
- _evalOrArguments = _leftIdentifier?.HasEvalOrArguments == true;
- }
- protected override object EvaluateInternal()
- {
- var fastResult = _leftIdentifier != null
- ? UpdateIdentifier()
- : null;
- return fastResult ?? UpdateNonIdentifier();
- }
- private object UpdateNonIdentifier()
- {
- if (!(_argument.Evaluate() is Reference reference))
- {
- return ExceptionHelper.ThrowTypeError<object>(_engine, "Invalid left-hand side expression");
- }
- reference.AssertValid(_engine);
- var value = _engine.GetValue(reference, false);
- var isInteger = value._type == InternalTypes.Integer;
- var newValue = isInteger
- ? JsNumber.Create(value.AsInteger() + _change)
- : JsNumber.Create(TypeConverter.ToNumber(value) + _change);
- _engine.PutValue(reference, newValue);
- _engine._referencePool.Return(reference);
- return _prefix
- ? newValue
- : (isInteger ? value : JsNumber.Create(TypeConverter.ToNumber(value)));
- }
- private JsValue UpdateIdentifier()
- {
- var strict = StrictModeScope.IsStrictModeCode;
- var name = _leftIdentifier._expressionName;
- if (TryGetIdentifierEnvironmentWithBindingValue(
- name,
- out var environmentRecord,
- out var value))
- {
- if (strict && _evalOrArguments)
- {
- ExceptionHelper.ThrowSyntaxError(_engine);
- }
- var isInteger = value._type == InternalTypes.Integer;
- var newValue = isInteger
- ? JsNumber.Create(value.AsInteger() + _change)
- : JsNumber.Create(TypeConverter.ToNumber(value) + _change);
- environmentRecord.SetMutableBinding(name.Key.Name, newValue, strict);
- return _prefix
- ? newValue
- : (isInteger ? value : JsNumber.Create(TypeConverter.ToNumber(value)));
- }
- return null;
- }
- }
- }
|