Browse Source

Enable code analysis with latest-Recommended (#1681)

Marko Lahma 1 year ago
parent
commit
088f08f8e1
62 changed files with 248 additions and 229 deletions
  1. 15 0
      .editorconfig
  2. 4 3
      Jint.Tests/Runtime/EngineTests.cs
  3. 2 0
      Jint/Constraints/TimeConstraint.cs
  4. 1 0
      Jint/Jint.csproj
  5. 2 0
      Jint/Native/ArrayBuffer/JsArrayBuffer.cs
  6. 3 2
      Jint/Native/BigInt/BigIntPrototype.cs
  7. 10 9
      Jint/Native/Date/DatePrototype.cs
  8. 7 1
      Jint/Native/Date/MimeKit.cs
  9. 1 1
      Jint/Native/FinalizationRegistry/FinalizationRegistryInstance.cs
  10. 1 1
      Jint/Native/FinalizationRegistry/FinalizationRegistryPrototype.cs
  11. 1 1
      Jint/Native/Function/ClassDefinition.cs
  12. 2 2
      Jint/Native/Function/ScriptFunctionInstance.cs
  13. 15 15
      Jint/Native/Global/GlobalObject.cs
  14. 1 1
      Jint/Native/Intl/DateTimeFormatConstructor.cs
  15. 3 3
      Jint/Native/Intl/NumberFormatConstructor.cs
  16. 1 1
      Jint/Native/Intl/PluralRulesConstructor.cs
  17. 1 1
      Jint/Native/Intl/RelativeTimeFormatConstructor.cs
  18. 3 12
      Jint/Native/JsBigInt.cs
  19. 6 1
      Jint/Native/JsBoolean.cs
  20. 7 8
      Jint/Native/JsNull.cs
  21. 9 12
      Jint/Native/JsNumber.cs
  22. 6 21
      Jint/Native/JsString.cs
  23. 5 12
      Jint/Native/JsSymbol.cs
  24. 7 8
      Jint/Native/JsUndefined.cs
  25. 3 12
      Jint/Native/JsValue.cs
  26. 2 2
      Jint/Native/Json/JsonParser.cs
  27. 2 1
      Jint/Native/Json/JsonSerializer.cs
  28. 9 9
      Jint/Native/Number/Dtoa/Bignum.cs
  29. 23 27
      Jint/Native/Number/NumberPrototype.cs
  30. 6 5
      Jint/Native/Object/ObjectInstance.cs
  31. 1 1
      Jint/Native/Promise/PromiseOperations.cs
  32. 1 1
      Jint/Native/Proxy/JsProxy.cs
  33. 6 0
      Jint/Native/RegExp/RegExpPrototype.cs
  34. 9 3
      Jint/Native/String/StringPrototype.cs
  35. 2 1
      Jint/Native/TypedArray/JsTypedArray.cs
  36. 2 1
      Jint/Native/TypedArray/TypedArrayConstructor.cs
  37. 2 2
      Jint/Options.cs
  38. 2 0
      Jint/Pooling/ConcurrentObjectPool.cs
  39. 2 0
      Jint/Pooling/ObjectPool.cs
  40. 7 5
      Jint/Runtime/CallStack/JintCallStack.cs
  41. 2 2
      Jint/Runtime/CallStack/StackGuard.cs
  42. 0 2
      Jint/Runtime/Debugger/BreakPointCollection.cs
  43. 2 0
      Jint/Runtime/DefaultTimeSystem.cs
  44. 5 1
      Jint/Runtime/Interop/ClrFunctionInstance.cs
  45. 7 1
      Jint/Runtime/Interop/ClrHelper.cs
  46. 7 6
      Jint/Runtime/Interop/DefaultObjectConverter.cs
  47. 4 4
      Jint/Runtime/Interop/DelegateWrapper.cs
  48. 1 1
      Jint/Runtime/Interop/MethodDescriptor.cs
  49. 1 1
      Jint/Runtime/Interop/NamespaceReference.cs
  50. 4 7
      Jint/Runtime/Interop/ObjectWrapper.cs
  51. 3 3
      Jint/Runtime/Interop/TypeReference.cs
  52. 1 2
      Jint/Runtime/Interpreter/Expressions/BindingPatternAssignmentExpression.cs
  53. 2 1
      Jint/Runtime/Interpreter/Expressions/JintCallExpression.cs
  54. 1 1
      Jint/Runtime/Interpreter/Expressions/JintMemberExpression.cs
  55. 1 1
      Jint/Runtime/Interpreter/JintFunctionDefinition.cs
  56. 1 1
      Jint/Runtime/Interpreter/Statements/JintExportDefaultDeclaration.cs
  57. 2 0
      Jint/Runtime/Interpreter/Statements/JintForInForOfStatement.cs
  58. 1 1
      Jint/Runtime/Modules/DefaultModuleLoader.cs
  59. 2 0
      Jint/Runtime/Modules/FailFastModuleLoader.cs
  60. 2 2
      Jint/Runtime/Modules/SourceTextModuleRecord.cs
  61. 1 1
      Jint/Runtime/OrderedDictionary.cs
  62. 6 6
      Jint/Runtime/TypeConverter.cs

+ 15 - 0
.editorconfig

@@ -36,6 +36,21 @@ indent_size = 2
 # IDE0055: Fix formatting
 dotnet_diagnostic.IDE0055.severity = warning
 
+# Error CA1051 : Do not declare visible instance fields
+dotnet_diagnostic.CA1051.severity = none
+
+#  Error CA1720 : Identifiers should not contain type names
+dotnet_diagnostic.CA1720.severity = none
+
+#  Error CA1711: Identifiers should not have incorrect suffix
+dotnet_diagnostic.CA1711.severity = none
+
+#  Error CA1710: Identifiers should have correct suffix
+dotnet_diagnostic.CA1710.severity = none
+
+#  Error CA1716: Identifiers should have correct suffix
+dotnet_diagnostic.CA1716.severity = none
+
 # Sort using and Import directives with System.* appearing first
 dotnet_sort_system_directives_first = true
 dotnet_separate_import_directive_groups = false

+ 4 - 3
Jint.Tests/Runtime/EngineTests.cs

@@ -4,6 +4,7 @@ using Esprima;
 using Esprima.Ast;
 using Jint.Native;
 using Jint.Native.Array;
+using Jint.Native.Number;
 using Jint.Native.Object;
 using Jint.Runtime;
 using Jint.Runtime.Debugger;
@@ -823,8 +824,8 @@ namespace Jint.Tests.Runtime
         [Fact]
         public void ShouldComputeFractionInBase()
         {
-            Assert.Equal("011", _engine.Realm.Intrinsics.Number.PrototypeObject.ToFractionBase(0.375, 2));
-            Assert.Equal("14141414141414141414141414141414141414141414141414", _engine.Realm.Intrinsics.Number.PrototypeObject.ToFractionBase(0.375, 5));
+            Assert.Equal("011", NumberPrototype.ToFractionBase(0.375, 2));
+            Assert.Equal("14141414141414141414141414141414141414141414141414", NumberPrototype.ToFractionBase(0.375, 5));
         }
 
         [Fact]
@@ -910,7 +911,7 @@ namespace Jint.Tests.Runtime
         [InlineData("2qgpckvng1s", 10000000000000000L, 36)]
         public void ShouldConvertNumbersToDifferentBase(string expected, long number, int radix)
         {
-            var result = _engine.Realm.Intrinsics.Number.PrototypeObject.ToBase(number, radix);
+            var result = NumberPrototype.ToBase(number, radix);
             Assert.Equal(expected, result);
         }
 

+ 2 - 0
Jint/Constraints/TimeConstraint.cs

@@ -3,7 +3,9 @@ using System.Threading;
 
 namespace Jint.Constraints;
 
+#pragma warning disable CA1001
 internal sealed class TimeConstraint : Constraint
+#pragma warning restore CA1001
 {
     private readonly TimeSpan _timeout;
     private CancellationTokenSource? _cts;

+ 1 - 0
Jint/Jint.csproj

@@ -9,6 +9,7 @@
     <ImplicitUsings>enable</ImplicitUsings>
     <Nullable>enable</Nullable>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <AnalysisLevel>latest-Recommended</AnalysisLevel>
   </PropertyGroup>
 
   <PropertyGroup Condition=" '$(TargetFramework)' == 'net6.0' or '$(TargetFramework)' == 'netstandard2.1' ">

+ 2 - 0
Jint/Native/ArrayBuffer/JsArrayBuffer.cs

@@ -37,7 +37,9 @@ namespace Jint.Native.ArrayBuffer
         internal byte[]? ArrayBufferData => _arrayBufferData;
 
         internal bool IsDetachedBuffer => _arrayBufferData is null;
+#pragma warning disable CA1822
         internal bool IsSharedArrayBuffer => false; // TODO SharedArrayBuffer
+#pragma warning restore CA1822
 
         /// <summary>
         /// https://tc39.es/ecma262/#sec-detacharraybuffer

+ 3 - 2
Jint/Native/BigInt/BigIntPrototype.cs

@@ -1,3 +1,4 @@
+using System.Globalization;
 using System.Numerics;
 using Jint.Collections;
 using Jint.Native.Object;
@@ -55,7 +56,7 @@ internal sealed class BigIntPrototype : Prototype
         var x = ThisBigIntValue(thisObject);
         //var numberFormat = (NumberFormat) Construct(_realm.Intrinsics.NumberFormat, new[] {  locales, options });
         // numberFormat.FormatNumeric(x);
-        return x._value.ToString("R");
+        return x._value.ToString("R", CultureInfo.InvariantCulture);
     }
 
     /// <summary>
@@ -103,7 +104,7 @@ internal sealed class BigIntPrototype : Prototype
 
         if (radixMV == 10)
         {
-            return value.ToString("R");
+            return value.ToString("R", CultureInfo.InvariantCulture);
         }
 
         var negative = value < 0;

+ 10 - 9
Jint/Native/Date/DatePrototype.cs

@@ -1,3 +1,4 @@
+using System.Globalization;
 using System.Runtime.CompilerServices;
 using Jint.Collections;
 using Jint.Native.Object;
@@ -775,9 +776,9 @@ namespace Jint.Native.Date
 
             var weekday = _dayNames[WeekDay(tv)];
             var month = _monthNames[MonthFromTime(tv)];
-            var day = DateFromTime(tv).ToString("00");
+            var day = DateFromTime(tv).ToString("00", CultureInfo.InvariantCulture);
             var yv = YearFromTime(tv);
-            var paddedYear = yv.ToString("0000");
+            var paddedYear = yv.ToString("0000", CultureInfo.InvariantCulture);
 
             return $"{weekday}, {day} {month} {paddedYear} {TimeString(tv)}";
         }
