Browse Source

Update test262 harness and fix issues (#2126)

* fix promise issues
* fix ObjectPrototype.setPrototypeOf
* exclude some unsupported regex cases
* assignment cleanup & exclude some cases
* add more validation to decodeURIComponent
Marko Lahma 1 month ago
parent
commit
203a19b729

+ 20 - 2
Jint.Tests.Test262/Test262Harness.settings.json

@@ -1,5 +1,5 @@
 {
 {
-  "SuiteGitSha": "b0f03cb22d8b9233347782d166e7793d4d4c757f",
+  "SuiteGitSha": "a073f479f80b336256b7fc4e04700c827293e2fe",
   //"SuiteDirectory": "//mnt/c/work/test262",
   //"SuiteDirectory": "//mnt/c/work/test262",
   "TargetPath": "./Generated",
   "TargetPath": "./Generated",
   "Namespace": "Jint.Tests.Test262",
   "Namespace": "Jint.Tests.Test262",
@@ -22,7 +22,8 @@
     "source-phase-imports",
     "source-phase-imports",
     "tail-call-optimization",
     "tail-call-optimization",
     "Temporal",
     "Temporal",
-    "u180e"
+    "u180e",
+    "upsert"
   ],
   ],
   "ExcludedFlags": [
   "ExcludedFlags": [
   ],
   ],
@@ -35,6 +36,10 @@
     // requires rewrite of destructing towards spec
     // requires rewrite of destructing towards spec
     "language/destructuring/binding/keyed-destructuring-property-reference-target-evaluation-order-with-bindings.js",
     "language/destructuring/binding/keyed-destructuring-property-reference-target-evaluation-order-with-bindings.js",
     "language/expressions/assignment/destructuring/keyed-destructuring-property-reference-target-evaluation-order-with-bindings.js",
     "language/expressions/assignment/destructuring/keyed-destructuring-property-reference-target-evaluation-order-with-bindings.js",
+    "language/expressions/assignment/destructuring/default-expr-throws-iterator-return-get-throws.js",
+    "language/expressions/assignment/destructuring/default-expr-throws-iterator-return-is-not-callable.js",
+    "language/expressions/assignment/destructuring/target-assign-throws-iterator-return-get-throws.js",
+    "language/expressions/assignment/destructuring/target-assign-throws-iterator-return-is-not-callable.js",
 
 
     // Acornima doesn't implement unicode 15/16 yet
     // Acornima doesn't implement unicode 15/16 yet
     "language/identifiers/*-unicode-15.*.js",
     "language/identifiers/*-unicode-15.*.js",
@@ -52,6 +57,19 @@
     "built-ins/RegExp/quantifier-integer-limit.js",
     "built-ins/RegExp/quantifier-integer-limit.js",
     "language/literals/regexp/named-groups/forward-reference.js",
     "language/literals/regexp/named-groups/forward-reference.js",
 
 
+    "built-ins/RegExp/CharacterClassEscapes/character-class-digit-class-escape-negative-cases.js",
+    "built-ins/RegExp/CharacterClassEscapes/character-class-digit-class-escape-positive-cases.js",
+    "built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape-negative-cases.js",
+    "built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape-positive-cases.js",
+    "built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape-negative-cases.js",
+    "built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape-positive-cases.js",
+    "built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape-negative-cases.js",
+    "built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape-positive-cases.js",
+    "built-ins/RegExp/CharacterClassEscapes/character-class-whitespace-class-escape-negative-cases.js",
+    "built-ins/RegExp/CharacterClassEscapes/character-class-whitespace-class-escape-positive-cases.js",
+    "built-ins/RegExp/CharacterClassEscapes/character-class-word-class-escape-negative-cases.js",
+    "built-ins/RegExp/CharacterClassEscapes/character-class-word-class-escape-positive-cases.js",
+
     // RegExp handling problems
     // RegExp handling problems
     "built-ins/RegExp/nullable-quantifier.js",
     "built-ins/RegExp/nullable-quantifier.js",
     "built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T6.js",
     "built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T6.js",

+ 1 - 1
Jint.Tests/Jint.Tests.csproj

@@ -25,7 +25,7 @@
     <PackageReference Include="Microsoft.NET.Test.Sdk" />
     <PackageReference Include="Microsoft.NET.Test.Sdk" />
     <PackageReference Include="MongoDB.Bson.signed" />
     <PackageReference Include="MongoDB.Bson.signed" />
     <PackageReference Include="Newtonsoft.Json" />
     <PackageReference Include="Newtonsoft.Json" />
-    <PackageReference Include="System.Text.Json" />
+    <PackageReference Include="System.Text.Json" Condition="'$(TargetFramework)' == 'net472'" />
     <PackageReference Include="xunit" />
     <PackageReference Include="xunit" />
     <PackageReference Include="xunit.runner.visualstudio" />
     <PackageReference Include="xunit.runner.visualstudio" />
   </ItemGroup>
   </ItemGroup>

+ 50 - 0
Jint/Native/Global/GlobalObject.cs

@@ -300,6 +300,7 @@ public sealed partial class GlobalObject : ObjectInstance
         return Encode(uriString, UriUnescaped);
         return Encode(uriString, UriUnescaped);
     }
     }
 
 
