using Jint.Native.Object; using Jint.Runtime; using Jint.Runtime.Descriptors; using Jint.Runtime.Environments; using Jint.Runtime.Interpreter; using Environment = Jint.Runtime.Environments.Environment; namespace Jint.Native.Function; /// /// https://tc39.es/ecma262/#sec-function-constructor /// public sealed class FunctionConstructor : Constructor { private static readonly JsString _functionName = new JsString("Function"); internal FunctionConstructor( Engine engine, Realm realm, ObjectPrototype objectPrototype) : base(engine, realm, _functionName) { PrototypeObject = new FunctionPrototype(engine, realm, objectPrototype); _prototype = PrototypeObject; _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden); _length = new PropertyDescriptor(JsNumber.PositiveOne, PropertyFlag.Configurable); } internal FunctionPrototype PrototypeObject { get; } protected internal override JsValue Call(JsValue thisObject, JsCallArguments arguments) { return Construct(arguments, thisObject); } public override ObjectInstance Construct(JsCallArguments arguments, JsValue newTarget) { var function = CreateDynamicFunction( this, newTarget, FunctionKind.Normal, arguments); return function; } /// /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiatefunctionobject /// internal Function InstantiateFunctionObject( JintFunctionDefinition functionDeclaration, Environment scope, PrivateEnvironment? privateEnv) { var function = functionDeclaration.Function; if (!function.Generator) { return function.Async ? InstantiateAsyncFunctionObject(functionDeclaration, scope, privateEnv) : InstantiateOrdinaryFunctionObject(functionDeclaration, scope, privateEnv); } else { return InstantiateGeneratorFunctionObject(functionDeclaration, scope, privateEnv); } } /// /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiateasyncfunctionobject /// private ScriptFunction InstantiateAsyncFunctionObject( JintFunctionDefinition functionDeclaration, Environment env, PrivateEnvironment? privateEnv) { var F = OrdinaryFunctionCreate( _realm.Intrinsics.AsyncFunction.PrototypeObject, functionDeclaration, functionDeclaration.ThisMode, env, privateEnv); F.SetFunctionName(functionDeclaration.Name ?? "default"); return F; } /// /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiateordinaryfunctionobject /// private ScriptFunction InstantiateOrdinaryFunctionObject( JintFunctionDefinition functionDeclaration, Environment env, PrivateEnvironment? privateEnv) { var F = OrdinaryFunctionCreate( _realm.Intrinsics.Function.PrototypeObject, functionDeclaration, functionDeclaration.ThisMode, env, privateEnv); var name = functionDeclaration.Name ?? "default"; F.SetFunctionName(name); F.MakeConstructor(); return F; } /// /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiategeneratorfunctionobject /// private ScriptFunction InstantiateGeneratorFunctionObject( JintFunctionDefinition functionDeclaration, Environment scope, PrivateEnvironment? privateScope) { var thisMode = functionDeclaration.Strict || _engine._isStrict ? FunctionThisMode.Strict : FunctionThisMode.Global; var name = functionDeclaration.Function.Id?.Name ?? "default"; var F = OrdinaryFunctionCreate( _realm.Intrinsics.GeneratorFunction.PrototypeObject, functionDeclaration, thisMode, scope, privateScope); F.SetFunctionName(name); var prototype = OrdinaryObjectCreate(_engine, _realm.Intrinsics.GeneratorFunction.PrototypeObject.PrototypeObject); F.DefinePropertyOrThrow(CommonProperties.Prototype, new PropertyDescriptor(prototype, PropertyFlag.Writable)); return F; } }