@@ -1355,11 +1356,11 @@ namespace Jint.Native.Date
             var month = _monthNames[MonthFromTime(tv)];
 
             var dateFromTime = DateFromTime(tv);
-            var day = System.Math.Max(1, dateFromTime).ToString("00");
+            var day = System.Math.Max(1, dateFromTime).ToString("00", CultureInfo.InvariantCulture);
             var yv = YearFromTime(tv);
             var yearSign = yv < 0 ? "-" : "";
             var year = System.Math.Abs(yv);
-            var paddedYear = year.ToString("0000");
+            var paddedYear = year.ToString("0000", CultureInfo.InvariantCulture);
 
             return weekday + " " + month + " " + day + " " + yearSign + paddedYear;
         }
@@ -1369,9 +1370,9 @@ namespace Jint.Native.Date
         /// </summary>
         private static string TimeString(DatePresentation t)
         {
-            var hour = HourFromTime(t).ToString("00");
-            var minute = MinFromTime(t).ToString("00");
-            var second = SecFromTime(t).ToString("00");
+            var hour = HourFromTime(t).ToString("00", CultureInfo.InvariantCulture);
+            var minute = MinFromTime(t).ToString("00", CultureInfo.InvariantCulture);
+            var second = SecFromTime(t).ToString("00", CultureInfo.InvariantCulture);
 
             return hour + ":" + minute + ":" + second + " GMT";
         }
@@ -1396,8 +1397,8 @@ namespace Jint.Native.Date
                 absOffset = -1 * offset;
             }
 
-            var offsetMin = MinFromTime(absOffset).ToString("00");
-            var offsetHour = HourFromTime(absOffset).ToString("00");
+            var offsetMin = MinFromTime(absOffset).ToString("00", CultureInfo.InvariantCulture);
+            var offsetHour = HourFromTime(absOffset).ToString("00", CultureInfo.InvariantCulture);
 
             var tzName = " (" + _timeSystem.DefaultTimeZone.StandardName + ")";
 

+ 7 - 1
Jint/Native/Date/MimeKit.cs

@@ -180,6 +180,7 @@ internal static class DateUtils
                 any[1] = (char) c;
             }
 
+#pragma warning disable CA2249
             if (NumericZoneCharacters.IndexOf((char) c) == -1)
                 datetok[c] |= DateTokenFlags.NonNumericZone;
             if (AlphaZoneCharacters.IndexOf((char) c) == -1)
@@ -192,6 +193,7 @@ internal static class DateUtils
                 datetok[c] |= DateTokenFlags.NonMonth;
             if (TimeCharacters.IndexOf((char) c) == -1)
                 datetok[c] |= DateTokenFlags.NonTime;
+#pragma warning restore CA2249
         }
 
         datetok[':'] |= DateTokenFlags.HasColon;
@@ -518,7 +520,9 @@ internal static class DateUtils
                 int endIndex = tokens[i].Start + tokens[i].Length;
                 int index = tokens[i].Start;
 
+#pragma warning disable CA1806
                 ParseUtils.TryParseInt32(text, ref index, endIndex, out value);
+#pragma warning restore CA1806
 
                 if (month == null && value > 0 && value <= 12)
                 {
@@ -727,7 +731,9 @@ internal static class ParseUtils
             if (!SkipComment(text, ref index, endIndex))
             {
                 if (throwOnError)
-                    throw new Exception($"Incomplete comment token at offset {startIndex}");
+                {
+                    throw new ArgumentException($"Incomplete comment token at offset {startIndex}");
+                }
 
                 return false;
             }

+ 1 - 1
Jint/Native/FinalizationRegistry/FinalizationRegistryInstance.cs

@@ -19,7 +19,7 @@ internal sealed class FinalizationRegistryInstance : ObjectInstance
         _callable = engine._host.MakeJobCallBack(cleanupCallback);
     }
 
-    public void CleanupFinalizationRegistry(ICallable? callback)
+    public static void CleanupFinalizationRegistry(ICallable? callback)
     {
     }
 

+ 1 - 1
Jint/Native/FinalizationRegistry/FinalizationRegistryPrototype.cs

@@ -98,7 +98,7 @@ internal sealed class FinalizationRegistryPrototype : Prototype
             ExceptionHelper.ThrowTypeError(_realm, callback + " must be callable");
         }
 
-        finalizationRegistry.CleanupFinalizationRegistry(callback as ICallable);
+        FinalizationRegistryInstance.CleanupFinalizationRegistry(callback as ICallable);
 
         return Undefined;
     }

+ 1 - 1
Jint/Native/Function/ClassDefinition.cs

@@ -276,7 +276,7 @@ internal sealed class ClassDefinition
 
     private sealed class ClassFieldFunction : Node, IFunction
     {
-        private readonly NodeList<Node> _nodeList = new();
+        private readonly NodeList<Node> _nodeList;
         private readonly BlockStatement _statement;
 
         public ClassFieldFunction(Expression expression) : base(Nodes.ExpressionStatement)

+ 2 - 2
Jint/Native/Function/ScriptFunctionInstance.cs

@@ -57,7 +57,7 @@ namespace Jint.Native.Function
         /// <summary>
         /// https://tc39.es/ecma262/#sec-ecmascript-function-objects-call-thisargument-argumentslist
         /// </summary>
-        protected internal override JsValue Call(JsValue thisArgument, JsValue[] arguments)
+        protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
             var strict = _functionDefinition.Strict || _thisMode == FunctionThisMode.Strict;
             using (new StrictModeScope(strict, true))
@@ -71,7 +71,7 @@ namespace Jint.Native.Function
                         ExceptionHelper.ThrowTypeError(calleeContext.Realm, $"Class constructor {_functionDefinition.Name} cannot be invoked without 'new'");
                     }
 
-                    OrdinaryCallBindThis(calleeContext, thisArgument);
+                    OrdinaryCallBindThis(calleeContext, thisObject);
 
                     // actual call
                     var context = _engine._activeEvaluationContext ?? new EvaluationContext(_engine);

+ 15 - 15
Jint/Native/Global/GlobalObject.cs