+    [MethodImpl(512)]
     private JsValue Encode(string uriString, SearchValues<char> allowedCharacters)
     private JsValue Encode(string uriString, SearchValues<char> allowedCharacters)
     {
     {
         var strLen = uriString.Length;
         var strLen = uriString.Length;
@@ -408,6 +409,7 @@ uriError:
         return Decode(componentString, null);
         return Decode(componentString, null);
     }
     }
 
 
+    [MethodImpl(512)]
     private JsValue Decode(string uriString, SearchValues<char>? reservedSet)
     private JsValue Decode(string uriString, SearchValues<char>? reservedSet)
     {
     {
         var strLen = uriString.Length;
         var strLen = uriString.Length;
@@ -507,6 +509,54 @@ uriError:
                         octets[j] = B;
                         octets[j] = B;
                     }
                     }
 
 
+                    switch (n)
+                    {
+                        case 2:
+                            {
+                                // Overlong encoding check for 2-byte sequences
+                                var x = octets[0] & 0x1F; // 0x00
+                                var y = octets[1] & 0x3F; // 0x2F
+                                var codepoint = (x << 6) | y; // 0x2F
+
+                                if (codepoint < 0x80) // 2-byte should be ≥ 0x80
+                                {
+                                    goto uriError;
+                                }
+
+                                break;
+                            }
+                        case 3:
+                            {
+                                // Reserved surrogate pair (U+D800-DFFF)
+                                var x = octets[0] & 0x0F;
+                                var y = octets[1] & 0x3F;
+                                var z = octets[2] & 0x3F;
+                                var codepoint = (x << 12) | (y << 6) | z;
+
+                                if (codepoint is >= 0xD800 and <= 0xDFFF)
+                                {
+                                    goto uriError;
+                                }
+
+                                break;
+                            }
+                        case 4:
+                            {
+                                var x = octets[0] & 0x07;
+                                var y = octets[1] & 0x3F;
+                                var z = octets[2] & 0x3F;
+                                var w = octets[3] & 0x3F;
+                                var codepoint = (x << 18) | (y << 12) | (z << 6) | w;
+
+                                if (codepoint > 0x10FFFF)
+                                {
+                                    goto uriError;
+                                }
+
+                                break;
+                            }
+                    }
+
 #if SUPPORTS_SPAN_PARSE
 #if SUPPORTS_SPAN_PARSE
                     _stringBuilder.Append(Encoding.UTF8.GetString(octets.Slice(0, n)));
                     _stringBuilder.Append(Encoding.UTF8.GetString(octets.Slice(0, n)));
 #else
 #else

+ 5 - 14
Jint/Native/Iterator/IteratorInstance.cs

@@ -77,29 +77,20 @@ internal abstract class IteratorInstance : ObjectInstance
 
 
         public override void Close(CompletionType completion)
         public override void Close(CompletionType completion)
         {
         {
-            if (!_target.TryGetValue(CommonProperties.Return, out var func)
-                || func.IsNullOrUndefined())
-            {
-                return;
-            }
-
-            var callable = func as ICallable;
+            var callable = _target.GetMethod(CommonProperties.Return);
             if (callable is null)
             if (callable is null)
             {
             {
-                ExceptionHelper.ThrowTypeError(_target.Engine.Realm, func + " is not a function");
+                return;
             }
             }
 
 
-            var innerResult = Undefined;
+            JsValue innerResult;
             try
             try
             {
             {
                 innerResult = callable.Call(_target, Arguments.Empty);
                 innerResult = callable.Call(_target, Arguments.Empty);
             }
             }
-            catch
+            catch (JavaScriptException) when (completion == CompletionType.Throw)
             {
             {
-                if (completion != CompletionType.Throw)
-                {
-                    throw;
-                }
+                return;
             }
             }
 
 
             if (completion != CompletionType.Throw && !innerResult.IsObject())
             if (completion != CompletionType.Throw && !innerResult.IsObject())

+ 1 - 1
Jint/Native/Object/ObjectInstance.cs

@@ -1391,7 +1391,7 @@ public partial class ObjectInstance : JsValue, IEquatable<ObjectInstance>
         var callable = jsValue as ICallable;
         var callable = jsValue as ICallable;
         if (callable is null)
         if (callable is null)
         {
         {
-            ExceptionHelper.ThrowTypeError(realm, "Value returned for property '" + p + "' of object is not a function");
+            ExceptionHelper.ThrowTypeError(realm, $"Value returned for property '{p}' of object is not a function");
         }
         }
         return callable;
         return callable;
     }
     }

