Skip to content

Commit

Permalink
Add NET 8 support (#1686)
Browse files Browse the repository at this point in the history
* add NET 8 target for Jint
* switch to NET 8 for tests, benchmarks and REPL
* add SearchValues polyfill
  • Loading branch information
lahma authored Nov 24, 2023
1 parent 473ca00 commit 197ebd8
Show file tree
Hide file tree
Showing 24 changed files with 130 additions and 115 deletions.
10 changes: 5 additions & 5 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
<PackageVersion Include="Esprima" Version="3.0.2" />
<PackageVersion Include="Flurl.Http.Signed" Version="3.2.4" />
<PackageVersion Include="Jurassic" Version="3.2.7" />
<PackageVersion Include="Meziantou.Analyzer" Version="2.0.106" />
<PackageVersion Include="Meziantou.Analyzer" Version="2.0.110" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageVersion Include="MongoDB.Bson.signed" Version="2.19.0" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="NiL.JS" Version="2.5.1674" />
Expand All @@ -21,13 +21,13 @@
<PackageVersion Include="Spectre.Console.Cli" Version="0.45.0" />
<PackageVersion Include="System.Text.Json" Version="6.0.8" />
<PackageVersion Include="Test262Harness" Version="0.0.22" />
<PackageVersion Include="xunit" Version="2.6.1" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.5.3" />
<PackageVersion Include="xunit" Version="2.6.2" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.5.4" PrivateAssets="all" />
<PackageVersion Include="YantraJS.Core" Version="1.2.203" />
</ItemGroup>
<ItemGroup>
<GlobalPackageReference Include="GitHubActionsTestLogger" Version="2.3.3" />
<GlobalPackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" />
<GlobalPackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<GlobalPackageReference Include="PolySharp" Version="1.13.2" />
</ItemGroup>
</Project>
2 changes: 1 addition & 1 deletion Jint.Benchmark/Jint.Benchmark.csproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
<GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute>
Expand Down
2 changes: 1 addition & 1 deletion Jint.Repl/Jint.Repl.csproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<IsPackable>false</IsPackable>
<ImplicitUsings>enable</ImplicitUsings>
Expand Down
5 changes: 3 additions & 2 deletions Jint.Tests.CommonScripts/Jint.Tests.CommonScripts.csproj
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<!--<TargetFrameworks Condition="'$(OS)' == 'Windows_NT'">$(TargetFrameworks);net461</TargetFrameworks>-->
<TargetFrameworks>net8.0</TargetFrameworks>
<TargetFrameworks Condition="'$(OS)' == 'Windows_NT'">$(TargetFrameworks);net462</TargetFrameworks>
<IsPackable>false</IsPackable>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>latest</LangVersion>
</PropertyGroup>

<ItemGroup>
Expand Down
4 changes: 3 additions & 1 deletion Jint.Tests.PublicInterface/ConstraintUsageTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ public class ConstraintUsageTests
{
// this test case is problematic due to nature of cancellation token source in old framework
// in NET 6 it's better designed and signals more reliably
#if NET6_0_OR_GREATER

// TODO NET 8 also has problems with this
#if NET6_0
[Fact]
public void CanFindAndResetCancellationConstraint()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
<TargetFrameworks Condition="'$(OS)' == 'Windows_NT'">$(TargetFrameworks);net462</TargetFrameworks>
<AssemblyOriginatorKeyFile>..\Jint\Jint.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
Expand Down
2 changes: 1 addition & 1 deletion Jint.Tests.Test262/Jint.Tests.Test262.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<!--<TargetFrameworks Condition="'$(OS)' == 'Windows_NT'">$(TargetFrameworks);net461</TargetFrameworks>-->
<AssemblyOriginatorKeyFile>..\Jint\Jint.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
Expand Down
4 changes: 2 additions & 2 deletions Jint.Tests.Test262/Test262Test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ private Engine BuildTestExecutor(Test262File file)
cfg.EnableModules(new Test262ModuleLoader(State.Test262Stream.Options.FileSystem, relativePath));
});

