From 08abcd0e1c85db766c735497c8b35b03a4056afd Mon Sep 17 00:00:00 2001 From: Dag Brattli Date: Sun, 30 Aug 2026 09:24:15 +0200 Subject: [PATCH 1/2] fix(compiler): preserve project FSharp.Core reference --- src/Fable.Compiler/ProjectCracker.fs | 10 +---- .../Integration/CompilationTests.fs | 41 +++++++++++++++++++ .../fixtures/taskNetstandardPython/Task.fs | 16 ++++++++ .../taskNetstandardPython.fsproj | 11 +++++ 4 files changed, 69 insertions(+), 9 deletions(-) create mode 100644 tests/Integration/Integration/fixtures/taskNetstandardPython/Task.fs create mode 100644 tests/Integration/Integration/fixtures/taskNetstandardPython/taskNetstandardPython.fsproj diff --git a/src/Fable.Compiler/ProjectCracker.fs b/src/Fable.Compiler/ProjectCracker.fs index 24bc8b08e2..bf2ee2705d 100644 --- a/src/Fable.Compiler/ProjectCracker.fs +++ b/src/Fable.Compiler/ProjectCracker.fs @@ -1002,7 +1002,6 @@ let getFullProjectOpts (resolver: ProjectCrackerResolver) (opts: CrackerOptions) let ignoredRefs = HashSet [ - "FSharp.Core" "WindowsBase" "Microsoft.Win32.Primitives" "Microsoft.VisualBasic" @@ -1027,14 +1026,7 @@ let getFullProjectOpts (resolver: ProjectCrackerResolver) (opts: CrackerOptions) let projRefs = projRefs |> List.map (fun p -> p.ProjectFile) - let otherOptions = - [| - yield! otherOptions - yield! dllRefs - // For some reason, in my tests it seems to work without the FSharp.Core reference - // but we add it just in case - yield "-r:" + typeof>.Assembly.Location - |] + let otherOptions = [| yield! otherOptions; yield! dllRefs |] let outputType = match mainProj.OutputType with diff --git a/tests/Integration/Integration/CompilationTests.fs b/tests/Integration/Integration/CompilationTests.fs index 8d592785df..8c731fdda9 100644 --- a/tests/Integration/Integration/CompilationTests.fs +++ b/tests/Integration/Integration/CompilationTests.fs @@ -7,6 +7,46 @@ open Fable.Compiler.Util let private data = Path.Combine(__SOURCE_DIRECTORY__, "data") +let private taskNetstandardPythonTest = + testCase "Python task expressions use the project's netstandard FSharp.Core" <| fun () -> + let testCaseDir = Path.Combine(__SOURCE_DIRECTORY__, "fixtures", "taskNetstandardPython") + let project = Path.Combine(testCaseDir, "taskNetstandardPython.fsproj") + let outputDir = Path.Combine(testCaseDir, "out") + + if Directory.Exists outputDir then + Directory.Delete(outputDir, true) + + let configuration = + System.Reflection.Assembly.GetExecutingAssembly().Location + |> Path.GetDirectoryName + |> Directory.GetParent + |> _.Name + + let compiler = + Path.GetFullPath( + Path.Combine(__SOURCE_DIRECTORY__, $"../../../src/Fable.Cli/bin/%s{configuration}/net10.0/fable.dll") + ) + + let exitCode = + Process.runSync + testCaseDir + "dotnet" + [ compiler + project + "--cwd" + testCaseDir + "--lang" + "Python" + "--outDir" + outputDir + "--noCache" ] + + Expect.equal exitCode 0 "Expected the netstandard task project to compile" + + let output = File.ReadAllText(Path.Combine(outputDir, "task.py")) + Expect.isFalse (output.Contains("raise 1")) "Task lowering must not emit the FCS recovery expression" + Expect.stringContains output "task()" "Expected task-builder-generated Python" + /// `fable precompile` writes each chunk of inline expressions twice: the compact copy the CLI /// reads, and the browser copy fable-standalone reads. This asks four things of every chunk: /// @@ -116,4 +156,5 @@ let tests = })) |> Seq.toList + |> List.append [ taskNetstandardPythonTest ] |> testList "Compilation" diff --git a/tests/Integration/Integration/fixtures/taskNetstandardPython/Task.fs b/tests/Integration/Integration/fixtures/taskNetstandardPython/Task.fs new file mode 100644 index 0000000000..9bfd91c22a --- /dev/null +++ b/tests/Integration/Integration/fixtures/taskNetstandardPython/Task.fs @@ -0,0 +1,16 @@ +module TaskRegression + +open System.Threading.Tasks + +let run shouldThrow : Task> = + task { + let! value = Task.FromResult 42 + + try + if shouldThrow then + failwith "boom" + + return Ok value + with error -> + return Error error + } diff --git a/tests/Integration/Integration/fixtures/taskNetstandardPython/taskNetstandardPython.fsproj b/tests/Integration/Integration/fixtures/taskNetstandardPython/taskNetstandardPython.fsproj new file mode 100644 index 0000000000..873bdf229f --- /dev/null +++ b/tests/Integration/Integration/fixtures/taskNetstandardPython/taskNetstandardPython.fsproj @@ -0,0 +1,11 @@ + + + netstandard2.0 + + + + + + + + From f3a2254e81d68d5d0ee6513f07fb284be5a83fd8 Mon Sep 17 00:00:00 2001 From: Mangel Maxime Date: Mon, 31 Aug 2026 16:55:02 +0200 Subject: [PATCH 2/2] test: use the compilation snapshot harness for the FSharp.Core fixture --- .../Integration/CompilationTests.fs | 41 ------------------- .../taskNetstandard/TaskBuilder.fs} | 2 +- .../taskNetstandard/TaskBuilder.jsx.expected | 13 ++++++ .../taskNetstandard/taskNetstandard.fsproj} | 8 +++- 4 files changed, 20 insertions(+), 44 deletions(-) rename tests/Integration/Integration/{fixtures/taskNetstandardPython/Task.fs => data/taskNetstandard/TaskBuilder.fs} (93%) create mode 100644 tests/Integration/Integration/data/taskNetstandard/TaskBuilder.jsx.expected rename tests/Integration/Integration/{fixtures/taskNetstandardPython/taskNetstandardPython.fsproj => data/taskNetstandard/taskNetstandard.fsproj} (85%) diff --git a/tests/Integration/Integration/CompilationTests.fs b/tests/Integration/Integration/CompilationTests.fs index 8c731fdda9..8d592785df 100644 --- a/tests/Integration/Integration/CompilationTests.fs +++ b/tests/Integration/Integration/CompilationTests.fs @@ -7,46 +7,6 @@ open Fable.Compiler.Util let private data = Path.Combine(__SOURCE_DIRECTORY__, "data") -let private taskNetstandardPythonTest = - testCase "Python task expressions use the project's netstandard FSharp.Core" <| fun () -> - let testCaseDir = Path.Combine(__SOURCE_DIRECTORY__, "fixtures", "taskNetstandardPython") - let project = Path.Combine(testCaseDir, "taskNetstandardPython.fsproj") - let outputDir = Path.Combine(testCaseDir, "out") - - if Directory.Exists outputDir then - Directory.Delete(outputDir, true) - - let configuration = - System.Reflection.Assembly.GetExecutingAssembly().Location - |> Path.GetDirectoryName - |> Directory.GetParent - |> _.Name - - let compiler = - Path.GetFullPath( - Path.Combine(__SOURCE_DIRECTORY__, $"../../../src/Fable.Cli/bin/%s{configuration}/net10.0/fable.dll") - ) - - let exitCode = - Process.runSync - testCaseDir - "dotnet" - [ compiler - project - "--cwd" - testCaseDir - "--lang" - "Python" - "--outDir" - outputDir - "--noCache" ] - - Expect.equal exitCode 0 "Expected the netstandard task project to compile" - - let output = File.ReadAllText(Path.Combine(outputDir, "task.py")) - Expect.isFalse (output.Contains("raise 1")) "Task lowering must not emit the FCS recovery expression" - Expect.stringContains output "task()" "Expected task-builder-generated Python" - /// `fable precompile` writes each chunk of inline expressions twice: the compact copy the CLI /// reads, and the browser copy fable-standalone reads. This asks four things of every chunk: /// @@ -156,5 +116,4 @@ let tests = })) |> Seq.toList - |> List.append [ taskNetstandardPythonTest ] |> testList "Compilation" diff --git a/tests/Integration/Integration/fixtures/taskNetstandardPython/Task.fs b/tests/Integration/Integration/data/taskNetstandard/TaskBuilder.fs similarity index 93% rename from tests/Integration/Integration/fixtures/taskNetstandardPython/Task.fs rename to tests/Integration/Integration/data/taskNetstandard/TaskBuilder.fs index 9bfd91c22a..9c41313ad7 100644 --- a/tests/Integration/Integration/fixtures/taskNetstandardPython/Task.fs +++ b/tests/Integration/Integration/data/taskNetstandard/TaskBuilder.fs @@ -1,4 +1,4 @@ -module TaskRegression +module TaskBuilder open System.Threading.Tasks diff --git a/tests/Integration/Integration/data/taskNetstandard/TaskBuilder.jsx.expected b/tests/Integration/Integration/data/taskNetstandard/TaskBuilder.jsx.expected new file mode 100644 index 0000000000..33b008a4da --- /dev/null +++ b/tests/Integration/Integration/data/taskNetstandard/TaskBuilder.jsx.expected @@ -0,0 +1,13 @@ + +import { task } from "./fable_modules/fable-library-js.5.15.0/TaskBuilder.js"; +import { fromResult } from "./fable_modules/fable-library-js.5.15.0/Task.js"; +import { Exception } from "./fable_modules/fable-library-js.5.15.0/Util.js"; +import { FSharpResult$2 } from "./fable_modules/fable-library-js.5.15.0/Result.js"; + +export function run(shouldThrow) { + const builder$0040 = task(); + return builder$0040.Run(builder$0040.Delay(() => builder$0040.Bind(fromResult(42), (_arg) => builder$0040.TryWith(builder$0040.Delay(() => builder$0040.Combine(shouldThrow ? (((() => { + throw new Exception("boom"); + })(), builder$0040.Zero())) : builder$0040.Zero(), builder$0040.Delay(() => builder$0040.Return(new FSharpResult$2(/* Ok */ 0, [_arg]))))), (_arg_1) => builder$0040.Return(new FSharpResult$2(/* Error */ 1, [_arg_1])))))); +} + diff --git a/tests/Integration/Integration/fixtures/taskNetstandardPython/taskNetstandardPython.fsproj b/tests/Integration/Integration/data/taskNetstandard/taskNetstandard.fsproj similarity index 85% rename from tests/Integration/Integration/fixtures/taskNetstandardPython/taskNetstandardPython.fsproj rename to tests/Integration/Integration/data/taskNetstandard/taskNetstandard.fsproj index 873bdf229f..024261748d 100644 --- a/tests/Integration/Integration/fixtures/taskNetstandardPython/taskNetstandardPython.fsproj +++ b/tests/Integration/Integration/data/taskNetstandard/taskNetstandard.fsproj @@ -1,11 +1,15 @@ + netstandard2.0 + - + + - + +