+ 5 - 0
Jint/Native/Object/ObjectPrototype.cs

@@ -63,6 +63,11 @@ public sealed class ObjectPrototype : Prototype
         SetProperties(properties);
         SetProperties(properties);
     }
     }
 
 
+    internal override bool SetPrototypeOf(JsValue value)
+    {
+        return SameValue(value, _prototype ?? Null);
+    }
+
     public override bool DefineOwnProperty(JsValue property, PropertyDescriptor desc)
     public override bool DefineOwnProperty(JsValue property, PropertyDescriptor desc)
     {
     {
         TrackChanges(property);
         TrackChanges(property);

+ 32 - 7
Jint/Native/Promise/PromiseConstructor.cs

@@ -333,7 +333,14 @@ internal sealed class PromiseConstructor : Constructor
         }
         }
         catch (JavaScriptException e)
         catch (JavaScriptException e)
         {
         {
-            iterator.Close(CompletionType.Throw);
+            try
+            {
+                iterator.Close(CompletionType.Throw);
+            }
+            catch (JavaScriptException)
+            {
+                // ignore any errors from closing the iterator
+            }
             capability.Reject.Call(Undefined, e.Error);
             capability.Reject.Call(Undefined, e.Error);
             return capability.PromiseInstance;
             return capability.PromiseInstance;
         }
         }
@@ -449,7 +456,14 @@ internal sealed class PromiseConstructor : Constructor
         }
         }
         catch (JavaScriptException e)
         catch (JavaScriptException e)
         {
         {
-            iterator.Close(CompletionType.Throw);
+            try
+            {
+                iterator.Close(CompletionType.Throw);
+            }
+            catch (JavaScriptException)
+            {
+                // ignore any errors from closing the iterator
+            }
             capability.Reject.Call(Undefined, e.Error);
             capability.Reject.Call(Undefined, e.Error);
             return capability.PromiseInstance;
             return capability.PromiseInstance;
         }
         }
@@ -551,7 +565,14 @@ internal sealed class PromiseConstructor : Constructor
         }
         }
         catch (JavaScriptException e)
         catch (JavaScriptException e)
         {
         {
-            iterator.Close(CompletionType.Throw);
+            try
+            {
+                iterator.Close(CompletionType.Throw);
+            }
+            catch (JavaScriptException)
+            {
+                // ignore any errors from closing the iterator
+            }
             capability.Reject.Call(Undefined, e.Error);
             capability.Reject.Call(Undefined, e.Error);
             return capability.PromiseInstance;
             return capability.PromiseInstance;
         }
         }
@@ -597,10 +618,14 @@ internal sealed class PromiseConstructor : Constructor
         }
         }
         catch (JavaScriptException e)
         catch (JavaScriptException e)
         {
         {
-            // 8. If result is an abrupt completion, then
-            // a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result).
-            //     b. IfAbruptRejectPromise(result, promiseCapability).
-            iterator.Close(CompletionType.Throw);
+            try
+            {
+                iterator.Close(CompletionType.Throw);
+            }
+            catch (JavaScriptException)
+            {
+                // ignore any errors from closing the iterator
+            }
             capability.Reject.Call(Undefined, e.Error);
             capability.Reject.Call(Undefined, e.Error);
             return capability.PromiseInstance;
             return capability.PromiseInstance;
         }
         }

+ 3 - 8
Jint/Runtime/Interpreter/Expressions/DestructuringPatternAssignmentExpression.cs

@@ -240,12 +240,7 @@ internal sealed class DestructuringPatternAssignmentExpression : JintExpression
                     if (value.IsUndefined())
                     if (value.IsUndefined())
                     {
                     {
                         var jintExpression = Build(assignmentPattern.Right);
                         var jintExpression = Build(assignmentPattern.Right);
-                        var completion = jintExpression.GetValue(context);
-                        if (context.IsAbrupt())
-                        {
-                            return completion;
-                        }
-                        value = completion;
+                        value = jintExpression.GetValue(context);
                     }
                     }
 
 
                     if (assignmentPattern.Left is Identifier leftIdentifier)
                     if (assignmentPattern.Left is Identifier leftIdentifier)
@@ -278,9 +273,9 @@ internal sealed class DestructuringPatternAssignmentExpression : JintExpression
         }
         }
         finally
         finally
         {
         {
-            if (close && !done)
+            if (close && !done && iterator is not null)
             {
             {
-                iterator?.Close(completionType);
+                iterator.Close(completionType);
             }
             }
         }
         }