Skip to content

Commit

Permalink
Use latest test262 suite and fix/implement accordingly (#1497)
Browse files Browse the repository at this point in the history
  • Loading branch information
lahma committed Mar 16, 2023
1 parent d372b34 commit fbaad9f
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 25 deletions.
3 changes: 2 additions & 1 deletion Jint.Tests.Test262/Test262Harness.settings.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
{
"SuiteGitSha": "83a46bfe0e79aed8274a1b9f4beb0a2efa0b3533",
"SuiteGitSha": "9704d7f22f6342d6c4753ab9a8d62d6725de8c4e",
//"SuiteDirectory": "//mnt/c/work/test262",
"TargetPath": "./Generated",
"Namespace": "Jint.Tests.Test262",
"Parallel": true,
"ExcludedFeatures": [
"Array.fromAsync",
"async-iteration",
"Atomics",
"class-fields-private",
Expand Down
2 changes: 1 addition & 1 deletion Jint/Native/Array/ArrayInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1187,7 +1187,7 @@ internal JsArray Map(JsValue[] arguments)
/// <inheritdoc />
internal sealed override bool FindWithCallback(
JsValue[] arguments,
out uint index,
out ulong index,
out JsValue value,
bool visitUnassigned,
bool fromEnd = false)
Expand Down
19 changes: 18 additions & 1 deletion Jint/Native/ArrayBuffer/ArrayBufferPrototype.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ internal sealed class ArrayBufferPrototype : Prototype
protected override void Initialize()
{
const PropertyFlag lengthFlags = PropertyFlag.Configurable;
var properties = new PropertyDictionary(3, checkExistingKeys: false)
var properties = new PropertyDictionary(4, checkExistingKeys: false)
{
["byteLength"] = new GetSetPropertyDescriptor(new ClrFunctionInstance(_engine, "get byteLength", ByteLength, 0, lengthFlags), Undefined, PropertyFlag.Configurable),
["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.NonEnumerable),
["detached"] = new GetSetPropertyDescriptor(new ClrFunctionInstance(_engine, "get detached", Detached, 0, lengthFlags), Undefined, PropertyFlag.Configurable),
["slice"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "slice", Slice, 2, lengthFlags), PropertyFlag.Configurable | PropertyFlag.Writable)
};
SetProperties(properties);
Expand All @@ -41,6 +42,22 @@ protected override void Initialize()
SetSymbols(symbols);
}

private JsValue Detached(JsValue thisObj, JsValue[] arguments)
{
var o = thisObj as ArrayBufferInstance;
if (o is null)
{
ExceptionHelper.ThrowTypeError(_realm, "Method ArrayBuffer.prototype.detached called on incompatible receiver " + thisObj);
}

if (o.IsSharedArrayBuffer)
{
ExceptionHelper.ThrowTypeError(_realm);
}

return o.IsDetachedBuffer;
}

/// <summary>
/// https://tc39.es/ecma262/#sec-get-arraybuffer.prototype.bytelength
/// </summary>
Expand Down
49 changes: 36 additions & 13 deletions Jint/Native/Object/ObjectInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1046,22 +1046,22 @@ private object ToObject(ObjectTraverseStack stack)
/// </summary>
internal virtual bool FindWithCallback(
JsValue[] arguments,
out uint index,
out ulong index,
out JsValue value,
bool visitUnassigned,
bool fromEnd = false)
{
long GetLength()
ulong GetLength()
{
var descValue = Get(CommonProperties.Length);
var len = TypeConverter.ToNumber(descValue);

return (long) System.Math.Max(
return (ulong) System.Math.Max(
0,
System.Math.Min(len, ArrayOperations.MaxArrayLikeLength));
}

bool TryGetValue(uint idx, out JsValue jsValue)
bool TryGetValue(ulong idx, out JsValue jsValue)
{
var property = JsString.Create(idx);
var kPresent = HasProperty(property);
Expand All @@ -1083,18 +1083,41 @@ bool TryGetValue(uint idx, out JsValue jsValue)

var args = _engine._jsValueArrayPool.RentArray(3);
args[2] = this;
for (uint k = 0; k < length; k++)

if (!fromEnd)
{
if (TryGetValue(k, out var kvalue) || visitUnassigned)
for (ulong k = 0; k < length; k++)
{
args[0] = kvalue;
args[1] = k;
var testResult = callable.Call(thisArg, args);
if (TypeConverter.ToBoolean(testResult))
if (TryGetValue(k, out var kvalue) || visitUnassigned)
{
index = k;
value = kvalue;
return true;
args[0] = kvalue;
args[1] = k;
var testResult = callable.Call(thisArg, args);
if (TypeConverter.ToBoolean(testResult))
{
index = k;
value = kvalue;
return true;
}
}
}
}
else
{
for (ulong k = length - 1; k >= 0; k--)
{
if (TryGetValue(k, out var kvalue) || visitUnassigned)
{
kvalue ??= Undefined;
args[0] = kvalue;
args[1] = k;
var testResult = callable.Call(thisArg, args);
if (TypeConverter.ToBoolean(testResult))
{
index = k;
value = kvalue;
return true;
}
}
}
}
Expand Down
104 changes: 95 additions & 9 deletions Jint/Native/String/StringPrototype.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Runtime.CompilerServices;
using System.Text;
using Jint.Collections;
using Jint.Native.Json;
using Jint.Native.Object;
using Jint.Native.RegExp;
using Jint.Native.Symbol;
Expand Down Expand Up @@ -39,7 +40,7 @@ protected override void Initialize()

var trimStart = new PropertyDescriptor(new ClrFunctionInstance(Engine, "trimStart", TrimStart, 0, lengthFlags), propertyFlags);
var trimEnd = new PropertyDescriptor(new ClrFunctionInstance(Engine, "trimEnd", TrimEnd, 0, lengthFlags), propertyFlags);
var properties = new PropertyDictionary(35, checkExistingKeys: false)
var properties = new PropertyDictionary(37, checkExistingKeys: false)
{
["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.NonEnumerable),
["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToStringString, 0, lengthFlags), propertyFlags),
Expand Down Expand Up @@ -77,6 +78,8 @@ protected override void Initialize()
["normalize"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "normalize", Normalize, 0, lengthFlags), propertyFlags),
["repeat"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "repeat", Repeat, 1, lengthFlags), propertyFlags),
["at"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "at", At, 1, lengthFlags), propertyFlags),
["isWellFormed"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "isWellFormed", IsWellFormed, 0, lengthFlags), propertyFlags),
["toWellFormed"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toWellFormed", ToWellFormed, 0, lengthFlags), propertyFlags),
};
SetProperties(properties);

Expand Down Expand Up @@ -862,16 +865,36 @@ private JsValue CodePointAt(JsValue thisObj, JsValue[] arguments)
return Undefined;
}

var first = (long) s[position];
if (first >= 0xD800 && first <= 0xDBFF && s.Length > position + 1)
return CodePointAt(s, position).CodePoint;
}

private readonly record struct CodePointResult(int CodePoint, int CodeUnitCount, bool IsUnpairedSurrogate);

private static CodePointResult CodePointAt(string s, int position)
{
var size = s.Length;
var first = s.CharCodeAt(position);
var cp = s.CharCodeAt(position);

var firstIsLeading = char.IsHighSurrogate(first);
var firstIsTrailing = char.IsLowSurrogate(first);
if (!firstIsLeading && !firstIsTrailing)
{
long second = s[position + 1];
if (second >= 0xDC00 && second <= 0xDFFF)
{
return (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
}
return new CodePointResult(cp, 1, false);
}

if (firstIsTrailing || position + 1 == size)
{
return new CodePointResult(cp, 1, true);
}

var second = s.CharCodeAt(position + 1);
if (!char.IsLowSurrogate(second))
{
return new CodePointResult(cp, 1, true);
}
return first;

return new CodePointResult(char.ConvertToUtf32(first, second), 2, false);
}

private JsValue CharAt(JsValue thisObj, JsValue[] arguments)
Expand Down Expand Up @@ -1121,5 +1144,68 @@ private JsValue Repeat(JsValue thisObj, JsValue[] arguments)

return sb.ToString();
}

private JsValue IsWellFormed(JsValue thisObj, JsValue[] arguments)
{
TypeConverter.CheckObjectCoercible(_engine, thisObj);
var s = TypeConverter.ToString(thisObj);

return IsStringWellFormedUnicode(s);
}

private JsValue ToWellFormed(JsValue thisObj, JsValue[] arguments)
{
TypeConverter.CheckObjectCoercible(_engine, thisObj);
var s = TypeConverter.ToString(thisObj);

var strLen = s.Length;
var k = 0;

using var builder = StringBuilderPool.Rent();
var result = builder.Builder;
while (k < strLen)
{
var cp = CodePointAt(s, k);
if (cp.IsUnpairedSurrogate)
{
result.Append("\uFFFD");
}
else
{
result.Append(s, k, cp.CodeUnitCount);
}
k += cp.CodeUnitCount;
}

return result.ToString();
}

private static bool IsStringWellFormedUnicode(string s)
{
for (var i = 0; i < s.Length; ++i)
{
var isSurrogate = (s.CharCodeAt(i) & 0xF800) == 0xD800;
if (!isSurrogate)
{
continue;
}

var isLeadingSurrogate = s.CharCodeAt(i) < 0xDC00;
if (!isLeadingSurrogate)
{
return false; // unpaired trailing surrogate
}

var isFollowedByTrailingSurrogate = i + 1 < s.Length && (s.CharCodeAt(i + 1) & 0xFC00) == 0xDC00;
if (!isFollowedByTrailingSurrogate)
{
return false; // unpaired leading surrogate
}

++i;
}

return true;
}
}
}

0 comments on commit fbaad9f

Please sign in to comment.