if (file.Flags.IndexOf("raw") != -1)
if (file.Flags.Contains("raw"))
{
// nothing should be loaded
return engine;
Expand Down Expand Up @@ -76,7 +76,7 @@ private Engine BuildTestExecutor(Test262File file)
engine.Execute(State.Sources[include]);
}

if (file.Flags.IndexOf("async") != -1)
if (file.Flags.Contains("async"))
{
engine.Execute(State.Sources["doneprintHandle.js"]);
}
Expand Down
2 changes: 1 addition & 1 deletion Jint.Tests/Jint.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net6.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
<TargetFrameworks Condition="'$(OS)' == 'Windows_NT'">$(TargetFrameworks);net462</TargetFrameworks>
<AssemblyOriginatorKeyFile>..\Jint\Jint.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
Expand Down
16 changes: 11 additions & 5 deletions Jint.Tests/Runtime/DateTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,17 @@ public void ValuePrecisionIsIntegral()
[Fact]
public void ToStringFollowsJavaScriptFormat()
{
var engine = new Engine(
conf =>
{
conf.LocalTimeZone(TimeZoneInfo.FindSystemTimeZoneById("China Standard Time"));
});
TimeZoneInfo timeZoneInfo;
try
{
timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Asia/Shanghai");
}
catch
{
timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("China Standard Time");
}

var engine = new Engine(options => options.LocalTimeZone(timeZoneInfo));

Assert.Equal("Tue Feb 01 2022 00:00:00 GMT+0800 (China Standard Time)", engine.Evaluate("new Date(2022,1,1).toString()"));
Assert.Equal("Tue Feb 01 2022 00:00:00 GMT+0800 (China Standard Time)", engine.Evaluate("new Date(2022,1,1)").ToString());
Expand Down
4 changes: 2 additions & 2 deletions Jint.Tests/Runtime/EngineLimitTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ public class EngineLimitTests
{

#if RELEASE
const int FunctionNestingCount = 960;
const int FunctionNestingCount = 840;
#else
const int FunctionNestingCount = 520;
const int FunctionNestingCount = 510;
#endif

[Fact]
Expand Down
21 changes: 8 additions & 13 deletions Jint.Tests/Runtime/EngineTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,40 +24,35 @@ public partial class EngineTests : IDisposable
private static readonly TimeZoneInfo _tongaTimeZone;
private static readonly TimeZoneInfo _easternTimeZone;


static EngineTests()
{
// https://stackoverflow.com/questions/47848111/how-should-i-fetch-timezoneinfo-in-a-platform-agnostic-way
// should be natively supported soon https://github.com/dotnet/runtime/issues/18644
try
{
_pacificTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
_pacificTimeZone = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
}
catch (TimeZoneNotFoundException)
{
// https://stackoverflow.com/questions/47848111/how-should-i-fetch-timezoneinfo-in-a-platform-agnostic-way
// should be natively supported soon https://github.com/dotnet/runtime/issues/18644
_pacificTimeZone = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
_pacificTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
}

try
{
_tongaTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Tonga Standard Time");
_tongaTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific/Tongatapu");
}
catch (TimeZoneNotFoundException)
{
// https://stackoverflow.com/questions/47848111/how-should-i-fetch-timezoneinfo-in-a-platform-agnostic-way
// should be natively supported soon https://github.com/dotnet/runtime/issues/18644
_tongaTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific/Tongatapu");
_tongaTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Tonga Standard Time");
}

try
{
_easternTimeZone = TimeZoneInfo.FindSystemTimeZoneById("US Eastern Standard Time");
_easternTimeZone = TimeZoneInfo.FindSystemTimeZoneById("America/New_York");
}
catch (TimeZoneNotFoundException)
{
// https://stackoverflow.com/questions/47848111/how-should-i-fetch-timezoneinfo-in-a-platform-agnostic-way
// should be natively supported soon https://github.com/dotnet/runtime/issues/18644
_easternTimeZone = TimeZoneInfo.FindSystemTimeZoneById("America/New_York");
_easternTimeZone = TimeZoneInfo.FindSystemTimeZoneById("US Eastern Standard Time");
}
}

Expand Down
5 changes: 3 additions & 2 deletions Jint.Tests/Runtime/InteropTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2809,8 +2809,9 @@ public void ShouldBeAbleToHandleInvalidClrConversionViaCatchClrExceptions()
{
var engine = new Engine(cfg => cfg.CatchClrExceptions());
engine.SetValue("a", new Person());
var ex = Assert.Throws<JavaScriptException>(() => engine.Execute("a.age = \"It won't work, but it's normal\""));
Assert.Equal("Input string was not in a correct format.", ex.Message);
var ex = Assert.Throws<JavaScriptException>(() => engine.Execute("a.age = 'It will not work, but it is normal'"));
Assert.Contains("input string ", ex.Message, StringComparison.OrdinalIgnoreCase);
Assert.Contains(" was not in a correct format", ex.Message, StringComparison.OrdinalIgnoreCase);
}

[Fact]
Expand Down
9 changes: 9 additions & 0 deletions Jint/Extensions/Polyfills.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
using System.Runtime.CompilerServices;

namespace Jint;

internal static class Polyfills
{
#if NETFRAMEWORK || NETSTANDARD2_0
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool Contains(this string source, char c) => source.IndexOf(c) != -1;
#endif

#if NETFRAMEWORK
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool Contains(this ReadOnlySpan<string> source, string c) => source.IndexOf(c) != -1;
#endif

#if NETFRAMEWORK || NETSTANDARD2_0
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool StartsWith(this string source, char c) => source.Length > 0 && source[0] == c;
#endif
}
44 changes: 44 additions & 0 deletions Jint/Extensions/SearchValues.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#if !NET8_0_OR_GREATER

using System.Runtime.CompilerServices;

namespace System.Buffers;

internal static class SearchValues
{
internal static SearchValues<char> Create(string input) => new(input.AsSpan());
internal static SearchValues<char> Create(ReadOnlySpan<char> input) => new(input);
}

internal sealed class SearchValues<T>
{
private readonly bool[] _data;
private readonly char _min;
private readonly char _max;

internal SearchValues(ReadOnlySpan<char> input)
{
_min = char.MaxValue;
_max = char.MinValue;
foreach (var c in input)
{
_min = (char) Math.Min(_min, c);
_max = (char) Math.Max(_max, c);
}

_data = new bool[_max - _min + 1];
foreach (var c in input)
{
_data[c - _min] = true;
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains(char c)
{
var i = (uint) (c - _min);
var temp = _data;
return i < temp.Length && temp[i];
}
}
#endif
4 changes: 2 additions & 2 deletions Jint/Jint.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<NeutralLanguage>en-US</NeutralLanguage>
<TargetFrameworks>net462;netstandard2.0;netstandard2.1;net6.0</TargetFrameworks>
<TargetFrameworks>net462;netstandard2.0;netstandard2.1;net6.0;net8.0</TargetFrameworks>

<AssemblyOriginatorKeyFile>Jint.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
Expand All @@ -21,7 +21,7 @@

</PropertyGroup>

<PropertyGroup Condition=" '$(TargetFramework)' == 'net6.0' or '$(TargetFramework)' == 'netstandard2.1' ">
<PropertyGroup Condition=" '$(TargetFramework)' != 'net462' and '$(TargetFramework)' != 'netstandard2.0' ">
<DefineConstants>$(DefineConstants);SUPPORTS_SPAN_PARSE;SUPPORTS_WEAK_TABLE_ADD_OR_UPDATE;SUPPORTS_WEAK_TABLE_CLEAR</DefineConstants>
</PropertyGroup>

Expand Down
27 changes: 15 additions & 12 deletions Jint/Native/Global/GlobalObject.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Buffers;
using System.Globalization;
using System.Linq;
using System.Runtime.CompilerServices;
Expand Down Expand Up @@ -272,12 +273,11 @@ public static JsValue IsFinite(JsValue thisObject, JsValue[] arguments)
return true;
}

private static readonly string UriReserved = new (new [] { ';', '/', '?', ':', '@', '&', '=', '+', '$', ',' });
private static readonly string UriUnescaped = new(new [] { '-', '_', '.', '!', '~', '*', '\'', '(', ')' });
private static readonly string UnescapedUriSet = UriReserved + UriUnescaped + '#';
private static readonly string ReservedUriSet = UriReserved + '#';

private const string HexaMap = "0123456789ABCDEF";
private const string UriReservedString = ";/?:@&=+$,";
private const string UriUnescapedString = "-_.!~*'()";
private static readonly SearchValues<char> UriUnescaped = SearchValues.Create(UriUnescapedString);
private static readonly SearchValues<char> UnescapedUriSet = SearchValues.Create(UriReservedString + UriUnescapedString + '#');
private static readonly SearchValues<char> ReservedUriSet = SearchValues.Create(UriReservedString + '#');

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool IsValidHexaChar(char c) => Uri.IsHexDigit(c);
Expand Down Expand Up @@ -309,13 +309,15 @@ public JsValue EncodeUriComponent(JsValue thisObject, JsValue[] arguments)
return Encode(uriString, UriUnescaped);
}

private JsValue Encode(string uriString, string unescapedUriSet)
private JsValue Encode(string uriString, SearchValues<char> unescapedUriSet)
{
const string HexaMap = "0123456789ABCDEF";

var strLen = uriString.Length;

_stringBuilder.EnsureCapacity(uriString.Length);
_stringBuilder.Clear();
var buffer = new byte[4];
Span<byte> buffer = stackalloc byte[4];

for (var k = 0; k < strLen; k++)
{
Expand Down Expand Up @@ -421,7 +423,7 @@ public JsValue DecodeUriComponent(JsValue thisObject, JsValue[] arguments)
return Decode(componentString, null);
}

private JsValue Decode(string uriString, string? reservedSet)
private JsValue Decode(string uriString, SearchValues<char>? reservedSet)
{
var strLen = uriString.Length;

Expand Down Expand Up @@ -463,7 +465,7 @@ private JsValue Decode(string uriString, string? reservedSet)
{
C = (char)B;
#pragma warning disable CA2249
if (reservedSet == null || reservedSet.IndexOf(C) == -1)
if (reservedSet == null || !reservedSet.Contains(C))
#pragma warning restore CA2249
{
_stringBuilder.Append(C);
Expand Down Expand Up @@ -589,12 +591,13 @@ private static bool IsDigit(char c, int radix, out int result)
return tmp < radix;
}

private static readonly SearchValues<char> EscapeAllowList = SearchValues.Create("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@*_ + -./");

/// <summary>
/// http://www.ecma-international.org/ecma-262/5.1/#sec-B.2.1
/// </summary>
public JsValue Escape(JsValue thisObject, JsValue[] arguments)
{
const string AllowList = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@*_ + -./";
var uriString = TypeConverter.ToString(arguments.At(0));

var strLen = uriString.Length;
Expand All @@ -605,7 +608,7 @@ public JsValue Escape(JsValue thisObject, JsValue[] arguments)
for (var k = 0; k < strLen; k++)
{
var c = uriString[k];
if (AllowList.Contains(c))
if (EscapeAllowList.Contains(c))
{
_stringBuilder.Append(c);
}
Expand Down
Loading

0 comments on commit 197ebd8

Please sign in to comment.