diff --git a/Jint.Tests.Test262/Test262Harness.settings.json b/Jint.Tests.Test262/Test262Harness.settings.json index cdc1b1cf7b..37cc70ebf9 100644 --- a/Jint.Tests.Test262/Test262Harness.settings.json +++ b/Jint.Tests.Test262/Test262Harness.settings.json @@ -339,6 +339,53 @@ "language/statements/function/scope-param-elem-var-open.js", "language/statements/function/scope-param-rest-elem-var-close.js", "language/statements/function/scope-param-rest-elem-var-open.js", - "language/statements/with/cptn-abrupt-empty.js" + "language/statements/with/cptn-abrupt-empty.js", + + // need to wait for further updates from Esprima + "built-ins/Function/prototype/toString/arrow-function.js", + "built-ins/Function/prototype/toString/async-arrow-function.js", + "built-ins/Function/prototype/toString/async-function-declaration.js", + "built-ins/Function/prototype/toString/async-function-expression.js", + "built-ins/Function/prototype/toString/async-method-class-expression-static.js", + "built-ins/Function/prototype/toString/async-method-class-expression.js", + "built-ins/Function/prototype/toString/async-method-class-statement-static.js", + "built-ins/Function/prototype/toString/async-method-class-statement.js", + "built-ins/Function/prototype/toString/async-method-object.js", + "built-ins/Function/prototype/toString/AsyncFunction.js", + "built-ins/Function/prototype/toString/class-declaration-complex-heritage.js", + "built-ins/Function/prototype/toString/class-declaration-explicit-ctor.js", + "built-ins/Function/prototype/toString/class-declaration-implicit-ctor.js", + "built-ins/Function/prototype/toString/class-expression-explicit-ctor.js", + "built-ins/Function/prototype/toString/class-expression-implicit-ctor.js", + "built-ins/Function/prototype/toString/function-declaration-non-simple-parameter-list.js", + "built-ins/Function/prototype/toString/function-declaration.js", + "built-ins/Function/prototype/toString/function-expression.js", + "built-ins/Function/prototype/toString/Function.js", + "built-ins/Function/prototype/toString/generator-function-declaration.js", + "built-ins/Function/prototype/toString/generator-function-expression.js", + "built-ins/Function/prototype/toString/generator-method.js", + "built-ins/Function/prototype/toString/getter-class-expression-static.js", + "built-ins/Function/prototype/toString/getter-class-expression.js", + "built-ins/Function/prototype/toString/getter-class-statement-static.js", + "built-ins/Function/prototype/toString/getter-class-statement.js", + "built-ins/Function/prototype/toString/getter-object.js", + "built-ins/Function/prototype/toString/line-terminator-normalisation-CR-LF.js", + "built-ins/Function/prototype/toString/line-terminator-normalisation-CR.js", + "built-ins/Function/prototype/toString/line-terminator-normalisation-LF.js", + "built-ins/Function/prototype/toString/method-class-expression-static.js", + "built-ins/Function/prototype/toString/method-class-expression.js", + "built-ins/Function/prototype/toString/method-class-statement-static.js", + "built-ins/Function/prototype/toString/method-class-statement.js", + "built-ins/Function/prototype/toString/method-object.js", + "built-ins/Function/prototype/toString/private-method-class-expression.js", + "built-ins/Function/prototype/toString/private-method-class-statement.js", + "built-ins/Function/prototype/toString/private-static-method-class-expression.js", + "built-ins/Function/prototype/toString/private-static-method-class-statement.js", + "built-ins/Function/prototype/toString/setter-class-expression-static.js", + "built-ins/Function/prototype/toString/setter-class-expression.js", + "built-ins/Function/prototype/toString/setter-class-statement-static.js", + "built-ins/Function/prototype/toString/setter-class-statement.js", + "built-ins/Function/prototype/toString/setter-object.js", + "built-ins/Function/prototype/toString/unicode.js" ] } \ No newline at end of file diff --git a/Jint/Native/Function/ClassDefinition.cs b/Jint/Native/Function/ClassDefinition.cs index 8cf1ecb224..cbc54bac41 100644 --- a/Jint/Native/Function/ClassDefinition.cs +++ b/Jint/Native/Function/ClassDefinition.cs @@ -1,3 +1,4 @@ +using System.Text.RegularExpressions; using Esprima; using Esprima.Ast; using Esprima.Utils; @@ -19,6 +20,7 @@ internal sealed class ClassDefinition internal static readonly MethodDefinition _emptyConstructor; internal readonly string? _className; + private readonly string _classSource; private readonly Expression? _superClass; private readonly ClassBody _body; @@ -39,10 +41,12 @@ static MethodDefinition CreateConstructorMethodDefinition(string source) public ClassDefinition( string? className, + string classSource, Expression? superClass, ClassBody body) { _className = className; + _classSource = classSource; _superClass = superClass; _body = body; } @@ -145,6 +149,7 @@ public JsValue BuildConstructor(EvaluationContext context, Environment env) F = constructorInfo.Closure; F.SetFunctionName(_className ?? ""); + F._sourceText = _classSource; F.MakeConstructor(writableProperty: false, proto); F._constructorKind = _superClass is null ? ConstructorKind.Base : ConstructorKind.Derived; @@ -359,6 +364,10 @@ public ClassStaticBlockFunction(StaticBlock staticBlock) : base(Nodes.StaticBloc { var methodDef = method.DefineMethod(obj); methodDef.Closure.SetFunctionName(methodDef.Key); + // TODO currently in the SourceText retrieved from Esprima, the method name is incorrect, so for now, use a string replacement. + var oldSourceText = methodDef.Closure.ToString(); + var index = oldSourceText.IndexOf("function", StringComparison.Ordinal); + methodDef.Closure._sourceText = index > -1 ? oldSourceText.Remove(index, 8).Insert(index, methodDef.Closure._functionDefinition.Name ?? string.Empty) : oldSourceText; return DefineMethodProperty(obj, methodDef.Key, methodDef.Closure, enumerable); } diff --git a/Jint/Native/Function/Function.cs b/Jint/Native/Function/Function.cs index 881edbe974..f76f8853b9 100644 --- a/Jint/Native/Function/Function.cs +++ b/Jint/Native/Function/Function.cs @@ -28,6 +28,7 @@ public abstract partial class Function : ObjectInstance, ICallable internal Realm _realm; internal PrivateEnvironment? _privateEnvironment; + internal string? _sourceText; private readonly IScriptOrModule? _scriptOrModule; protected Function( @@ -206,6 +207,18 @@ internal void SetFunctionName(JsValue name, string? prefix = null, bool force = if (!string.IsNullOrWhiteSpace(prefix)) { name = prefix + " " + name; + if (prefix is "get" or "set") + { + // TODO currently in the SourceText retrieved from Esprima, the method name is incorrect, so for now, use a string replacement. + var oldSourceText = ToString(); + var index = oldSourceText.IndexOf("function", StringComparison.Ordinal); + _sourceText = index > -1 ? oldSourceText.Remove(index, 8).Insert(index, name.AsString()) : oldSourceText; + } + } + + if (_functionDefinition != null) + { + _functionDefinition.Name = name.AsString(); } _nameDescriptor = new PropertyDescriptor(name, PropertyFlag.Configurable); @@ -367,7 +380,15 @@ internal void SetFunctionLength(JsNumber length) public override string ToString() { - // TODO no way to extract SourceText from Esprima at the moment, just returning native code + if (_sourceText != null) + { + return _sourceText; + } + if ((_sourceText = _functionDefinition?.Function?.ToString()) != null) + { + return _sourceText; + } + var nameValue = _nameDescriptor != null ? UnwrapJsValue(_nameDescriptor) : JsString.Empty; var name = ""; if (!nameValue.IsUndefined()) @@ -377,7 +398,7 @@ public override string ToString() name = name.TrimStart(_functionNameTrimStartChars); - return "function " + name + "() { [native code] }"; + return _sourceText = "function " + name + "() { [native code] }"; } private sealed class ObjectInstanceWithConstructor : ObjectInstance diff --git a/Jint/Runtime/Interpreter/Expressions/JintClassExpression.cs b/Jint/Runtime/Interpreter/Expressions/JintClassExpression.cs index f721bb539f..0d38ac9c22 100644 --- a/Jint/Runtime/Interpreter/Expressions/JintClassExpression.cs +++ b/Jint/Runtime/Interpreter/Expressions/JintClassExpression.cs @@ -1,4 +1,5 @@ using Esprima.Ast; +using Esprima.Utils; using Jint.Native.Function; namespace Jint.Runtime.Interpreter.Expressions @@ -9,7 +10,7 @@ internal sealed class JintClassExpression : JintExpression public JintClassExpression(ClassExpression expression) : base(expression) { - _classDefinition = new ClassDefinition(expression.Id?.Name, expression.SuperClass, expression.Body); + _classDefinition = new ClassDefinition(className: expression.Id?.Name, classSource: expression.ToString(), superClass: expression.SuperClass, body: expression.Body); } protected override object EvaluateInternal(EvaluationContext context) diff --git a/Jint/Runtime/Interpreter/JintFunctionDefinition.cs b/Jint/Runtime/Interpreter/JintFunctionDefinition.cs index bc2283c7aa..c9bdf13ee0 100644 --- a/Jint/Runtime/Interpreter/JintFunctionDefinition.cs +++ b/Jint/Runtime/Interpreter/JintFunctionDefinition.cs @@ -17,7 +17,7 @@ internal sealed class JintFunctionDefinition private JintExpression? _bodyExpression; private JintStatementList? _bodyStatementList; - public readonly string? Name; + public string? Name; public readonly IFunction Function; public JintFunctionDefinition(IFunction function) diff --git a/Jint/Runtime/Interpreter/Statements/JintClassDeclarationStatement.cs b/Jint/Runtime/Interpreter/Statements/JintClassDeclarationStatement.cs index bb55ae6536..f0f6ebd63e 100644 --- a/Jint/Runtime/Interpreter/Statements/JintClassDeclarationStatement.cs +++ b/Jint/Runtime/Interpreter/Statements/JintClassDeclarationStatement.cs @@ -1,4 +1,5 @@ using Esprima.Ast; +using Esprima.Utils; using Jint.Native; using Jint.Native.Function; @@ -10,7 +11,7 @@ internal sealed class JintClassDeclarationStatement : JintStatement