@@ -138,7 +138,7 @@ namespace Jint.Native.Global
                 if (trimmedString[0] == '-')
                 {
                     i++;
-                    if (trimmedString.Length > 1 && trimmedString[1] == 'I' && trimmedString.StartsWith("-Infinity"))
+                    if (trimmedString.Length > 1 && trimmedString[1] == 'I' && trimmedString.StartsWith("-Infinity", StringComparison.Ordinal))
                     {
                         return JsNumber.DoubleNegativeInfinity;
                     }
@@ -147,18 +147,18 @@ namespace Jint.Native.Global
                 if (trimmedString[0] == '+')
                 {
                     i++;
-                    if (trimmedString.Length > 1 && trimmedString[1] == 'I' && trimmedString.StartsWith("+Infinity"))
+                    if (trimmedString.Length > 1 && trimmedString[1] == 'I' && trimmedString.StartsWith("+Infinity", StringComparison.Ordinal))
                     {
                         return JsNumber.DoublePositiveInfinity;
                     }
                 }
 
-                if (trimmedString.StartsWith("Infinity"))
+                if (trimmedString.StartsWith("Infinity", StringComparison.Ordinal))
                 {
                     return JsNumber.DoublePositiveInfinity;
                 }
 
-                if (trimmedString.StartsWith("NaN"))
+                if (trimmedString.StartsWith("NaN", StringComparison.Ordinal))
                 {
                     return JsNumber.DoubleNaN;
                 }
@@ -462,7 +462,9 @@ uriError:
                     if ((B & 0x80) == 0)
                     {
                         C = (char)B;
+#pragma warning disable CA2249
                         if (reservedSet == null || reservedSet.IndexOf(C) == -1)
+#pragma warning restore CA2249
                         {
                             _stringBuilder.Append(C);
                         }
@@ -590,7 +592,7 @@ uriError:
         /// </summary>
         public JsValue Escape(JsValue thisObject, JsValue[] arguments)
         {
-            const string whiteList = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@*_ + -./";
+            const string WhiteList = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@*_ + -./";
             var uriString = TypeConverter.ToString(arguments.At(0));
 
             var strLen = uriString.Length;
@@ -601,17 +603,17 @@ uriError:
             for (var k = 0; k < strLen; k++)
             {
                 var c = uriString[k];
-                if (whiteList.IndexOf(c) != -1)
+                if (WhiteList.IndexOf(c) != -1)
                 {
                     _stringBuilder.Append(c);
                 }
                 else if (c < 256)
                 {
-                    _stringBuilder.Append($"%{((int) c):X2}");
+                    _stringBuilder.Append('%').AppendFormat(CultureInfo.InvariantCulture, "{0:X2}", (int) c);
                 }
                 else
                 {
-                    _stringBuilder.Append($"%u{((int) c):X4}");
+                    _stringBuilder.Append("%u").AppendFormat(CultureInfo.InvariantCulture, "{0:X4}", (int) c);
                 }
             }
 
@@ -639,18 +641,16 @@ uriError:
                         && uriString[k + 1] == 'u'
                         && uriString.Skip(k + 2).Take(4).All(IsValidHexaChar))
                     {
-                        c = (char)int.Parse(
-                            string.Join(string.Empty, uriString.Skip(k + 2).Take(4)),
-                            NumberStyles.AllowHexSpecifier);
+                        var joined = string.Join(string.Empty, uriString.Skip(k + 2).Take(4));
+                        c = (char) int.Parse(joined, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture);
 
                         k += 5;
                     }
                     else if (k <= strLen - 3
-                        && uriString.Skip(k + 1).Take(2).All(IsValidHexaChar))
+                             && uriString.Skip(k + 1).Take(2).All(IsValidHexaChar))
                     {
-                        c = (char)int.Parse(
-                            string.Join(string.Empty, uriString.Skip(k + 1).Take(2)),
-                            NumberStyles.AllowHexSpecifier);
+                        var joined = string.Join(string.Empty, uriString.Skip(k + 1).Take(2));
+                        c = (char) int.Parse(joined, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture);
 
                         k += 2;
                     }

+ 1 - 1
Jint/Native/Intl/DateTimeFormatConstructor.cs

@@ -48,7 +48,7 @@ internal sealed class DateTimeFormatConstructor : Constructor
     /// <summary>
     /// https://tc39.es/ecma402/#sec-initializedatetimeformat
     /// </summary>
-    private void InitializeDateTimeFormat(JsObject dateTimeFormat, JsValue locales, JsValue options)
+    private static void InitializeDateTimeFormat(JsObject dateTimeFormat, JsValue locales, JsValue options)
     {
         // TODO
     }

+ 3 - 3
Jint/Native/Intl/NumberFormatConstructor.cs

@@ -201,7 +201,7 @@ internal sealed class NumberFormatConstructor : Constructor
     /// <summary>
     /// https://tc39.es/ecma402/#sec-iswellformedunitidentifier
     /// </summary>
-    private bool IsWellFormedUnitIdentifier(JsValue unitIdentifier)
+    private static bool IsWellFormedUnitIdentifier(JsValue unitIdentifier)
     {
         var value = unitIdentifier.ToString();
         if (IsSanctionedSingleUnitIdentifier(value))
@@ -209,8 +209,8 @@ internal sealed class NumberFormatConstructor : Constructor
             return true;
         }
 
-        var i = value.IndexOf("-per-");
-        if (i == -1 || value.IndexOf("-per-", i + 1) != -1)
+        var i = value.IndexOf("-per-", StringComparison.Ordinal);
+        if (i == -1 || value.IndexOf("-per-", i + 1, StringComparison.Ordinal) != -1)
         {
             return false;
         }

+ 1 - 1
Jint/Native/Intl/PluralRulesConstructor.cs

@@ -48,7 +48,7 @@ internal sealed class PluralRulesConstructor : Constructor
     /// <summary>
     /// https://tc39.es/ecma402/#sec-initializepluralrules
     /// </summary>
-    private void InitializePluralRules(JsObject pluralRules, JsValue locales, JsValue options)
+    private static void InitializePluralRules(JsObject pluralRules, JsValue locales, JsValue options)
     {
         // TODO
     }

+ 1 - 1
Jint/Native/Intl/RelativeTimeFormatConstructor.cs

@@ -48,7 +48,7 @@ internal sealed class RelativeTimeFormatConstructor : Constructor
     /// <summary>
     /// https://tc39.es/ecma402/#sec-InitializeRelativeTimeFormat
     /// </summary>
-    private void InitializeRelativeTimeFormat(JsObject relativeTimeFormat, JsValue locales, JsValue options)
+    private static void InitializeRelativeTimeFormat(JsObject relativeTimeFormat, JsValue locales, JsValue options)
     {
         // TODO
     }

+ 3 - 12
Jint/Native/JsBigInt.cs

@@ -95,15 +95,9 @@ public sealed class JsBigInt : JsValue, IEquatable<JsBigInt>
         return false;
     }
 
-    public override bool Equals(object? other)
-    {
-        return Equals(other as JsBigInt);
-    }
+    public override bool Equals(object? obj) => Equals(obj as JsBigInt);
 
-    public override bool Equals(JsValue? other)
-    {
-        return Equals(other as JsBigInt);
-    }
+    public override bool Equals(JsValue? other) => Equals(other as JsBigInt);
 
     public bool Equals(JsBigInt? other)
     {
@@ -115,8 +109,5 @@ public sealed class JsBigInt : JsValue, IEquatable<JsBigInt>
         return ReferenceEquals(this, other) || _value == other._value;
     }
 
-    public override int GetHashCode()
-    {
-        return _value.GetHashCode();
-    }
+    public override int GetHashCode() => _value.GetHashCode();
 }

+ 6 - 1
Jint/Native/JsBoolean.cs

@@ -38,11 +38,16 @@ public sealed class JsBoolean : JsValue, IEquatable<JsBoolean>
         return !value.IsNullOrUndefined() && base.IsLooselyEqual(value);
     }
 
-    public override bool Equals(JsValue? obj)
+    public override bool Equals(object? obj)
     {
         return Equals(obj as JsBoolean);
     }
 
+    public override bool Equals(JsValue? other)
+    {
+        return Equals(other as JsBoolean);
+    }
+
     public bool Equals(JsBoolean? other)
     {
         if (ReferenceEquals(this, other))

+ 7 - 8
Jint/Native/JsNull.cs

@@ -1,3 +1,4 @@
+using System.Runtime.CompilerServices;
 using Jint.Runtime;
 
 namespace Jint.Native;
@@ -17,13 +18,11 @@ public sealed class JsNull : JsValue, IEquatable<JsNull>
         return ReferenceEquals(Null, value) || ReferenceEquals(Undefined, value);
     }
 
