JintUnaryExpression.cs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. using Esprima.Ast;
  2. using Jint.Native;
  3. using Jint.Runtime.Environments;
  4. using Jint.Runtime.References;
  5. namespace Jint.Runtime.Interpreter.Expressions
  6. {
  7. internal sealed class JintUnaryExpression : JintExpression
  8. {
  9. private readonly JintExpression _argument;
  10. private readonly UnaryOperator _operator;
  11. public JintUnaryExpression(Engine engine, UnaryExpression expression) : base(engine, expression)
  12. {
  13. _argument = Build(engine, expression.Argument);
  14. _operator = expression.Operator;
  15. }
  16. protected override object EvaluateInternal()
  17. {
  18. switch (_operator)
  19. {
  20. case UnaryOperator.Plus:
  21. return JsNumber.Create(TypeConverter.ToNumber(_argument.GetValue()));
  22. case UnaryOperator.Minus:
  23. var n = TypeConverter.ToNumber(_argument.GetValue());
  24. return JsNumber.Create(double.IsNaN(n) ? double.NaN : n * -1);
  25. case UnaryOperator.BitwiseNot:
  26. return JsNumber.Create(~TypeConverter.ToInt32(_argument.GetValue()));
  27. case UnaryOperator.LogicalNot:
  28. return !TypeConverter.ToBoolean(_argument.GetValue()) ? JsBoolean.True : JsBoolean.False;
  29. case UnaryOperator.Delete:
  30. var r = _argument.Evaluate() as Reference;
  31. if (r == null)
  32. {
  33. return JsBoolean.True;
  34. }
  35. if (r.IsUnresolvableReference())
  36. {
  37. if (r._strict)
  38. {
  39. ExceptionHelper.ThrowSyntaxError(_engine);
  40. }
  41. _engine._referencePool.Return(r);
  42. return JsBoolean.True;
  43. }
  44. if (r.IsPropertyReference())
  45. {
  46. var o = TypeConverter.ToObject(_engine, r.GetBase());
  47. var jsValue = o.Delete(r.GetReferencedName(), r._strict);
  48. _engine._referencePool.Return(r);
  49. return jsValue ? JsBoolean.True : JsBoolean.False;
  50. }
  51. if (r._strict)
  52. {
  53. ExceptionHelper.ThrowSyntaxError(_engine);
  54. }
  55. var bindings = r.GetBase().TryCast<EnvironmentRecord>();
  56. var referencedName = r.GetReferencedName();
  57. _engine._referencePool.Return(r);
  58. return bindings.DeleteBinding(referencedName) ? JsBoolean.True : JsBoolean.False;
  59. case UnaryOperator.Void:
  60. _argument.GetValue();
  61. return Undefined.Instance;
  62. case UnaryOperator.TypeOf:
  63. var value = _argument.Evaluate();
  64. r = value as Reference;
  65. if (r != null)
  66. {
  67. if (r.IsUnresolvableReference())
  68. {
  69. _engine._referencePool.Return(r);
  70. return JsString.UndefinedString;
  71. }
  72. }
  73. var v = _argument.GetValue();
  74. if (v.IsUndefined())
  75. {
  76. return JsString.UndefinedString;
  77. }
  78. if (v.IsNull())
  79. {
  80. return JsString.ObjectString;
  81. }
  82. switch (v.Type)
  83. {
  84. case Types.Boolean: return JsString.BooleanString;
  85. case Types.Number: return JsString.NumberString;
  86. case Types.String: return JsString.StringString;
  87. }
  88. if (v.TryCast<ICallable>() != null)
  89. {
  90. return JsString.FunctionString;
  91. }
  92. return JsString.ObjectString;
  93. default:
  94. return ExceptionHelper.ThrowArgumentException<object>();
  95. }
  96. }
  97. }
  98. }