FunctionInstance.Dynamic.cs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. using Jint.Native.Object;
  2. using Jint.Runtime;
  3. using Jint.Runtime.Descriptors;
  4. using Jint.Runtime.Environments;
  5. using Jint.Runtime.Interpreter;
  6. using Environment = Jint.Runtime.Environments.Environment;
  7. namespace Jint.Native.Function;
  8. #pragma warning disable MA0049
  9. public partial class Function
  10. #pragma warning restore MA0049
  11. {
  12. private static readonly JsString _functionNameAnonymous = new JsString("anonymous");
  13. /// <summary>
  14. /// https://tc39.es/ecma262/#sec-createdynamicfunction
  15. /// </summary>
  16. internal Function CreateDynamicFunction(
  17. ObjectInstance constructor,
  18. JsValue newTarget,
  19. FunctionKind kind,
  20. JsValue[] arguments)
  21. {
  22. // TODO var callerContext = _engine.GetExecutionContext(1);
  23. var callerContext = _engine.ExecutionContext;
  24. var callerRealm = callerContext.Realm;
  25. var calleeRealm = _engine.ExecutionContext.Realm;
  26. _engine._host.EnsureCanCompileStrings(callerRealm, calleeRealm);
  27. if (newTarget.IsUndefined())
  28. {
  29. newTarget = constructor;
  30. }
  31. Func<Intrinsics, ObjectInstance>? fallbackProto = null;
  32. switch (kind)
  33. {
  34. case FunctionKind.Normal:
  35. fallbackProto = static intrinsics => intrinsics.Function.PrototypeObject;
  36. break;
  37. case FunctionKind.Async:
  38. fallbackProto = static intrinsics => intrinsics.AsyncFunction.PrototypeObject;
  39. break;
  40. case FunctionKind.Generator:
  41. fallbackProto = static intrinsics => intrinsics.GeneratorFunction.PrototypeObject;
  42. break;
  43. case FunctionKind.AsyncGenerator:
  44. default:
  45. ExceptionHelper.ThrowArgumentOutOfRangeException(nameof(kind), kind.ToString());
  46. break;
  47. }
  48. var argCount = arguments.Length;
  49. var p = "";
  50. var body = "";
  51. if (argCount == 1)
  52. {
  53. body = TypeConverter.ToString(arguments[0]);
  54. }
  55. else if (argCount > 1)
  56. {
  57. var firstArg = arguments[0];
  58. p = TypeConverter.ToString(firstArg);
  59. for (var k = 1; k < argCount - 1; k++)
  60. {
  61. var nextArg = arguments[k];
  62. p += "," + TypeConverter.ToString(nextArg);
  63. }
  64. body = TypeConverter.ToString(arguments[argCount - 1]);
  65. }
  66. IFunction? function = null;
  67. try
  68. {
  69. string? functionExpression = null;
  70. if (argCount == 0)
  71. {
  72. switch (kind)
  73. {
  74. case FunctionKind.Normal:
  75. functionExpression = "function f(){}";
  76. break;
  77. case FunctionKind.Generator:
  78. functionExpression = "function* f(){}";
  79. break;
  80. case FunctionKind.Async:
  81. functionExpression = "async function f(){}";
  82. break;
  83. case FunctionKind.AsyncGenerator:
  84. ExceptionHelper.ThrowNotImplementedException("Async generators not implemented");
  85. break;
  86. default:
  87. ExceptionHelper.ThrowArgumentOutOfRangeException(nameof(kind), kind.ToString());
  88. break;
  89. }
  90. }
  91. else
  92. {
  93. switch (kind)
  94. {
  95. case FunctionKind.Normal:
  96. functionExpression = "function f(";
  97. break;
  98. case FunctionKind.Async:
  99. functionExpression = "async function f(";
  100. break;
  101. case FunctionKind.Generator:
  102. functionExpression = "function* f(";
  103. break;
  104. case FunctionKind.AsyncGenerator:
  105. ExceptionHelper.ThrowNotImplementedException("Async generators not implemented");
  106. break;
  107. default:
  108. ExceptionHelper.ThrowArgumentOutOfRangeException(nameof(kind), kind.ToString());
  109. break;
  110. }
  111. if (p.Contains('/'))
  112. {
  113. // ensure comments don't screw up things
  114. functionExpression += "\n" + p + "\n";
  115. }
  116. else
  117. {
  118. functionExpression += p;
  119. }
  120. functionExpression += ")";
  121. if (body.Contains('/'))
  122. {
  123. // ensure comments don't screw up things
  124. functionExpression += "{\n" + body + "\n}";
  125. }
  126. else
  127. {
  128. functionExpression += "{" + body + "}";
  129. }
  130. }
  131. JavaScriptParser parser = new(new ParserOptions
  132. {
  133. Tolerant = false,
  134. RegexTimeout = _engine.Options.Constraints.RegexTimeout
  135. });
  136. function = (IFunction) parser.ParseScript(functionExpression, source: null, _engine._isStrict).Body[0];
  137. }
  138. catch (ParserException ex)
  139. {
  140. ExceptionHelper.ThrowSyntaxError(_engine.ExecutionContext.Realm, ex.Message);
  141. }
  142. var proto = GetPrototypeFromConstructor(newTarget, fallbackProto);
  143. var realmF = _realm;
  144. var scope = realmF.GlobalEnv;
  145. PrivateEnvironment? privateEnv = null;
  146. var definition = new JintFunctionDefinition(function);
  147. Function F = OrdinaryFunctionCreate(proto, definition, function.Strict ? FunctionThisMode.Strict : FunctionThisMode.Global, scope, privateEnv);
  148. F.SetFunctionName(_functionNameAnonymous, force: true);
  149. if (kind == FunctionKind.Generator)
  150. {
  151. var prototype = OrdinaryObjectCreate(_engine, _realm.Intrinsics.GeneratorFunction.PrototypeObject.PrototypeObject);
  152. F.DefinePropertyOrThrow(CommonProperties.Prototype, new PropertyDescriptor(prototype, PropertyFlag.Writable));
  153. }
  154. else if (kind == FunctionKind.AsyncGenerator)
  155. {
  156. // TODO
  157. // Let prototype be ! OrdinaryObjectCreate(%AsyncGeneratorFunction.prototype.prototype%).
  158. // Perform DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
  159. ExceptionHelper.ThrowNotImplementedException("async generators not implemented");
  160. }
  161. else if (kind == FunctionKind.Normal)
  162. {
  163. F.MakeConstructor();
  164. }
  165. return F;
  166. }
  167. /// <summary>
  168. /// https://tc39.es/ecma262/#sec-ordinaryfunctioncreate
  169. /// </summary>
  170. internal ScriptFunction OrdinaryFunctionCreate(
  171. ObjectInstance functionPrototype,
  172. JintFunctionDefinition function,
  173. FunctionThisMode thisMode,
  174. Environment scope,
  175. PrivateEnvironment? privateScope)
  176. {
  177. return new ScriptFunction(
  178. _engine,
  179. function,
  180. scope,
  181. thisMode,
  182. functionPrototype) { _privateEnvironment = privateScope, _realm = _realm };
  183. }
  184. }