-    public override bool Equals(JsValue? obj)
-    {
-        return Equals(obj as JsNull);
-    }
+    public override bool Equals(object? obj) => Equals(obj as JsNull);
 
-    public bool Equals(JsNull? other)
-    {
-        return other is not null;
-    }
+    public override bool Equals(JsValue? other) => Equals(other as JsNull);
+
+    public bool Equals(JsNull? other) => other is not null;
+
+    public override int GetHashCode() => RuntimeHelpers.GetHashCode(this);
 }

+ 9 - 12
Jint/Native/JsNumber.cs

@@ -1,4 +1,5 @@
 using System.Diagnostics;
+using System.Globalization;
 using System.Numerics;
 using System.Runtime.CompilerServices;
 using Jint.Native.Number;
@@ -90,10 +91,10 @@ public sealed class JsNumber : JsValue, IEquatable<JsNumber>
         var underlyingType = System.Type.GetTypeCode(Enum.GetUnderlyingType(value.GetType()));
         return underlyingType switch
         {
-            TypeCode.Int64 => Create(Convert.ToInt64(value)),
-            TypeCode.UInt32 => Create(Convert.ToUInt64(value)),
-            TypeCode.UInt64 => Create(Convert.ToUInt64(value)),
-            _ => Create(Convert.ToInt32(value))
+            TypeCode.Int64 => Create(Convert.ToInt64(value, CultureInfo.InvariantCulture)),
+            TypeCode.UInt32 => Create(Convert.ToUInt64(value, CultureInfo.InvariantCulture)),
+            TypeCode.UInt64 => Create(Convert.ToUInt64(value, CultureInfo.InvariantCulture)),
+            _ => Create(Convert.ToInt32(value, CultureInfo.InvariantCulture))
         };
     }
 
@@ -265,10 +266,9 @@ public sealed class JsNumber : JsValue, IEquatable<JsNumber>
         return base.IsLooselyEqual(value);
     }
 
-    public override bool Equals(JsValue? obj)
-    {
-        return Equals(obj as JsNumber);
-    }
+    public override bool Equals(object? obj) => Equals(obj as JsNumber);
+
+    public override bool Equals(JsValue? other) => Equals(other as JsNumber);
 
     public bool Equals(JsNumber? other)
     {
@@ -290,8 +290,5 @@ public sealed class JsNumber : JsValue, IEquatable<JsNumber>
         return _value == other._value;
     }
 
-    public override int GetHashCode()
-    {
-        return _value.GetHashCode();
-    }
+    public override int GetHashCode() => _value.GetHashCode();
 }

+ 6 - 21
Jint/Native/JsString.cs

@@ -286,15 +286,11 @@ public class JsString : JsValue, IEquatable<JsString>, IEquatable<string>
         return ToString().Substring(startIndex);
     }
 
-    public sealed override bool Equals(JsValue? obj)
-    {
-        return Equals(obj as JsString);
-    }
+    public sealed override bool Equals(object? obj) => Equals(obj as JsString);
 
-    public virtual bool Equals(string? s)
-    {
-        return s != null && ToString() == s;
-    }
+    public sealed override bool Equals(JsValue? other) => Equals(other as JsString);
+
+    public virtual bool Equals(string? other) => other != null && ToString() == other;
 
     public virtual bool Equals(JsString? other)
     {
@@ -326,15 +322,7 @@ public class JsString : JsValue, IEquatable<JsString>, IEquatable<string>
         return base.IsLooselyEqual(value);
     }
 
-    public sealed override bool Equals(object? obj)
-    {
-        return Equals(obj as JsString);
-    }
-
-    public override int GetHashCode()
-    {
-        return _value.GetHashCode();
-    }
+    public override int GetHashCode() => _value.GetHashCode();
 
     internal sealed class ConcatenatedString : JsString
     {
@@ -445,10 +433,7 @@ public class JsString : JsValue, IEquatable<JsString>, IEquatable<string>
             return ToString() == other.ToString();
         }
 
-        public override int GetHashCode()
-        {
-            return _stringBuilder?.GetHashCode() ?? _value.GetHashCode();
-        }
+        public override int GetHashCode() => _stringBuilder?.GetHashCode() ?? _value.GetHashCode();
 
         internal override JsValue DoClone()
         {

+ 5 - 12
Jint/Native/JsSymbol.cs

@@ -27,18 +27,11 @@ public sealed class JsSymbol : JsValue, IEquatable<JsSymbol>
         return "Symbol(" + value + ")";
     }
 
-    public override bool Equals(JsValue? obj)
-    {
-        return Equals(obj as JsSymbol);
-    }
+    public override bool Equals(object? obj) => Equals(obj as JsSymbol);
 
-    public bool Equals(JsSymbol? other)
-    {
-        return ReferenceEquals(this, other);
-    }
+    public override bool Equals(JsValue? other) => Equals(other as JsSymbol);
 
-    public override int GetHashCode()
-    {
-        return RuntimeHelpers.GetHashCode(this);
-    }
+    public bool Equals(JsSymbol? other) => ReferenceEquals(this, other);
+
+    public override int GetHashCode() => RuntimeHelpers.GetHashCode(this);
 }

+ 7 - 8
Jint/Native/JsUndefined.cs

@@ -1,3 +1,4 @@
+using System.Runtime.CompilerServices;
 using Jint.Runtime;
 
 namespace Jint.Native;
@@ -17,13 +18,11 @@ public sealed class JsUndefined : JsValue, IEquatable<JsUndefined>
         return ReferenceEquals(Undefined, value) || ReferenceEquals(Null, value);
     }
 
-    public override bool Equals(JsValue? obj)
-    {
-        return Equals(obj as JsUndefined);
-    }
+    public override bool Equals(object? obj) => Equals(obj as JsUndefined);
 
-    public bool Equals(JsUndefined? other)
-    {
-        return !ReferenceEquals(null, other);
-    }
+    public override bool Equals(JsValue? other) => Equals(other as JsUndefined);
+
+    public bool Equals(JsUndefined? other) => !ReferenceEquals(null, other);
+
+    public override int GetHashCode() => RuntimeHelpers.GetHashCode(this);
 }

+ 3 - 12
Jint/Native/JsValue.cs

@@ -350,23 +350,14 @@ namespace Jint.Native
         /// <summary>
         /// Strict equality.
         /// </summary>
-        public override bool Equals(object? obj)
-        {
-            return Equals(obj as JsValue);
-        }
+        public override bool Equals(object? obj) => Equals(obj as JsValue);
 
         /// <summary>
         /// Strict equality.
         /// </summary>
-        public virtual bool Equals(JsValue? other)
-        {
-            return ReferenceEquals(this, other);
-        }
+        public virtual bool Equals(JsValue? other) => ReferenceEquals(this, other);
 
-        public override int GetHashCode()
-        {
-            return _type.GetHashCode();
-        }
+        public override int GetHashCode() => _type.GetHashCode();
 
         /// <summary>
         /// Some values need to be cloned in order to be assigned, like ConcatenatedString.

+ 2 - 2
Jint/Native/Json/JsonParser.cs

@@ -460,7 +460,7 @@ namespace Jint.Native.Json
         [DoesNotReturn]
         private void ThrowError(int position, string messageFormat, params object[] arguments)
         {
-            string msg = System.String.Format(messageFormat, arguments);
+            var msg = string.Format(CultureInfo.InvariantCulture, messageFormat, arguments);
             ExceptionHelper.ThrowSyntaxError(_engine.Realm, $"{msg} at position {position}");
         }
 
@@ -756,7 +756,7 @@ namespace Jint.Native.Json
             public char FirstCharacter;
             public JsValue Value = JsValue.Undefined;
             public string Text = null!;
-            public TextRange Range = default;
+            public TextRange Range;
         }
 
         private readonly struct TextRange

+ 2 - 1
Jint/Native/Json/JsonSerializer.cs

@@ -1,3 +1,4 @@
+using System.Globalization;
 using System.Runtime.CompilerServices;
 using System.Text;
 using Jint.Collections;
