diff --git a/Jint.Tests.Test262/Test262Harness.settings.json b/Jint.Tests.Test262/Test262Harness.settings.json index fcd82c74dd..7158019a5f 100644 --- a/Jint.Tests.Test262/Test262Harness.settings.json +++ b/Jint.Tests.Test262/Test262Harness.settings.json @@ -1,5 +1,5 @@ { - "SuiteGitSha": "b0f03cb22d8b9233347782d166e7793d4d4c757f", + "SuiteGitSha": "a073f479f80b336256b7fc4e04700c827293e2fe", //"SuiteDirectory": "//mnt/c/work/test262", "TargetPath": "./Generated", "Namespace": "Jint.Tests.Test262", @@ -22,7 +22,8 @@ "source-phase-imports", "tail-call-optimization", "Temporal", - "u180e" + "u180e", + "upsert" ], "ExcludedFlags": [ ], @@ -35,6 +36,10 @@ // requires rewrite of destructing towards spec "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/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 "language/identifiers/*-unicode-15.*.js", @@ -52,6 +57,19 @@ "built-ins/RegExp/quantifier-integer-limit.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 "built-ins/RegExp/nullable-quantifier.js", "built-ins/RegExp/prototype/exec/S15.10.6.2_A1_T6.js", diff --git a/Jint.Tests/Jint.Tests.csproj b/Jint.Tests/Jint.Tests.csproj index 387212c061..767e50304a 100644 --- a/Jint.Tests/Jint.Tests.csproj +++ b/Jint.Tests/Jint.Tests.csproj @@ -25,7 +25,7 @@ - + diff --git a/Jint/Native/Global/GlobalObject.cs b/Jint/Native/Global/GlobalObject.cs index 2e832be327..f75c8163b5 100644 --- a/Jint/Native/Global/GlobalObject.cs +++ b/Jint/Native/Global/GlobalObject.cs @@ -300,6 +300,7 @@ private JsValue EncodeUriComponent(JsValue thisObject, JsCallArguments arguments return Encode(uriString, UriUnescaped); } + [MethodImpl(512)] private JsValue Encode(string uriString, SearchValues allowedCharacters) { var strLen = uriString.Length; @@ -408,6 +409,7 @@ private JsValue DecodeUriComponent(JsValue thisObject, JsCallArguments arguments return Decode(componentString, null); } + [MethodImpl(512)] private JsValue Decode(string uriString, SearchValues? reservedSet) { var strLen = uriString.Length; @@ -507,6 +509,54 @@ private JsValue Decode(string uriString, SearchValues? reservedSet) 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 _stringBuilder.Append(Encoding.UTF8.GetString(octets.Slice(0, n))); #else diff --git a/Jint/Native/Iterator/IteratorInstance.cs b/Jint/Native/Iterator/IteratorInstance.cs index 31c1161ab4..880e52c938 100644 --- a/Jint/Native/Iterator/IteratorInstance.cs +++ b/Jint/Native/Iterator/IteratorInstance.cs @@ -77,29 +77,20 @@ private ObjectInstance IteratorNext() 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) { - ExceptionHelper.ThrowTypeError(_target.Engine.Realm, func + " is not a function"); + return; } - var innerResult = Undefined; + JsValue innerResult; try { 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()) diff --git a/Jint/Native/Object/ObjectInstance.cs b/Jint/Native/Object/ObjectInstance.cs index 1e68bbc81a..18c25ae3c8 100644 --- a/Jint/Native/Object/ObjectInstance.cs +++ b/Jint/Native/Object/ObjectInstance.cs @@ -1391,7 +1391,7 @@ internal static JsObject OrdinaryObjectCreate(Engine engine, ObjectInstance? pro var callable = jsValue as ICallable; 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; } diff --git a/Jint/Native/Object/ObjectPrototype.cs b/Jint/Native/Object/ObjectPrototype.cs index 341a07053f..000565a254 100644 --- a/Jint/Native/Object/ObjectPrototype.cs +++ b/Jint/Native/Object/ObjectPrototype.cs @@ -63,6 +63,11 @@ protected override void Initialize() SetProperties(properties); } + internal override bool SetPrototypeOf(JsValue value) + { + return SameValue(value, _prototype ?? Null); + } + public override bool DefineOwnProperty(JsValue property, PropertyDescriptor desc) { TrackChanges(property); diff --git a/Jint/Native/Promise/PromiseConstructor.cs b/Jint/Native/Promise/PromiseConstructor.cs index 2dad7c48a8..bd2d71c3c4 100644 --- a/Jint/Native/Promise/PromiseConstructor.cs +++ b/Jint/Native/Promise/PromiseConstructor.cs @@ -333,7 +333,14 @@ void ResolveIfFinished() } 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); return capability.PromiseInstance; } @@ -449,7 +456,14 @@ void ResolveIfFinished() } 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); return capability.PromiseInstance; } @@ -551,7 +565,14 @@ void RejectIfAllRejected() } 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); return capability.PromiseInstance; } @@ -597,10 +618,14 @@ private JsValue Race(JsValue thisObject, JsCallArguments arguments) } 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); return capability.PromiseInstance; } diff --git a/Jint/Runtime/Interpreter/Expressions/DestructuringPatternAssignmentExpression.cs b/Jint/Runtime/Interpreter/Expressions/DestructuringPatternAssignmentExpression.cs index 2102ac44d4..0e678218d9 100644 --- a/Jint/Runtime/Interpreter/Expressions/DestructuringPatternAssignmentExpression.cs +++ b/Jint/Runtime/Interpreter/Expressions/DestructuringPatternAssignmentExpression.cs @@ -240,12 +240,7 @@ private static JsValue HandleArrayPattern( if (value.IsUndefined()) { 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) @@ -278,9 +273,9 @@ private static JsValue HandleArrayPattern( } finally { - if (close && !done) + if (close && !done && iterator is not null) { - iterator?.Close(completionType); + iterator.Close(completionType); } }