JintFunctionExpression.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. using Esprima.Ast;
  2. using Jint.Native;
  3. using Jint.Native.Function;
  4. using Jint.Native.Object;
  5. using Jint.Runtime.Descriptors;
  6. using Jint.Runtime.Environments;
  7. namespace Jint.Runtime.Interpreter.Expressions
  8. {
  9. internal sealed class JintFunctionExpression : JintExpression
  10. {
  11. private readonly JintFunctionDefinition _function;
  12. public JintFunctionExpression(FunctionExpression function) : base(function)
  13. {
  14. _function = new JintFunctionDefinition(function);
  15. }
  16. protected override object EvaluateInternal(EvaluationContext context)
  17. {
  18. return GetValue(context);
  19. }
  20. public override JsValue GetValue(EvaluationContext context)
  21. {
  22. ScriptFunction closure;
  23. var functionName = _function.Name ?? "";
  24. if (!_function.Function.Generator)
  25. {
  26. closure = _function.Function.Async
  27. ? InstantiateAsyncFunctionExpression(context, functionName)
  28. : InstantiateOrdinaryFunctionExpression(context, functionName);
  29. }
  30. else
  31. {
  32. closure = InstantiateGeneratorFunctionExpression(context, functionName);
  33. }
  34. return closure;
  35. }
  36. /// <summary>
  37. /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiateordinaryfunctionexpression
  38. /// </summary>
  39. private ScriptFunction InstantiateOrdinaryFunctionExpression(EvaluationContext context, string? name = "")
  40. {
  41. var engine = context.Engine;
  42. var runningExecutionContext = engine.ExecutionContext;
  43. var scope = runningExecutionContext.LexicalEnvironment;
  44. DeclarativeEnvironment? funcEnv = null;
  45. if (!string.IsNullOrWhiteSpace(name))
  46. {
  47. funcEnv = JintEnvironment.NewDeclarativeEnvironment(engine, engine.ExecutionContext.LexicalEnvironment);
  48. funcEnv.CreateImmutableBinding(name!, strict: false);
  49. }
  50. var privateEnv = runningExecutionContext.PrivateEnvironment;
  51. var thisMode = _function.Strict
  52. ? FunctionThisMode.Strict
  53. : FunctionThisMode.Global;
  54. var intrinsics = engine.Realm.Intrinsics;
  55. var closure = intrinsics.Function.OrdinaryFunctionCreate(
  56. intrinsics.Function.PrototypeObject,
  57. _function,
  58. thisMode,
  59. funcEnv ?? scope,
  60. privateEnv
  61. );
  62. if (name is not null)
  63. {
  64. closure.SetFunctionName(name);
  65. }
  66. closure.MakeConstructor();
  67. funcEnv?.InitializeBinding(name!, closure);
  68. return closure;
  69. }
  70. /// <summary>
  71. /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiateasyncfunctionexpression
  72. /// </summary>
  73. private ScriptFunction InstantiateAsyncFunctionExpression(EvaluationContext context, string? name = "")
  74. {
  75. var engine = context.Engine;
  76. var runningExecutionContext = engine.ExecutionContext;
  77. var scope = runningExecutionContext.LexicalEnvironment;
  78. DeclarativeEnvironment? funcEnv = null;
  79. if (!string.IsNullOrWhiteSpace(name))
  80. {
  81. funcEnv = JintEnvironment.NewDeclarativeEnvironment(engine, engine.ExecutionContext.LexicalEnvironment);
  82. funcEnv.CreateImmutableBinding(name!, strict: false);
  83. }
  84. var privateScope = runningExecutionContext.PrivateEnvironment;
  85. var thisMode = _function.Strict
  86. ? FunctionThisMode.Strict
  87. : FunctionThisMode.Global;
  88. var intrinsics = engine.Realm.Intrinsics;
  89. var closure = intrinsics.Function.OrdinaryFunctionCreate(
  90. intrinsics.AsyncFunction.PrototypeObject,
  91. _function,
  92. thisMode,
  93. funcEnv ?? scope,
  94. privateScope
  95. );
  96. closure.SetFunctionName(name ?? "");
  97. funcEnv?.InitializeBinding(name!, closure);
  98. return closure;
  99. }
  100. /// <summary>
  101. /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiategeneratorfunctionexpression
  102. /// </summary>
  103. private ScriptFunction InstantiateGeneratorFunctionExpression(EvaluationContext context, string? name)
  104. {
  105. var engine = context.Engine;
  106. var runningExecutionContext = engine.ExecutionContext;
  107. var scope = runningExecutionContext.LexicalEnvironment;
  108. DeclarativeEnvironment? funcEnv = null;
  109. if (!string.IsNullOrWhiteSpace(name))
  110. {
  111. funcEnv = JintEnvironment.NewDeclarativeEnvironment(engine, engine.ExecutionContext.LexicalEnvironment);
  112. funcEnv.CreateImmutableBinding(name!, strict: false);
  113. }
  114. var privateScope = runningExecutionContext.PrivateEnvironment;
  115. var thisMode = _function.Strict || engine._isStrict
  116. ? FunctionThisMode.Strict
  117. : FunctionThisMode.Global;
  118. var intrinsics = engine.Realm.Intrinsics;
  119. var closure = intrinsics.Function.OrdinaryFunctionCreate(
  120. intrinsics.GeneratorFunction.PrototypeObject,
  121. _function,
  122. thisMode,
  123. funcEnv ?? scope,
  124. privateScope
  125. );
  126. if (name is not null)
  127. {
  128. closure.SetFunctionName(name);
  129. }
  130. var prototype = ObjectInstance.OrdinaryObjectCreate(engine, intrinsics.GeneratorFunction.PrototypeObject.PrototypeObject);
  131. closure.DefinePropertyOrThrow(CommonProperties.Prototype, new PropertyDescriptor(prototype, PropertyFlag.Writable));
  132. funcEnv?.InitializeBinding(name!, closure);
  133. return closure;
  134. }
  135. }
  136. }