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 ParserOptions ParserOptions = new ParserOptions { Tolerant = false };
  12. private static readonly JsString _functionName = new JsString("eval");
  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. var parser = new JavaScriptParser(x.ToString(), ParserOptions);
  61. Script script = null;
  62. try
  63. {
  64. script = parser.ParseScript(strictCaller);
  65. }
  66. catch (ParserException e)
  67. {
  68. if (e.Description == Messages.InvalidLHSInAssignment)
  69. {
  70. ExceptionHelper.ThrowReferenceError(callerRealm, (string) null);
  71. }
  72. else
  73. {
  74. ExceptionHelper.ThrowSyntaxError(callerRealm, e.Message);
  75. }
  76. }
  77. var body = script.Body;
  78. if (body.Count == 0)
  79. {
  80. return Undefined;
  81. }
  82. if (!inFunction)
  83. {
  84. // if body Contains NewTarget, throw a SyntaxError exception.
  85. }
  86. if (!inMethod)
  87. {
  88. // if body Contains SuperProperty, throw a SyntaxError exception.
  89. }
  90. if (!inDerivedConstructor)
  91. {
  92. // if body Contains SuperCall, throw a SyntaxError exception.
  93. }
  94. var strictEval = script.Strict || _engine._isStrict;
  95. var ctx = _engine.ExecutionContext;
  96. using (new StrictModeScope(strictEval))
  97. {
  98. EnvironmentRecord lexEnv;
  99. EnvironmentRecord varEnv;
  100. PrivateEnvironmentRecord privateEnv;
  101. if (direct)
  102. {
  103. lexEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, ctx.LexicalEnvironment);
  104. varEnv = ctx.VariableEnvironment;
  105. privateEnv = ctx.PrivateEnvironment;
  106. }
  107. else
  108. {
  109. lexEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, evalRealm.GlobalEnv);
  110. varEnv = evalRealm.GlobalEnv;
  111. privateEnv = null;
  112. }
  113. if (strictEval)
  114. {
  115. varEnv = lexEnv;
  116. }
  117. // If ctx is not already suspended, suspend ctx.
  118. Engine.EnterExecutionContext(lexEnv, varEnv, evalRealm, privateEnv);
  119. try
  120. {
  121. Engine.EvalDeclarationInstantiation(script, varEnv, lexEnv, privateEnv, strictEval);
  122. var statement = new JintScript(script);
  123. var result = statement.Execute(_engine._activeEvaluationContext);
  124. var value = result.GetValueOrDefault();
  125. if (result.Type == CompletionType.Throw)
  126. {
  127. var ex = new JavaScriptException(value).SetCallstack(_engine, result.Location);
  128. throw ex;
  129. }
  130. else
  131. {
  132. return value;
  133. }
  134. }
  135. finally
  136. {
  137. Engine.LeaveExecutionContext();
  138. }
  139. }
  140. }
  141. }
  142. }