From 3ae103746e1fb946995eb856afe6d15de2c21c15 Mon Sep 17 00:00:00 2001 From: Mangel Maxime Date: Thu, 25 Jun 2026 21:09:06 +0200 Subject: [PATCH] fix: drop allowAccessToPrivateRepresentation arg from reflection calls --- src/Fable.Transforms/Python/Replacements.fs | 13 ++++++++++++- src/Fable.Transforms/Replacements.fs | 13 ++++++++++++- tests/Js/Main/ReflectionTests.fs | 18 ++++++++++++++++++ tests/Python/TestReflection.fs | 19 +++++++++++++++++++ 4 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/Fable.Transforms/Python/Replacements.fs b/src/Fable.Transforms/Python/Replacements.fs index c137a9611..6325a88b2 100644 --- a/src/Fable.Transforms/Python/Replacements.fs +++ b/src/Fable.Transforms/Python/Replacements.fs @@ -3967,7 +3967,8 @@ let fsharpType com methName (r: SourceLocation option) t (i: CallInfo) (args: Ex |> Some // Prevent name clash with FSharpValue.GetRecordFields | "GetRecordFields" -> - Helper.LibCall(com, "Reflection", "get_record_elements", t, args, i.SignatureArgTypes, ?loc = r) + // Drop the trailing `allowAccessToPrivateRepresentation` flag (no meaning in Python) + Helper.LibCall(com, "Reflection", "get_record_elements", t, List.truncate 1 args, i.SignatureArgTypes, ?loc = r) |> Some | "GetUnionCases" | "GetTupleElements" @@ -3992,6 +3993,16 @@ let fsharpValue com methName (r: SourceLocation option) t (i: CallInfo) (args: E | "MakeUnion" | "MakeRecord" | "MakeTuple" -> + // Drop the trailing `allowAccessToPrivateRepresentation` flag, a .NET-only + // concept the runtime helpers don't accept. + let args = + match methName with + | "GetRecordFields" -> List.truncate 1 args + | "GetUnionFields" + | "MakeUnion" + | "MakeRecord" -> List.truncate 2 args + | _ -> args + Helper.LibCall(com, "Reflection", Naming.lowerFirst methName, t, args, i.SignatureArgTypes, ?loc = r) |> Some | "GetExceptionFields" -> None // TODO!!! diff --git a/src/Fable.Transforms/Replacements.fs b/src/Fable.Transforms/Replacements.fs index 0c3366179..446cb86b9 100644 --- a/src/Fable.Transforms/Replacements.fs +++ b/src/Fable.Transforms/Replacements.fs @@ -4154,7 +4154,8 @@ let fsharpType com (ctx: Context) methName (r: SourceLocation option) t (i: Call |> Some // Prevent name clash with FSharpValue.GetRecordFields | "GetRecordFields" -> - Helper.LibCall(com, "Reflection", "getRecordElements", t, args, i.SignatureArgTypes, ?loc = r) + // Drop the trailing `allowAccessToPrivateRepresentation` flag (no meaning in JS/TS) + Helper.LibCall(com, "Reflection", "getRecordElements", t, List.truncate 1 args, i.SignatureArgTypes, ?loc = r) |> Some | "GetUnionCases" | "GetTupleElements" @@ -4185,6 +4186,16 @@ let fsharpValue com methName (r: SourceLocation option) t (i: CallInfo) (args: E | "MakeUnion" | "MakeRecord" | "MakeTuple" -> + // Drop the trailing `allowAccessToPrivateRepresentation` flag, a .NET-only + // concept the runtime helpers don't accept. + let args = + match methName with + | "GetRecordFields" -> List.truncate 1 args + | "GetUnionFields" + | "MakeUnion" + | "MakeRecord" -> List.truncate 2 args + | _ -> args + Helper.LibCall(com, "Reflection", Naming.lowerFirst methName, t, args, i.SignatureArgTypes, ?loc = r) |> Some | "GetExceptionFields" -> None // TODO!!! diff --git a/tests/Js/Main/ReflectionTests.fs b/tests/Js/Main/ReflectionTests.fs index 20cdbda9c..fc68a77ab 100644 --- a/tests/Js/Main/ReflectionTests.fs +++ b/tests/Js/Main/ReflectionTests.fs @@ -381,6 +381,24 @@ let reflectionTests = [ let all = isRecord && matchRecordFields && matchIndividualRecordFields && canMakeSameRecord all |> equal true + testCase "Reflection functions accept allowAccessToPrivateRepresentation" <| fun () -> + let recordType = typeof + let record = { String = "a"; Int = 1 } + + FSharpType.GetRecordFields(recordType, allowAccessToPrivateRepresentation = true).Length |> equal 2 + + let values = FSharpValue.GetRecordFields(record, allowAccessToPrivateRepresentation = true) + let rebuilt = + FSharpValue.MakeRecord(recordType, values, allowAccessToPrivateRepresentation = true) :?> TestRecord + rebuilt |> equal record + + let unionType = typeof + let intCase = FSharpType.GetUnionCases(unionType).[1] + let u = FSharpValue.MakeUnion(intCase, [| box 5 |], allowAccessToPrivateRepresentation = true) :?> TestUnion + let info, fields = FSharpValue.GetUnionFields(u, unionType, allowAccessToPrivateRepresentation = true) + info.Name |> equal "IntCase" + fields.[0] |> equal (box 5) + testCase "PropertyInfo.GetValue works" <| fun () -> let value: obj = { Firstname = "Maxime"; Age = 12 } :> obj diff --git a/tests/Python/TestReflection.fs b/tests/Python/TestReflection.fs index 21a152792..572debd8e 100644 --- a/tests/Python/TestReflection.fs +++ b/tests/Python/TestReflection.fs @@ -218,6 +218,25 @@ let ``test Reflection Array`` () = typeof = elType |> equal false liType.GetElementType() |> equal null +[] +let ``test reflection functions accept allowAccessToPrivateRepresentation`` () = + let recordType = typeof + let record = { String = "a"; Int = 1 } + + FSharpType.GetRecordFields(recordType, allowAccessToPrivateRepresentation = true).Length |> equal 2 + + let values = FSharpValue.GetRecordFields(record, allowAccessToPrivateRepresentation = true) + let rebuilt = + FSharpValue.MakeRecord(recordType, values, allowAccessToPrivateRepresentation = true) :?> MyRecord + rebuilt |> equal record + + let unionType = typeof + let intCase = FSharpType.GetUnionCases(unionType).[1] + let u = FSharpValue.MakeUnion(intCase, [| box 5 |], allowAccessToPrivateRepresentation = true) :?> MyUnion + let info, fields = FSharpValue.GetUnionFields(u, unionType, allowAccessToPrivateRepresentation = true) + info.Name |> equal "IntCase" + fields.[0] |> equal (box 5) + #if FABLE_COMPILER [] let ``test FSharp.Reflection Record`` () =