@@ -398,7 +399,7 @@ namespace Jint.Native.Json
                     else if (c < 0x20 || char.IsSurrogate(c))
                     {
                         target.Append("\\u");
-                        target.Append(((int) c).ToString("x4"));
+                        target.Append(((int) c).ToString("x4", CultureInfo.InvariantCulture));
                     }
                     else
                     {

+ 9 - 9
Jint/Native/Number/Dtoa/Bignum.cs

@@ -108,7 +108,7 @@ namespace Jint.Native.Number.Dtoa
                 // We replace some of the hidden digits (X) of a with 0 digits.
                 // a:  aaaaaa000X   or a:   aaaaa0XX
                 int zero_digits = exponent_ - other.exponent_;
-                EnsureCapacity(used_digits_ + zero_digits);
+                ValidateCapacity(used_digits_ + zero_digits);
                 for (int i = used_digits_ - 1; i >= 0; --i)
                 {
                     bigits_[i + zero_digits] = bigits_[i];
@@ -126,7 +126,7 @@ namespace Jint.Native.Number.Dtoa
             }
         }
 
-        void EnsureCapacity(int size)
+        private static void ValidateCapacity(int size)
         {
             if (size > kBigitCapacity)
             {
@@ -161,7 +161,7 @@ namespace Jint.Native.Number.Dtoa
             Zero();
             if (value == 0) return;
 
-            EnsureCapacity(1);
+            ValidateCapacity(1);
             bigits_[0] = value;
             used_digits_ = 1;
         }
@@ -174,7 +174,7 @@ namespace Jint.Native.Number.Dtoa
             if (value == 0) return;
 
             int needed_bigits = kUInt64Size / kBigitSize + 1;
-            EnsureCapacity(needed_bigits);
+            ValidateCapacity(needed_bigits);
             for (int i = 0; i < needed_bigits; ++i)
             {
                 bigits_[i] = (uint) (value & kBigitMask);
@@ -419,7 +419,7 @@ namespace Jint.Native.Number.Dtoa
 
             while (carry != 0)
             {
-                EnsureCapacity(used_digits_ + 1);
+                ValidateCapacity(used_digits_ + 1);
                 bigits_[used_digits_] = (uint) (carry & kBigitMask);
                 used_digits_++;
                 carry >>= kBigitSize;
@@ -449,7 +449,7 @@ namespace Jint.Native.Number.Dtoa
             }
             while (carry != 0)
             {
-                EnsureCapacity(used_digits_ + 1);
+                ValidateCapacity(used_digits_ + 1);
                 bigits_[used_digits_] = (uint) (carry & kBigitMask);
                 used_digits_++;
                 carry >>= kBigitSize;
@@ -461,7 +461,7 @@ namespace Jint.Native.Number.Dtoa
             if (used_digits_ == 0) return;
             exponent_ += shift_amount / kBigitSize;
             int local_shift = shift_amount % kBigitSize;
-            EnsureCapacity(used_digits_ + 1);
+            ValidateCapacity(used_digits_ + 1);
             BigitsShiftLeft(local_shift);
         }
 
@@ -516,7 +516,7 @@ namespace Jint.Native.Number.Dtoa
 
             int final_size = bit_size * power_exponent;
             // 1 extra bigit for the shifting, and one for rounded final_size.
-            EnsureCapacity(final_size / kBigitSize + 2);
+            ValidateCapacity(final_size / kBigitSize + 2);
 
             // Left to Right exponentiation.
             int mask = 1;
@@ -578,7 +578,7 @@ namespace Jint.Native.Number.Dtoa
         {
             Debug.Assert(IsClamped());
             int product_length = 2 * used_digits_;
-            EnsureCapacity(product_length);
+            ValidateCapacity(product_length);
 
             // Comba multiplication: compute each column separately.
             // Example: r = a2a1a0 * b2b1b0.

+ 23 - 27
Jint/Native/Number/NumberPrototype.cs

@@ -303,7 +303,7 @@ namespace Jint.Native.Number
             }
         }
 
-        private string CreateExponentialRepresentation(
+        private static string CreateExponentialRepresentation(
             DtoaBuilder buffer,
             int exponent,
             bool negative,
@@ -384,63 +384,59 @@ namespace Jint.Native.Number
             var integer = (long) x;
             var fraction = x -  integer;
 
-            string result = ToBase(integer, radix);
+            string result = NumberPrototype.ToBase(integer, radix);
             if (fraction != 0)
             {
-                result += "." + ToFractionBase(fraction, radix);
+                result += "." + NumberPrototype.ToFractionBase(fraction, radix);
             }
 
             return result;
         }
 
-        public string ToBase(long n, int radix)
+        internal static string ToBase(long n, int radix)
         {
-            const string digits = "0123456789abcdefghijklmnopqrstuvwxyz";
+            const string Digits = "0123456789abcdefghijklmnopqrstuvwxyz";
             if (n == 0)
             {
                 return "0";
             }
 
-            using (var result = StringBuilderPool.Rent())
+            using var result = StringBuilderPool.Rent();
+            while (n > 0)
             {
-                while (n > 0)
-                {
-                    var digit = (int) (n % radix);
-                    n = n / radix;
-                    result.Builder.Insert(0, digits[digit]);
-                }
-
-                return result.ToString();
+                var digit = (int) (n % radix);
+                n = n / radix;
+                result.Builder.Insert(0, Digits[digit]);
             }
+
+            return result.ToString();
         }
 
-        public string ToFractionBase(double n, int radix)
+        internal static string ToFractionBase(double n, int radix)
         {
             // based on the repeated multiplication method
             // http://www.mathpath.org/concepts/Num/frac.htm
 
-            const string digits = "0123456789abcdefghijklmnopqrstuvwxyz";
+            const string Digits = "0123456789abcdefghijklmnopqrstuvwxyz";
             if (n == 0)
             {
                 return "0";
             }
 
-            using (var result = StringBuilderPool.Rent())
+            using var result = StringBuilderPool.Rent();
+            while (n > 0 && result.Length < 50) // arbitrary limit
             {
-                while (n > 0 && result.Length < 50) // arbitrary limit
-                {
-                    var c = n*radix;
-                    var d = (int) c;
-                    n = c - d;
-
-                    result.Builder.Append(digits[d]);
-                }
+                var c = n*radix;
+                var d = (int) c;
+                n = c - d;
 
-                return result.ToString();
+                result.Builder.Append(Digits[d]);
             }
+
+            return result.ToString();
         }
 
-        private string ToNumberString(double m)
+        private static string ToNumberString(double m)
         {
             using var stringBuilder = StringBuilderPool.Rent();
             NumberToString(m, new DtoaBuilder(), stringBuilder.Builder);

+ 6 - 5
Jint/Native/Object/ObjectInstance.cs

@@ -1073,7 +1073,7 @@ namespace Jint.Native.Object
                             TypedArrayElementType.Uint16 => typedArrayInstance.ToNativeArray<ushort>(),
                             TypedArrayElementType.Uint32 => typedArrayInstance.ToNativeArray<uint>(),
                             TypedArrayElementType.BigUint64 => typedArrayInstance.ToNativeArray<ulong>(),
-                            _ => throw new ArgumentOutOfRangeException()
+                            _ => throw new ArgumentOutOfRangeException("", "cannot handle element type")
                         };
 
                         break;
@@ -1475,10 +1475,9 @@ namespace Jint.Native.Object
             ExceptionHelper.ThrowTypeError(_engine.Realm, $"Method {methodName} called on incompatible receiver {value}");
         }
 
-        public override bool Equals(JsValue? obj)
-        {
-            return Equals(obj as ObjectInstance);
-        }
+        public override bool Equals(object? obj) => Equals(obj as ObjectInstance);
+
+        public override bool Equals(JsValue? other) => Equals(other as ObjectInstance);
 
         public bool Equals(ObjectInstance? other)
         {
@@ -1495,6 +1494,8 @@ namespace Jint.Native.Object
             return false;
         }
 
+        public override int GetHashCode() => RuntimeHelpers.GetHashCode(this);
+
         internal IEnumerable<JsValue> GetKeys()
         {
             var visited = new HashSet<JsValue>();

+ 1 - 1
Jint/Native/Promise/PromiseOperations.cs

@@ -58,7 +58,7 @@ namespace Jint.Native.Promise
                             break;
 
                         default:
-                            throw new ArgumentOutOfRangeException();
+                            throw new ArgumentOutOfRangeException(nameof(reaction), "Unknown reaction type");
                     }
                 }
             };

+ 1 - 1
Jint/Native/Proxy/JsProxy.cs

