FunctionConstructor.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. using System;
  2. using Esprima;
  3. using Esprima.Ast;
  4. using Jint.Native.Object;
  5. using Jint.Runtime;
  6. using Jint.Runtime.Descriptors;
  7. using Jint.Runtime.Environments;
  8. using Jint.Runtime.Interpreter;
  9. namespace Jint.Native.Function
  10. {
  11. /// <summary>
  12. /// https://tc39.es/ecma262/#sec-function-constructor
  13. /// </summary>
  14. public sealed class FunctionConstructor : FunctionInstance, IConstructor
  15. {
  16. private static readonly ParserOptions ParserOptions = new ParserOptions { Tolerant = false };
  17. private static readonly JsString _functionName = new JsString("Function");
  18. private static readonly JsString _functionNameAnonymous = new JsString("anonymous");
  19. internal FunctionConstructor(
  20. Engine engine,
  21. Realm realm,
  22. ObjectPrototype objectPrototype)
  23. : base(engine, realm, _functionName)
  24. {
  25. PrototypeObject = new FunctionPrototype(engine, realm, objectPrototype);
  26. _prototype = PrototypeObject;
  27. _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
  28. _length = new PropertyDescriptor(JsNumber.PositiveOne, PropertyFlag.Configurable);
  29. }
  30. public FunctionPrototype PrototypeObject { get; }
  31. protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments)
  32. {
  33. return Construct(arguments, thisObject);
  34. }
  35. ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget) => Construct(arguments, newTarget);
  36. private ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
  37. {
  38. var function = CreateDynamicFunction(
  39. this,
  40. newTarget,
  41. FunctionKind.Normal,
  42. arguments);
  43. return function;
  44. }
  45. /// <summary>
  46. /// https://tc39.es/ecma262/#sec-createdynamicfunction
  47. /// </summary>
  48. internal FunctionInstance CreateDynamicFunction(
  49. ObjectInstance constructor,
  50. JsValue newTarget,
  51. FunctionKind kind,
  52. JsValue[] args)
  53. {
  54. // TODO var callerContext = _engine.GetExecutionContext(1);
  55. var callerContext = _engine.ExecutionContext;
  56. var callerRealm = callerContext.Realm;
  57. var calleeRealm = _engine.ExecutionContext.Realm;
  58. _engine._host.EnsureCanCompileStrings(callerRealm, calleeRealm);
  59. if (newTarget.IsUndefined())
  60. {
  61. newTarget = constructor;
  62. }
  63. Func<Intrinsics, ObjectInstance> fallbackProto = null;
  64. switch (kind)
  65. {
  66. case FunctionKind.Normal:
  67. fallbackProto = static intrinsics => intrinsics.Function.PrototypeObject;
  68. break;
  69. case FunctionKind.Generator:
  70. case FunctionKind.AsyncGenerator:
  71. case FunctionKind.Async:
  72. default:
  73. ExceptionHelper.ThrowArgumentOutOfRangeException(nameof(kind), kind.ToString());
  74. break;
  75. }
  76. var argCount = args.Length;
  77. var p = "";
  78. var body = "";
  79. if (argCount == 1)
  80. {
  81. body = TypeConverter.ToString(args[0]);
  82. }
  83. else if (argCount > 1)
  84. {
  85. var firstArg = args[0];
  86. p = TypeConverter.ToString(firstArg);
  87. for (var k = 1; k < argCount - 1; k++)
  88. {
  89. var nextArg = args[k];
  90. p += "," + TypeConverter.ToString(nextArg);
  91. }
  92. body = TypeConverter.ToString(args[argCount - 1]);
  93. }
  94. IFunction function = null;
  95. try
  96. {
  97. string functionExpression = null;
  98. if (argCount == 0)
  99. {
  100. switch (kind)
  101. {
  102. case FunctionKind.Normal:
  103. functionExpression = "function f(){}";
  104. break;
  105. case FunctionKind.Generator:
  106. functionExpression = "function* f(){}";
  107. break;
  108. case FunctionKind.Async:
  109. ExceptionHelper.ThrowNotImplementedException("Async functions not implemented");
  110. break;
  111. case FunctionKind.AsyncGenerator:
  112. ExceptionHelper.ThrowNotImplementedException("Async generators not implemented");
  113. break;
  114. default:
  115. ExceptionHelper.ThrowArgumentOutOfRangeException(nameof(kind), kind.ToString());
  116. break;
  117. }
  118. }
  119. else
  120. {
  121. switch (kind)
  122. {
  123. case FunctionKind.Normal:
  124. functionExpression = "function f(";
  125. break;
  126. case FunctionKind.Generator:
  127. functionExpression = "function* f(";
  128. break;
  129. case FunctionKind.Async:
  130. ExceptionHelper.ThrowNotImplementedException("Async functions not implemented");
  131. break;
  132. case FunctionKind.AsyncGenerator:
  133. ExceptionHelper.ThrowNotImplementedException("Async generators not implemented");
  134. break;
  135. default:
  136. ExceptionHelper.ThrowArgumentOutOfRangeException(nameof(kind), kind.ToString());
  137. break;
  138. }
  139. if (p.IndexOf('/') != -1)
  140. {
  141. // ensure comments don't screw up things
  142. functionExpression += "\n" + p + "\n";
  143. }
  144. else
  145. {
  146. functionExpression += p;
  147. }
  148. functionExpression += ")";
  149. if (body.IndexOf('/') != -1)
  150. {
  151. // ensure comments don't screw up things
  152. functionExpression += "{\n" + body + "\n}";
  153. }
  154. else
  155. {
  156. functionExpression += "{" + body + "}";
  157. }
  158. }
  159. var parser = new JavaScriptParser(functionExpression, ParserOptions);
  160. function = (IFunction) parser.ParseScript().Body[0];
  161. }
  162. catch (ParserException ex)
  163. {
  164. ExceptionHelper.ThrowSyntaxError(_engine.ExecutionContext.Realm, ex.Message);
  165. }
  166. var proto = GetPrototypeFromConstructor(newTarget, fallbackProto);
  167. var realmF = _realm;
  168. var scope = realmF.GlobalEnv;
  169. PrivateEnvironmentRecord privateScope = null;
  170. var definition = new JintFunctionDefinition(_engine, function);
  171. FunctionInstance F = OrdinaryFunctionCreate(proto, definition, function.Strict ? FunctionThisMode.Strict : FunctionThisMode.Global, scope, privateScope);
  172. F.SetFunctionName(_functionNameAnonymous, force: true);
  173. if (kind == FunctionKind.Generator)
  174. {
  175. ExceptionHelper.ThrowNotImplementedException("generators not implemented");
  176. }
  177. else if (kind == FunctionKind.AsyncGenerator)
  178. {
  179. // TODO
  180. // Let prototype be ! OrdinaryObjectCreate(%AsyncGeneratorFunction.prototype.prototype%).
  181. // Perform DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
  182. ExceptionHelper.ThrowNotImplementedException("async generators not implemented");
  183. }
  184. else if (kind == FunctionKind.Normal)
  185. {
  186. F.MakeConstructor();
  187. }
  188. return F;
  189. }
  190. /// <summary>
  191. /// https://tc39.es/ecma262/#sec-ordinaryfunctioncreate
  192. /// </summary>
  193. internal ScriptFunctionInstance OrdinaryFunctionCreate(
  194. ObjectInstance functionPrototype,
  195. JintFunctionDefinition function,
  196. FunctionThisMode thisMode,
  197. EnvironmentRecord scope,
  198. PrivateEnvironmentRecord privateScope)
  199. {
  200. return new ScriptFunctionInstance(
  201. _engine,
  202. function,
  203. scope,
  204. thisMode,
  205. functionPrototype)
  206. {
  207. _privateEnvironment = privateScope,
  208. _realm = _realm
  209. };
  210. }
  211. /// <summary>
  212. /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiatefunctionobject
  213. /// </summary>
  214. internal FunctionInstance InstantiateFunctionObject(
  215. JintFunctionDefinition functionDeclaration,
  216. EnvironmentRecord scope,
  217. PrivateEnvironmentRecord privateScope)
  218. {
  219. return !functionDeclaration.Function.Generator
  220. ? InstantiateOrdinaryFunctionObject(functionDeclaration, scope, privateScope)
  221. : InstantiateGeneratorFunctionObject(functionDeclaration, scope, privateScope);
  222. }
  223. /// <summary>
  224. /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiateordinaryfunctionobject
  225. /// </summary>
  226. private FunctionInstance InstantiateOrdinaryFunctionObject(
  227. JintFunctionDefinition functionDeclaration,
  228. EnvironmentRecord scope,
  229. PrivateEnvironmentRecord privateScope)
  230. {
  231. var F = OrdinaryFunctionCreate(
  232. _realm.Intrinsics.Function.PrototypeObject,
  233. functionDeclaration,
  234. functionDeclaration.ThisMode,
  235. scope,
  236. privateScope);
  237. var name = functionDeclaration.Name ?? "default";
  238. F.SetFunctionName(name);
  239. F.MakeConstructor();
  240. return F;
  241. }
  242. /// <summary>
  243. /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiategeneratorfunctionobject
  244. /// </summary>
  245. private FunctionInstance InstantiateGeneratorFunctionObject(
  246. JintFunctionDefinition functionDeclaration,
  247. EnvironmentRecord scope,
  248. PrivateEnvironmentRecord privateScope)
  249. {
  250. // TODO generators
  251. return InstantiateOrdinaryFunctionObject(functionDeclaration, scope, privateScope);
  252. }
  253. }
  254. }