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 related to JSON, Math, RegExp and Proxy #1045

Merged
merged 1 commit into from
Jan 9, 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
2 changes: 1 addition & 1 deletion Jint/Engine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ Engine DoInvoke()
return this;
}

var strict = _isStrict | script.Strict;
var strict = _isStrict || script.Strict;
ExecuteWithConstraints(strict, DoInvoke);

return this;
Expand Down
7 changes: 4 additions & 3 deletions Jint/Native/Array/ArrayConstructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -348,12 +348,13 @@ private ArrayInstance Construct(JsValue[] arguments, uint capacity, ObjectInstan
/// <summary>
/// https://tc39.es/ecma262/#sec-arraycreate
/// </summary>
private ArrayInstance ArrayCreate(uint capacity, ObjectInstance proto)
internal ArrayInstance ArrayCreate(uint length, ObjectInstance proto = null)
{
proto ??= PrototypeObject;
var instance = new ArrayInstance(Engine, capacity)
var instance = new ArrayInstance(Engine, length)
{
_prototype = proto
_prototype = proto,
_length = new PropertyDescriptor(length, PropertyFlag.OnlyWritable)
};
return instance;
}
Expand Down
2 changes: 1 addition & 1 deletion Jint/Native/BigInt/BigIntPrototype.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ internal BigIntPrototype(
Realm realm,
BigIntConstructor constructor,
ObjectPrototype objectPrototype)
: base(engine)
: base(engine, ObjectClass.Object, InternalTypes.BigInt)
{
_prototype = objectPrototype;
_realm = realm;
Expand Down
13 changes: 6 additions & 7 deletions Jint/Native/JsValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,8 @@ public virtual bool IsLooselyEqual(JsValue value)
return true;
}

// TODO move to type specific IsLooselyEqual

var x = this;
var y = value;

Expand All @@ -311,14 +313,12 @@ public virtual bool IsLooselyEqual(JsValue value)
return x.IsLooselyEqual(TypeConverter.ToNumber(y));
}

const InternalTypes stringOrNumber = InternalTypes.String | InternalTypes.Integer | InternalTypes.Number | InternalTypes.BigInt;

if (y.IsObject() && (x._type & stringOrNumber) != 0)
if (y.IsObject() && (x._type & InternalTypes.Primitive) != 0)
{
return x.IsLooselyEqual(TypeConverter.ToPrimitive(y));
}

if (x.IsObject() && (y._type & stringOrNumber) != 0)
if (x.IsObject() && (y._type & InternalTypes.Primitive) != 0)
{
return y.IsLooselyEqual(TypeConverter.ToPrimitive(x));
}
Expand Down Expand Up @@ -500,13 +500,12 @@ internal static bool SameValue(JsValue x, JsValue y)

internal static IConstructor AssertConstructor(Engine engine, JsValue c)
{
var constructor = c as IConstructor;
if (constructor is null)
if (!c.IsConstructor)
{
ExceptionHelper.ThrowTypeError(engine.Realm, c + " is not a constructor");
}

return constructor;
return (IConstructor) c;
}
}
}
72 changes: 36 additions & 36 deletions Jint/Native/Json/JsonSerializer.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using Jint.Collections;
using Jint.Native.BigInt;
using Jint.Native.Boolean;
Expand Down Expand Up @@ -40,43 +39,47 @@ public JsValue Serialize(JsValue value, JsValue replacer, JsValue space)
return Undefined.Instance;
}

if (replacer.IsObject())
if (replacer is ObjectInstance oi)
{
if (replacer is ICallable)
if (oi.IsCallable)
{
_replacerFunction = replacer;
}
else
{
var replacerObj = replacer.AsObject();
_propertyList = new List<JsValue>();

foreach (var pair in replacerObj.GetOwnProperties())
if (oi.IsArray())
{
var v = replacerObj.UnwrapJsValue(pair.Value);
string item = null;
if (v.IsString())
{
item = v.ToString();
}
else if (v.IsNumber())
{
item = TypeConverter.ToString(v);
}
else if (v.IsObject())
_propertyList = new List<JsValue>();
var len = oi.Length;
var k = 0;
while (k < len)
{
var propertyObj = v.AsObject();
if (propertyObj.Class == ObjectClass.String || propertyObj.Class == ObjectClass.Number)
var prop = JsString.Create(k);
var v = replacer.Get(prop);
var item = JsValue.Undefined;
if (v.IsString())
{
item = v;
}
else if (v.IsNumber())
{
item = TypeConverter.ToString(v);
}
}
else if (v.IsObject())
{
if (v is StringInstance or NumberInstance)
{
item = TypeConverter.ToString(v);
}
}

if (item != null && !_propertyList.Contains(item))
{
_propertyList.Add(item);
}
if (!item.IsUndefined() && !_propertyList.Contains(item))
{
_propertyList.Add(item);
}

k++;
}
}
}
}
Expand Down Expand Up @@ -141,27 +144,26 @@ private JsValue SerializeJSONProperty(JsValue key, JsValue holder)
{
if (toJson.AsObject() is ICallable callableToJson)
{
value = callableToJson.Call(value, Arguments.From(key));
value = callableToJson.Call(value, Arguments.From(TypeConverter.ToPropertyKey(key)));
}
}
}

if (!_replacerFunction.IsUndefined())
{
var replacerFunctionCallable = (ICallable) _replacerFunction.AsObject();
value = replacerFunctionCallable.Call(holder, Arguments.From(key, value));
value = replacerFunctionCallable.Call(holder, Arguments.From(TypeConverter.ToPropertyKey(key), value));
}