@@ -288,7 +288,7 @@ namespace Jint.Native.Proxy
         /// <summary>
         /// https://tc39.es/ecma262/#sec-completepropertydescriptor
         /// </summary>
-        private void CompletePropertyDescriptor(PropertyDescriptor desc)
+        private static void CompletePropertyDescriptor(PropertyDescriptor desc)
         {
             if (desc.IsGenericDescriptor() || desc.IsDataDescriptor())
             {

+ 6 - 0
Jint/Native/RegExp/RegExpPrototype.cs

@@ -286,9 +286,11 @@ namespace Jint.Native.RegExp
 
                 if (position >= nextSourcePosition)
                 {
+#pragma warning disable CA1845
                     accumulatedResult = accumulatedResult +
                                         s.Substring(nextSourcePosition, position - nextSourcePosition) +
                                         replacement;
+#pragma warning restore CA1845
 
                     nextSourcePosition = position + matchLength;
                 }
@@ -299,7 +301,9 @@ namespace Jint.Native.RegExp
                 return accumulatedResult;
             }
 
+#pragma warning disable CA1845
             return accumulatedResult + s.Substring(nextSourcePosition);
+#pragma warning restore CA1845
         }
 
         private static string CallFunctionalReplace(JsValue replacer, List<JsValue> replacerArgs)
@@ -347,12 +351,14 @@ namespace Jint.Native.RegExp
                         case '&':
                             sb.Append(matched);
                             break;
+#pragma warning disable CA1846
                         case '`':
                             sb.Append(str.Substring(0, position));
                             break;
                         case '\'':
                             sb.Append(str.Substring(position + matched.Length));
                             break;
+#pragma warning restore CA1846
                         case '<':
                             var gtPos = replacement.IndexOf('>', i + 1);
                             if (gtPos == -1 || namedCaptures.IsUndefined())

+ 9 - 3
Jint/Native/String/StringPrototype.cs

@@ -1,3 +1,4 @@
+using System.Globalization;
 using System.Runtime.CompilerServices;
 using System.Text;
 using Jint.Collections;
@@ -228,7 +229,7 @@ namespace Jint.Native.String
         {
             TypeConverter.CheckObjectCoercible(_engine, thisObject);
             var s = TypeConverter.ToString(thisObject);
-            return new JsString(s.ToUpper());
+            return new JsString(s.ToUpper(CultureInfo.InvariantCulture));
         }
 
         private JsValue ToUpperCase(JsValue thisObject, JsValue[] arguments)
@@ -242,7 +243,7 @@ namespace Jint.Native.String
         {
             TypeConverter.CheckObjectCoercible(_engine, thisObject);
             var s = TypeConverter.ToString(thisObject);
-            return new JsString(s.ToLower());
+            return new JsString(s.ToLower(CultureInfo.InvariantCulture));
         }
 
         private JsValue ToLowerCase(JsValue thisObject, JsValue[] arguments)
@@ -666,7 +667,11 @@ namespace Jint.Native.String
 
             if (endOfLastMatch < thisString.Length)
             {
+#if NETFRAMEWORK
                 result.Append(thisString.Substring(endOfLastMatch));
+#else
+                result.Append(thisString[endOfLastMatch..]);
+#endif
             }
 
             return result.ToString();
@@ -1168,7 +1173,8 @@ namespace Jint.Native.String
                 var cp = CodePointAt(s, k);
                 if (cp.IsUnpairedSurrogate)
                 {
-                    result.Append("\uFFFD");
+                    // \uFFFD
+                    result.Append('�');
                 }
                 else
                 {

+ 2 - 1
Jint/Native/TypedArray/JsTypedArray.cs

@@ -1,3 +1,4 @@
+using System.Globalization;
 using System.Runtime.CompilerServices;
 using Esprima;
 using Jint.Native.ArrayBuffer;
@@ -376,7 +377,7 @@ namespace Jint.Native.TypedArray
             {
                 var indexedPosition = i * elementSize + byteOffset;
                 var value = buffer.RawBytesToNumeric(_arrayElementType, indexedPosition, BitConverter.IsLittleEndian);
-                array[i] = (T) Convert.ChangeType(value, conversionType);
+                array[i] = (T) Convert.ChangeType(value, conversionType, CultureInfo.InvariantCulture);
             }
 
             return array;

+ 2 - 1
Jint/Native/TypedArray/TypedArrayConstructor.cs

@@ -1,3 +1,4 @@
+using System.Globalization;
 using Jint.Collections;
 using Jint.Native.Array;
 using Jint.Native.ArrayBuffer;
@@ -271,7 +272,7 @@ namespace Jint.Native.TypedArray
         {
             for (var i = 0; i < values.Length; ++i)
             {
-                target.DoIntegerIndexedElementSet(i, Convert.ToDouble(values[i]));
+                target.DoIntegerIndexedElementSet(i, Convert.ToDouble(values[i], CultureInfo.InvariantCulture));
             }
         }
 

+ 2 - 2
Jint/Options.cs

@@ -201,7 +201,7 @@ namespace Jint
                 // make sure we register both lower case and upper case
                 if (char.IsUpper(overloads.Key[0]))
                 {
-                    key = char.ToLower(overloads.Key[0]) + overloads.Key.Substring(1);
+                    key = char.ToLower(overloads.Key[0], CultureInfo.InvariantCulture) + overloads.Key.Substring(1);
 
                     if (prototype.HasOwnProperty(key) &&
                         prototype.GetOwnProperty(key).Value is ClrFunctionInstance lowerclrFunctionInstance)
@@ -281,7 +281,7 @@ namespace Jint
         /// memory usage to grow when targeting large set and freeing of memory can be delayed due to ConditionalWeakTable semantics.
         /// Defaults to false.
         /// </summary>
-        public bool TrackObjectWrapperIdentity { get; set; } = false;
+        public bool TrackObjectWrapperIdentity { get; set; }
 
         /// <summary>
         /// If no known type could be guessed, objects are by default wrapped as an

+ 2 - 0
Jint/Pooling/ConcurrentObjectPool.cs

@@ -1,3 +1,5 @@
+#pragma warning disable CA1822
+
 #nullable disable
 
 // Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

+ 2 - 0
Jint/Pooling/ObjectPool.cs

@@ -1,3 +1,5 @@
+#pragma warning disable CA1822
+
 #nullable disable
 
 // Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

+ 7 - 5
Jint/Runtime/CallStack/JintCallStack.cs

@@ -62,7 +62,9 @@ namespace Jint.Runtime.CallStack
             _stack.Push(item);
             if (_statistics is not null)
             {
+#pragma warning disable CA1854
                 if (_statistics.ContainsKey(item))
+#pragma warning restore CA1854
                 {
                     return ++_statistics[item];
                 }
@@ -126,7 +128,7 @@ namespace Jint.Runtime.CallStack
                 if (!string.IsNullOrWhiteSpace(shortDescription))
                 {
                     sb
-                        .Append(" ")
+                        .Append(' ')
                         .Append(shortDescription);
                 }
 
@@ -144,15 +146,15 @@ namespace Jint.Runtime.CallStack
                         var arg = element.Value.Arguments.Value[index];
                         sb.Append(GetPropertyKey(arg));
                     }
-                    sb.Append(")");
+                    sb.Append(')');
                 }
 
                 sb
-                    .Append(" ")
+                    .Append(' ')
                     .Append(loc.Source)
-                    .Append(":")
+                    .Append(':')
                     .Append(loc.End.Line)
-                    .Append(":")
+                    .Append(':')
                     .Append(loc.Start.Column + 1) // report column number instead of index
                     .AppendLine();
             }

+ 2 - 2
Jint/Runtime/CallStack/StackGuard.cs

@@ -50,7 +50,7 @@ internal sealed class StackGuard
         return false;
     }
 
