using Jint.Native.Object;
using Jint.Runtime;
using Jint.Runtime.Descriptors;
using Jint.Runtime.Environments;
using Jint.Runtime.Interpreter;
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, JsValue[] arguments)
{
return Construct(arguments, thisObject);
}
public override ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
{
var function = CreateDynamicFunction(
this,
newTarget,
FunctionKind.Normal,
arguments);
return function;
}
///
/// https://tc39.es/ecma262/#sec-runtime-semantics-instantiatefunctionobject
///
internal FunctionInstance InstantiateFunctionObject(
JintFunctionDefinition functionDeclaration,
EnvironmentRecord scope,
PrivateEnvironmentRecord? 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 FunctionInstance InstantiateAsyncFunctionObject(
JintFunctionDefinition functionDeclaration,
EnvironmentRecord env,
PrivateEnvironmentRecord? 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 FunctionInstance InstantiateOrdinaryFunctionObject(
JintFunctionDefinition functionDeclaration,
EnvironmentRecord env,
PrivateEnvironmentRecord? 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 FunctionInstance InstantiateGeneratorFunctionObject(
JintFunctionDefinition functionDeclaration,
EnvironmentRecord scope,
PrivateEnvironmentRecord? privateScope)
{
// TODO generators
return InstantiateOrdinaryFunctionObject(functionDeclaration, scope, privateScope);
}
}
}