JintFunctionExpression.cs 7.3 KB

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