-    public TR RunOnEmptyStack<T1, TR>(Func<T1, TR> action, T1 arg1)
+    public static TR RunOnEmptyStack<T1, TR>(Func<T1, TR> action, T1 arg1)
     {
 #if NETFRAMEWORK || NETSTANDARD2_0
         return RunOnEmptyStackCore(static s =>
@@ -69,7 +69,7 @@ internal sealed class StackGuard
 
     }
 
-    private R RunOnEmptyStackCore<R>(Func<object, R> action, object state)
+    private static R RunOnEmptyStackCore<R>(Func<object, R> action, object state)
     {
         // Using default scheduler rather than picking up the current scheduler.
         Task<R> task = Task.Factory.StartNew((Func<object?, R>) action, state, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);

+ 0 - 2
Jint/Runtime/Debugger/BreakPointCollection.cs

@@ -25,8 +25,6 @@ namespace Jint.Runtime.Debugger
 
         public int Count => _breakPoints.Count;
 
-        public bool IsReadOnly => false;
-
         /// <summary>
         /// Sets a new breakpoint. Note that this will replace any breakpoint at the same location (source/column/line).
         /// </summary>

+ 2 - 0
Jint/Runtime/DefaultTimeSystem.cs

@@ -137,7 +137,9 @@ public class DefaultTimeSystem : ITimeSystem
         }
 
         // create replacement string
+#pragma warning disable CA1845
         var dateToParse = "2000" + date.Substring(7);
+#pragma warning restore CA1845
         if (!DateTime.TryParse(dateToParse, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out var parsed))
         {
             return false;

+ 5 - 1
Jint/Runtime/Interop/ClrFunctionInstance.cs

@@ -57,7 +57,9 @@ public sealed class ClrFunctionInstance : FunctionInstance, IEquatable<ClrFuncti
         }
     }
 
-    public override bool Equals(JsValue? obj) => Equals(obj as ClrFunctionInstance);
+    public override bool Equals(JsValue? other) => Equals(other as ClrFunctionInstance);
+
+    public override bool Equals(object? obj) => Equals(obj as ClrFunctionInstance);
 
     public bool Equals(ClrFunctionInstance? other)
     {
@@ -78,4 +80,6 @@ public sealed class ClrFunctionInstance : FunctionInstance, IEquatable<ClrFuncti
 
         return false;
     }
+
+    public override int GetHashCode() => _func.GetHashCode();
 }

+ 7 - 1
Jint/Runtime/Interop/ClrHelper.cs

@@ -14,7 +14,9 @@ public class ClrHelper
     /// <summary>
     /// Call JsValue.ToString(), mainly for NamespaceReference.
     /// </summary>
+#pragma warning disable CA1822
     public JsValue ToString(JsValue value)
+#pragma warning restore CA1822
     {
         return value.ToString();
     }
@@ -22,7 +24,9 @@ public class ClrHelper
     /// <summary>
     /// Cast `obj as ISomeInterface` to `obj`
     /// </summary>
+#pragma warning disable CA1822
     public JsValue Unwrap(ObjectWrapper obj)
+#pragma warning restore CA1822
     {
         return new ObjectWrapper(obj.Engine, obj.Target);
     }
@@ -30,7 +34,9 @@ public class ClrHelper
     /// <summary>
     /// Cast `obj` to `obj as ISomeInterface`
     /// </summary>
+#pragma warning disable CA1822
     public JsValue Wrap(ObjectWrapper obj, TypeReference type)
+#pragma warning restore CA1822
     {
         if (!type.ReferenceType.IsInstanceOfType(obj.Target))
         {
@@ -70,7 +76,7 @@ public class ClrHelper
         }
         else
         {
-            ExceptionHelper.ThrowArgumentException("Must be an ObjectWrapper of Type", "obj");
+            ExceptionHelper.ThrowArgumentException("Must be an ObjectWrapper of Type", nameof(obj));
         }
         return JsValue.Undefined;
     }

+ 7 - 6
Jint/Runtime/Interop/DefaultObjectConverter.cs

@@ -1,4 +1,5 @@
 using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
 using System.Runtime.CompilerServices;
 using System.Threading;
 using Jint.Native;
@@ -74,10 +75,10 @@ namespace Jint
                     var t = value.GetType();
 
                     if (!engine.Options.Interop.AllowSystemReflection
-                        && t.Namespace?.StartsWith("System.Reflection") == true)
+                        && t.Namespace?.StartsWith("System.Reflection", StringComparison.Ordinal) == true)
                     {
-                        const string message = "Cannot access System.Reflection namespace, check Engine's interop options";
-                        ExceptionHelper.ThrowInvalidOperationException(message);
+                        const string Message = "Cannot access System.Reflection namespace, check Engine's interop options";
+                        ExceptionHelper.ThrowInvalidOperationException(Message);
                     }
 
                     if (t.IsEnum)
@@ -86,17 +87,17 @@ namespace Jint
 
                         if (ut == typeof(ulong))
                         {
-                            result = JsNumber.Create(Convert.ToDouble(value));
+                            result = JsNumber.Create(Convert.ToDouble(value, CultureInfo.InvariantCulture));
                         }
                         else
                         {
                             if (ut == typeof(uint) || ut == typeof(long))
                             {
-                                result = JsNumber.Create(Convert.ToInt64(value));
+                                result = JsNumber.Create(Convert.ToInt64(value, CultureInfo.InvariantCulture));
                             }
                             else
                             {
-                                result = JsNumber.Create(Convert.ToInt32(value));
+                                result = JsNumber.Create(Convert.ToInt32(value, CultureInfo.InvariantCulture));
                             }
                         }
                     }

+ 4 - 4
Jint/Runtime/Interop/DelegateWrapper.cs

@@ -36,7 +36,7 @@ namespace Jint.Runtime.Interop
             }
         }
 
-        protected internal override JsValue Call(JsValue thisObject, JsValue[] jsArguments)
+        protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
             var parameterInfos = _d.Method.GetParameters();
 
@@ -53,7 +53,7 @@ namespace Jint.Runtime.Interop
             int delegateArgumentsCount = parameterInfos.Length;
             int delegateNonParamsArgumentsCount = _delegateContainsParamsArgument ? delegateArgumentsCount - 1 : delegateArgumentsCount;
 
-            int jsArgumentsCount = jsArguments.Length;
+            int jsArgumentsCount = arguments.Length;
             int jsArgumentsWithoutParamsCount = Math.Min(jsArgumentsCount, delegateNonParamsArgumentsCount);
 
             var clrTypeConverter = Engine.ClrTypeConverter;
@@ -64,7 +64,7 @@ namespace Jint.Runtime.Interop
             for (var i = 0; i < jsArgumentsWithoutParamsCount; i++)
             {
                 var parameterType = parameterInfos[i].ParameterType;
-                var value = jsArguments[i];
+                var value = arguments[i];
                 object? converted;
 
                 if (parameterType == typeof(JsValue))
@@ -107,7 +107,7 @@ namespace Jint.Runtime.Interop
                 for (var i = paramsArgumentIndex; i < jsArgumentsCount; i++)
                 {
                     var paramsIndex = i - paramsArgumentIndex;
-                    var value = jsArguments[i];
+                    var value = arguments[i];
                     object? converted;
 
                     if (paramsParameterType == typeof(JsValue))

+ 1 - 1
Jint/Runtime/Interop/MethodDescriptor.cs

@@ -148,7 +148,7 @@ namespace Jint.Runtime.Interop
                 }
                 else
                 {
-                    throw new Exception("Method is unknown type");
+                    throw new ArgumentException("Method is unknown type");
                 }
             }
             catch (TargetInvocationException exception)

+ 1 - 1
Jint/Runtime/Interop/NamespaceReference.cs

