Skip to content

Commit 1c7c1d2

Browse files
committed
Restore Fable compatibility in JSON runtime
1 parent 7fc7b2f commit 1c7c1d2

2 files changed

Lines changed: 49 additions & 11 deletions

File tree

src/CodecMapper/Core.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ module Core =
572572
else
573573
(x :> IByteWriter).WriteString(value.ToString("R", CultureInfo.InvariantCulture))
574574
#else
575-
(x :> IByteWriter).WriteString(Schema.formatFloat value)
575+
(x :> IByteWriter).WriteString(value.ToString())
576576
#endif
577577

578578
member x.WriteDecimal(value: decimal) =

src/CodecMapper/Json.fs

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ namespace CodecMapper
33
open System.Text
44
open System.Collections.Generic
55
open System.Globalization
6+
#if !FABLE_COMPILER
67
open System.Collections.Concurrent
8+
#endif
79
open Microsoft.FSharp.Reflection
810

911
/// JSON codec compilation and runtime helpers.
@@ -62,7 +64,11 @@ module Json =
6264
sprintf "JSON decode error at %s: %s" (renderPath path) detail
6365

6466
module internal Runtime =
67+
#if !FABLE_COMPILER
6568
let private objectArrayPools = ConcurrentDictionary<int, ConcurrentBag<obj array>>()
69+
#else
70+
let private objectArrayPools = Dictionary<int, ResizeArray<obj array>>()
71+
#endif
6672

6773
let private asDecodeException detail path inner =
6874
JsonDecodeException(path, detail, inner) :> exn
@@ -279,10 +285,10 @@ module Json =
279285
let mutable finished = false
280286
let mutable hadEscapes = false
281287

282-
///
283-
/// Unknown-field skipping should stay linear even for escaped text,
284-
/// so scan forward once instead of recounting backslashes at every
285-
/// candidate quote.
288+
//
289+
// Unknown-field skipping should stay linear even for escaped text,
290+
// so scan forward once instead of recounting backslashes at every
291+
// candidate quote.
286292
while i < data.Length && not finished do
287293
match data[i] with
288294
| 34uy -> finished <- true
@@ -576,13 +582,17 @@ module Json =
576582

577583
equal
578584

585+
#if !FABLE_COMPILER
579586
let private listBuilders = ConcurrentDictionary<System.Type, obj array -> obj>()
587+
#else
588+
let private listBuilders = Dictionary<System.Type, obj array -> obj>()
589+
#endif
580590

581591
let makeListBuilder (elementType: System.Type) =
592+
#if !FABLE_COMPILER
582593
listBuilders.GetOrAdd(
583594
elementType,
584595
System.Func<_, _>(fun elementType ->
585-
#if !FABLE_COMPILER
586596
let listType = typedefof<_ list>.MakeGenericType([| elementType |])
587597
let emptyList = listType.GetProperty("Empty").GetValue(null)
588598
let cons = listType.GetMethod("Cons")
@@ -593,12 +603,16 @@ module Json =
593603
for i in elements.Length - 1 .. -1 .. 0 do
594604
result <- cons.Invoke(null, [| elements[i]; result |])
595605

596-
result
606+
result)
607+
)
597608
#else
598-
fun (elements: obj array) -> List.ofArray elements |> box
609+
match listBuilders.TryGetValue(elementType) with
610+
| true, builder -> builder
611+
| false, _ ->
612+
let builder = fun (elements: obj array) -> List.ofArray elements |> box
613+
listBuilders[elementType] <- builder
614+
builder
599615
#endif
600-
)
601-
)
602616

603617
///
604618
/// XML shares the same erased list-construction helper, so keep the
@@ -616,20 +630,44 @@ module Json =
616630
/// pooling the `obj[]` buffers removes one of the largest remaining
617631
/// allocation sources on nested decode workloads.
618632
let rentObjectArray length =
633+
#if !FABLE_COMPILER
619634
let pool = objectArrayPools.GetOrAdd(length, fun _ -> ConcurrentBag<obj array>())
620635
let mutable rented = Unchecked.defaultof<obj array>
621636

622637
if pool.TryTake(&rented) then
623638
rented
624639
else
625640
Array.zeroCreate length
641+
#else
642+
match objectArrayPools.TryGetValue(length) with
643+
| true, pool when pool.Count > 0 ->
644+
let lastIndex = pool.Count - 1
645+
let rented = pool[lastIndex]
646+
pool.RemoveAt(lastIndex)
647+
rented
648+
| _ -> Array.zeroCreate length
649+
#endif
626650

627651
///
628652
/// Record field buffers may hold arbitrary user objects, so return
629653
/// them cleared to avoid keeping payload graphs alive across runs.
630654
let returnObjectArray (buffer: obj array) (usedLength: int) =
631-
System.Array.Clear(buffer, 0, usedLength)
655+
for i in 0 .. usedLength - 1 do
656+
buffer[i] <- null
657+
658+
#if !FABLE_COMPILER
632659
objectArrayPools.GetOrAdd(usedLength, fun _ -> ConcurrentBag<obj array>()).Add(buffer)
660+
#else
661+
let pool =
662+
match objectArrayPools.TryGetValue(usedLength) with
663+
| true, existing -> existing
664+
| false, _ ->
665+
let created = ResizeArray<obj array>()
666+
objectArrayPools[usedLength] <- created
667+
created
668+
669+
pool.Add(buffer)
670+
#endif
633671

634672
type CompiledCodec = {
635673
Encode: IByteWriter -> obj -> unit

0 commit comments

Comments
 (0)