EvalFunctionInstance.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. using Esprima;
  2. using Esprima.Ast;
  3. using Esprima.Utils;
  4. using Jint.Runtime;
  5. using Jint.Runtime.Descriptors;
  6. using Jint.Runtime.Environments;
  7. using Jint.Runtime.Interpreter.Statements;
  8. namespace Jint.Native.Function;
  9. internal sealed class EvalFunctionInstance : FunctionInstance
  10. {
  11. private static readonly JsString _functionName = new("eval");
  12. private static readonly ParserOptions _parserOptions = ParserOptions.Default with { Tolerant = true };
  13. private readonly JavaScriptParser _parser = new(_parserOptions);
  14. public EvalFunctionInstance(
  15. Engine engine,
  16. Realm realm,
  17. FunctionPrototype functionPrototype)
  18. : base(
  19. engine,
  20. realm,
  21. _functionName,
  22. StrictModeScope.IsStrictModeCode ? FunctionThisMode.Strict : FunctionThisMode.Global)
  23. {
  24. _prototype = functionPrototype;
  25. _length = new PropertyDescriptor(JsNumber.PositiveOne, PropertyFlag.Configurable);
  26. }
  27. protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments)
  28. {
  29. var callerRealm = _engine.ExecutionContext.Realm;
  30. var x = arguments.At(0);
  31. return PerformEval(x, callerRealm, false, false);
  32. }
  33. /// <summary>
  34. /// https://tc39.es/ecma262/#sec-performeval
  35. /// </summary>
  36. public JsValue PerformEval(JsValue x, Realm callerRealm, bool strictCaller, bool direct)
  37. {
  38. if (!x.IsString())
  39. {
  40. return x;
  41. }
  42. var evalRealm = _realm;
  43. _engine._host.EnsureCanCompileStrings(callerRealm, evalRealm);
  44. var inFunction = false;
  45. var inMethod = false;
  46. var inDerivedConstructor = false;
  47. var inClassFieldInitializer = false;
  48. if (direct)
  49. {
  50. var thisEnvRec = _engine.ExecutionContext.GetThisEnvironment();
  51. if (thisEnvRec is FunctionEnvironmentRecord functionEnvironmentRecord)
  52. {
  53. var F = functionEnvironmentRecord._functionObject;
  54. inFunction = true;
  55. inMethod = thisEnvRec.HasSuperBinding();
  56. if (F._constructorKind == ConstructorKind.Derived)
  57. {
  58. inDerivedConstructor = true;
  59. }
  60. var classFieldInitializerName = (F as ScriptFunctionInstance)?._classFieldInitializerName;
  61. if (!string.IsNullOrEmpty(classFieldInitializerName?.ToString()))
  62. {
  63. inClassFieldInitializer = true;
  64. }
  65. }
  66. }
  67. Script? script = null;
  68. try
  69. {
  70. script = _parser.ParseScript(x.ToString(), strict: strictCaller);
  71. }
  72. catch (ParserException e)
  73. {
  74. if (e.Description == Messages.InvalidLHSInAssignment)
  75. {
  76. ExceptionHelper.ThrowReferenceError(callerRealm, (string?) null);
  77. }
  78. else
  79. {
  80. ExceptionHelper.ThrowSyntaxError(callerRealm, e.Message);
  81. }
  82. }
  83. var body = script.Body;
  84. if (body.Count == 0)
  85. {
  86. return Undefined;
  87. }
  88. var analyzer = new EvalScriptAnalyzer();
  89. analyzer.Visit(script);
  90. if (!inFunction)
  91. {
  92. // if body Contains NewTarget, throw a SyntaxError exception.
  93. if (analyzer._containsNewTarget)
  94. {
  95. ExceptionHelper.ThrowSyntaxError(evalRealm, "new.target expression is not allowed here");
  96. }
  97. }
  98. if (!inMethod)
  99. {
  100. // if body Contains SuperProperty, throw a SyntaxError exception.
  101. if (analyzer._containsSuperProperty)
  102. {
  103. ExceptionHelper.ThrowSyntaxError(evalRealm, "'super' keyword unexpected here");
  104. }
  105. }
  106. if (!inDerivedConstructor)
  107. {
  108. // if body Contains SuperCall, throw a SyntaxError exception.
  109. if (analyzer._containsSuperCall)
  110. {
  111. ExceptionHelper.ThrowSyntaxError(evalRealm, "'super' keyword unexpected here");
  112. }
  113. }
  114. if (inClassFieldInitializer)
  115. {
  116. // if ContainsArguments of body is true, throw a SyntaxError exception.
  117. if (analyzer._containsArguments)
  118. {
  119. ExceptionHelper.ThrowSyntaxError(evalRealm, "'arguments' is not allowed in class field initializer or static initialization block");
  120. }
  121. }
  122. var strictEval = script.Strict || _engine._isStrict;
  123. var ctx = _engine.ExecutionContext;
  124. using (new StrictModeScope(strictEval))
  125. {
  126. EnvironmentRecord lexEnv;
  127. EnvironmentRecord varEnv;
  128. PrivateEnvironmentRecord? privateEnv;
  129. if (direct)
  130. {
  131. lexEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, ctx.LexicalEnvironment);
  132. varEnv = ctx.VariableEnvironment;
  133. privateEnv = ctx.PrivateEnvironment;
  134. }
  135. else
  136. {
  137. lexEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, evalRealm.GlobalEnv);
  138. varEnv = evalRealm.GlobalEnv;
  139. privateEnv = null;
  140. }
  141. if (strictEval)
  142. {
  143. varEnv = lexEnv;
  144. }
  145. // If ctx is not already suspended, suspend ctx.
  146. Engine.EnterExecutionContext(lexEnv, varEnv, evalRealm, privateEnv);
  147. try
  148. {
  149. Engine.EvalDeclarationInstantiation(script, varEnv, lexEnv, privateEnv, strictEval);
  150. var statement = new JintScript(script);
  151. var result = statement.Execute(_engine._activeEvaluationContext!);
  152. var value = result.GetValueOrDefault();
  153. if (result.Type == CompletionType.Throw)
  154. {
  155. ExceptionHelper.ThrowJavaScriptException(_engine, value, result);
  156. return null!;
  157. }
  158. else
  159. {
  160. return value;
  161. }
  162. }
  163. finally
  164. {
  165. Engine.LeaveExecutionContext();
  166. }
  167. }
  168. }
  169. private sealed class EvalScriptAnalyzer : AstVisitor
  170. {
  171. public bool _containsArguments;
  172. public bool _containsNewTarget;
  173. public bool _containsSuperCall;
  174. public bool _containsSuperProperty;
  175. protected override object VisitIdentifier(Identifier identifier)
  176. {
  177. _containsArguments |= identifier.Name == "arguments";
  178. return identifier;
  179. }
  180. protected override object VisitMetaProperty(MetaProperty metaProperty)
  181. {
  182. _containsNewTarget |= metaProperty.Meta.Name == "new" && metaProperty.Property.Name == "target";
  183. return metaProperty;
  184. }
  185. protected override object? VisitMemberExpression(MemberExpression memberExpression)
  186. {
  187. _containsSuperProperty |= memberExpression.Object.Type == Nodes.Super;
  188. return base.VisitMemberExpression(memberExpression);
  189. }
  190. protected override object? VisitCallExpression(CallExpression callExpression)
  191. {
  192. _containsSuperCall |= callExpression.Callee.Type == Nodes.Super;
  193. return base.VisitCallExpression(callExpression);
  194. }
  195. }
  196. }