@@ -124,7 +124,7 @@ namespace Jint.Runtime.Interop
                 {
                     foreach (Type nType in GetAllNestedTypes(type))
                     {
-                        if (nType.FullName != null && nType.FullName.Replace("+", ".").Equals(comparedPath))
+                        if (nType.FullName != null && nType.FullName.Replace("+", ".").Equals(comparedPath, StringComparison.Ordinal))
                         {
                             _engine.TypeCache.Add(comparedPath, nType);
                             return TypeReference.CreateTypeReference(_engine, nType);

+ 4 - 7
Jint/Runtime/Interop/ObjectWrapper.cs

@@ -301,7 +301,9 @@ namespace Jint.Runtime.Interop
             return Target is ICollection ? 0 : base.GetSmallestIndex(length);
         }
 
-        public override bool Equals(JsValue? obj) => Equals(obj as ObjectWrapper);
+        public override bool Equals(object? obj) => Equals(obj as ObjectWrapper);
+
+        public override bool Equals(JsValue? other) => Equals(other as ObjectWrapper);
 
         public bool Equals(ObjectWrapper? other)
         {
@@ -318,12 +320,7 @@ namespace Jint.Runtime.Interop
             return Equals(Target, other.Target);
         }
 
-        public override int GetHashCode()
-        {
-            var hashCode = -1468639730;
-            hashCode = hashCode * -1521134295 + Target.GetHashCode();
-            return hashCode;
-        }
+        public override int GetHashCode() => Target.GetHashCode();
 
         private sealed class DictionaryIterator : IteratorInstance
         {

+ 3 - 3
Jint/Runtime/Interop/TypeReference.cs

@@ -204,14 +204,14 @@ namespace Jint.Runtime.Interop
 
         private readonly record struct ObjectCreateState(TypeReference TypeReference, JsValue[] Arguments);
 
-        public override bool Equals(JsValue? obj)
+        public override bool Equals(JsValue? other)
         {
-            if (obj is TypeReference typeReference)
+            if (other is TypeReference typeReference)
             {
                 return this.ReferenceType == typeReference.ReferenceType;
             }
 
-            return base.Equals(obj);
+            return base.Equals(other);
         }
 
         internal override bool OrdinaryHasInstance(JsValue v)

+ 1 - 2
Jint/Runtime/Interpreter/Expressions/BindingPatternAssignmentExpression.cs

@@ -265,8 +265,7 @@ namespace Jint.Runtime.Interpreter.Expressions
                     }
                     else
                     {
-                        ExceptionHelper.ThrowArgumentOutOfRangeException("pattern",
-                            "Unable to determine how to handle array pattern element " + left);
+                        ExceptionHelper.ThrowArgumentOutOfRangeException(nameof(pattern), $"Unable to determine how to handle array pattern element {left}");
                         break;
                     }
                 }

+ 2 - 1
Jint/Runtime/Interpreter/Expressions/JintCallExpression.cs

@@ -4,6 +4,7 @@ using Esprima.Ast;
 using Jint.Native;
 using Jint.Native.Function;
 using Jint.Native.Object;
+using Jint.Runtime.CallStack;
 using Jint.Runtime.Environments;
 using Jint.Runtime.References;
 
@@ -86,7 +87,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
             if (!context.Engine._stackGuard.TryEnterOnCurrentStack())
             {
-                return context.Engine._stackGuard.RunOnEmptyStack(EvaluateInternal, context);
+                return StackGuard.RunOnEmptyStack(EvaluateInternal, context);
             }
 
             if (_calleeExpression._expression.Type == Nodes.Super)

+ 1 - 1
Jint/Runtime/Interpreter/Expressions/JintMemberExpression.cs

@@ -140,7 +140,7 @@ namespace Jint.Runtime.Interpreter.Expressions
         /// <summary>
         /// https://tc39.es/ecma262/#sec-makeprivatereference
         /// </summary>
-        private object MakePrivateReference(Engine engine, JsValue baseValue, JsValue privateIdentifier)
+        private static object MakePrivateReference(Engine engine, JsValue baseValue, JsValue privateIdentifier)
         {
             var privEnv = engine.ExecutionContext.PrivateEnvironment;
             var privateName = privEnv!.ResolvePrivateIdentifier(privateIdentifier.ToString());

+ 1 - 1
Jint/Runtime/Interpreter/JintFunctionDefinition.cs

@@ -148,7 +148,7 @@ internal sealed class JintFunctionDefinition
     /// <summary>
     /// https://tc39.es/ecma262/#sec-runtime-semantics-evaluategeneratorbody
     /// </summary>
-    private Completion EvaluateGeneratorBody(FunctionInstance functionObject, JsValue[] argumentsList)
+    private static Completion EvaluateGeneratorBody(FunctionInstance functionObject, JsValue[] argumentsList)
     {
         ExceptionHelper.ThrowNotImplementedException("generators not implemented");
         return default;

+ 1 - 1
Jint/Runtime/Interpreter/Statements/JintExportDefaultDeclaration.cs

@@ -80,7 +80,7 @@ internal sealed class JintExportDefaultDeclaration : JintStatement<ExportDefault
     /// <summary>
     /// https://tc39.es/ecma262/#sec-initializeboundname
     /// </summary>
-    private void InitializeBoundName(string name, JsValue value, EnvironmentRecord? environment)
+    private static void InitializeBoundName(string name, JsValue value, EnvironmentRecord? environment)
     {
         if (environment is not null)
         {

+ 2 - 0
Jint/Runtime/Interpreter/Statements/JintForInForOfStatement.cs

@@ -317,7 +317,9 @@ namespace Jint.Runtime.Interpreter.Statements
                         // if we already have and exception, use it
                         if (completionType != CompletionType.Throw)
                         {
+#pragma warning disable CA2219
                             throw;
+#pragma warning restore CA2219
                         }
                     }
                 }

+ 1 - 1
Jint/Runtime/Modules/DefaultModuleLoader.cs

@@ -151,6 +151,6 @@ public sealed class DefaultModuleLoader : IModuleLoader
 
     private static bool IsRelative(string specifier)
     {
-        return specifier.StartsWith(".") || specifier.StartsWith("/");
+        return specifier.StartsWith(".", StringComparison.Ordinal) || specifier.StartsWith("/", StringComparison.Ordinal);
     }
 }

+ 2 - 0
Jint/Runtime/Modules/FailFastModuleLoader.cs

@@ -6,7 +6,9 @@ internal sealed class FailFastModuleLoader : IModuleLoader
 {
     public static readonly IModuleLoader Instance = new FailFastModuleLoader();
 
+#pragma warning disable CA1822
     public Uri BasePath
+#pragma warning restore CA1822
     {
         get
         {

+ 2 - 2
Jint/Runtime/Modules/SourceTextModuleRecord.cs

@@ -107,7 +107,7 @@ internal class SourceTextModuleRecord : CyclicModuleRecord
             for (var j = 0; j < starNames.Count; j++)
             {
                 var n = starNames[j];
-                if (!"default".Equals(n) && !exportedNames.Contains(n))
+                if (!"default".Equals(n, StringComparison.Ordinal) && !exportedNames.Contains(n))
                 {
                     exportedNames.Add(n);
                 }
@@ -164,7 +164,7 @@ internal class SourceTextModuleRecord : CyclicModuleRecord
             }
         }
 
-        if ("default".Equals(exportName))
+        if ("default".Equals(exportName, StringComparison.Ordinal))
         {
             // Assert: A default export was not explicitly defined by this module
             return null;

+ 1 - 1
Jint/Runtime/OrderedDictionary.cs

@@ -515,7 +515,7 @@ namespace Jint.Runtime
             {
                 if (arrayIndex < 0)
                 {
-                    ExceptionHelper.ThrowArgumentOutOfRangeException(nameof(arrayIndex), string.Format(TooSmall, 0));
+                    ExceptionHelper.ThrowArgumentOutOfRangeException(nameof(arrayIndex), string.Format(CultureInfo.InvariantCulture, TooSmall, 0));
                 }
                 if (parent.dictionary.Count > array.Length - arrayIndex)
                 {

+ 6 - 6
Jint/Runtime/TypeConverter.cs

@@ -78,7 +78,7 @@ namespace Jint.Runtime
         {
             for (var i = 0; i < intToString.Length; ++i)
             {
-                intToString[i] = i.ToString();
+                intToString[i] = i.ToString(CultureInfo.InvariantCulture);
             }
 
             for (var i = 0; i < charToString.Length; ++i)
@@ -848,7 +848,7 @@ namespace Jint.Runtime
             var temp = intToString;
             return (ulong) i < (ulong) temp.Length
                 ? temp[i]
-                : i.ToString();
+                : i.ToString(CultureInfo.InvariantCulture);
         }
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -857,7 +857,7 @@ namespace Jint.Runtime
             var temp = intToString;
             return (uint) i < (uint) temp.Length
                 ? temp[i]
-                : i.ToString();
+                : i.ToString(CultureInfo.InvariantCulture);
         }
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -866,7 +866,7 @@ namespace Jint.Runtime
             var temp = intToString;
             return i < (uint) temp.Length
                 ? temp[i]
-                : i.ToString();
+                : i.ToString(CultureInfo.InvariantCulture);
         }
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -884,7 +884,7 @@ namespace Jint.Runtime
             var temp = intToString;
             return i < (ulong) temp.Length
                 ? temp[i]
-                : i.ToString();
+                : i.ToString(CultureInfo.InvariantCulture);
         }
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -925,7 +925,7 @@ namespace Jint.Runtime
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         internal static string ToString(BigInteger bigInteger)
         {
-            return bigInteger.ToString();
+            return bigInteger.ToString(CultureInfo.InvariantCulture);
         }
 
         /// <summary>