diff --git a/Compilation/RuntimeEmitter.Json.Stringify.cs b/Compilation/RuntimeEmitter.Json.Stringify.cs index 1fa1ff8f..b959bfe1 100644 --- a/Compilation/RuntimeEmitter.Json.Stringify.cs +++ b/Compilation/RuntimeEmitter.Json.Stringify.cs @@ -425,6 +425,18 @@ private MethodBuilder EmitJsonStringifyHelper(TypeBuilder typeBuilder, EmittedRu il.Emit(OpCodes.Isinst, _types.DictionaryStringObject); il.Emit(OpCodes.Brfalse, notBoxedPrim); il.MarkLabel(doBoxedUnwrap); + // #565: only a genuine boxed wrapper (carrying a string __primitiveType tag) + // is unwrapped — an ordinary object that merely has a __primitiveValue field + // must serialize as a normal object, matching the interpreter and + // RuntimeEmitter.Json.StringifyFull.cs. + var boxedPrimType = il.DeclareLocal(_types.Object); + il.Emit(OpCodes.Ldloc, valueLocal); + il.Emit(OpCodes.Ldstr, "__primitiveType"); + il.Emit(OpCodes.Call, runtime.GetProperty); + il.Emit(OpCodes.Stloc, boxedPrimType); + il.Emit(OpCodes.Ldloc, boxedPrimType); + il.Emit(OpCodes.Isinst, _types.String); + il.Emit(OpCodes.Brfalse, notBoxedPrim); var boxedPrimVal = il.DeclareLocal(_types.Object); il.Emit(OpCodes.Ldloc, valueLocal); il.Emit(OpCodes.Ldstr, "__primitiveValue"); diff --git a/Execution/Interpreter.Async.cs b/Execution/Interpreter.Async.cs index d95d4fe2..dba6c6fa 100644 --- a/Execution/Interpreter.Async.cs +++ b/Execution/Interpreter.Async.cs @@ -913,7 +913,8 @@ private async Task EvaluateTemplateLiteralAsync(Expr.TemplateLiter var evaluatedExprs = new List(); foreach (var expr in template.Expressions) { - evaluatedExprs.Add((await EvaluateAsync(expr)).ToObject()); + // ToPrimitive (string hint) so boxed wrappers render their primitive (#708). + evaluatedExprs.Add(ToPrimitive((await EvaluateAsync(expr)).ToObject(), PrimitiveHint.String)); } return RuntimeValue.FromString(BuildTemplateLiteralString(template.Strings, evaluatedExprs)); } diff --git a/Execution/Interpreter.Expressions.cs b/Execution/Interpreter.Expressions.cs index 2f153b91..854473cb 100644 --- a/Execution/Interpreter.Expressions.cs +++ b/Execution/Interpreter.Expressions.cs @@ -378,7 +378,11 @@ private RuntimeValue EvaluateLiteral(Expr.Literal literal) /// MDN Template Literals private RuntimeValue EvaluateTemplateLiteral(Expr.TemplateLiteral template) { - var evaluatedExprs = template.Expressions.Select(Evaluate).ToList(); + // ToString coercion of an interpolated value goes through ToPrimitive + // (string hint), so a boxed wrapper / object with own toString renders + // its primitive (`${new String("ab")}` → "ab") rather than "[object Object]" (#708). + var evaluatedExprs = template.Expressions + .Select(e => ToPrimitive(Evaluate(e), PrimitiveHint.String)).ToList(); return RuntimeValue.FromString(BuildTemplateLiteralString(template.Strings, evaluatedExprs)); } diff --git a/Execution/Interpreter.Operators.cs b/Execution/Interpreter.Operators.cs index e35545d8..4c10311f 100644 --- a/Execution/Interpreter.Operators.cs +++ b/Execution/Interpreter.Operators.cs @@ -249,6 +249,13 @@ private Task EvaluatePostfixIncrementAsync(Expr.PostfixIncrement p /// MDN Addition Operator private object EvaluatePlus(object? left, object? right) { + // ECMA-262 §13.15.3 ApplyStringOrNumericBinaryOperator: ToPrimitive both + // operands (default hint) before deciding string-concat vs numeric add. + // Reduces boxed Number/String/Boolean wrappers (and objects with an own + // valueOf/toString) to their primitive so `"x" + new Number(5)` → "x5" + // and `new Number(5) + 1` → 6 (#708). No-op for other values. + left = ToPrimitive(left, PrimitiveHint.Default); + right = ToPrimitive(right, PrimitiveHint.Default); if (left is double l && right is double r) return l + r; if (left is string || right is string) { @@ -371,6 +378,14 @@ private RuntimeValue EvaluateUnaryOperationRV(Token op, RuntimeValue rv) /// private static double CoerceToNumber(object? value) => CoerceToNumber(RuntimeValue.FromBoxed(value)); + /// + /// JS ToNumber for a boxed value, unwrapping a boxed Number/String/Boolean + /// wrapper to its primitive first (#708). Exposed for numeric built-ins + /// (e.g. String.fromCharCode) that otherwise hard-crash on a wrapper + /// argument via . + /// + internal static double ToNumber(object? value) => CoerceToNumber(RuntimeValue.FromBoxed(value)); + private static double CoerceToNumber(RuntimeValue rv) { if (rv.IsNumber) return rv.AsNumber(); @@ -386,9 +401,110 @@ private static double CoerceToNumber(RuntimeValue rv) return d; return double.NaN; } + // ECMA-262 ToNumber on an object goes through ToPrimitive (number hint). + // For a boxed Number/String/Boolean wrapper that reduces to its + // [[PrimitiveValue]]; without this `new Number(5) * 2`, comparisons, and + // bitwise ops on wrappers coerce to NaN (#708). A user-overridden valueOf + // is honored on the instance ToPrimitive paths (+, ==, templates, JSON). + if (rv.Kind == ValueKind.Object && TryGetBoxedPrimitiveValue(rv.ToObject(), out var prim)) + return CoerceToNumber(RuntimeValue.FromBoxed(prim)); return double.NaN; } + private enum PrimitiveHint { Default, Number, String } + + private static readonly List _toPrimitiveNoArgs = new(); + + /// + /// True when is a boxed new Number/String/Boolean + /// wrapper (carries a __primitiveType tag); yields its __primitiveValue. + /// + internal static bool TryGetBoxedPrimitiveValue(object? value, out object? primitive) + { + primitive = null; + if (value is SharpTSObject obj + && obj.GetProperty("__primitiveType") is string pt + && pt is "Number" or "String" or "Boolean" + && obj.HasProperty("__primitiveValue")) + { + primitive = obj.GetProperty("__primitiveValue"); + return true; + } + return false; + } + + /// + /// ECMA-262 §7.1.1 ToPrimitive / OrdinaryToPrimitive for the cases the + /// interpreter must coerce explicitly: boxed primitive wrappers and plain + /// objects carrying an own valueOf/toString. Calls the own + /// conversion methods in hint order (honoring a user override — #574), then + /// falls back to a wrapper's __primitiveValue (#708). Every other + /// value (already-primitive, array, class instance, plain object without an + /// own conversion) is returned unchanged so existing behavior is preserved. + /// + private object? ToPrimitive(object? value, PrimitiveHint hint) + { + if (value is not SharpTSObject obj) return value; + bool isWrapper = TryGetBoxedPrimitiveValue(obj, out var primitiveValue); + bool hasOwnValueOf = obj.HasProperty("valueOf"); + bool hasOwnToString = obj.HasProperty("toString"); + if (!isWrapper && !hasOwnValueOf && !hasOwnToString) return value; + + string first = hint == PrimitiveHint.String ? "toString" : "valueOf"; + string second = hint == PrimitiveHint.String ? "valueOf" : "toString"; + if (TryCallOwnConversion(obj, first, out var r1)) return r1; + if (TryCallOwnConversion(obj, second, out var r2)) return r2; + return isWrapper ? primitiveValue : value; + } + + /// + /// Invokes an own valueOf/toString on bound + /// to it; succeeds only when the result is a primitive (per OrdinaryToPrimitive, + /// an object result is skipped so the next method is tried). + /// + private bool TryCallOwnConversion(SharpTSObject obj, string name, out object? result) + { + result = null; + if (!obj.HasProperty(name)) return false; + var fn = obj.GetProperty(name); + if (fn is SharpTSArrowFunction af && af.HasOwnThis) fn = af.Bind(obj); + if (fn is not ISharpTSCallable callable) return false; + var r = callable.CallBoxed(this, _toPrimitiveNoArgs); + if (IsObjectLike(r)) return false; + result = r; + return true; + } + + /// + /// ECMA-262 §25.5.2.2 SerializeJSONProperty step 4: coerce a boxed + /// Number/String/Boolean wrapper to the primitive JSON serializes. Number→ + /// ToNumber, String→ToString (both via , so a user + /// override of valueOf/toString is honored — #574); Boolean→its + /// [[BooleanData]] (no coercion per spec). Returns false for any non-wrapper. + /// + internal bool TryCoerceBoxedPrimitiveForJson(object? value, out object? primitive) + { + primitive = null; + if (value is not SharpTSObject obj + || obj.GetProperty("__primitiveType") is not string tag) + return false; + switch (tag) + { + case "Number": + primitive = CoerceToNumber(RuntimeValue.FromBoxed(ToPrimitive(obj, PrimitiveHint.Number))); + return true; + case "String": + var sp = ToPrimitive(obj, PrimitiveHint.String); + primitive = sp as string ?? Stringify(sp); + return true; + case "Boolean": + primitive = obj.GetProperty("__primitiveValue"); + return true; + default: + return false; + } + } + /// /// Evaluates the delete operator. /// @@ -637,9 +753,21 @@ private bool IsEqual(object? a, object? b) bool bIsNullish = b == null || b is SharpTSUndefined; if (aIsNullish && bIsNullish) return true; if (aIsNullish || bIsNullish) return false; + // ECMA-262 §7.2.15 steps 10-11: Object vs primitive coerces the object + // through ToPrimitive, so `new Number(0) == 0` is true (#708). Only when + // the other operand is a primitive — object == object stays reference-based. + if (a is SharpTSObject && IsPrimitiveOperand(b)) a = ToPrimitive(a, PrimitiveHint.Default); + else if (b is SharpTSObject && IsPrimitiveOperand(a)) b = ToPrimitive(b, PrimitiveHint.Default); return a!.Equals(b); } + /// + /// True for JS primitive operands that trigger object→primitive coercion on + /// the other side of loose == (number, string, boolean, bigint). + /// + private static bool IsPrimitiveOperand(object? value) => + value is double or string or bool or SharpTSBigInt; + /// /// Determines if two values are equal using strict equality (===). /// diff --git a/Runtime/BuiltIns/JSONBuiltIns.cs b/Runtime/BuiltIns/JSONBuiltIns.cs index e32377bb..6ecd7b75 100644 --- a/Runtime/BuiltIns/JSONBuiltIns.cs +++ b/Runtime/BuiltIns/JSONBuiltIns.cs @@ -212,7 +212,7 @@ private static RuntimeValue StringifyJson(Interpreter interp, RuntimeValue _, Re // ECMA-262 25.5.2.1 step 5: a boxed Number/String wrapper passed as `space` // contributes its primitive value before the numeric/string indent rules below. // (Compiled mode does the same — RuntimeEmitter.Json.StringifyFull.cs.) - if (TryUnwrapBoxedPrimitive(space, out var unwrappedSpace)) + if (TryUnwrapBoxedPrimitive(interp, space, out var unwrappedSpace)) space = unwrappedSpace; // Handle space parameter: number = spaces, string = literal indent string @@ -273,7 +273,7 @@ private static bool StringifyValue(Interpreter interp, object? value, object? ke // serializes as its underlying primitive — not as an object exposing the internal // __primitiveType/__primitiveValue marker slots. Applied after toJSON/replacer, // before the type switch. (Compiled mode does the same — RuntimeEmitter.Json.Stringify.cs.) - if (TryUnwrapBoxedPrimitive(value, out var unwrappedPrimitive)) + if (TryUnwrapBoxedPrimitive(interp, value, out var unwrappedPrimitive)) value = unwrappedPrimitive; switch (value) @@ -350,18 +350,8 @@ private static bool StringifyValue(Interpreter interp, object? value, object? ke /// objects with a genuine [[NumberData]]/[[StringData]]/[[BooleanData]] slot are unwrapped. /// Compiled mode performs the equivalent unwrap (RuntimeEmitter.Json.Stringify*.cs). /// - private static bool TryUnwrapBoxedPrimitive(object? value, out object? primitive) - { - if (value is SharpTSObject obj - && obj.GetProperty("__primitiveType") is string tag - && tag is "Number" or "String" or "Boolean") - { - primitive = obj.GetProperty("__primitiveValue"); - return true; - } - primitive = null; - return false; - } + private static bool TryUnwrapBoxedPrimitive(Interpreter interp, object? value, out object? primitive) + => interp.TryCoerceBoxedPrimitiveForJson(value, out primitive); private static string FormatJsonNumber(double d) { diff --git a/Runtime/BuiltIns/NumberBuiltIns.cs b/Runtime/BuiltIns/NumberBuiltIns.cs index 731f4f11..1b826305 100644 --- a/Runtime/BuiltIns/NumberBuiltIns.cs +++ b/Runtime/BuiltIns/NumberBuiltIns.cs @@ -62,6 +62,11 @@ public static class NumberBuiltIns .MethodV2("toPrecision", 0, 1, ToPrecisionV2) .MethodV2("toExponential", 0, 1, ToExponentialV2) .MethodV2("toString", 0, 1, ToStringMethodV2) + // ECMA-262 §21.1.3.7: Number.prototype.valueOf returns thisNumberValue. + // Needed so `(new Number(5)).valueOf()` and ToPrimitive(number-wrapper) + // unwrap to the primitive instead of resolving Object.prototype.valueOf. + .MethodV2("valueOf", 0, (Interpreter _, double value, ReadOnlySpan _) + => RuntimeValue.FromNumber(value)) .Build(); /// diff --git a/Runtime/BuiltIns/StringBuiltIns.cs b/Runtime/BuiltIns/StringBuiltIns.cs index 78ea243e..e2563dec 100644 --- a/Runtime/BuiltIns/StringBuiltIns.cs +++ b/Runtime/BuiltIns/StringBuiltIns.cs @@ -42,6 +42,14 @@ public static class StringBuiltIns .MethodV2("at", 1, AtV2) .MethodV2("normalize", 0, 1, NormalizeV2) .MethodV2("localeCompare", 1, LocaleCompareV2) + // ECMA-262 §22.1.3.28/.31: String.prototype.toString and valueOf both + // return thisStringValue. Needed so `(new String("x")).toString()` and + // ToPrimitive(string-wrapper) unwrap to the primitive instead of + // resolving Object.prototype.toString ("[object Object]"). + .MethodV2("toString", 0, (Interpreter _, string s, ReadOnlySpan _) + => RuntimeValue.FromString(s)) + .MethodV2("valueOf", 0, (Interpreter _, string s, ReadOnlySpan _) + => RuntimeValue.FromString(s)) .Build(); private static readonly BuiltInStaticMemberLookup _staticLookup = @@ -222,19 +230,27 @@ private static RuntimeValue FromCharCodeV2(Interpreter _, RuntimeValue receiver, if (args.Length == 1) { - var code = (int)args[0].AsNumber(); + var code = (int)NumArg(args[0]); return RuntimeValue.FromString(((char)(code & 0xFFFF)).ToString()); } var chars = new char[args.Length]; for (int i = 0; i < args.Length; i++) { - var code = (int)args[i].AsNumber(); + var code = (int)NumArg(args[i]); chars[i] = (char)(code & 0xFFFF); } return RuntimeValue.FromString(new string(chars)); } + /// + /// ToNumber-coerces a numeric argument, routing a non-number (notably a + /// boxed new Number(x) wrapper) through the interpreter's ToNumber so + /// it unwraps to its primitive instead of throwing on AsNumber() (#708). + /// + private static double NumArg(RuntimeValue rv) + => rv.Kind == ValueKind.Number ? rv.AsNumber() : Interpreter.ToNumber(rv.ToObject()); + private static RuntimeValue FromCodePointV2(Interpreter _, RuntimeValue receiver, ReadOnlySpan args) { if (args.Length == 0) return RuntimeValue.EmptyString; @@ -244,7 +260,7 @@ private static RuntimeValue FromCodePointV2(Interpreter _, RuntimeValue receiver { // ECMA-262 §22.1.2.2: each code point must be an integral Number in // [0, 0x10FFFF]; NaN / Infinity / fractional values throw RangeError. - var num = arg.AsNumber(); + var num = NumArg(arg); if (!double.IsInteger(num) || num < 0 || num > 0x10FFFF) throw new Exception($"RangeError: Invalid code point {num}"); AppendCodePoint(sb, (int)num); diff --git a/SharpTS.Test262/baselines/interpreted.txt b/SharpTS.Test262/baselines/interpreted.txt index f4a3e1ea..6462d257 100644 --- a/SharpTS.Test262/baselines/interpreted.txt +++ b/SharpTS.Test262/baselines/interpreted.txt @@ -496,8 +496,8 @@ test/built-ins/Array/prototype/every/15.4.4.16-5-19.js Pass test/built-ins/Array/prototype/every/15.4.4.16-5-2.js Pass test/built-ins/Array/prototype/every/15.4.4.16-5-21.js RuntimeError test/built-ins/Array/prototype/every/15.4.4.16-5-22.js Pass -test/built-ins/Array/prototype/every/15.4.4.16-5-23.js RuntimeError -test/built-ins/Array/prototype/every/15.4.4.16-5-24.js RuntimeError +test/built-ins/Array/prototype/every/15.4.4.16-5-23.js Pass +test/built-ins/Array/prototype/every/15.4.4.16-5-24.js Pass test/built-ins/Array/prototype/every/15.4.4.16-5-3.js Pass test/built-ins/Array/prototype/every/15.4.4.16-5-4.js Pass test/built-ins/Array/prototype/every/15.4.4.16-5-5.js Pass @@ -739,8 +739,8 @@ test/built-ins/Array/prototype/filter/15.4.4.20-5-19.js Pass test/built-ins/Array/prototype/filter/15.4.4.20-5-2.js Pass test/built-ins/Array/prototype/filter/15.4.4.20-5-21.js RuntimeError test/built-ins/Array/prototype/filter/15.4.4.20-5-22.js Pass -test/built-ins/Array/prototype/filter/15.4.4.20-5-23.js RuntimeError -test/built-ins/Array/prototype/filter/15.4.4.20-5-24.js RuntimeError +test/built-ins/Array/prototype/filter/15.4.4.20-5-23.js Pass +test/built-ins/Array/prototype/filter/15.4.4.20-5-24.js Pass test/built-ins/Array/prototype/filter/15.4.4.20-5-27.js Pass test/built-ins/Array/prototype/filter/15.4.4.20-5-28.js Pass test/built-ins/Array/prototype/filter/15.4.4.20-5-29.js Pass @@ -1114,8 +1114,8 @@ test/built-ins/Array/prototype/forEach/15.4.4.18-5-19.js Pass test/built-ins/Array/prototype/forEach/15.4.4.18-5-2.js Pass test/built-ins/Array/prototype/forEach/15.4.4.18-5-21.js RuntimeError test/built-ins/Array/prototype/forEach/15.4.4.18-5-22.js Pass -test/built-ins/Array/prototype/forEach/15.4.4.18-5-23.js RuntimeError -test/built-ins/Array/prototype/forEach/15.4.4.18-5-24.js RuntimeError +test/built-ins/Array/prototype/forEach/15.4.4.18-5-23.js Pass +test/built-ins/Array/prototype/forEach/15.4.4.18-5-24.js Pass test/built-ins/Array/prototype/forEach/15.4.4.18-5-25.js Fail test/built-ins/Array/prototype/forEach/15.4.4.18-5-3.js Pass test/built-ins/Array/prototype/forEach/15.4.4.18-5-4.js Pass @@ -1772,8 +1772,8 @@ test/built-ins/Array/prototype/map/15.4.4.19-5-19.js Pass test/built-ins/Array/prototype/map/15.4.4.19-5-2.js Pass test/built-ins/Array/prototype/map/15.4.4.19-5-21.js RuntimeError test/built-ins/Array/prototype/map/15.4.4.19-5-22.js Pass -test/built-ins/Array/prototype/map/15.4.4.19-5-23.js RuntimeError -test/built-ins/Array/prototype/map/15.4.4.19-5-24.js RuntimeError +test/built-ins/Array/prototype/map/15.4.4.19-5-23.js Pass +test/built-ins/Array/prototype/map/15.4.4.19-5-24.js Pass test/built-ins/Array/prototype/map/15.4.4.19-5-3.js Pass test/built-ins/Array/prototype/map/15.4.4.19-5-4.js Pass test/built-ins/Array/prototype/map/15.4.4.19-5-5.js Pass @@ -2667,8 +2667,8 @@ test/built-ins/Array/prototype/some/15.4.4.17-5-19.js Pass test/built-ins/Array/prototype/some/15.4.4.17-5-2.js Pass test/built-ins/Array/prototype/some/15.4.4.17-5-21.js RuntimeError test/built-ins/Array/prototype/some/15.4.4.17-5-22.js Pass -test/built-ins/Array/prototype/some/15.4.4.17-5-23.js RuntimeError -test/built-ins/Array/prototype/some/15.4.4.17-5-24.js RuntimeError +test/built-ins/Array/prototype/some/15.4.4.17-5-23.js Pass +test/built-ins/Array/prototype/some/15.4.4.17-5-24.js Pass test/built-ins/Array/prototype/some/15.4.4.17-5-25.js Fail test/built-ins/Array/prototype/some/15.4.4.17-5-3.js Pass test/built-ins/Array/prototype/some/15.4.4.17-5-4.js Pass @@ -3317,10 +3317,10 @@ test/built-ins/JSON/stringify/replacer-function-tojson.js Fail test/built-ins/JSON/stringify/replacer-function-wrapper.js RuntimeError test/built-ins/JSON/stringify/replacer-wrong-type.js Pass test/built-ins/JSON/stringify/space-number-float.js Pass -test/built-ins/JSON/stringify/space-number-object.js RuntimeError +test/built-ins/JSON/stringify/space-number-object.js Pass test/built-ins/JSON/stringify/space-number-range.js Pass test/built-ins/JSON/stringify/space-number.js Pass -test/built-ins/JSON/stringify/space-string-object.js RuntimeError +test/built-ins/JSON/stringify/space-string-object.js Pass test/built-ins/JSON/stringify/space-string-range.js Pass test/built-ins/JSON/stringify/space-string.js Pass test/built-ins/JSON/stringify/space-wrong-type.js Pass @@ -3338,7 +3338,7 @@ test/built-ins/JSON/stringify/value-boolean-object.js Pass test/built-ins/JSON/stringify/value-function.js Pass test/built-ins/JSON/stringify/value-number-negative-zero.js Pass test/built-ins/JSON/stringify/value-number-non-finite.js Pass -test/built-ins/JSON/stringify/value-number-object.js RuntimeError +test/built-ins/JSON/stringify/value-number-object.js Pass test/built-ins/JSON/stringify/value-object-abrupt.js Fail test/built-ins/JSON/stringify/value-object-circular.js Fail test/built-ins/JSON/stringify/value-object-proxy-revoked.js Fail @@ -3346,7 +3346,7 @@ test/built-ins/JSON/stringify/value-object-proxy.js Fail test/built-ins/JSON/stringify/value-primitive-top-level.js Pass test/built-ins/JSON/stringify/value-string-escape-ascii.js Fail test/built-ins/JSON/stringify/value-string-escape-unicode.js Fail -test/built-ins/JSON/stringify/value-string-object.js RuntimeError +test/built-ins/JSON/stringify/value-string-object.js Pass test/built-ins/JSON/stringify/value-symbol.js Pass test/built-ins/JSON/stringify/value-tojson-abrupt.js Fail test/built-ins/JSON/stringify/value-tojson-arguments.js Fail @@ -3708,7 +3708,7 @@ test/built-ins/Number/S15.7.1.1_A1.js Pass test/built-ins/Number/S15.7.1.1_A2.js Pass test/built-ins/Number/S15.7.2.1_A1.js Fail test/built-ins/Number/S15.7.2.1_A2.js RuntimeError -test/built-ins/Number/S15.7.2.1_A3.js RuntimeError +test/built-ins/Number/S15.7.2.1_A3.js Pass test/built-ins/Number/S15.7.2.1_A4.js Fail test/built-ins/Number/S15.7.3_A1.js RuntimeError test/built-ins/Number/S15.7.3_A2.js RuntimeError @@ -3982,7 +3982,7 @@ test/built-ins/Number/prototype/valueOf/S15.7.4.4_A2_T04.js Pass test/built-ins/Number/prototype/valueOf/S15.7.4.4_A2_T05.js Pass test/built-ins/Number/prototype/valueOf/length.js Fail test/built-ins/Number/prototype/valueOf/name.js Fail -test/built-ins/Number/prototype/valueOf/not-a-constructor.js Fail +test/built-ins/Number/prototype/valueOf/not-a-constructor.js Pass test/built-ins/Number/prototype/valueOf/prop-desc.js Fail test/built-ins/Number/return-abrupt-tonumber-value-symbol.js Fail test/built-ins/Number/return-abrupt-tonumber-value.js Fail @@ -10050,7 +10050,7 @@ test/built-ins/String/S15.5.5.1_A2.js RuntimeError test/built-ins/String/S15.5.5.1_A3.js RuntimeError test/built-ins/String/S15.5.5.1_A4_T1.js RuntimeError test/built-ins/String/S15.5.5.1_A4_T2.js RuntimeError -test/built-ins/String/S15.5.5.1_A5.js RuntimeError +test/built-ins/String/S15.5.5.1_A5.js Pass test/built-ins/String/S15.5.5_A1_T1.js Pass test/built-ins/String/S15.5.5_A1_T2.js Pass test/built-ins/String/S15.5.5_A2_T1.js Pass @@ -10081,17 +10081,17 @@ test/built-ins/String/fromCharCode/S15.5.3.2_A4.js Fail test/built-ins/String/fromCharCode/S9.7_A1.js Fail test/built-ins/String/fromCharCode/S9.7_A2.1.js Fail test/built-ins/String/fromCharCode/S9.7_A2.2.js Pass -test/built-ins/String/fromCharCode/S9.7_A3.1_T1.js RuntimeError +test/built-ins/String/fromCharCode/S9.7_A3.1_T1.js Pass test/built-ins/String/fromCharCode/S9.7_A3.1_T2.js Pass -test/built-ins/String/fromCharCode/S9.7_A3.1_T3.js RuntimeError -test/built-ins/String/fromCharCode/S9.7_A3.1_T4.js RuntimeError +test/built-ins/String/fromCharCode/S9.7_A3.1_T3.js Pass +test/built-ins/String/fromCharCode/S9.7_A3.1_T4.js Fail test/built-ins/String/fromCharCode/S9.7_A3.2_T1.js Pass test/built-ins/String/fromCharCode/name.js Fail test/built-ins/String/fromCharCode/not-a-constructor.js Fail test/built-ins/String/fromCharCode/touint16-tonumber-throws-bigint.js Fail test/built-ins/String/fromCharCode/touint16-tonumber-throws-valueof.js Fail test/built-ins/String/fromCodePoint/argument-is-Symbol.js Fail -test/built-ins/String/fromCodePoint/argument-is-not-integer.js Fail +test/built-ins/String/fromCodePoint/argument-is-not-integer.js Pass test/built-ins/String/fromCodePoint/argument-not-coercible.js Fail test/built-ins/String/fromCodePoint/arguments-is-empty.js Pass test/built-ins/String/fromCodePoint/fromCodePoint.js Fail @@ -10960,9 +10960,9 @@ test/built-ins/String/prototype/toString/length.js Fail test/built-ins/String/prototype/toString/name.js Fail test/built-ins/String/prototype/toString/non-generic-realm.js RuntimeError test/built-ins/String/prototype/toString/non-generic.js Fail -test/built-ins/String/prototype/toString/not-a-constructor.js Fail +test/built-ins/String/prototype/toString/not-a-constructor.js Pass test/built-ins/String/prototype/toString/string-object.js Fail -test/built-ins/String/prototype/toString/string-primitive.js RuntimeError +test/built-ins/String/prototype/toString/string-primitive.js Pass test/built-ins/String/prototype/toUpperCase/S15.5.4.18_A10.js Pass test/built-ins/String/prototype/toUpperCase/S15.5.4.18_A11.js Pass test/built-ins/String/prototype/toUpperCase/S15.5.4.18_A1_T1.js RuntimeError @@ -11006,7 +11006,7 @@ test/built-ins/String/prototype/trim/15.5.4.20-1-4.js Pass test/built-ins/String/prototype/trim/15.5.4.20-1-5.js Fail test/built-ins/String/prototype/trim/15.5.4.20-1-6.js Pass test/built-ins/String/prototype/trim/15.5.4.20-1-7.js Pass -test/built-ins/String/prototype/trim/15.5.4.20-1-8.js RuntimeError +test/built-ins/String/prototype/trim/15.5.4.20-1-8.js Pass test/built-ins/String/prototype/trim/15.5.4.20-1-9.js Pass test/built-ins/String/prototype/trim/15.5.4.20-2-1.js Pass test/built-ins/String/prototype/trim/15.5.4.20-2-10.js Pass @@ -11176,9 +11176,9 @@ test/built-ins/String/prototype/valueOf/length.js Fail test/built-ins/String/prototype/valueOf/name.js Fail test/built-ins/String/prototype/valueOf/non-generic-realm.js RuntimeError test/built-ins/String/prototype/valueOf/non-generic.js Fail -test/built-ins/String/prototype/valueOf/not-a-constructor.js Fail +test/built-ins/String/prototype/valueOf/not-a-constructor.js Pass test/built-ins/String/prototype/valueOf/string-object.js RuntimeError -test/built-ins/String/prototype/valueOf/string-primitive.js RuntimeError +test/built-ins/String/prototype/valueOf/string-primitive.js Pass test/built-ins/String/raw/length.js Fail test/built-ins/String/raw/name.js Fail test/built-ins/String/raw/nextkey-is-symbol-throws.js Fail