|
@@ -1,5 +1,3 @@
|
|
|
-using Esprima;
|
|
|
-using Esprima.Ast;
|
|
|
using Jint.Native.Object;
|
|
|
using Jint.Runtime;
|
|
|
using Jint.Runtime.Descriptors;
|
|
@@ -14,9 +12,6 @@ namespace Jint.Native.Function
|
|
|
public sealed class FunctionConstructor : FunctionInstance, IConstructor
|
|
|
{
|
|
|
private static readonly JsString _functionName = new JsString("Function");
|
|
|
- private static readonly JsString _functionNameAnonymous = new JsString("anonymous");
|
|
|
-
|
|
|
- private readonly JavaScriptParser _parser = new(new ParserOptions { Tolerant = false });
|
|
|
|
|
|
internal FunctionConstructor(
|
|
|
Engine engine,
|
|
@@ -51,198 +46,44 @@ namespace Jint.Native.Function
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// https://tc39.es/ecma262/#sec-createdynamicfunction
|
|
|
+ /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiatefunctionobject
|
|
|
/// </summary>
|
|
|
- internal FunctionInstance CreateDynamicFunction(
|
|
|
- ObjectInstance constructor,
|
|
|
- JsValue newTarget,
|
|
|
- FunctionKind kind,
|
|
|
- JsValue[] args)
|
|
|
+ internal FunctionInstance InstantiateFunctionObject(
|
|
|
+ JintFunctionDefinition functionDeclaration,
|
|
|
+ EnvironmentRecord scope,
|
|
|
+ PrivateEnvironmentRecord? privateScope)
|
|
|
{
|
|
|
- // TODO var callerContext = _engine.GetExecutionContext(1);
|
|
|
- var callerContext = _engine.ExecutionContext;
|
|
|
- var callerRealm = callerContext.Realm;
|
|
|
- var calleeRealm = _engine.ExecutionContext.Realm;
|
|
|
-
|
|
|
- _engine._host.EnsureCanCompileStrings(callerRealm, calleeRealm);
|
|
|
-
|
|
|
- if (newTarget.IsUndefined())
|
|
|
- {
|
|
|
- newTarget = constructor;
|
|
|
- }
|
|
|
-
|
|
|
- Func<Intrinsics, ObjectInstance>? fallbackProto = null;
|
|
|
- switch (kind)
|
|
|
- {
|
|
|
- case FunctionKind.Normal:
|
|
|
- fallbackProto = static intrinsics => intrinsics.Function.PrototypeObject;
|
|
|
- break;
|
|
|
- case FunctionKind.Generator:
|
|
|
- case FunctionKind.AsyncGenerator:
|
|
|
- case FunctionKind.Async:
|
|
|
- default:
|
|
|
- ExceptionHelper.ThrowArgumentOutOfRangeException(nameof(kind), kind.ToString());
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- var argCount = args.Length;
|
|
|
- var p = "";
|
|
|
- var body = "";
|
|
|
-
|
|
|
- if (argCount == 1)
|
|
|
- {
|
|
|
- body = TypeConverter.ToString(args[0]);
|
|
|
- }
|
|
|
- else if (argCount > 1)
|
|
|
- {
|
|
|
- var firstArg = args[0];
|
|
|
- p = TypeConverter.ToString(firstArg);
|
|
|
- for (var k = 1; k < argCount - 1; k++)
|
|
|
- {
|
|
|
- var nextArg = args[k];
|
|
|
- p += "," + TypeConverter.ToString(nextArg);
|
|
|
- }
|
|
|
-
|
|
|
- body = TypeConverter.ToString(args[argCount - 1]);
|
|
|
- }
|
|
|
-
|
|
|
- IFunction? function = null;
|
|
|
- try
|
|
|
- {
|
|
|
- string? functionExpression = null;
|
|
|
- if (argCount == 0)
|
|
|
- {
|
|
|
- switch (kind)
|
|
|
- {
|
|
|
- case FunctionKind.Normal:
|
|
|
- functionExpression = "function f(){}";
|
|
|
- break;
|
|
|
- case FunctionKind.Generator:
|
|
|
- functionExpression = "function* f(){}";
|
|
|
- break;
|
|
|
- case FunctionKind.Async:
|
|
|
- ExceptionHelper.ThrowNotImplementedException("Async functions not implemented");
|
|
|
- break;
|
|
|
- case FunctionKind.AsyncGenerator:
|
|
|
- ExceptionHelper.ThrowNotImplementedException("Async generators not implemented");
|
|
|
- break;
|
|
|
- default:
|
|
|
- ExceptionHelper.ThrowArgumentOutOfRangeException(nameof(kind), kind.ToString());
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- switch (kind)
|
|
|
- {
|
|
|
- case FunctionKind.Normal:
|
|
|
- functionExpression = "function f(";
|
|
|
- break;
|
|
|
- case FunctionKind.Generator:
|
|
|
- functionExpression = "function* f(";
|
|
|
- break;
|
|
|
- case FunctionKind.Async:
|
|
|
- ExceptionHelper.ThrowNotImplementedException("Async functions not implemented");
|
|
|
- break;
|
|
|
- case FunctionKind.AsyncGenerator:
|
|
|
- ExceptionHelper.ThrowNotImplementedException("Async generators not implemented");
|
|
|
- break;
|
|
|
- default:
|
|
|
- ExceptionHelper.ThrowArgumentOutOfRangeException(nameof(kind), kind.ToString());
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- if (p.IndexOf('/') != -1)
|
|
|
- {
|
|
|
- // ensure comments don't screw up things
|
|
|
- functionExpression += "\n" + p + "\n";
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- functionExpression += p;
|
|
|
- }
|
|
|
-
|
|
|
- functionExpression += ")";
|
|
|
-
|
|
|
- if (body.IndexOf('/') != -1)
|
|
|
- {
|
|
|
- // ensure comments don't screw up things
|
|
|
- functionExpression += "{\n" + body + "\n}";
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- functionExpression += "{" + body + "}";
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- function = (IFunction) _parser.ParseScript(functionExpression).Body[0];
|
|
|
- }
|
|
|
- catch (ParserException ex)
|
|
|
- {
|
|
|
- ExceptionHelper.ThrowSyntaxError(_engine.ExecutionContext.Realm, ex.Message);
|
|
|
- }
|
|
|
-
|
|
|
- var proto = GetPrototypeFromConstructor(newTarget, fallbackProto);
|
|
|
- var realmF = _realm;
|
|
|
- var scope = realmF.GlobalEnv;
|
|
|
- PrivateEnvironmentRecord? privateScope = null;
|
|
|
-
|
|
|
- var definition = new JintFunctionDefinition(function);
|
|
|
- FunctionInstance F = OrdinaryFunctionCreate(proto, definition, function.Strict ? FunctionThisMode.Strict : FunctionThisMode.Global, scope, privateScope);
|
|
|
- F.SetFunctionName(_functionNameAnonymous, force: true);
|
|
|
-
|
|
|
- if (kind == FunctionKind.Generator)
|
|
|
+ var function = functionDeclaration.Function;
|
|
|
+ if (!function.Generator)
|
|
|
{
|
|
|
- ExceptionHelper.ThrowNotImplementedException("generators not implemented");
|
|
|
+ return function.Async
|
|
|
+ ? InstantiateAsyncFunctionObject(functionDeclaration, scope, privateScope)
|
|
|
+ : InstantiateOrdinaryFunctionObject(functionDeclaration, scope, privateScope);
|
|
|
}
|
|
|
- else if (kind == FunctionKind.AsyncGenerator)
|
|
|
+ else
|
|
|
{
|
|
|
- // TODO
|
|
|
- // Let prototype be ! OrdinaryObjectCreate(%AsyncGeneratorFunction.prototype.prototype%).
|
|
|
- // Perform DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
|
|
|
- ExceptionHelper.ThrowNotImplementedException("async generators not implemented");
|
|
|
+ return InstantiateGeneratorFunctionObject(functionDeclaration, scope, privateScope);
|
|
|
}
|
|
|
- else if (kind == FunctionKind.Normal)
|
|
|
- {
|
|
|
- F.MakeConstructor();
|
|
|
- }
|
|
|
-
|
|
|
- return F;
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// https://tc39.es/ecma262/#sec-ordinaryfunctioncreate
|
|
|
- /// </summary>
|
|
|
- internal ScriptFunctionInstance OrdinaryFunctionCreate(
|
|
|
- ObjectInstance functionPrototype,
|
|
|
- JintFunctionDefinition function,
|
|
|
- FunctionThisMode thisMode,
|
|
|
- EnvironmentRecord scope,
|
|
|
- PrivateEnvironmentRecord? privateScope)
|
|
|
- {
|
|
|
- return new ScriptFunctionInstance(
|
|
|
- _engine,
|
|
|
- function,
|
|
|
- scope,
|
|
|
- thisMode,
|
|
|
- functionPrototype)
|
|
|
- {
|
|
|
- _privateEnvironment = privateScope,
|
|
|
- _realm = _realm
|
|
|
- };
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiatefunctionobject
|
|
|
+ /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiateasyncfunctionobject
|
|
|
/// </summary>
|
|
|
- internal FunctionInstance InstantiateFunctionObject(
|
|
|
+ private FunctionInstance InstantiateAsyncFunctionObject(
|
|
|
JintFunctionDefinition functionDeclaration,
|
|
|
- EnvironmentRecord scope,
|
|
|
- PrivateEnvironmentRecord? privateScope)
|
|
|
+ EnvironmentRecord env,
|
|
|
+ PrivateEnvironmentRecord? privateEnv)
|
|
|
{
|
|
|
- return !functionDeclaration.Function.Generator
|
|
|
- ? InstantiateOrdinaryFunctionObject(functionDeclaration, scope, privateScope)
|
|
|
- : InstantiateGeneratorFunctionObject(functionDeclaration, scope, privateScope);
|
|
|
+ var F = OrdinaryFunctionCreate(
|
|
|
+ _realm.Intrinsics.AsyncFunction.PrototypeObject,
|
|
|
+ functionDeclaration,
|
|
|
+ functionDeclaration.ThisMode,
|
|
|
+ env,
|
|
|
+ privateEnv);
|
|
|
+
|
|
|
+ F.SetFunctionName(functionDeclaration.Name ?? "default");
|
|
|
+
|
|
|
+ return F;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
@@ -250,15 +91,15 @@ namespace Jint.Native.Function
|
|
|
/// </summary>
|
|
|
private FunctionInstance InstantiateOrdinaryFunctionObject(
|
|
|
JintFunctionDefinition functionDeclaration,
|
|
|
- EnvironmentRecord scope,
|
|
|
- PrivateEnvironmentRecord? privateScope)
|
|
|
+ EnvironmentRecord env,
|
|
|
+ PrivateEnvironmentRecord? privateEnv)
|
|
|
{
|
|
|
var F = OrdinaryFunctionCreate(
|
|
|
_realm.Intrinsics.Function.PrototypeObject,
|
|
|
functionDeclaration,
|
|
|
functionDeclaration.ThisMode,
|
|
|
- scope,
|
|
|
- privateScope);
|
|
|
+ env,
|
|
|
+ privateEnv);
|
|
|
|
|
|
var name = functionDeclaration.Name ?? "default";
|
|
|
F.SetFunctionName(name);
|