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.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); } } } }
/// <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.HasValue) { v = stmt.Value.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.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.HasValue) { v = stmt.Value.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)); } 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 static bool StrictlyEqual(JsValue x, JsValue y) { var typea = x.Type; var typeb = y.Type; if (typea != typeb) { return(false); } if (typea == Types.Undefined || typea == Types.Null) { return(true); } 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(false); } if (nx.Equals(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); }
/// <inheritdoc /> internal override bool FindWithCallback( JsValue[] arguments, out uint index, out JsValue value) { var len = GetLength(); if (len == 0) { index = 0; value = Undefined; return(false); } var callbackfn = arguments.At(0); var thisArg = arguments.At(1); var callable = GetCallable(callbackfn); var args = _engine._jsValueArrayPool.RentArray(3); args[2] = this; for (uint k = 0; k < len; k++) { var kvalue = args[0]; if (TryGetValue(k, out kvalue)) { args[0] = kvalue; args[1] = k; var testResult = callable.Call(thisArg, args); if (TypeConverter.ToBoolean(testResult)) { index = k; value = kvalue; return(true); } } } _engine._jsValueArrayPool.ReturnArray(args); index = 0; value = Undefined; return(false); }
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 void ExecuteIfStatement(RuntimeState state) { IfStatement ifStatement = (IfStatement)state.arg; if (state.stage == 0) { if (state.calleeReturned) { state.calleeReturned = false; state.stage = 1; } else { Call(_engine.EvaluateExpression, ifStatement.Test); return; } } // Stage 1 if (state.calleeReturned) { Return(state.calleeReturnValue); return; } if (TypeConverter.ToBoolean(_engine.GetValue(state.calleeReturnValue, true))) { Call(_engine.ExecuteStatement, ifStatement.Consequent); } else if (ifStatement.Alternate != null) { Call(_engine.ExecuteStatement, ifStatement.Alternate); } else { Return(new Completion(CompletionType.Normal, null, null)); } return; }
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(); } }
/// <summary> /// http://www.ecma-international.org/ecma-262/5.1/#sec-12.6.3 /// </summary> /// <param name="forStatement"></param> /// <returns></returns> public void ExecuteForStatement(RuntimeState state) { ForStatement forStatement = (ForStatement)state.arg; ExecuteForStatementLocal local; if (state.local == null) { state.local = local = new ExecuteForStatementLocal(); local.init = forStatement.Init; local.v = Undefined.Instance; local.stage = 0; } else { local = (ExecuteForStatementLocal)state.local; } if (local.stage == 0) { if (state.calleeReturned) { if (state.stage == 1) { _engine.GetValue(state.calleeReturnValue, true); } state.calleeReturned = false; state.calleeReturnValue = null; local.stage = 1; return; } if (local.init != null) { if (local.init.Type == Nodes.VariableDeclaration) { Call(_engine.ExecuteStatement, (Statement)local.init); return; } else { state.stage = 1; Call(_engine.EvaluateExpression, local.init); return; } } local.stage = 1; } if (local.stage == 1) { if (state.calleeReturned && state.stage != 10) { Completion stmt = (Completion)state.calleeReturnValue; state.calleeReturned = false; state.calleeReturnValue = null; if (!ReferenceEquals(stmt.Value, null)) { local.v = stmt.Value; } var stmtType = stmt.Type; if (stmtType == CompletionType.Break && (stmt.Identifier == null || stmt.Identifier == forStatement?.LabelSet?.Name)) { Return(new Completion(CompletionType.Normal, local.v, null)); return; } if (stmtType != CompletionType.Continue || ((stmt.Identifier != null) && stmt.Identifier != forStatement?.LabelSet?.Name)) { if (stmtType != CompletionType.Normal) { Return(stmt); return; } } if (forStatement.Update != null) { local.stage = 2; Call(_engine.EvaluateExpression, forStatement.Update); return; } } if (forStatement.Test != null) { if (state.calleeReturned) { state.stage = 0; state.calleeReturned = false; var testExprRef = state.calleeReturnValue; if (!TypeConverter.ToBoolean(_engine.GetValue(testExprRef, true))) { Return(new Completion(CompletionType.Normal, local.v, null)); return; } } else { Call(_engine.EvaluateExpression, forStatement.Test); state.stage = 10; return; } } Call(_engine.ExecuteStatement, forStatement.Body); return; } if (local.stage == 2) { if (state.calleeReturned) { state.calleeReturned = false; _engine.GetValue(state.calleeReturnValue, true); local.stage = 1; return; } } }
/// <summary> /// http://www.ecma-international.org/ecma-262/5.1/#sec-12.6.2 /// </summary> /// <param name="whileStatement"></param> /// <returns></returns> public void ExecuteWhileStatement(RuntimeState state) { WhileStatement whileStatement = (WhileStatement)state.arg; ExecuteWhileStatementLocal local; if (state.local == null) { state.local = local = new ExecuteWhileStatementLocal(); local.v = Undefined.Instance; } else { local = (ExecuteWhileStatementLocal)state.local; } if (state.stage == 0) { if (state.calleeReturned) { state.calleeReturned = false; state.stage = 1; var jsValue = _engine.GetValue(state.calleeReturnValue, true); if (!TypeConverter.ToBoolean(jsValue)) { Return(new Completion(CompletionType.Normal, local.v, null)); return; } } else { Call(_engine.EvaluateExpression, whileStatement.Test); return; } } // Stage 1 if (state.calleeReturned) { state.calleeReturned = false; var stmt = (Completion)state.calleeReturnValue; if (!ReferenceEquals(stmt.Value, null)) { local.v = stmt.Value; } if (stmt.Type != CompletionType.Continue || stmt.Identifier != whileStatement?.LabelSet?.Name) { if (stmt.Type == CompletionType.Break && (stmt.Identifier == null || stmt.Identifier == whileStatement?.LabelSet?.Name)) { Return(new Completion(CompletionType.Normal, local.v, null)); return; } if (stmt.Type != CompletionType.Normal) { Return(stmt); return; } } state.stage = 0; return; } Call(_engine.ExecuteStatement, whileStatement.Body); return; }