diff --git a/Sources/AngouriMath/extension.dib b/Sources/AngouriMath/extension.dib index 20b1d6e95..ee0154644 100644 --- a/Sources/AngouriMath/extension.dib +++ b/Sources/AngouriMath/extension.dib @@ -34,3 +34,16 @@ if (FindType("Numbers", "PeterO.Numbers.ERational") is { } rational) RegisterLatex(rational, o => $@"\frac{{{rational.GetProperty("Numerator").GetValue(o)}}}{{{rational.GetProperty("Denominator").GetValue(o)}}}"); "Extensions for LaTeX loaded!" + +#!csharp + +// The namespaces a C# notebook writes without opening: `AngouriMath` and `AngouriMath.Extensions` are opened only +// when the cell above was compiled against AngouriMath, which is when this kernel loaded the package rather than +// another kernel of the same notebook, and the opening is deferred to this kernel's next submission. +static object PropertyOf(object o, string name) => o?.GetType().GetProperty(name)?.GetValue(o); + +if (PropertyOf(PropertyOf(PropertyOf(Microsoft.DotNet.Interactive.Kernel.Current, "ScriptState"), "Script"), "Options") is { } options + && PropertyOf(options, "MetadataReferences") is System.Collections.IEnumerable references + && references.Cast().Any(r => PropertyOf(r, "Display") is string path && System.IO.Path.GetFileName(path) == "AngouriMath.dll")) + Microsoft.DotNet.Interactive.Kernel.Current.DeferCommand( + new Microsoft.DotNet.Interactive.Commands.SubmitCode("using AngouriMath;\nusing AngouriMath.Extensions;")); diff --git a/Sources/Tests/InteractiveWrapperUnitTests/HostCompatibility.fs b/Sources/Tests/InteractiveWrapperUnitTests/HostCompatibility.fs new file mode 100644 index 000000000..d548dc03b --- /dev/null +++ b/Sources/Tests/InteractiveWrapperUnitTests/HostCompatibility.fs @@ -0,0 +1,28 @@ +// +// Copyright (c) 2019-2026 Angouri. +// AngouriMath is licensed under MIT. +// Details: https://github.com/asc-community/AngouriMath/blob/master/LICENSE.md. +// Website: https://am.angouri.org. +// + +module AngouriMath.Interactive.Tests.HostCompatibility + +open System.Reflection +open Xunit + +let private fsharpCoreReferencedBy (assembly : Assembly) = + assembly.GetReferencedAssemblies() + |> Array.find (fun name -> name.Name = "FSharp.Core") + |> fun name -> name.Version + +// A notebook host runs its own FSharp.Core and cannot give a package a newer one. Built against +// FSharp.Core 10.1 under a host carrying 10.0, the kernel extension hung a C# kernel as it loaded, +// and an F# kernel failed its first call into the wrappers unless the extension had loaded first: +// https://github.com/asc-community/AngouriMath/issues/2108 +[] +let ``The wrappers ask for no newer FSharp.Core than the F# kernel is built against`` () = + let kernel = fsharpCoreReferencedBy typeof.Assembly + for wrapper in [ typeof.Assembly + Assembly.Load "AngouriMath.FSharp" ] do + let asked = fsharpCoreReferencedBy wrapper + Assert.True(asked <= kernel, $"{wrapper.GetName().Name} asks for FSharp.Core {asked}, the F# kernel is built against {kernel}") diff --git a/Sources/Tests/InteractiveWrapperUnitTests/InteractiveWrapperUnitTests.fsproj b/Sources/Tests/InteractiveWrapperUnitTests/InteractiveWrapperUnitTests.fsproj index d64e56be4..a726b5225 100644 --- a/Sources/Tests/InteractiveWrapperUnitTests/InteractiveWrapperUnitTests.fsproj +++ b/Sources/Tests/InteractiveWrapperUnitTests/InteractiveWrapperUnitTests.fsproj @@ -10,6 +10,7 @@ + diff --git a/Sources/Wrappers/AngouriMath.FSharp/AngouriMath.FSharp.fsproj b/Sources/Wrappers/AngouriMath.FSharp/AngouriMath.FSharp.fsproj index 4c82eb5e4..2e79661e6 100644 --- a/Sources/Wrappers/AngouriMath.FSharp/AngouriMath.FSharp.fsproj +++ b/Sources/Wrappers/AngouriMath.FSharp/AngouriMath.FSharp.fsproj @@ -27,6 +27,13 @@ + + + + + diff --git a/Sources/Wrappers/AngouriMath.Interactive/AngouriMath.Interactive.fsproj b/Sources/Wrappers/AngouriMath.Interactive/AngouriMath.Interactive.fsproj index af93108b7..c256984fd 100644 --- a/Sources/Wrappers/AngouriMath.Interactive/AngouriMath.Interactive.fsproj +++ b/Sources/Wrappers/AngouriMath.Interactive/AngouriMath.Interactive.fsproj @@ -47,6 +47,10 @@ + +