Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
lahma committed Jul 18, 2021
1 parent e752354 commit 9afa790
Show file tree
Hide file tree
Showing 35 changed files with 818 additions and 171 deletions.
15 changes: 15 additions & 0 deletions Jint.Tests.Test262/Language/Expressions/YieldTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Xunit;

namespace Jint.Tests.Test262.Language.Expressions
{
public class YieldTests : Test262Test
{
[Theory(DisplayName = "language\\expressions\\yield")]
[MemberData(nameof(SourceFiles), "language\\expressions\\yield", false)]
[MemberData(nameof(SourceFiles), "language\\expressions\\yield", true, Skip = "Skipped")]
protected void New(SourceFile sourceFile)
{
RunTestInternal(sourceFile);
}
}
}
4 changes: 0 additions & 4 deletions Jint.Tests.Test262/Test262Test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -244,10 +244,6 @@ public static IEnumerable<object[]> SourceFiles(string pathPrefix, bool skipped)
skip = true;
reason = "BigInt not implemented";
break;
case "generators":
skip = true;
reason = "generators not implemented";
break;
case "async-functions":
skip = true;
reason = "async-functions not implemented";
Expand Down
8 changes: 8 additions & 0 deletions Jint/Engine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Jint.Native;
using Jint.Native.Argument;
using Jint.Native.Function;
using Jint.Native.Generator;
using Jint.Native.Object;
using Jint.Native.Promise;
using Jint.Native.Symbol;
Expand Down Expand Up @@ -1222,6 +1223,13 @@ internal void UpdateVariableEnvironment(EnvironmentRecord newEnv)
_executionContexts.ReplaceTopVariableEnvironment(newEnv);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal ExecutionContext UpdateGenerator(Generator generator)
{
// TODO
return ExecutionContext;
}

internal JsValue Call(ICallable callable, JsValue thisObject, JsValue[] arguments, JintExpression expression)
{
if (callable is FunctionInstance functionInstance)
Expand Down
3 changes: 2 additions & 1 deletion Jint/Native/Array/ArrayConstructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
}

var proto = GetPrototypeFromConstructor(
_engine,
newTarget,
static intrinsics => intrinsics.Array.PrototypeObject);

