Skip to content

Commit

Permalink
Update test suite and implement Set.union (#1692)
Browse files Browse the repository at this point in the history
  • Loading branch information
lahma authored Nov 25, 2023
1 parent 4ad19bc commit c3fe5c5
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 73 deletions.
2 changes: 1 addition & 1 deletion Jint.Benchmark/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ dotnet run -c Release --allCategories EngineComparison
* tests are run in global engine strict mode, as YantraJS always uses strict mode which improves performance
* `Jint` and `Jint_ParsedScript` shows the difference between always parsing the script source file and reusing parsed `Script` instance.

Last updated 2023-11-05
Last updated 2023-11-24

* Jint main
* Jurassic 3.2.7
Expand Down
6 changes: 5 additions & 1 deletion Jint.Tests.Test262/Test262Harness.settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"SuiteGitSha": "6396ebde0316639292530460d1ef961fd9bbe0d4",
"SuiteGitSha": "2060494f280ba89d71a0f51d4ff171bafe476a05",
//"SuiteDirectory": "//mnt/c/work/test262",
"TargetPath": "./Generated",
"Namespace": "Jint.Tests.Test262",
Expand All @@ -12,6 +12,7 @@
"decorators",
"generators",
"import-assertions",
"import-attributes",
"iterator-helpers",
"regexp-duplicate-named-groups",
"regexp-lookbehind",
Expand Down Expand Up @@ -47,6 +48,7 @@
"built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T6.js",
"language/literals/regexp/u-case-mapping.js",
"built-ins/RegExp/lookahead-quantifier-match-groups.js",
"built-ins/RegExp/unicode_full_case_folding.js",

// requires investigation how to process complex function name evaluation for property
"built-ins/Function/prototype/toString/method-computed-property-name.js",
Expand Down Expand Up @@ -85,6 +87,8 @@
"language/expressions/object/method-definition/name-prop-name-yield-id.js",
"language/statements/class/elements/*-generator-method-*.js",
"language/expressions/class/elements/*-generator-method-*.js",
"built-ins/Set/prototype/union/allows-set-like-class.js",
"built-ins/Set/prototype/union/allows-set-like-object.js",

// generators not implemented
"built-ins/Object/prototype/toString/proxy-function.js",
Expand Down
13 changes: 12 additions & 1 deletion Jint/Native/JsValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,18 @@ internal IteratorInstance GetIterator(Realm realm, GeneratorKind hint = Generato
}

[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal IteratorInstance GetIteratorFromMethod(Realm realm, ICallable method)
{
var iterator = method.Call(this);
if (iterator is not ObjectInstance objectInstance)
{
ExceptionHelper.ThrowTypeError(realm);
return null!;
}
return new IteratorInstance.ObjectIterator(objectInstance);
}

[Pure]
internal bool TryGetIterator(Realm realm, [NotNullWhen(true)] out IteratorInstance? iterator, GeneratorKind hint = GeneratorKind.Sync, ICallable? method = null)
{
var obj = TypeConverter.ToObject(realm, this);
Expand Down
8 changes: 6 additions & 2 deletions Jint/Native/Set/JsSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@ internal sealed class JsSet : ObjectInstance
{
internal readonly OrderedSet<JsValue> _set;

public JsSet(Engine engine) : base(engine)
public JsSet(Engine engine) : this(engine, new OrderedSet<JsValue>(SameValueZeroComparer.Instance))
{
_set = new OrderedSet<JsValue>(SameValueZeroComparer.Instance);
}

public JsSet(Engine engine, OrderedSet<JsValue> set) : base(engine)
{
_set = set;
}

public override PropertyDescriptor GetOwnProperty(JsValue property)
Expand Down
2 changes: 1 addition & 1 deletion Jint/Native/Set/SetConstructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ internal SetConstructor(
_prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
}

private SetPrototype PrototypeObject { get; }
internal SetPrototype PrototypeObject { get; }

protected override void Initialize()
{
Expand Down
81 changes: 72 additions & 9 deletions Jint/Native/Set/SetPrototype.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,16 @@ protected override void Initialize()
{
["length"] = new PropertyDescriptor(0, PropertyFlag.Configurable),
["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.NonEnumerable),
["add"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "add", Add, 1, PropertyFlag.Configurable), true, false, true),
["clear"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "clear", Clear, 0, PropertyFlag.Configurable), true, false, true),
["delete"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "delete", Delete, 1, PropertyFlag.Configurable), true, false, true),
["entries"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "entries", Entries, 0, PropertyFlag.Configurable), true, false, true),
["forEach"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "forEach", ForEach, 1, PropertyFlag.Configurable), true, false, true),
["has"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "has", Has, 1, PropertyFlag.Configurable), true, false, true),
["keys"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "keys", Values, 0, PropertyFlag.Configurable), true, false, true),
["values"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "values", Values, 0, PropertyFlag.Configurable), true, false, true),
["size"] = new GetSetPropertyDescriptor(get: new ClrFunctionInstance(Engine, "get size", Size, 0, PropertyFlag.Configurable), set: null, PropertyFlag.Configurable)
["add"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "add", Add, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["clear"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "clear", Clear, 0, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["delete"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "delete", Delete, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["entries"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "entries", Entries, 0, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["forEach"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "forEach", ForEach, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["has"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "has", Has, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["keys"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "keys", Values, 0, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["values"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "values", Values, 0, PropertyFlag.Configurable), PropertyFlag.NonEnumerable),
["size"] = new GetSetPropertyDescriptor(get: new ClrFunctionInstance(Engine, "get size", Size, 0, PropertyFlag.Configurable), set: null, PropertyFlag.Configurable),
["union"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "union", Union, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable)
};
SetProperties(properties);

Expand Down Expand Up @@ -112,6 +113,68 @@ private JsValue ForEach(JsValue thisObject, JsValue[] arguments)
return Undefined;
}

private JsValue Union(JsValue thisObject, JsValue[] arguments)
{
var set = AssertSetInstance(thisObject);
var other = arguments.At(0);
var otherRec = GetSetRecord(other);
var keysIter = otherRec.Set.GetIteratorFromMethod(_realm, otherRec.Keys);
var resultSetData = set._set.Clone();
while (keysIter.TryIteratorStep(out var next))
{
var nextValue = next.Get(CommonProperties.Value);
if (nextValue == JsNumber.NegativeZero)
{
nextValue = JsNumber.PositiveZero;
}
resultSetData.Add(nextValue);
}

var result = new JsSet(_engine, resultSetData)
{
_prototype = _engine.Realm.Intrinsics.Set.PrototypeObject
};
return result;

}

private readonly record struct SetRecord(JsValue Set, double Size, ICallable Has, ICallable Keys);

private SetRecord GetSetRecord(JsValue obj)
{
if (obj is not ObjectInstance)
{
ExceptionHelper.ThrowTypeError(_realm);
}

var rawSize = obj.Get("size");
var numSize = TypeConverter.ToNumber(rawSize);
if (double.IsNaN(numSize))
{
ExceptionHelper.ThrowTypeError(_realm);
}

var intSize = TypeConverter.ToIntegerOrInfinity(numSize);
if (intSize < 0)
{
ExceptionHelper.ThrowRangeError(_realm);
}

var has = obj.Get(CommonProperties.Has);
if (!has.IsCallable)
{
ExceptionHelper.ThrowTypeError(_realm);
}

var keys = obj.Get(CommonProperties.Keys);
if (!keys.IsCallable)
{
ExceptionHelper.ThrowTypeError(_realm);
}

return new SetRecord(Set: obj, Size: intSize, Has: (ICallable) has, Keys: (ICallable) keys);
}

private ObjectInstance Values(JsValue thisObject, JsValue[] arguments)
{
var set = AssertSetInstance(thisObject);
Expand Down
51 changes: 26 additions & 25 deletions Jint/Runtime/CommonProperties.cs
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
using Jint.Native;

namespace Jint.Runtime
namespace Jint.Runtime;

internal static class CommonProperties
{
internal static class CommonProperties
{
internal static readonly JsString Arguments = JsString.CachedCreate("arguments");
internal static readonly JsString Caller = JsString.CachedCreate("caller");
internal static readonly JsString Callee = JsString.CachedCreate("callee");
internal static readonly JsString Constructor = JsString.CachedCreate("constructor");
internal static readonly JsString Eval = JsString.CachedCreate("eval");
internal static readonly JsString Infinity = JsString.CachedCreate("Infinity");
internal static readonly JsString Length = JsString.CachedCreate("length");
internal static readonly JsString Name = JsString.CachedCreate("name");
internal static readonly JsString Prototype = JsString.CachedCreate("prototype");
internal static readonly JsString Size = JsString.CachedCreate("size");
internal static readonly JsString Next = JsString.CachedCreate("next");
internal static readonly JsString Done = JsString.CachedCreate("done");
internal static readonly JsString Value = JsString.CachedCreate("value");
internal static readonly JsString Return = JsString.CachedCreate("return");
internal static readonly JsString Set = JsString.CachedCreate("set");
internal static readonly JsString Get = JsString.CachedCreate("get");
internal static readonly JsString Writable = JsString.CachedCreate("writable");
internal static readonly JsString Enumerable = JsString.CachedCreate("enumerable");
internal static readonly JsString Configurable = JsString.CachedCreate("configurable");
internal static readonly JsString Stack = JsString.CachedCreate("stack");
internal static readonly JsString Message = JsString.CachedCreate("message");
}
internal static readonly JsString Arguments = JsString.CachedCreate("arguments");
internal static readonly JsString Callee = JsString.CachedCreate("callee");
internal static readonly JsString Caller = JsString.CachedCreate("caller");
internal static readonly JsString Configurable = JsString.CachedCreate("configurable");
internal static readonly JsString Constructor = JsString.CachedCreate("constructor");
internal static readonly JsString Done = JsString.CachedCreate("done");
internal static readonly JsString Enumerable = JsString.CachedCreate("enumerable");
internal static readonly JsString Eval = JsString.CachedCreate("eval");
internal static readonly JsString Get = JsString.CachedCreate("get");
internal static readonly JsString Has = JsString.CachedCreate("has");
internal static readonly JsString Infinity = JsString.CachedCreate("Infinity");
internal static readonly JsString Keys = JsString.CachedCreate("keys");
internal static readonly JsString Length = JsString.CachedCreate("length");
internal static readonly JsString Message = JsString.CachedCreate("message");
internal static readonly JsString Name = JsString.CachedCreate("name");
internal static readonly JsString Next = JsString.CachedCreate("next");
internal static readonly JsString Prototype = JsString.CachedCreate("prototype");
internal static readonly JsString Return = JsString.CachedCreate("return");
internal static readonly JsString Set = JsString.CachedCreate("set");
internal static readonly JsString Size = JsString.CachedCreate("size");
internal static readonly JsString Stack = JsString.CachedCreate("stack");
internal static readonly JsString Value = JsString.CachedCreate("value");
internal static readonly JsString Writable = JsString.CachedCreate("writable");
}
74 changes: 41 additions & 33 deletions Jint/Runtime/OrderedSet.cs
Original file line number Diff line number Diff line change
@@ -1,50 +1,58 @@
namespace Jint.Runtime
namespace Jint.Runtime;

internal sealed class OrderedSet<T>
{
internal sealed class OrderedSet<T>
{
internal readonly List<T> _list;
private readonly HashSet<T> _set;
internal List<T> _list;
private HashSet<T> _set;

public OrderedSet(IEqualityComparer<T> comparer)
{
_list = new List<T>();
_set = new HashSet<T>(comparer);
}
public OrderedSet(IEqualityComparer<T> comparer)
{
_list = new List<T>();
_set = new HashSet<T>(comparer);
}

public T this[int index]
public T this[int index]
{
get => _list[index];
set
{
get => _list[index];
set
if (_set.Add(value))
{
if (_set.Add(value))
{
_list[index] = value;
}
_list[index] = value;
}
}
}

public void Add(T item)
public OrderedSet<T> Clone()
{
return new OrderedSet<T>(EqualityComparer<T>.Default)
{
if (_set.Add(item))
{
_list.Add(item);
}
}
_set = new HashSet<T>(this._set, this._set.Comparer),
_list = new List<T>(this._list)
};
}

public void Clear()
public void Add(T item)
{
if (_set.Add(item))
{
_list.Clear();
_set.Clear();
_list.Add(item);
}
}

public void Clear()
{
_list.Clear();
_set.Clear();
}

public bool Contains(T item) => _set.Contains(item);
public bool Contains(T item) => _set.Contains(item);

public int Count => _list.Count;
public int Count => _list.Count;

public bool Remove(T item)
{
_set.Remove(item);
return _list.Remove(item);
}
public bool Remove(T item)
{
_set.Remove(item);
return _list.Remove(item);
}
}

0 comments on commit c3fe5c5

Please sign in to comment.