if (value.IsObject())
{
var valueObj = value.AsObject();
switch (valueObj)
switch (value)
{
case NumberInstance numberInstance:
value = numberInstance.NumberData;
case NumberInstance:
value = TypeConverter.ToNumber(value);
break;
case StringInstance stringInstance:
value = stringInstance.StringData;
case StringInstance:
value = TypeConverter.ToString(value);
break;
case BooleanInstance booleanInstance:
value = booleanInstance.BooleanData;
Expand Down Expand Up @@ -326,9 +328,7 @@ private string SerializeJSONObject(ObjectInstance value)
var stepback = _indent;
_indent += _gap;

var k = _propertyList ?? value.GetOwnProperties()
.Where(x => !x.Key.IsSymbol() && x.Value.Enumerable)
.Select(x => x.Key);
var k = (IEnumerable<JsValue>) _propertyList ?? value.EnumerableOwnPropertyNames(ObjectInstance.EnumerableOwnPropertyNamesKind.Key);

var partial = new List<string>();
foreach (var p in k)
Expand Down
108 changes: 74 additions & 34 deletions Jint/Native/Math/MathInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ private static JsValue Ceil(JsValue thisObject, JsValue[] arguments)
return JsNumber.NegativeZero;
}
#endif

return System.Math.Ceiling(x);
}

Expand Down Expand Up @@ -600,66 +600,68 @@ private static JsValue Log10(JsValue thisObject, JsValue[] arguments)
return System.Math.Log10(x);
}

/// <summary>
/// https://tc39.es/ecma262/#sec-math.max
/// </summary>
private static JsValue Max(JsValue thisObject, JsValue[] arguments)
{
if (arguments.Length == 0)
{
return JsNumber.DoubleNegativeInfinity;
}

double max = TypeConverter.ToNumber(arguments.At(0));

if (double.IsNaN(max))
{
return JsNumber.DoubleNaN;
}

for (int i = 0; i < arguments.Length; i++)
var highest = double.NegativeInfinity;
foreach (var number in Coerced(arguments))
{
var value = TypeConverter.ToNumber(arguments[i]);

if (double.IsNaN(value))
if (double.IsNaN(number))
{
return JsNumber.DoubleNaN;
}

if (max == 0 && value == 0)
if (NumberInstance.IsPositiveZero(number) && NumberInstance.IsNegativeZero(highest))
{
max = NumberInstance.IsNegativeZero(value)
? max
: value;
highest = 0;
}
else

if (number > highest)
{
max = System.Math.Max(max, value);
highest = number;
}
}
return max;

return highest;
}

/// <summary>
/// https://tc39.es/ecma262/#sec-math.min
/// </summary>
private static JsValue Min(JsValue thisObject, JsValue[] arguments)
{
if (arguments.Length == 0)
{
return JsNumber.DoublePositiveInfinity;
}

double min = TypeConverter.ToNumber(arguments.At(0));
for (int i = 0; i < arguments.Length; i++)
var lowest = double.PositiveInfinity;
foreach (var number in Coerced(arguments))
{
var value = TypeConverter.ToNumber(arguments[i]);
if (min == 0 && value == 0)
if (double.IsNaN(number))
{
min = NumberInstance.IsNegativeZero(min)
? min
: value;
return JsNumber.DoubleNaN;
}
else

if (NumberInstance.IsNegativeZero(number) && NumberInstance.IsPositiveZero(lowest))
{
min = System.Math.Min(min, value);
lowest = JsNumber.NegativeZero._value;
}

if (number < lowest)
{
lowest = number;
}
}
return min;

return lowest;
}

private static JsValue Pow(JsValue thisObject, JsValue[] arguments)
Expand All @@ -677,7 +679,7 @@ private static JsValue Pow(JsValue thisObject, JsValue[] arguments)
{
return 1;
}

return HandlePowUnlikely(y, x);
}

Expand Down Expand Up @@ -822,7 +824,7 @@ private JsValue Random(JsValue thisObject, JsValue[] arguments)
{
_random = new Random();
}

return _random.NextDouble();
}

Expand Down Expand Up @@ -997,21 +999,59 @@ private static JsValue Cbrt(JsValue thisObject, JsValue[] arguments)
return -1 * System.Math.Pow(System.Math.Abs(x), 1.0 / 3.0);
}

/// <summary>
/// https://tc39.es/ecma262/#sec-math.hypot
/// </summary>
private static JsValue Hypot(JsValue thisObject, JsValue[] arguments)
{
double y = 0;
for (int i = 0; i < arguments.Length; ++i)
var coerced = Coerced(arguments);

foreach (var number in coerced)
{
var number = TypeConverter.ToNumber(arguments[i]);
if (double.IsInfinity(number))
{
return JsNumber.DoublePositiveInfinity;
}
}

var onlyZero = true;
double y = 0;
foreach (var number in coerced)
{
if (double.IsNaN(number))
{
return JsNumber.DoubleNaN;
}

if (onlyZero && number != 0)
{
onlyZero = false;
}

y += number * number;
}

if (onlyZero)
{
return JsNumber.PositiveZero;
}

return System.Math.Sqrt(y);
}

private static double[] Coerced(JsValue[] arguments)
{
// TODO stackalloc
var coerced = new double[arguments.Length];
for (var i = 0; i < arguments.Length; i++)
{
var argument = arguments[i];
coerced[i] = TypeConverter.ToNumber(argument);
}

return coerced;
}

private static JsValue Imul(JsValue thisObject, JsValue[] arguments)
{
var x = TypeConverter.ToInt32(arguments.At(0));
Expand Down
Loading