EvalFunctionInstance.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. using Esprima;
  2. using Esprima.Ast;
  3. using Jint.Runtime;
  4. using Jint.Runtime.Descriptors;
  5. using Jint.Runtime.Environments;
  6. using Jint.Runtime.Interpreter.Statements;
  7. namespace Jint.Native.Function
  8. {
  9. public sealed class EvalFunctionInstance : FunctionInstance
  10. {
  11. private static readonly ParserOptions ParserOptions = new ParserOptions { AdaptRegexp = true, Tolerant = false };
  12. private static readonly JsString _functionName = new JsString("eval");
  13. public EvalFunctionInstance(Engine engine)
  14. : base(engine, _functionName, StrictModeScope.IsStrictModeCode ? FunctionThisMode.Strict : FunctionThisMode.Global)
  15. {
  16. _prototype = Engine.Function.PrototypeObject;
  17. _length = PropertyDescriptor.AllForbiddenDescriptor.NumberOne;
  18. }
  19. public override JsValue Call(JsValue thisObject, JsValue[] arguments)
  20. {
  21. return Call(thisObject, arguments, false);
  22. }
  23. /// <summary>
  24. /// https://tc39.es/ecma262/#sec-performeval
  25. /// </summary>
  26. public JsValue Call(JsValue thisObject, JsValue[] arguments, bool direct)
  27. {
  28. if (!(arguments.At(0) is JsString x))
  29. {
  30. return arguments.At(0);
  31. }
  32. var parser = new JavaScriptParser(x.ToString(), ParserOptions);
  33. Script script;
  34. try
  35. {
  36. script = parser.ParseScript(StrictModeScope.IsStrictModeCode);
  37. }
  38. catch (ParserException e)
  39. {
  40. return e.Description == Messages.InvalidLHSInAssignment
  41. ? ExceptionHelper.ThrowReferenceError<JsValue>(_engine)
  42. : ExceptionHelper.ThrowSyntaxError<JsValue>(_engine);
  43. }
  44. var body = script.Body;
  45. if (body.Count == 0)
  46. {
  47. return Undefined;
  48. }
  49. var strictEval = script.Strict || _engine._isStrict;
  50. var ctx = _engine.ExecutionContext;
  51. using (new StrictModeScope(strictEval))
  52. {
  53. LexicalEnvironment lexEnv;
  54. LexicalEnvironment varEnv;
  55. if (direct)
  56. {
  57. lexEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, ctx.LexicalEnvironment);
  58. varEnv = ctx.VariableEnvironment;
  59. }
  60. else
  61. {
  62. lexEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, Engine.GlobalEnvironment);
  63. varEnv = Engine.GlobalEnvironment;
  64. }
  65. if (strictEval)
  66. {
  67. varEnv = lexEnv;
  68. }
  69. // If ctx is not already suspended, suspend ctx.
  70. Engine.EnterExecutionContext(lexEnv, varEnv);
  71. try
  72. {
  73. Engine.EvalDeclarationInstantiation(script, varEnv, lexEnv, strictEval);
  74. var statement = JintStatement.Build(_engine, script);
  75. var result = statement.Execute();
  76. var value = result.GetValueOrDefault();
  77. if (result.Type == CompletionType.Throw)
  78. {
  79. var ex = new JavaScriptException(value).SetCallstack(_engine, result.Location);
  80. throw ex;
  81. }
  82. else
  83. {
  84. return value;
  85. }
  86. }
  87. finally
  88. {
  89. Engine.LeaveExecutionContext();
  90. }
  91. }
  92. }
  93. }
  94. }