Skip to content

Update every package the solution can update, and adapt to xUnit v4 - #3064

Merged
lahma merged 1 commit into
sebastienros:mainfrom
lahma:package-updates
Aug 19, 2026
Merged

Update every package the solution can update, and adapt to xUnit v4#3064
lahma merged 1 commit into
sebastienros:mainfrom
lahma:package-updates

Conversation

@lahma

@lahma lahma commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Supersedes #3034, which fails CI on xUnit's new xUnit1069 analyzer rule. This takes the same three packages plus everything else the solution can move, and fixes what the new versions actually break.

Packages

Package From To
xunit.v3.mtp-off 3.2.2 4.0.0
xunit.runner.visualstudio 3.1.5 4.0.0
Meziantou.Analyzer 3.0.156 3.0.167
Microsoft.CodeAnalysis.Analyzers 5.6.0 5.9.0
Microsoft.CodeAnalysis.CSharp 5.6.0 5.9.0
System.Text.Json 10.0.10 10.0.11
Test262Harness 1.1.1 1.1.2
YantraJS.Core 1.2.422 1.2.462

Everything else in Directory.Packages.props is already current or only has a prerelease ahead of it — BenchmarkDotNet 0.16.0-preview.1, NUnit 5.0.0-beta.1, Verify.NUnit 32.0.0-beta.8, Newtonsoft.Json 13.0.5-beta1, and the 11.0.0-preview Microsoft.Extensions.* / System.Text.Json line — so those stay put. Test262Harness.Console in Jint.Tests.Test262/.config/dotnet-tools.json was already 1.1.2.

The Roslyn floor tracks the compiler in the SDK the pipeline installs: 10.0.400 ships Roslyn 5.9.0, so Jint.SourceGenerators still loads.

Code adjustments

Both are in Jint.Tests, and both are things the new versions were right to surface.

xUnit1069 — a Timeout that could not bite

GeneratorTests.YieldInForLoopUpdateExpression carried [Fact(Timeout = 10000)] without referencing the test's cancellation token, which is exactly the rule's complaint. The method is synchronous, so xUnit cannot abort it on its own: a regression that reintroduced the infinite loop this test guards would have hung the run rather than failing it, and the ten seconds bought nothing.

Handing the token to the engine as a CancellationConstraint is what makes the Timeout real. Verified with a throwaway probe — an engine wired this way under a 3 s Timeout throws ExecutionCanceledException 2.9 s into while (true) {}, where before it would have run until the process was killed.

xUnit 4.0.0 changed how a theory's DateTime argument is serialized

EngineTests.TestDates fed DateTime values through MemberData. In 3.2.2 SerializationHelper formatted them as-is:

(object v, Type _) => ((DateTime)v).ToString("O", CultureInfo.InvariantCulture)

In 4.0.0 it goes through ToRtf(), which is ToUniversalTime().ToString("O", CultureInfo.InvariantCulture). For a DateTimeKind.Unspecified value ToUniversalTime() reinterprets it as the runner machine's local time and shifts it, so the test method received a different instant depending on where the suite ran — new DateTime(2000, 1, 1) arrived as 1999-12-31T22:00:00Z here (UTC+2). Being Utc, it then threw straight out of new DateTimeOffset(value, pacificOffset) with "The UTC Offset for Utc DateTime instances must be 0", which is the second half of the CI failure on #3034.

These six dates are wall-clock readings in the Pacific zone, so they now travel as text and are parsed back with an explicit Unspecified kind — which is what they always meant, and no longer depends on the serializer's fidelity or on the runner's timezone.

Verification

Release, all green:

  • Jint.Tests — 5,937 passed (net10.0), 5,852 passed (net472)
  • Jint.Tests.PublicInterface — 1,488 / 1,487 passed
  • both of the above again under JINT_HOST_CONTRACT_VERIFICATION=1
  • Jint.Tests.CommonScripts — 28 passed on both frameworks
  • Jint.Tests.SourceGenerators — 52 passed
  • Jint.Tests.Test262 — 102,394 passed, 287 skipped

One deliberate non-change: Jint.Benchmark/README.md's "Engine versions" list still says YantraJS.Core 1.2.422. That list records the packages that produced the published comparison table, not the current pins, so bumping it without re-running the session would misattribute the numbers.

The linux leg first failed on built-ins/Atomics/waitAsync/returns-result-object-value-is-promise-resolves-to-timed-out.js. That family races a 1000 ms wall-clock budget and flakes on main too — runs 32242568634 (...resolves-to-ok.js) and 32159876438 (true-for-timeout.js) are recent examples. Re-ran the job; green.

Dependabot's grouped bump (sebastienros#3034) fails CI on the new xUnit1069 analyzer, and
three further packages are behind. This takes all of them and fixes what the
new versions actually break.

Bumped: xunit.v3.mtp-off and xunit.runner.visualstudio 4.0.0, Meziantou.Analyzer
3.0.167, Microsoft.CodeAnalysis(.Analyzers|.CSharp) 5.9.0, System.Text.Json
10.0.11, Test262Harness 1.1.2, YantraJS.Core 1.2.462. Everything else is either
already current or only has a prerelease ahead of it (BenchmarkDotNet 0.16.0-preview.1,
NUnit 5.0.0-beta.1, Verify.NUnit 32.0.0-beta.8, Newtonsoft.Json 13.0.5-beta1,
the 11.0.0-preview Microsoft.Extensions/System.Text.Json line), which stays out.
The Roslyn floor matches the compiler in the SDK the pipeline installs (10.0.400
ships Roslyn 5.9.0), and Test262Harness.Console in the tool manifest was already
1.1.2.

Two code adjustments, both in Jint.Tests:

xUnit1069 wants a test carrying a Timeout to reference the test's cancellation
token, and it is right that GeneratorTests.YieldInForLoopUpdateExpression did
not: the method is synchronous, so xUnit cannot abort it and the ten-second
Timeout bought nothing — a regression that reintroduced the infinite loop would
have hung the run rather than failing it. Handing the token to the engine as a
CancellationConstraint is what makes the Timeout bite; measured, the engine now
throws ExecutionCanceledException 2.9 s into a 3 s Timeout instead of spinning.

EngineTests.TestDates fed DateTime values through MemberData, and xUnit 4.0.0
changed how a theory's DateTime argument is serialized: SerializationHelper now
goes through ToRtf(), i.e. ToUniversalTime().ToString("O"), where it used to
format the value as-is. For a DateTimeKind.Unspecified value ToUniversalTime()
reinterprets it as the *runner machine's* local time and shifts it, so the test
received an instant that depended on where the suite ran — and, being Utc,
immediately threw out of `new DateTimeOffset(value, pacificOffset)`. These six
dates are wall-clock readings in the Pacific zone, so they now travel as text
and are parsed back with an explicit Unspecified kind, which is what they always
meant.

Green on Jint.Tests, Jint.Tests.PublicInterface (both also under
JINT_HOST_CONTRACT_VERIFICATION=1), Jint.Tests.CommonScripts,
Jint.Tests.SourceGenerators and Jint.Tests.Test262 (102,394 passed).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@lahma
lahma merged commit 28d2fd2 into sebastienros:main Aug 19, 2026
9 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant