EvalFunctionInstance.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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 JsString _functionName = new("eval");
  12. private readonly JavaScriptParser _parser = new(new ParserOptions { Tolerant = false });
  13. public EvalFunctionInstance(
  14. Engine engine,
  15. Realm realm,
  16. FunctionPrototype functionPrototype)
  17. : base(
  18. engine,
  19. realm,
  20. _functionName,
  21. StrictModeScope.IsStrictModeCode ? FunctionThisMode.Strict : FunctionThisMode.Global)
  22. {
  23. _prototype = functionPrototype;
  24. _length = new PropertyDescriptor(JsNumber.PositiveOne, PropertyFlag.Configurable);
  25. }
  26. protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments)
  27. {
  28. var callerRealm = _engine.ExecutionContext.Realm;
  29. var x = arguments.At(0);
  30. return PerformEval(x, callerRealm, false, false);
  31. }
  32. /// <summary>
  33. /// https://tc39.es/ecma262/#sec-performeval
  34. /// </summary>
  35. public JsValue PerformEval(JsValue x, Realm callerRealm, bool strictCaller, bool direct)
  36. {
  37. if (!x.IsString())
  38. {
  39. return x;
  40. }
  41. var evalRealm = _realm;
  42. _engine._host.EnsureCanCompileStrings(callerRealm, evalRealm);
  43. var inFunction = false;
  44. var inMethod = false;
  45. var inDerivedConstructor = false;
  46. if (direct)
  47. {
  48. var thisEnvRec = _engine.ExecutionContext.GetThisEnvironment();
  49. if (thisEnvRec is FunctionEnvironmentRecord functionEnvironmentRecord)
  50. {
  51. var F = functionEnvironmentRecord._functionObject;
  52. inFunction = true;
  53. inMethod = thisEnvRec.HasSuperBinding();
  54. if (F._constructorKind == ConstructorKind.Derived)
  55. {
  56. inDerivedConstructor = true;
  57. }
  58. }
  59. }
  60. Script? script = null;
  61. try
  62. {
  63. script = _parser.ParseScript(x.ToString(), strict: strictCaller);
  64. }
  65. catch (ParserException e)
  66. {
  67. if (e.Description == Messages.InvalidLHSInAssignment)
  68. {
  69. ExceptionHelper.ThrowReferenceError(callerRealm, (string?) null);
  70. }
  71. else
  72. {
  73. ExceptionHelper.ThrowSyntaxError(callerRealm, e.Message);
  74. }
  75. }
  76. var body = script.Body;
  77. if (body.Count == 0)
  78. {
  79. return Undefined;
  80. }
  81. if (!inFunction)
  82. {
  83. // if body Contains NewTarget, throw a SyntaxError exception.
  84. }
  85. if (!inMethod)
  86. {
  87. // if body Contains SuperProperty, throw a SyntaxError exception.
  88. }
  89. if (!inDerivedConstructor)
  90. {
  91. // if body Contains SuperCall, throw a SyntaxError exception.
  92. }
  93. var strictEval = script.Strict || _engine._isStrict;
  94. var ctx = _engine.ExecutionContext;
  95. using (new StrictModeScope(strictEval))
  96. {
  97. EnvironmentRecord lexEnv;
  98. EnvironmentRecord varEnv;
  99. PrivateEnvironmentRecord? privateEnv;
  100. if (direct)
  101. {
  102. lexEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, ctx.LexicalEnvironment);
  103. varEnv = ctx.VariableEnvironment;
  104. privateEnv = ctx.PrivateEnvironment;
  105. }
  106. else
  107. {
  108. lexEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, evalRealm.GlobalEnv);
  109. varEnv = evalRealm.GlobalEnv;
  110. privateEnv = null;
  111. }
  112. if (strictEval)
  113. {
  114. varEnv = lexEnv;
  115. }
  116. // If ctx is not already suspended, suspend ctx.
  117. Engine.EnterExecutionContext(lexEnv, varEnv, evalRealm, privateEnv);
  118. try
  119. {
  120. Engine.EvalDeclarationInstantiation(script, varEnv, lexEnv, privateEnv, strictEval);
  121. var statement = new JintScript(script);
  122. var result = statement.Execute(_engine._activeEvaluationContext!);
  123. var value = result.GetValueOrDefault();
  124. if (result.Type == CompletionType.Throw)
  125. {
  126. ExceptionHelper.ThrowJavaScriptException(_engine, value, result);
  127. return null!;
  128. }
  129. else
  130. {
  131. return value;
  132. }
  133. }
  134. finally
  135. {
  136. Engine.LeaveExecutionContext();
  137. }
  138. }
  139. }
  140. }
  141. }