Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issues uncovered by latest test262 suite #1040

Merged
merged 2 commits into from
Jan 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

14 changes: 12 additions & 2 deletions Jint/EsprimaExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Esprima;
using Esprima.Ast;
using Jint.Native;
using Jint.Native.Function;
Expand All @@ -17,12 +18,17 @@ namespace Jint
{
public static class EsprimaExtensions
{
public static JsValue GetKey(this ClassProperty property, Engine engine) => GetKey(property.Key, engine, property.Computed);
public static JsValue GetKey<T>(this T property, Engine engine) where T : ClassProperty => GetKey(property.Key, engine, property.Computed);

public static JsValue GetKey(this Expression expression, Engine engine, bool resolveComputed = false)
{
if (expression is Literal literal)
{
if (literal.TokenType == TokenType.NullLiteral)
{
return JsValue.Null;
}

return LiteralKeyToString(literal);
}

Expand All @@ -49,7 +55,11 @@ or Nodes.BinaryExpression
or Nodes.UpdateExpression
or Nodes.AssignmentExpression
or Nodes.UnaryExpression
or Nodes.MemberExpression)
or Nodes.MemberExpression
or Nodes.LogicalExpression
or Nodes.ConditionalExpression
or Nodes.ArrowFunctionExpression
or Nodes.FunctionExpression)
{
var context = engine._activeEvaluationContext;
propertyKey = TypeConverter.ToPropertyKey(JintExpression.Build(engine, expression).GetValue(context).Value);
Expand Down
13 changes: 9 additions & 4 deletions Jint/Native/Array/ArrayPrototype.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1281,13 +1281,18 @@ internal JsValue ToString(JsValue thisObj, JsValue[] arguments)
{
var array = TypeConverter.ToObject(_realm, thisObj);

ICallable func = array.Get("join", array) as ICallable;
if (func is null)
Func<JsValue, JsValue[], JsValue> func;
var joinFunc = array.Get("join") as ICallable;
if (joinFunc is not null)
{
func = _realm.Intrinsics.Object.PrototypeObject.Get("toString", array) as ICallable;
func = joinFunc.Call;
}
else
{
func = _realm.Intrinsics.Object.PrototypeObject.ToObjectString;
}

return func.Call(array, Arguments.Empty);
return func(array, Arguments.Empty);
}

private JsValue ReduceRight(JsValue thisObj, JsValue[] arguments)
Expand Down
3 changes: 3 additions & 0 deletions Jint/Native/Date/DatePrototype.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ protected override void Initialize()
SetSymbols(symbols);
}

/// <summary>
/// https://tc39.es/ecma262/#sec-date.prototype-@@toprimitive
/// </summary>
private JsValue ToPrimitive(JsValue thisObject, JsValue[] arguments)
{
var oi = thisObject as ObjectInstance;
Expand Down
13 changes: 8 additions & 5 deletions Jint/Native/Function/FunctionPrototype.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ internal FunctionPrototype(
: base(engine, realm, JsString.Empty)
{
_prototype = objectPrototype;
_length = PropertyDescriptor.AllForbiddenDescriptor.NumberZero;
_length = new PropertyDescriptor(JsNumber.PositiveZero, PropertyFlag.Configurable);
}

protected override void Initialize()
Expand All @@ -33,7 +33,7 @@ protected override void Initialize()
["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToString, 0, lengthFlags), propertyFlags),
["apply"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "apply", Apply, 2, lengthFlags), propertyFlags),
["call"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "call", CallImpl, 1, lengthFlags), propertyFlags),
["bind"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "bind", Bind, 1, PropertyFlag.AllForbidden), propertyFlags),
["bind"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "bind", Bind, 1, lengthFlags), propertyFlags),
["arguments"] = _engine._callerCalleeArgumentsThrowerConfigurable,
["caller"] = _engine._callerCalleeArgumentsThrowerConfigurable
};
Expand Down Expand Up @@ -143,19 +143,22 @@ internal JsValue Apply(JsValue thisObject, JsValue[] arguments)
return func.Call(thisArg, Arguments.Empty);
}

var argList = CreateListFromArrayLike(argArray);
var argList = CreateListFromArrayLike(_realm, argArray);

var result = func.Call(thisArg, argList);

return result;
}