Expand Down Expand Up @@ -418,7 +419,7 @@ public ObjectInstance ArraySpeciesCreate(ObjectInstance originalArray, ulong len
if (c.IsConstructor)
{
var thisRealm = _engine.ExecutionContext.Realm;
var realmC = GetFunctionRealm(c);
var realmC = GetFunctionRealm(_engine, c);
if (!ReferenceEquals(thisRealm, realmC))
{
if (ReferenceEquals(c, realmC.Intrinsics.Array))
Expand Down
175 changes: 136 additions & 39 deletions Jint/Native/Function/FunctionConstructor.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
using Esprima;
using System;
using Esprima;
using Esprima.Ast;
using Jint.Native.Generator;
using Jint.Native.Object;
using Jint.Runtime;
using Jint.Runtime.Descriptors;
using Jint.Runtime.Environments;
using Jint.Runtime.Interpreter;

namespace Jint.Native.Function
{
Expand Down Expand Up @@ -32,43 +35,116 @@ public override JsValue Call(JsValue thisObject, JsValue[] arguments)
return Construct(arguments, thisObject);
}

public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
{
var function = CreateDynamicFunction(
_engine,
this,
newTarget,
FunctionKind.Normal,
arguments);

return function;
}

/// <summary>
/// https://tc39.es/ecma262/#sec-createdynamicfunction
/// </summary>
public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
internal static FunctionInstance CreateDynamicFunction(
Engine engine,
ObjectInstance constructor,
JsValue newTarget,
FunctionKind kind,
JsValue[] args)
{
var argCount = arguments.Length;
string p = "";
string body = "";
if (newTarget.IsUndefined())
{
newTarget = constructor;
}

Func<Intrinsics, ObjectInstance> fallbackProto = null;
switch (kind)
{
case FunctionKind.Normal:
fallbackProto = intrinsics => intrinsics.Function.PrototypeObject;
break;
case FunctionKind.Generator:
fallbackProto = intrinsics => intrinsics.GeneratorFunction.PrototypeObject;
break;
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(arguments[0]);
body = TypeConverter.ToString(args[0]);
}
else if (argCount > 1)
{
var firstArg = arguments[0];
var firstArg = args[0];
p = TypeConverter.ToString(firstArg);
for (var k = 1; k < argCount - 1; k++)
{
var nextArg = arguments[k];
var nextArg = args[k];
p += "," + TypeConverter.ToString(nextArg);
}

body = TypeConverter.ToString(arguments[argCount-1]);
body = TypeConverter.ToString(args[argCount - 1]);
}

IFunction function = null;
try
{
string functionExpression;
string functionExpression = null;
if (argCount == 0)
{
functionExpression = "function f(){}";
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
{
functionExpression = "function f(";
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
Expand All @@ -95,49 +171,70 @@ public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
var parser = new JavaScriptParser(functionExpression, ParserOptions);
function = (IFunction) parser.ParseScript().Body[0];
}
catch (ParserException)
catch (ParserException ex)
{
ExceptionHelper.ThrowSyntaxError(_realm);
ExceptionHelper.ThrowSyntaxError(engine.Realm, ex.Message);
}

// TODO generators etc, rewrite logic
var proto = GetPrototypeFromConstructor(newTarget, static intrinsics => intrinsics.Function.PrototypeObject);

var functionObject = new ScriptFunctionInstance(
Engine,
function,
_realm.GlobalEnv,
function.Strict,
proto)
{
_realm = _realm
};
var proto = GetPrototypeFromConstructor(engine, newTarget, fallbackProto);
var thisMode = function.Strict
? FunctionThisMode.Strict
: FunctionThisMode.Global;

functionObject.MakeConstructor();
FunctionInstance F = new ScriptFunctionInstance(
engine,
new JintFunctionDefinition(engine, function),
engine.Realm.GlobalEnv,
thisMode,
proto);

// the function is not actually a named function
functionObject.SetFunctionName(_functionNameAnonymous, force: true);
if (kind == FunctionKind.Generator)
{
F = new GeneratorFunctionInstance(engine, engine.Realm, F);
}
else if (kind == FunctionKind.AsyncGenerator)
{
// TODO
// Let prototype be ! OrdinaryObjectCreate(%AsyncGeneratorFunction.prototype.prototype%).
// Perform DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
ExceptionHelper.ThrowNotImplementedException();
}
else if (kind == FunctionKind.Normal)
{
F.MakeConstructor();
}

return functionObject;
F.SetFunctionName(_functionNameAnonymous, force: true);
return F;
}

/// <summary>
/// https://tc39.es/ecma262/#sec-runtime-semantics-instantiatefunctionobject
/// </summary>
internal FunctionInstance InstantiateFunctionObject(FunctionDeclaration functionDeclaration, EnvironmentRecord env)
internal FunctionInstance InstantiateFunctionObject(FunctionDeclaration functionDeclaration, EnvironmentRecord scope)
{
var functionObject = new ScriptFunctionInstance(
var strict = functionDeclaration.Strict || _engine._isStrict;
FunctionInstance F = new ScriptFunctionInstance(
Engine,
functionDeclaration,
env,
functionDeclaration.Strict || _engine._isStrict)
{
_realm = _realm
};
scope,
strict,
_realm.Intrinsics.Function.PrototypeObject);;

functionObject.MakeConstructor();
var name = functionDeclaration.Id?.Name ?? "default";
if (functionDeclaration.Generator)
{
// https://tc39.es/ecma262/#sec-generator-function-definitions-runtime-semantics-instantiatefunctionobject
F = new GeneratorFunctionInstance(_engine, _realm, F);
}
else
{
// https://tc39.es/ecma262/#sec-function-definitions-runtime-semantics-instantiatefunctionobject
F.MakeConstructor();
}

return functionObject;
F.SetFunctionName(name);
return F;
}
}
}
Loading

0 comments on commit 9afa790

Please sign in to comment.