protected internal static JintExpression Build(Engine engine, Expression expression) { switch (expression.Type) { case Nodes.AssignmentExpression: return(JintAssignmentExpression.Build(engine, (AssignmentExpression)expression)); case Nodes.ArrayExpression: return(new JintArrayExpression(engine, (ArrayExpression)expression)); case Nodes.ArrowFunctionExpression: return(new JintArrowFunctionExpression(engine, (IFunction)expression)); case Nodes.BinaryExpression: return(JintBinaryExpression.Build(engine, (BinaryExpression)expression)); case Nodes.CallExpression: return(new JintCallExpression(engine, (CallExpression)expression)); case Nodes.ConditionalExpression: return(new JintConditionalExpression(engine, (ConditionalExpression)expression)); case Nodes.FunctionExpression: return(new JintFunctionExpression(engine, (IFunction)expression)); case Nodes.Identifier: return(new JintIdentifierExpression(engine, (Identifier)expression)); case Nodes.Literal: return(JintLiteralExpression.Build(engine, (Literal)expression)); case Nodes.LogicalExpression: switch (((BinaryExpression)expression).Operator) { case BinaryOperator.LogicalAnd: return(new JintLogicalAndExpression(engine, (BinaryExpression)expression)); case BinaryOperator.LogicalOr: return(new JintLogicalOrExpression(engine, (BinaryExpression)expression)); default: return(ExceptionHelper.ThrowArgumentOutOfRangeException <JintExpression>()); } case Nodes.MemberExpression: return(new JintMemberExpression(engine, (MemberExpression)expression)); case Nodes.NewExpression: return(new JintNewExpression(engine, (NewExpression)expression)); case Nodes.ObjectExpression: return(new JintObjectExpression(engine, (ObjectExpression)expression)); case Nodes.SequenceExpression: return(new JintSequenceExpression(engine, (SequenceExpression)expression)); case Nodes.ThisExpression: return(new JintThisExpression(engine, (ThisExpression)expression)); case Nodes.UpdateExpression: return(new JintUpdateExpression(engine, (UpdateExpression)expression)); case Nodes.UnaryExpression: return(JintUnaryExpression.Build(engine, (UnaryExpression)expression)); case Nodes.SpreadElement: return(new JintSpreadExpression(engine, (SpreadElement)expression)); case Nodes.TemplateLiteral: return(new JintTemplateLiteralExpression(engine, (TemplateLiteral)expression)); case Nodes.TaggedTemplateExpression: return(new JintTaggedTemplateExpression(engine, (TaggedTemplateExpression)expression)); default: return(ExceptionHelper.ThrowArgumentOutOfRangeException <JintExpression>(nameof(expression), $"unsupported expression type '{expression.Type}'")); } }
public NullishCoalescingExpression(Engine engine, BinaryExpression expression) : base(expression) { _left = Build(engine, expression.Left); // we can create a fast path for common literal case like variable ?? 0 if (expression.Right is Literal l) { _constant = JintLiteralExpression.ConvertToJsValue(l); } else { _right = Build(engine, expression.Right); } }
internal static JintExpression Build(Engine engine, UnaryExpression expression) { if (expression.Operator == UnaryOperator.Minus && expression.Argument is Literal literal) { var value = JintLiteralExpression.ConvertToJsValue(literal); if (!(value is null)) { // valid for caching return(new JintConstantExpression(engine, expression, EvaluateMinus(value))); } } return(new JintUnaryExpression(engine, expression)); }
protected override void Initialize(EvaluationContext context) { _memberExpression = (MemberExpression)_expression; _objectExpression = Build(context.Engine, _memberExpression.Object); if (!_memberExpression.Computed) { _determinedProperty = ((Identifier)_memberExpression.Property).Name; } else if (_memberExpression.Property.Type == Nodes.Literal) { _determinedProperty = JintLiteralExpression.ConvertToJsValue((Literal)_memberExpression.Property); } if (_determinedProperty is null) { _propertyExpression = Build(context.Engine, _memberExpression.Property); } }
protected internal static JintExpression Build(Engine engine, Expression expression) { return(expression.Type switch { Nodes.AssignmentExpression => JintAssignmentExpression.Build(engine, (AssignmentExpression)expression), Nodes.ArrayExpression => new JintArrayExpression(engine, (ArrayExpression)expression), Nodes.ArrowFunctionExpression => new JintArrowFunctionExpression(engine, (IFunction)expression), Nodes.BinaryExpression => JintBinaryExpression.Build(engine, (BinaryExpression)expression), Nodes.CallExpression => new JintCallExpression(engine, (CallExpression)expression), Nodes.ConditionalExpression => new JintConditionalExpression(engine, (ConditionalExpression)expression), Nodes.FunctionExpression => new JintFunctionExpression(engine, (IFunction)expression), Nodes.Identifier => new JintIdentifierExpression(engine, (Identifier)expression), Nodes.Literal => JintLiteralExpression.Build(engine, (Literal)expression), Nodes.LogicalExpression => ((BinaryExpression)expression).Operator switch { BinaryOperator.LogicalAnd => new JintLogicalAndExpression(engine, (BinaryExpression)expression), BinaryOperator.LogicalOr => new JintLogicalOrExpression(engine, (BinaryExpression)expression), _ => ExceptionHelper.ThrowArgumentOutOfRangeException <JintExpression>() },
protected override void Initialize() { var expression = (MemberExpression)_expression; _objectExpression = Build(_engine, expression.Object); _objectIdentifierExpression = _objectExpression as JintIdentifierExpression; _objectThisExpression = _objectExpression as JintThisExpression; if (!expression.Computed) { _determinedProperty = ((Identifier)expression.Property).Name; } else if (expression.Property.Type == Nodes.Literal) { _determinedProperty = JintLiteralExpression.ConvertToJsValue((Literal)expression.Property); } if (_determinedProperty is null) { _propertyExpression = Build(_engine, expression.Property); } }
internal static JintExpression Build(Engine engine, BinaryExpression expression) { JintBinaryExpression result; switch (expression.Operator) { case BinaryOperator.StrictlyEqual: result = new StrictlyEqualBinaryExpression(engine, expression); break; case BinaryOperator.StricltyNotEqual: result = new StrictlyNotEqualBinaryExpression(engine, expression); break; case BinaryOperator.Less: result = new LessBinaryExpression(engine, expression); break; case BinaryOperator.Greater: result = new GreaterBinaryExpression(engine, expression); break; case BinaryOperator.Plus: result = new PlusBinaryExpression(engine, expression); break; case BinaryOperator.Minus: result = new MinusBinaryExpression(engine, expression); break; case BinaryOperator.Times: result = new TimesBinaryExpression(engine, expression); break; case BinaryOperator.Divide: result = new DivideBinaryExpression(engine, expression); break; case BinaryOperator.Equal: result = new EqualBinaryExpression(engine, expression); break; case BinaryOperator.NotEqual: result = new EqualBinaryExpression(engine, expression, invert: true); break; case BinaryOperator.GreaterOrEqual: result = new CompareBinaryExpression(engine, expression, leftFirst: true); break; case BinaryOperator.LessOrEqual: result = new CompareBinaryExpression(engine, expression, leftFirst: false); break; case BinaryOperator.BitwiseAnd: case BinaryOperator.BitwiseOr: case BinaryOperator.BitwiseXOr: case BinaryOperator.LeftShift: case BinaryOperator.RightShift: case BinaryOperator.UnsignedRightShift: result = new BitwiseBinaryExpression(engine, expression); break; case BinaryOperator.InstanceOf: result = new InstanceOfBinaryExpression(engine, expression); break; case BinaryOperator.Exponentiation: result = new ExponentiationBinaryExpression(engine, expression); break; case BinaryOperator.Modulo: result = new ModuloBinaryExpression(engine, expression); break; case BinaryOperator.In: result = new InBinaryExpression(engine, expression); break; default: result = ExceptionHelper.ThrowArgumentOutOfRangeException <JintBinaryExpression>(nameof(_operatorType), "cannot handle operator"); break; } if (expression.Operator != BinaryOperator.InstanceOf && expression.Operator != BinaryOperator.In && expression.Left is Literal leftLiteral && expression.Right is Literal rightLiteral) { var lval = JintLiteralExpression.ConvertToJsValue(leftLiteral); var rval = JintLiteralExpression.ConvertToJsValue(rightLiteral); if (!(lval is null) && !(rval is null)) { // we have fixed result return(new JintConstantExpression(engine, expression, result.GetValue())); } } return(result); }