diff --git a/Jint.Tests.Test262/Test262Harness.settings.json b/Jint.Tests.Test262/Test262Harness.settings.json
index 2d2031e4b1..9bcf95bcb5 100644
--- a/Jint.Tests.Test262/Test262Harness.settings.json
+++ b/Jint.Tests.Test262/Test262Harness.settings.json
@@ -1,5 +1,5 @@
{
- "SuiteGitSha": "c3a326ace810e7c80a4e1b8df8c8b704ed223c28",
+ "SuiteGitSha": "b8cb40b66a61afd57550a84f4170e16ebfbd1e46",
//"SuiteDirectory": "//mnt/c/work/test262",
"TargetPath": "./Generated",
"Namespace": "Jint.Tests.Test262",
@@ -11,11 +11,14 @@
"decorators",
"import-assertions",
"iterator-helpers",
+ "Math.sumPrecise",
"regexp-lookbehind",
"regexp-modifiers",
"regexp-unicode-property-escapes",
"regexp-v-flag",
+ "source-phase-imports",
"tail-call-optimization",
+ "uint8array-base64",
"Temporal",
"u180e"
],
diff --git a/Jint/IsExternalInit.cs b/Jint/IsExternalInit.cs
deleted file mode 100644
index 6b9e1a7f42..0000000000
--- a/Jint/IsExternalInit.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-#if !NET5_0_OR_GREATER
-
-// Source: https://github.com/dotnet/runtime/blob/v6.0.5/src/libraries/Common/src/System/Runtime/CompilerServices/IsExternalInit.cs
-
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.ComponentModel;
-
-namespace System.Runtime.CompilerServices;
-
-///
-/// Reserved to be used by the compiler for tracking metadata.
-/// This class should not be used by developers in source code.
-///
-[EditorBrowsable(EditorBrowsableState.Never)]
-internal static class IsExternalInit
-{
-}
-
-#endif
diff --git a/Jint/Jint.csproj b/Jint/Jint.csproj
index 460620fc9d..1730ed547d 100644
--- a/Jint/Jint.csproj
+++ b/Jint/Jint.csproj
@@ -19,7 +19,7 @@
true
- System.Runtime.CompilerServices.IsExternalInit;System.Runtime.CompilerServices.RequiresLocationAttribute
+ System.Runtime.CompilerServices.RequiresLocationAttribute
true
diff --git a/Jint/Native/Array/ArrayOperations.cs b/Jint/Native/Array/ArrayOperations.cs
index 3ba1b68091..9865558963 100644
--- a/Jint/Native/Array/ArrayOperations.cs
+++ b/Jint/Native/Array/ArrayOperations.cs
@@ -351,7 +351,7 @@ public override void EnsureCapacity(ulong capacity)
public override bool TryGetValue(ulong index, out JsValue value)
{
- if (index < _target.GetLength())
+ if (_target.IsValidIntegerIndex(index))
{
value = _target[(int) index];
return true;
diff --git a/Jint/Native/AsyncGenerator/AsyncGeneratorFunctionConstructor.cs b/Jint/Native/AsyncGenerator/AsyncGeneratorFunctionConstructor.cs
new file mode 100644
index 0000000000..f3a5139518
--- /dev/null
+++ b/Jint/Native/AsyncGenerator/AsyncGeneratorFunctionConstructor.cs
@@ -0,0 +1,47 @@
+using Jint.Native.AsyncFunction;
+using Jint.Native.Function;
+using Jint.Native.Iterator;
+using Jint.Native.Object;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+
+namespace Jint.Native.Generator;
+
+///
+/// https://tc39.es/ecma262/#sec-asyncgeneratorfunction-constructor
+///
+internal sealed class AsyncGeneratorFunctionConstructor : Constructor
+{
+ private static readonly JsString _functionName = new("AsyncGeneratorFunction");
+
+ internal AsyncGeneratorFunctionConstructor(
+ Engine engine,
+ Realm realm,
+ AsyncFunctionPrototype prototype,
+ IteratorPrototype iteratorPrototype)
+ : base(engine, realm, _functionName)
+ {
+ PrototypeObject = new AsyncGeneratorFunctionPrototype(engine, this, prototype, iteratorPrototype);
+ _prototype = PrototypeObject;
+ _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
+ _length = new PropertyDescriptor(JsNumber.PositiveOne, PropertyFlag.Configurable);
+ }
+
+ public AsyncGeneratorFunctionPrototype 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 = _realm.Intrinsics.Function.CreateDynamicFunction(
+ this,
+ newTarget,
+ FunctionKind.AsyncGenerator,
+ arguments);
+
+ return function;
+ }
+}
diff --git a/Jint/Native/AsyncGenerator/AsyncGeneratorFunctionPrototype.cs b/Jint/Native/AsyncGenerator/AsyncGeneratorFunctionPrototype.cs
new file mode 100644
index 0000000000..0c65fceec6
--- /dev/null
+++ b/Jint/Native/AsyncGenerator/AsyncGeneratorFunctionPrototype.cs
@@ -0,0 +1,44 @@
+using Jint.Collections;
+using Jint.Native.AsyncFunction;
+using Jint.Native.Iterator;
+using Jint.Native.Symbol;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+
+namespace Jint.Native.Generator;
+
+///
+/// https://tc39.es/ecma262/#sec-properties-of-asyncgeneratorfunction-prototype
+///
+internal sealed class AsyncGeneratorFunctionPrototype : Prototype
+{
+ private readonly AsyncGeneratorFunctionConstructor? _constructor;
+
+ internal AsyncGeneratorFunctionPrototype(
+ Engine engine,
+ AsyncGeneratorFunctionConstructor constructor,
+ AsyncFunctionPrototype prototype,
+ IteratorPrototype iteratorPrototype) : base(engine, engine.Realm)
+ {
+ _constructor = constructor;
+ _prototype = prototype;
+ PrototypeObject = new AsyncGeneratorPrototype(engine, this, iteratorPrototype);
+ }
+
+ public AsyncGeneratorPrototype PrototypeObject { get; }
+
+ protected override void Initialize()
+ {
+ var properties = new PropertyDictionary(2, checkExistingKeys: false)
+ {
+ [KnownKeys.Constructor] = new PropertyDescriptor(_constructor, PropertyFlag.Configurable),
+ [KnownKeys.Prototype] = new PropertyDescriptor(PrototypeObject, PropertyFlag.Configurable)
+ };
+ SetProperties(properties);
+ var symbols = new SymbolDictionary(1)
+ {
+ [GlobalSymbolRegistry.ToStringTag] = new PropertyDescriptor("AsyncGeneratorFunction", PropertyFlag.Configurable)
+ };
+ SetSymbols(symbols);
+ }
+}
diff --git a/Jint/Native/AsyncGenerator/AsyncGeneratorPrototype.cs b/Jint/Native/AsyncGenerator/AsyncGeneratorPrototype.cs
new file mode 100644
index 0000000000..183136a0bf
--- /dev/null
+++ b/Jint/Native/AsyncGenerator/AsyncGeneratorPrototype.cs
@@ -0,0 +1,89 @@
+using Jint.Collections;
+using Jint.Native.Iterator;
+using Jint.Native.Object;
+using Jint.Native.Symbol;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+using Jint.Runtime.Interop;
+
+namespace Jint.Native.Generator;
+
+///
+/// https://tc39.es/ecma262/#sec-asyncgenerator-objects
+///
+internal sealed class AsyncGeneratorPrototype : ObjectInstance
+{
+ private readonly AsyncGeneratorFunctionPrototype _constructor;
+
+ internal AsyncGeneratorPrototype(
+ Engine engine,
+ AsyncGeneratorFunctionPrototype constructor,
+ IteratorPrototype iteratorPrototype) : base(engine)
+ {
+ _constructor = constructor;
+ _prototype = iteratorPrototype;
+ }
+
+ protected override void Initialize()
+ {
+ const PropertyFlag PropertyFlags = PropertyFlag.Configurable | PropertyFlag.Writable;
+ const PropertyFlag LengthFlags = PropertyFlag.Configurable;
+ var properties = new PropertyDictionary(4, false)
+ {
+ ["constructor"] = new(_constructor, PropertyFlag.Configurable),
+ ["next"] = new(new ClrFunction(Engine, "next", Next, 1, LengthFlags), PropertyFlags),
+ ["return"] = new(new ClrFunction(Engine, "return", Return, 1, LengthFlags), PropertyFlags),
+ ["throw"] = new(new ClrFunction(Engine, "throw", Throw, 1, LengthFlags), PropertyFlags)
+ };
+ SetProperties(properties);
+
+ var symbols = new SymbolDictionary(1)
+ {
+ [GlobalSymbolRegistry.ToStringTag] = new("Generator", PropertyFlag.Configurable)
+ };
+ SetSymbols(symbols);
+ }
+
+ ///
+ /// https://tc39.es/ecma262/#sec-generator.prototype.next
+ ///
+ private ObjectInstance Next(JsValue thisObject, JsValue[] arguments)
+ {
+ var g = AssertGeneratorInstance(thisObject);
+ var value = arguments.At(0, null!);
+ return g.GeneratorResume(value, null);
+ }
+
+ ///
+ /// https://tc39.es/ecma262/#sec-generator.prototype.return
+ ///
+ private JsValue Return(JsValue thisObject, JsValue[] arguments)
+ {
+ var g = AssertGeneratorInstance(thisObject);
+ var value = arguments.At(0);
+ var C = new Completion(CompletionType.Return, value, null!);
+ return g.GeneratorResumeAbrupt(C, null);
+ }
+
+ ///
+ /// https://tc39.es/ecma262/#sec-generator.prototype.throw
+ ///
+ private JsValue Throw(JsValue thisObject, JsValue[] arguments)
+ {
+ var g = AssertGeneratorInstance(thisObject);
+ var exception = arguments.At(0);
+ var C = new Completion(CompletionType.Throw, exception, null!);
+ return g.GeneratorResumeAbrupt(C, null);
+ }
+
+ private GeneratorInstance AssertGeneratorInstance(JsValue thisObj)
+ {
+ var generatorInstance = thisObj as GeneratorInstance;
+ if (generatorInstance is null)
+ {
+ ExceptionHelper.ThrowTypeError(_engine.Realm, "object must be a Generator instance");
+ }
+
+ return generatorInstance;
+ }
+}
diff --git a/Jint/Native/Function/FunctionInstance.Dynamic.cs b/Jint/Native/Function/FunctionInstance.Dynamic.cs
index d0071529df..5576bdd76f 100644
--- a/Jint/Native/Function/FunctionInstance.Dynamic.cs
+++ b/Jint/Native/Function/FunctionInstance.Dynamic.cs
@@ -47,6 +47,8 @@ internal Function CreateDynamicFunction(
fallbackProto = static intrinsics => intrinsics.GeneratorFunction.PrototypeObject;
break;
case FunctionKind.AsyncGenerator:
+ fallbackProto = static intrinsics => intrinsics.AsyncGeneratorFunction.PrototypeObject;
+ break;
default:
ExceptionHelper.ThrowArgumentOutOfRangeException(nameof(kind), kind.ToString());
break;
@@ -91,7 +93,7 @@ internal Function CreateDynamicFunction(
functionExpression = "async function f(){}";
break;
case FunctionKind.AsyncGenerator:
- ExceptionHelper.ThrowNotImplementedException("Async generators not implemented");
+ functionExpression = "async function* f(){}";
break;
default:
ExceptionHelper.ThrowArgumentOutOfRangeException(nameof(kind), kind.ToString());
@@ -112,7 +114,7 @@ internal Function CreateDynamicFunction(
functionExpression = "function* f(";
break;
case FunctionKind.AsyncGenerator:
- ExceptionHelper.ThrowNotImplementedException("Async generators not implemented");
+ functionExpression = "async function* f(";
break;
default:
ExceptionHelper.ThrowArgumentOutOfRangeException(nameof(kind), kind.ToString());
@@ -171,10 +173,8 @@ internal Function CreateDynamicFunction(
}
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("async generators not implemented");
+ var prototype = OrdinaryObjectCreate(_engine, _realm.Intrinsics.AsyncGeneratorFunction.PrototypeObject.PrototypeObject);
+ F.DefinePropertyOrThrow(CommonProperties.Prototype, new PropertyDescriptor(prototype, PropertyFlag.Writable));
}
else if (kind == FunctionKind.Normal)
{
diff --git a/Jint/Native/Math/MathInstance.cs b/Jint/Native/Math/MathInstance.cs
index 27fb3a73b3..94fd1f4ac2 100644
--- a/Jint/Native/Math/MathInstance.cs
+++ b/Jint/Native/Math/MathInstance.cs
@@ -21,50 +21,51 @@ protected override void Initialize()
{
var properties = new PropertyDictionary(45, checkExistingKeys: false)
{
+ ["E"] = new PropertyDescriptor(System.Math.E, PropertyFlag.AllForbidden),
+ ["LN10"] = new PropertyDescriptor(System.Math.Log(10), PropertyFlag.AllForbidden),
+ ["LN2"] = new PropertyDescriptor(System.Math.Log(2), PropertyFlag.AllForbidden),
+ ["LOG10E"] = new PropertyDescriptor(System.Math.Log(System.Math.E, 10), PropertyFlag.AllForbidden),
+ ["LOG2E"] = new PropertyDescriptor(System.Math.Log(System.Math.E, 2), PropertyFlag.AllForbidden),
+ ["PI"] = new PropertyDescriptor(System.Math.PI, PropertyFlag.AllForbidden),
+ ["SQRT1_2"] = new PropertyDescriptor(System.Math.Sqrt(0.5), PropertyFlag.AllForbidden),
+ ["SQRT2"] = new PropertyDescriptor(System.Math.Sqrt(2), PropertyFlag.AllForbidden),
["abs"] = new PropertyDescriptor(new ClrFunction(Engine, "abs", Abs, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["acos"] = new PropertyDescriptor(new ClrFunction(Engine, "acos", Acos, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["acosh"] = new PropertyDescriptor(new ClrFunction(Engine, "acosh", Acosh, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["asin"] = new PropertyDescriptor(new ClrFunction(Engine, "asin", Asin, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["asinh"] = new PropertyDescriptor(new ClrFunction(Engine, "asinh", Asinh, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["atan"] = new PropertyDescriptor(new ClrFunction(Engine, "atan", Atan, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
- ["atanh"] = new PropertyDescriptor(new ClrFunction(Engine, "atanh", Atanh, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["atan2"] = new PropertyDescriptor(new ClrFunction(Engine, "atan2", Atan2, 2, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
+ ["atanh"] = new PropertyDescriptor(new ClrFunction(Engine, "atanh", Atanh, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
+ ["cbrt"] = new PropertyDescriptor(new ClrFunction(Engine, "cbrt", Cbrt, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["ceil"] = new PropertyDescriptor(new ClrFunction(Engine, "ceil", Ceil, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
+ ["clz32"] = new PropertyDescriptor(new ClrFunction(Engine, "clz32", Clz32, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["cos"] = new PropertyDescriptor(new ClrFunction(Engine, "cos", Cos, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["cosh"] = new PropertyDescriptor(new ClrFunction(Engine, "cosh", Cosh, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["exp"] = new PropertyDescriptor(new ClrFunction(Engine, "exp", Exp, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["expm1"] = new PropertyDescriptor(new ClrFunction(Engine, "expm1", Expm1, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
- ["floor"] = new PropertyDescriptor(new ClrFunction(Engine, "floor", Floor, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["f16round"] = new PropertyDescriptor(new ClrFunction(Engine, "f16round", F16Round, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
+ ["floor"] = new PropertyDescriptor(new ClrFunction(Engine, "floor", Floor, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
+ ["fround"] = new PropertyDescriptor(new ClrFunction(Engine, "fround", Fround, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
+ ["hypot"] = new PropertyDescriptor(new ClrFunction(Engine, "hypot", Hypot, 2, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
+ ["imul"] = new PropertyDescriptor(new ClrFunction(Engine, "imul", Imul, 2, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["log"] = new PropertyDescriptor(new ClrFunction(Engine, "log", Log, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
+ ["log10"] = new PropertyDescriptor(new ClrFunction(Engine, "log10", Log10, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["log1p"] = new PropertyDescriptor(new ClrFunction(Engine, "log1p", Log1p, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["log2"] = new PropertyDescriptor(new ClrFunction(Engine, "log2", Log2, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
- ["log10"] = new PropertyDescriptor(new ClrFunction(Engine, "log10", Log10, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["max"] = new PropertyDescriptor(new ClrFunction(Engine, "max", Max, 2, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["min"] = new PropertyDescriptor(new ClrFunction(Engine, "min", Min, 2, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["pow"] = new PropertyDescriptor(new ClrFunction(Engine, "pow", Pow, 2, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["random"] = new PropertyDescriptor(new ClrFunction(Engine, "random", Random, 0, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["round"] = new PropertyDescriptor(new ClrFunction(Engine, "round", Round, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
- ["fround"] = new PropertyDescriptor(new ClrFunction(Engine, "fround", Fround, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
+ ["sign"] = new PropertyDescriptor(new ClrFunction(Engine, "sign", Sign, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["sin"] = new PropertyDescriptor(new ClrFunction(Engine, "sin", Sin, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["sinh"] = new PropertyDescriptor(new ClrFunction(Engine, "sinh", Sinh, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
+ ["sumPrecise"] = new PropertyDescriptor(new ClrFunction(Engine, "sumPrecise", SumPrecise, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["sqrt"] = new PropertyDescriptor(new ClrFunction(Engine, "sqrt", Sqrt, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["tan"] = new PropertyDescriptor(new ClrFunction(Engine, "tan", Tan, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["tanh"] = new PropertyDescriptor(new ClrFunction(Engine, "tanh", Tanh, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["trunc"] = new PropertyDescriptor(new ClrFunction(Engine, "trunc", Truncate, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
- ["sign"] = new PropertyDescriptor(new ClrFunction(Engine, "sign", Sign, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
- ["cbrt"] = new PropertyDescriptor(new ClrFunction(Engine, "cbrt", Cbrt, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
- ["hypot"] = new PropertyDescriptor(new ClrFunction(Engine, "hypot", Hypot, 2, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
- ["imul"] = new PropertyDescriptor(new ClrFunction(Engine, "imul", Imul, 2, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
- ["clz32"] = new PropertyDescriptor(new ClrFunction(Engine, "clz32", Clz32, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
- ["E"] = new PropertyDescriptor(System.Math.E, PropertyFlag.AllForbidden),
- ["LN10"] = new PropertyDescriptor(System.Math.Log(10), PropertyFlag.AllForbidden),
- ["LN2"] = new PropertyDescriptor(System.Math.Log(2), PropertyFlag.AllForbidden),
- ["LOG2E"] = new PropertyDescriptor(System.Math.Log(System.Math.E, 2), PropertyFlag.AllForbidden),
- ["LOG10E"] = new PropertyDescriptor(System.Math.Log(System.Math.E, 10), PropertyFlag.AllForbidden),
- ["PI"] = new PropertyDescriptor(System.Math.PI, PropertyFlag.AllForbidden),
- ["SQRT1_2"] = new PropertyDescriptor(System.Math.Sqrt(0.5), PropertyFlag.AllForbidden),
- ["SQRT2"] = new PropertyDescriptor(System.Math.Sqrt(2), PropertyFlag.AllForbidden),
};
SetProperties(properties);
@@ -1066,6 +1067,96 @@ private static JsValue Hypot(JsValue thisObject, JsValue[] arguments)
return System.Math.Sqrt(y);
}
+ ///
+ /// https://github.com/tc39/proposal-math-sum
+ ///
+ private JsValue SumPrecise(JsValue thisObject, JsValue[] arguments)
+ {
+ var items = arguments.At(0);
+ if (items.IsNullOrUndefined())
+ {
+ ExceptionHelper.ThrowTypeError(_engine.Realm);
+ }
+
+ var iteratorRecord = items.GetIterator(_engine.Realm);
+ var state = JsNumber.NegativeZero._value;
+ List sum = [];
+ long count = 0;
+ const double Finite = 1;
+ try
+ {
+ while (iteratorRecord.TryIteratorStep(out var next))
+ {
+ next.TryGetValue(CommonProperties.Value, out var value);
+ count++;
+ if (count > 9007199254740992)
+ {
+ ExceptionHelper.ThrowRangeError(_engine.Realm);
+ }
+
+ if (value is not JsNumber jsNumber)
+ {
+ ExceptionHelper.ThrowTypeError(_engine.Realm, "Input is not a number: " + next);
+ return default;
+ }
+
+ if (!double.IsNaN(state))
+ {
+ var n = jsNumber._value;
+ if (double.IsNaN(n))
+ {
+ state = double.NaN;
+ }
+ else if (double.IsPositiveInfinity(n))
+ {
+ if (double.IsNegativeInfinity(state))
+ {
+ state = double.NaN;
+ }
+ else
+ {
+ state = double.PositiveInfinity;
+ }
+ }
+ else if (double.IsNegativeInfinity(n))
+ {
+ if (double.IsPositiveInfinity(state))
+ {
+ state = double.NaN;
+ }
+ else
+ {
+ state = double.NegativeInfinity;
+ }
+ }
+ else if (!NumberInstance.IsNegativeZero(n) && (NumberInstance.IsNegativeZero(state) || state == Finite))
+ {
+ state = Finite;
+ sum.Add(n);
+ }
+ }
+ }
+
+ }
+ catch
+ {
+ iteratorRecord.Close(CompletionType.Throw);
+ iteratorRecord = null;
+ throw;
+ }
+ finally
+ {
+ iteratorRecord?.Close(CompletionType.Normal);
+ }
+
+ if (state != Finite)
+ {
+ return state;
+ }
+
+ return sum.FSum();
+ }
+
private static double[] Coerced(JsValue[] arguments)
{
// TODO stackalloc
diff --git a/Jint/Native/Math/MathX.cs b/Jint/Native/Math/MathX.cs
new file mode 100644
index 0000000000..87ac96bb50
--- /dev/null
+++ b/Jint/Native/Math/MathX.cs
@@ -0,0 +1,66 @@
+// based on https://raw.githubusercontent.com/AnthonyLloyd/CsCheck/master/Tests/MathX.cs
+
+namespace Jint.Native.Math;
+
+internal static class MathX
+{
+ private static double TwoSum(double a, double b, out double lo)
+ {
+ var hi = a + b;
+ lo = hi - b;
+ lo = lo - hi + b + (a - lo);
+ return hi;
+ }
+
+ /// Shewchuk summation
+ internal static double FSum(this List values)
+ {
+ if (values.Count < 3) return values.Count == 2 ? values[0] + values[1] : values.Count == 1 ? values[0] : 0.0;
+ Span partials = stackalloc double[16];
+ var hi = TwoSum(values[0], values[1], out var lo);
+ int count = 0;
+ for (int i = 2; i < values.Count; i++)
+ {
+ var v = TwoSum(values[i], lo, out lo);
+ int c = 0;
+ for (int j = 0; j < count; j++)
+ {
+ v = TwoSum(v, partials[j], out var p);
+ if (p != 0.0)
+ partials[c++] = p;
+ }
+
+ hi = TwoSum(hi, v, out v);
+ if (v != 0.0)
+ {
+ if (c == partials.Length)
+ {
+ var newPartials = new double[partials.Length * 2];
+ partials.CopyTo(newPartials);
+ partials = newPartials;
+ }
+
+ partials[c++] = v;
+ }
+
+ count = c;
+ }
+
+ if (count != 0)
+ {
+ if (lo == 0) // lo has a good chance of being zero
+ {
+ lo = partials[0];
+ if (count == 1) return lo + hi;
+ partials = partials.Slice(1, count - 1);
+ }
+ else
+ partials = partials.Slice(0, count);
+
+ foreach (var p in partials)
+ lo += p;
+ }
+
+ return lo + hi;
+ }
+}
diff --git a/Jint/Runtime/Interpreter/Expressions/JintArrowFunctionExpression.cs b/Jint/Runtime/Interpreter/Expressions/JintArrowFunctionExpression.cs
index cf165b2867..039c4fabfa 100644
--- a/Jint/Runtime/Interpreter/Expressions/JintArrowFunctionExpression.cs
+++ b/Jint/Runtime/Interpreter/Expressions/JintArrowFunctionExpression.cs
@@ -1,4 +1,3 @@
-using Jint.Native;
using Jint.Native.Function;
namespace Jint.Runtime.Interpreter.Expressions;
@@ -14,21 +13,61 @@ public JintArrowFunctionExpression(ArrowFunctionExpression function) : base(func
protected override object EvaluateInternal(EvaluationContext context)
{
- var engine = context.Engine;
- var env = engine.ExecutionContext.LexicalEnvironment;
- var privateEnv = engine.ExecutionContext.PrivateEnvironment;
+ return Build(context.Engine, _function);
+ }
+
+ private static ScriptFunction Build(Engine engine, JintFunctionDefinition function)
+ {
+ var functionName = function.Name ?? "";
+ var closure = function.Function.Async
+ ? InstantiateAsyncArrowFunctionExpression(engine, function, functionName)
+ : InstantiateArrowFunctionExpression(engine, function, functionName);
+
+ return closure;
+ }
+
+ ///
+ /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiatearrowfunctionexpression
+ ///
+ private static ScriptFunction InstantiateArrowFunctionExpression(Engine engine, JintFunctionDefinition function, string name)
+ {
+ var runningExecutionContext = engine.ExecutionContext;
+ var env = runningExecutionContext.LexicalEnvironment;
+ var privateEnv = runningExecutionContext.PrivateEnvironment;
+
+ var intrinsics = engine.Realm.Intrinsics;
+ var closure = intrinsics.Function.OrdinaryFunctionCreate(
+ intrinsics.Function.PrototypeObject,
+ function,
+ FunctionThisMode.Lexical,
+ env,
+ privateEnv
+ );
+
+ closure.SetFunctionName(name);
+
+ return closure;
+ }
+
+ ///
+ /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiateasyncarrowfunctionexpression
+ ///
+ private static ScriptFunction InstantiateAsyncArrowFunctionExpression(Engine engine, JintFunctionDefinition function, string name)
+ {
+ var executionContext = engine.ExecutionContext;
+ var env = executionContext.LexicalEnvironment;
+ var privateEnv = executionContext.PrivateEnvironment;
- var closure = engine.Realm.Intrinsics.Function.OrdinaryFunctionCreate(
- engine.Realm.Intrinsics.Function.PrototypeObject,
- _function,
+ var intrinsics = engine.Realm.Intrinsics;
+ var closure = intrinsics.Function.OrdinaryFunctionCreate(
+ intrinsics.AsyncFunction.PrototypeObject,
+ function,
FunctionThisMode.Lexical,
env,
- privateEnv);
+ privateEnv
+ );
- if (_function.Name is null)
- {
- closure.SetFunctionName(JsString.Empty);
- }
+ closure.SetFunctionName(name);
return closure;
}
diff --git a/Jint/Runtime/Interpreter/Expressions/JintFunctionExpression.cs b/Jint/Runtime/Interpreter/Expressions/JintFunctionExpression.cs
index d9a4e73c70..1c1708a9e1 100644
--- a/Jint/Runtime/Interpreter/Expressions/JintFunctionExpression.cs
+++ b/Jint/Runtime/Interpreter/Expressions/JintFunctionExpression.cs
@@ -4,163 +4,204 @@
using Jint.Runtime.Descriptors;
using Jint.Runtime.Environments;
-namespace Jint.Runtime.Interpreter.Expressions
+namespace Jint.Runtime.Interpreter.Expressions;
+
+internal sealed class JintFunctionExpression : JintExpression
{
- internal sealed class JintFunctionExpression : JintExpression
+ private readonly JintFunctionDefinition _function;
+
+ public JintFunctionExpression(FunctionExpression function) : base(function)
+ {
+ _function = new JintFunctionDefinition(function);
+ }
+
+ protected override object EvaluateInternal(EvaluationContext context)
{
- private readonly JintFunctionDefinition _function;
+ return Build(context.Engine, _function);
+ }
- public JintFunctionExpression(FunctionExpression function) : base(function)
+ public override JsValue GetValue(EvaluationContext context)
+ {
+ return Build(context.Engine, _function);
+ }
+
+ private static ScriptFunction Build(Engine engine, JintFunctionDefinition function)
+ {
+ ScriptFunction closure;
+ var functionName = function.Name ?? "";
+ if (!function.Function.Generator)
{
- _function = new JintFunctionDefinition(function);
+ closure = function.Function.Async
+ ? InstantiateAsyncFunctionExpression(engine, function, functionName)
+ : InstantiateOrdinaryFunctionExpression(engine, function, functionName);
}
+ else
+ {
+ closure = function.Function.Async
+ ? InstantiateAsyncGeneratorFunctionExpression(engine, function, functionName)
+ : InstantiateGeneratorFunctionExpression(engine, function, functionName);
+ }
+
+ return closure;
+ }
+
+ ///
+ /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiateordinaryfunctionexpression
+ ///
+ private static ScriptFunction InstantiateOrdinaryFunctionExpression(Engine engine, JintFunctionDefinition function, string? name = "")
+ {
+ var runningExecutionContext = engine.ExecutionContext;
+ var env = runningExecutionContext.LexicalEnvironment;
+ var privateEnv = runningExecutionContext.PrivateEnvironment;
- protected override object EvaluateInternal(EvaluationContext context)
+ DeclarativeEnvironment? funcEnv = null;
+ if (!string.IsNullOrWhiteSpace(name))
{
- return GetValue(context);
+ funcEnv = JintEnvironment.NewDeclarativeEnvironment(engine, engine.ExecutionContext.LexicalEnvironment);
+ funcEnv.CreateImmutableBinding(name!, strict: false);
}
- public override JsValue GetValue(EvaluationContext context)
+ var thisMode = function.Strict
+ ? FunctionThisMode.Strict
+ : FunctionThisMode.Global;
+
+ var intrinsics = engine.Realm.Intrinsics;
+ var closure = intrinsics.Function.OrdinaryFunctionCreate(
+ intrinsics.Function.PrototypeObject,
+ function,
+ thisMode,
+ funcEnv ?? env,
+ privateEnv
+ );
+
+ if (name is not null)
{
- ScriptFunction closure;
- var functionName = _function.Name ?? "";
- if (!_function.Function.Generator)
- {
- closure = _function.Function.Async
- ? InstantiateAsyncFunctionExpression(context, functionName)
- : InstantiateOrdinaryFunctionExpression(context, functionName);
- }
- else
- {
- closure = InstantiateGeneratorFunctionExpression(context, functionName);
- }
-
- return closure;
+ closure.SetFunctionName(name);
}
+ closure.MakeConstructor();
+
+ funcEnv?.InitializeBinding(name!, closure);
+
+ return closure;
+ }
- ///
- /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiateordinaryfunctionexpression
- ///
- private ScriptFunction InstantiateOrdinaryFunctionExpression(EvaluationContext context, string? name = "")
+ ///
+ /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiateasyncfunctionexpression
+ ///
+ private static ScriptFunction InstantiateAsyncFunctionExpression(Engine engine, JintFunctionDefinition function, string? name = "")
+ {
+ var runningExecutionContext = engine.ExecutionContext;
+ var env = runningExecutionContext.LexicalEnvironment;
+ var privateEnv = runningExecutionContext.PrivateEnvironment;
+
+ DeclarativeEnvironment? funcEnv = null;
+ if (!string.IsNullOrWhiteSpace(name))
{
- var engine = context.Engine;
- var runningExecutionContext = engine.ExecutionContext;
- var scope = runningExecutionContext.LexicalEnvironment;
-
- DeclarativeEnvironment? funcEnv = null;
- if (!string.IsNullOrWhiteSpace(name))
- {
- funcEnv = JintEnvironment.NewDeclarativeEnvironment(engine, engine.ExecutionContext.LexicalEnvironment);
- funcEnv.CreateImmutableBinding(name!, strict: false);
- }
-
- var privateEnv = runningExecutionContext.PrivateEnvironment;
-
- var thisMode = _function.Strict
- ? FunctionThisMode.Strict
- : FunctionThisMode.Global;
-
- var intrinsics = engine.Realm.Intrinsics;
- var closure = intrinsics.Function.OrdinaryFunctionCreate(
- intrinsics.Function.PrototypeObject,
- _function,
- thisMode,
- funcEnv ?? scope,
- privateEnv
- );
-
- if (name is not null)
- {
- closure.SetFunctionName(name);
- }
- closure.MakeConstructor();
-
- funcEnv?.InitializeBinding(name!, closure);
-
- return closure;
+ funcEnv = JintEnvironment.NewDeclarativeEnvironment(engine, engine.ExecutionContext.LexicalEnvironment);
+ funcEnv.CreateImmutableBinding(name!, strict: false);
}
- ///
- /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiateasyncfunctionexpression
- ///
- private ScriptFunction InstantiateAsyncFunctionExpression(EvaluationContext context, string? name = "")
+ var thisMode = function.Strict
+ ? FunctionThisMode.Strict
+ : FunctionThisMode.Global;
+
+ var intrinsics = engine.Realm.Intrinsics;
+ var closure = intrinsics.Function.OrdinaryFunctionCreate(
+ intrinsics.AsyncFunction.PrototypeObject,
+ function,
+ thisMode,
+ funcEnv ?? env,
+ privateEnv
+ );
+
+ closure.SetFunctionName(name ?? "");
+
+ funcEnv?.InitializeBinding(name!, closure);
+
+ return closure;
+ }
+
+ ///
+ /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiategeneratorfunctionexpression
+ ///
+ private static ScriptFunction InstantiateGeneratorFunctionExpression(Engine engine, JintFunctionDefinition function, string? name)
+ {
+ var runningExecutionContext = engine.ExecutionContext;
+ var env = runningExecutionContext.LexicalEnvironment;
+ var privateEnv = runningExecutionContext.PrivateEnvironment;
+
+ DeclarativeEnvironment? funcEnv = null;
+ if (!string.IsNullOrWhiteSpace(name))
{
- var engine = context.Engine;
- var runningExecutionContext = engine.ExecutionContext;
- var scope = runningExecutionContext.LexicalEnvironment;
+ funcEnv = JintEnvironment.NewDeclarativeEnvironment(engine, engine.ExecutionContext.LexicalEnvironment);
+ funcEnv.CreateImmutableBinding(name!, strict: false);
+ }
- DeclarativeEnvironment? funcEnv = null;
- if (!string.IsNullOrWhiteSpace(name))
- {
- funcEnv = JintEnvironment.NewDeclarativeEnvironment(engine, engine.ExecutionContext.LexicalEnvironment);
- funcEnv.CreateImmutableBinding(name!, strict: false);
- }
+ var thisMode = function.Strict || engine._isStrict
+ ? FunctionThisMode.Strict
+ : FunctionThisMode.Global;
- var privateScope = runningExecutionContext.PrivateEnvironment;
+ var intrinsics = engine.Realm.Intrinsics;
+ var closure = intrinsics.Function.OrdinaryFunctionCreate(
+ intrinsics.GeneratorFunction.PrototypeObject,
+ function,
+ thisMode,
+ funcEnv ?? env,
+ privateEnv
+ );
- var thisMode = _function.Strict
- ? FunctionThisMode.Strict
- : FunctionThisMode.Global;
+ if (name is not null)
+ {
+ closure.SetFunctionName(name);
+ }
- var intrinsics = engine.Realm.Intrinsics;
- var closure = intrinsics.Function.OrdinaryFunctionCreate(
- intrinsics.AsyncFunction.PrototypeObject,
- _function,
- thisMode,
- funcEnv ?? scope,
- privateScope
- );
+ var prototype = ObjectInstance.OrdinaryObjectCreate(engine, intrinsics.GeneratorFunction.PrototypeObject.PrototypeObject);
+ closure.DefinePropertyOrThrow(CommonProperties.Prototype, new PropertyDescriptor(prototype, PropertyFlag.Writable));
- closure.SetFunctionName(name ?? "");
+ funcEnv?.InitializeBinding(name!, closure);
- funcEnv?.InitializeBinding(name!, closure);
+ return closure;
+ }
+
+ ///
+ /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiateasyncgeneratorfunctionexpression
+ ///
+ private static ScriptFunction InstantiateAsyncGeneratorFunctionExpression(Engine engine, JintFunctionDefinition function, string? name)
+ {
+ var runningExecutionContext = engine.ExecutionContext;
+ var env = runningExecutionContext.LexicalEnvironment;
+ var privateEnv = runningExecutionContext.PrivateEnvironment;
- return closure;
+ DeclarativeEnvironment? funcEnv = null;
+ if (!string.IsNullOrWhiteSpace(name))
+ {
+ funcEnv = JintEnvironment.NewDeclarativeEnvironment(engine, engine.ExecutionContext.LexicalEnvironment);
+ funcEnv.CreateImmutableBinding(name!, strict: false);
}
+ var thisMode = function.Strict || engine._isStrict
+ ? FunctionThisMode.Strict
+ : FunctionThisMode.Global;
+
+ var intrinsics = engine.Realm.Intrinsics;
+ var closure = intrinsics.Function.OrdinaryFunctionCreate(
+ intrinsics.AsyncGeneratorFunction.PrototypeObject,
+ function,
+ thisMode,
+ funcEnv ?? env,
+ privateEnv
+ );
- ///
- /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiategeneratorfunctionexpression
- ///
- private ScriptFunction InstantiateGeneratorFunctionExpression(EvaluationContext context, string? name)
+ if (name is not null)
{
- var engine = context.Engine;
- var runningExecutionContext = engine.ExecutionContext;
- var scope = runningExecutionContext.LexicalEnvironment;
-
- DeclarativeEnvironment? funcEnv = null;
- if (!string.IsNullOrWhiteSpace(name))
- {
- funcEnv = JintEnvironment.NewDeclarativeEnvironment(engine, engine.ExecutionContext.LexicalEnvironment);
- funcEnv.CreateImmutableBinding(name!, strict: false);
- }
-
- var privateScope = runningExecutionContext.PrivateEnvironment;
-
- var thisMode = _function.Strict || engine._isStrict
- ? FunctionThisMode.Strict
- : FunctionThisMode.Global;
-
- var intrinsics = engine.Realm.Intrinsics;
- var closure = intrinsics.Function.OrdinaryFunctionCreate(
- intrinsics.GeneratorFunction.PrototypeObject,
- _function,
- thisMode,
- funcEnv ?? scope,
- privateScope
- );
-
- if (name is not null)
- {
- closure.SetFunctionName(name);
- }
-
- var prototype = ObjectInstance.OrdinaryObjectCreate(engine, intrinsics.GeneratorFunction.PrototypeObject.PrototypeObject);
- closure.DefinePropertyOrThrow(CommonProperties.Prototype, new PropertyDescriptor(prototype, PropertyFlag.Writable));
-
- funcEnv?.InitializeBinding(name!, closure);
-
- return closure;
+ closure.SetFunctionName(name);
}
+
+ var prototype = ObjectInstance.OrdinaryObjectCreate(engine, intrinsics.AsyncGeneratorFunction.PrototypeObject.PrototypeObject);
+ closure.DefinePropertyOrThrow(CommonProperties.Prototype, new PropertyDescriptor(prototype, PropertyFlag.Writable));
+
+ funcEnv?.InitializeBinding(name!, closure);
+
+ return closure;
}
}
diff --git a/Jint/Runtime/Intrinsics.cs b/Jint/Runtime/Intrinsics.cs
index 84e8d36d54..26b603a758 100644
--- a/Jint/Runtime/Intrinsics.cs
+++ b/Jint/Runtime/Intrinsics.cs
@@ -68,6 +68,7 @@ public sealed partial class Intrinsics
private MathInstance? _math;
private JsonInstance? _json;
private SymbolConstructor? _symbol;
+ private AsyncGeneratorFunctionConstructor? _asyncGeneratorFunction;
private GeneratorFunctionConstructor? _generatorFunction;
private RegExpConstructor? _regExp;
private RegExpStringIteratorPrototype? _regExpStringIteratorPrototype;
@@ -258,6 +259,9 @@ internal Intrinsics(Engine engine, Realm realm)
internal GeneratorFunctionConstructor GeneratorFunction =>
_generatorFunction ??= new GeneratorFunctionConstructor(_engine, _realm, Function.PrototypeObject, IteratorPrototype);
+ internal AsyncGeneratorFunctionConstructor AsyncGeneratorFunction =>
+ _asyncGeneratorFunction ??= new AsyncGeneratorFunctionConstructor(_engine, _realm, AsyncFunction.PrototypeObject, IteratorPrototype);
+
public EvalFunction Eval =>
_eval ??= new EvalFunction(_engine, _realm, Function.PrototypeObject);