internal JsValue[] CreateListFromArrayLike(JsValue argArray, Types? elementTypes = null)
/// <summary>
/// https://tc39.es/ecma262/#sec-createlistfromarraylike
/// </summary>
internal static JsValue[] CreateListFromArrayLike(Realm realm, JsValue argArray, Types? elementTypes = null)
{
var argArrayObj = argArray as ObjectInstance;
if (argArrayObj is null)
{
ExceptionHelper.ThrowTypeError(_realm);
ExceptionHelper.ThrowTypeError(realm);
}
var operations = ArrayOperations.For(argArrayObj);
var allowedTypes = elementTypes ??
Expand Down
4 changes: 2 additions & 2 deletions Jint/Native/Json/JsonInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ protected override void Initialize()
var properties = new PropertyDictionary(2, checkExistingKeys: false)
{
#pragma warning disable 618
["parse"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "parse", Parse, 2), true, false, true),
["stringify"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "stringify", Stringify, 3), true, false, true)
["parse"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "parse", Parse, 2, PropertyFlag.Configurable), true, false, true),
["stringify"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "stringify", Stringify, 3, PropertyFlag.Configurable), true, false, true)
#pragma warning restore 618
};
SetProperties(properties);
Expand Down
11 changes: 4 additions & 7 deletions Jint/Native/Json/JsonSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,11 @@ public JsValue Serialize(JsValue value, JsValue replacer, JsValue space)
else
{
var replacerObj = replacer.AsObject();
if (replacerObj.Class == ObjectClass.Array)
{
_propertyList = new List<JsValue>();
}
_propertyList = new List<JsValue>();

foreach (var property in replacerObj.GetOwnProperties().Select(x => x.Value))
foreach (var pair in replacerObj.GetOwnProperties())
{
JsValue v = _engine.GetValue(property, false);
var v = replacerObj.UnwrapJsValue(pair.Value);
string item = null;
if (v.IsString())
{
Expand Down Expand Up @@ -330,7 +327,7 @@ private string SerializeJSONObject(ObjectInstance value)
_indent += _gap;

var k = _propertyList ?? value.GetOwnProperties()
.Where(x => x.Value.Enumerable)
.Where(x => !x.Key.IsSymbol() && x.Value.Enumerable)
.Select(x => x.Key);

var partial = new List<string>();
Expand Down
7 changes: 2 additions & 5 deletions Jint/Native/Object/ObjectConstructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,8 @@ private static JsValue Is(JsValue thisObject, JsValue[] arguments)
public ObjectPrototype PrototypeObject { get; private set; }

/// <summary>
/// http://www.ecma-international.org/ecma-262/5.1/#sec-15.2.1.1
/// https://tc39.es/ecma262/#sec-object-value
/// </summary>
/// <param name="thisObject"></param>
/// <param name="arguments"></param>
/// <returns></returns>
public override JsValue Call(JsValue thisObject, JsValue[] arguments)
{
if (arguments.Length == 0)
Expand All @@ -138,7 +135,7 @@ public override JsValue Call(JsValue thisObject, JsValue[] arguments)
}

/// <summary>
/// http://www.ecma-international.org/ecma-262/5.1/#sec-15.2.2.1
/// https://tc39.es/ecma262/#sec-object-value
/// </summary>
public ObjectInstance Construct(JsValue[] arguments)
{
Expand Down
4 changes: 2 additions & 2 deletions Jint/Native/Object/ObjectInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ public virtual List<JsValue> GetOwnPropertyKeys(Types types = Types.String | Typ
{
foreach (var pair in _properties)
{
var isArrayIndex = ulong.TryParse(pair.Key, out var index);
var isArrayIndex = ulong.TryParse(pair.Key, out var index) && index < ArrayOperations.MaxArrayLength;
if (isArrayIndex)
{
keys.Add(JsString.Create(index));
Expand Down Expand Up @@ -754,7 +754,7 @@ protected static bool ValidateAndApplyPropertyDescriptor(ObjectInstance o, JsVal

if (o is object)
{
var flags = current.Flags & ~(PropertyFlag.Writable | PropertyFlag.WritableSet);
var flags = current.Flags & ~(PropertyFlag.Writable | PropertyFlag.WritableSet | PropertyFlag.CustomJsValue);
if (current.IsDataDescriptor())
{
o.SetOwnProperty(property, current = new GetSetPropertyDescriptor(
Expand Down
4 changes: 2 additions & 2 deletions Jint/Native/Proxy/ProxyInstance.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System.Collections.Generic;

using Jint.Native.Function;
using Jint.Native.Object;
using Jint.Runtime;
using Jint.Runtime.Descriptors;
Expand Down Expand Up @@ -122,7 +122,7 @@ public override List<JsValue> GetOwnPropertyKeys(Types types = Types.None | Type
return _target.GetOwnPropertyKeys(types);
}

var trapResult = new List<JsValue>(_engine.Realm.Intrinsics.Function.PrototypeObject.CreateListFromArrayLike(result, Types.String | Types.Symbol));
var trapResult = new List<JsValue>(FunctionPrototype.CreateListFromArrayLike(_engine.Realm, result, Types.String | Types.Symbol));

if (trapResult.Count != new HashSet<JsValue>(trapResult).Count)
{
Expand Down
27 changes: 22 additions & 5 deletions Jint/Native/Reflect/ReflectInstance.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using Jint.Collections;
using Jint.Native.Function;
using Jint.Native.Object;
using Jint.Native.Symbol;
using Jint.Runtime;
using Jint.Runtime.Descriptors;
using Jint.Runtime.Interop;
Expand Down Expand Up @@ -41,15 +43,30 @@ protected override void Initialize()
["setPrototypeOf"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "setPrototypeOf", SetPrototypeOf, 2, PropertyFlag.Configurable), true, false, true),
};
SetProperties(properties);

var symbols = new SymbolDictionary(1)
{
[GlobalSymbolRegistry.ToStringTag] = new PropertyDescriptor("Reflect", false, false, true)
};
SetSymbols(symbols);
}

private JsValue Apply(JsValue thisObject, JsValue[] arguments)
{
return _realm.Intrinsics.Function.PrototypeObject.Apply(arguments.At(0), new[]
var target = arguments.At(0);
var thisArgument = arguments.At(1);
var argumentsList = arguments.At(2);

if (!target.IsCallable)
{
arguments.At(1),
arguments.At(2)
});
ExceptionHelper.ThrowTypeError(_realm);
}

var args = FunctionPrototype.CreateListFromArrayLike(_realm, argumentsList);

// 3. Perform PrepareForTailCall().

return target.AsCallable().Call(thisArgument, args);
}

private JsValue Construct(JsValue thisObject, JsValue[] arguments)
Expand All @@ -60,7 +77,7 @@ private JsValue Construct(JsValue thisObject, JsValue[] arguments)
var newTargetArgument = arguments.At(2, arguments[0]);
AssertConstructor(_engine, newTargetArgument);

var args = _realm.Intrinsics.Function.PrototypeObject.CreateListFromArrayLike(arguments.At(1));
var args = FunctionPrototype.CreateListFromArrayLike(_realm, arguments.At(1));

return target.Construct(args, newTargetArgument);
}
Expand Down
13 changes: 6 additions & 7 deletions Jint/Native/String/StringInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,14 @@ public override PropertyDescriptor GetOwnProperty(JsValue property)

public override IEnumerable<KeyValuePair<JsValue, PropertyDescriptor>> GetOwnProperties()
{
if (_length != null)
foreach (var entry in base.GetOwnProperties())
{
yield return new KeyValuePair<JsValue, PropertyDescriptor>(CommonProperties.Length, _length);
yield return entry;
}

foreach (var entry in base.GetOwnProperties())
if (_length != null)
{
yield return entry;
yield return new KeyValuePair<JsValue, PropertyDescriptor>(CommonProperties.Length, _length);
}
}

Expand All @@ -86,9 +86,8 @@ public override List<JsValue> GetOwnPropertyKeys(Types types)
keys.Add(JsString.Create(i));
}

keys.AddRange(base.GetOwnPropertyKeys(types));
keys.Sort((v1, v2) => TypeConverter.ToNumber(v1).CompareTo(TypeConverter.ToNumber(v2)));

keys.AddRange(base.GetOwnPropertyKeys(Types.String));
keys.AddRange(base.GetOwnPropertyKeys(Types.Symbol));
keys.Add(JsString.LengthString);

return keys;
Expand Down