/// <summary> /// http://www.ecma-international.org/ecma-262/5.1/#sec-12.6.1 /// </summary> /// <param name="doWhileStatement"></param> /// <returns></returns> public Completion ExecuteDoWhileStatement(DoWhileStatement doWhileStatement) { JsValue v = Undefined.Instance; bool iterating; do { var stmt = ExecuteStatement(doWhileStatement.Body); if (stmt.Value != null) { v = stmt.Value; } if (stmt.Type != Completion.Continue || stmt.Identifier != doWhileStatement.LabelSet) { if (stmt.Type == Completion.Break && (stmt.Identifier == null || stmt.Identifier == doWhileStatement.LabelSet)) { return(new Completion(Completion.Normal, v, null)); } if (stmt.Type != Completion.Normal) { return(stmt); } } var exprRef = _engine.EvaluateExpression(doWhileStatement.Test); iterating = TypeConverter.ToBoolean(_engine.GetValue(exprRef)); } while (iterating); return(new Completion(Completion.Normal, v, null)); }
/// <summary> /// http://www.ecma-international.org/ecma-262/5.1/#sec-12.6.2 /// </summary> /// <param name="whileStatement"></param> /// <returns></returns> public Completion ExecuteWhileStatement(WhileStatement whileStatement) { JsValue v = Undefined.Instance; while (true) { var exprRef = _engine.EvaluateExpression(whileStatement.Test); if (!TypeConverter.ToBoolean(_engine.GetValue(exprRef))) { return(new Completion(Completion.Normal, v, null)); } var stmt = ExecuteStatement(whileStatement.Body); if (stmt.Value != null) { v = stmt.Value; } if (stmt.Type != Completion.Continue || stmt.Identifier != whileStatement.LabelSet) { if (stmt.Type == Completion.Break && (stmt.Identifier == null || stmt.Identifier == whileStatement.LabelSet)) { return(new Completion(Completion.Normal, v, null)); } if (stmt.Type != Completion.Normal) { return(stmt); } } } }
public JsValue EvaluateLogicalExpression(LogicalExpression logicalExpression) { var left = _engine.GetValue(EvaluateExpression(logicalExpression.Left)); switch (logicalExpression.Operator) { case LogicalOperator.LogicalAnd: if (!TypeConverter.ToBoolean(left)) { return(left); } return(_engine.GetValue(EvaluateExpression(logicalExpression.Right))); case LogicalOperator.LogicalOr: if (TypeConverter.ToBoolean(left)) { return(left); } return(_engine.GetValue(EvaluateExpression(logicalExpression.Right))); default: throw new NotImplementedException(); } }
/// <summary> /// http://www.ecma-international.org/ecma-262/5.1/#sec-12.6.3 /// </summary> /// <param name="forStatement"></param> /// <returns></returns> public Completion ExecuteForStatement(ForStatement forStatement) { if (forStatement.Init != null) { if (forStatement.Init.Type == SyntaxNodes.VariableDeclaration) { ExecuteStatement(forStatement.Init.As <Statement>()); } else { _engine.GetValue(_engine.EvaluateExpression(forStatement.Init.As <Expression>())); } } JsValue v = Undefined.Instance; while (true) { if (forStatement.Test != null) { var testExprRef = _engine.EvaluateExpression(forStatement.Test); if (!TypeConverter.ToBoolean(_engine.GetValue(testExprRef))) { return(new Completion(Completion.Normal, v, null)); } } var stmt = ExecuteStatement(forStatement.Body); if (stmt.Value != null) { v = stmt.Value; } if (stmt.Type == Completion.Break && (stmt.Identifier == null || stmt.Identifier == forStatement.LabelSet)) { return(new Completion(Completion.Normal, v, null)); } if (stmt.Type != Completion.Continue || ((stmt.Identifier != null) && stmt.Identifier != forStatement.LabelSet)) { if (stmt.Type != Completion.Normal) { return(stmt); } } if (forStatement.Update != null) { var incExprRef = _engine.EvaluateExpression(forStatement.Update); _engine.GetValue(incExprRef); } } }
public JsValue EvaluateConditionalExpression(ConditionalExpression conditionalExpression) { var lref = _engine.EvaluateExpression(conditionalExpression.Test); if (TypeConverter.ToBoolean(_engine.GetValue(lref))) { var trueRef = _engine.EvaluateExpression(conditionalExpression.Consequent); return(_engine.GetValue(trueRef)); } else { var falseRef = _engine.EvaluateExpression(conditionalExpression.Alternate); return(_engine.GetValue(falseRef)); } }
public static bool SameValue(JsValue x, JsValue y) { var typea = TypeConverter.GetPrimitiveType(x); var typeb = TypeConverter.GetPrimitiveType(y); if (typea != typeb) { return(false); } if (typea == Types.None) { return(true); } if (typea == Types.Number) { var nx = TypeConverter.ToNumber(x); var ny = TypeConverter.ToNumber(y); if (double.IsNaN(nx) && double.IsNaN(ny)) { return(true); } if (nx.Equals(ny)) { if (nx.Equals(0)) { // +0 !== -0 return(NumberInstance.IsNegativeZero(nx) == NumberInstance.IsNegativeZero(ny)); } return(true); } return(false); } if (typea == Types.String) { return(TypeConverter.ToString(x) == TypeConverter.ToString(y)); } if (typea == Types.Boolean) { return(TypeConverter.ToBoolean(x) == TypeConverter.ToBoolean(y)); } return(x == y); }
public Completion ExecuteIfStatement(IfStatement ifStatement) { var exprRef = _engine.EvaluateExpression(ifStatement.Test); Completion result; if (TypeConverter.ToBoolean(_engine.GetValue(exprRef))) { result = ExecuteStatement(ifStatement.Consequent); } else if (ifStatement.Alternate != null) { result = ExecuteStatement(ifStatement.Alternate); } else { return(new Completion(Completion.Normal, null, null)); } return(result); }
public JsValue EvaluateUnaryExpression(UnaryExpression unaryExpression) { var value = _engine.EvaluateExpression(unaryExpression.Argument); Reference r; switch (unaryExpression.Operator) { case UnaryOperator.Plus: return(TypeConverter.ToNumber(_engine.GetValue(value))); case UnaryOperator.Minus: var n = TypeConverter.ToNumber(_engine.GetValue(value)); return(double.IsNaN(n) ? double.NaN : n *-1); case UnaryOperator.BitwiseNot: return(~TypeConverter.ToInt32(_engine.GetValue(value))); case UnaryOperator.LogicalNot: return(!TypeConverter.ToBoolean(_engine.GetValue(value))); case UnaryOperator.Delete: r = value as Reference; if (r == null) { return(true); } if (r.IsUnresolvableReference()) { if (r.IsStrict()) { throw new JavaScriptException(_engine.SyntaxError); } return(true); } if (r.IsPropertyReference()) { var o = TypeConverter.ToObject(_engine, r.GetBase()); return(o.Delete(r.GetReferencedName(), r.IsStrict())); } if (r.IsStrict()) { throw new JavaScriptException(_engine.SyntaxError); } var bindings = r.GetBase().TryCast <EnvironmentRecord>(); return(bindings.DeleteBinding(r.GetReferencedName())); case UnaryOperator.Void: _engine.GetValue(value); return(Undefined.Instance); case UnaryOperator.TypeOf: r = value as Reference; if (r != null) { if (r.IsUnresolvableReference()) { return("undefined"); } } var v = _engine.GetValue(value); if (v == Undefined.Instance) { return("undefined"); } if (v == Null.Instance) { return("object"); } switch (v.Type) { case Types.Boolean: return("boolean"); case Types.Number: return("number"); case Types.String: return("string"); } if (v.TryCast <ICallable>() != null) { return("function"); } return("object"); default: throw new ArgumentException(); } }