File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -4282,7 +4282,13 @@ let fsharpValue com methName (r: SourceLocation option) t (i: CallInfo) (args: E
42824282 // concept the runtime helpers don't accept.
42834283 let args =
42844284 match methName with
4285- | " GetRecordFields" -> List.truncate 1 args
4285+ | " GetRecordFields" ->
4286+ let recordArg = List.head args
4287+ // For anonymous records, None fields are omitted from the JS object so
4288+ // Object.keys cannot enumerate them. Pass the TypeInfo so the runtime can
4289+ // use field names from the type instead of from the object's own keys.
4290+ let ( MaybeCasted innerArg ) = recordArg
4291+ [ recordArg; makeTypeInfo r innerArg.Type ]
42864292 | " GetUnionFields"
42874293 | " MakeUnion"
42884294 | " MakeRecord" -> List.truncate 2 args
Original file line number Diff line number Diff line change @@ -488,8 +488,14 @@ export function getUnionCaseFields(uci: CaseInfo): FieldInfo[] {
488488
489489// This is used as replacement of `FSharpValue.GetRecordFields`
490490// For `FSharpTypes.GetRecordFields` see `getRecordElements`
491- // Object.keys returns keys in the order they were added to the object
492- export function getRecordFields ( v : any ) : MutableArray < any > {
491+ // TypeInfo is used when available to enumerate fields by name: anonymous record None fields
492+ // are omitted from the JS object, so Object.keys alone would miss them.
493+ // Boxed anonymous record would are still not covered but this is the best we can do for now
494+ // without adding a __fields__ to every anonymous record being created
495+ export function getRecordFields ( v : any , t : TypeInfo ) : MutableArray < any > {
496+ if ( t . fields != null ) {
497+ return t . fields ( ) . map ( ( [ key , _ ] ) => v [ key ] ) ;
498+ }
493499 return Object . keys ( v ) . map ( ( k ) => v [ k ] ) ;
494500}
495501
Original file line number Diff line number Diff line change @@ -381,6 +381,13 @@ let reflectionTests = [
381381 let all = isRecord && matchRecordFields && matchIndividualRecordFields && canMakeSameRecord
382382 all |> equal true
383383
384+ testCase " FSharpValue.GetRecordFields with anonymous record returns all fields including None" <| fun () ->
385+ let fields = FSharpValue.GetRecordFields {| a = 3 ; b = ( None: int option ); c = Some 89 |}
386+ fields.Length |> equal 3
387+ fields.[ 0 ] |> equal ( box 3 )
388+ fields.[ 1 ] |> equal ( box None)
389+ fields.[ 2 ] |> equal ( box ( Some 89 ))
390+
384391 testCase " Reflection functions accept allowAccessToPrivateRepresentation" <| fun () ->
385392 let recordType = typeof< TestRecord>
386393 let record = { String = " a" ; Int = 1 }
You can’t perform that action at this time.
0 commit comments