@@ -631,7 +631,7 @@ var d = Object.defineProperty, p = SuryError.prototype;
631631d (p, ' message' , {
632632 get () {
633633 return message (this );
634- }
634+ },
635635})
636636d (p, ' reason' , {
637637 get () {
@@ -1587,6 +1587,12 @@ let failTransform = (b, ~inputVar, ~path, ~target) => {
15871587 )
15881588}
15891589
1590+ let jsonName = ` JSON`
1591+
1592+ let inputToString = (b , input : val ) => {
1593+ b -> B .val (` ""+${input.inline}` , ~schema = string )
1594+ }
1595+
15901596let rec parse = (prevB : b , ~schema , ~input as inputArg : val , ~path ) => {
15911597 let b = B .scope (prevB )
15921598
@@ -1606,8 +1612,21 @@ let rec parse = (prevB: b, ~schema, ~input as inputArg: val, ~path) => {
16061612 let isSameTag = input .contents .tag === schema .tag
16071613 let schemaTagFlag = TagFlag .get (schema .tag )
16081614 let inputTagFlag = TagFlag .get (input .contents .tag )
1615+ let isUnsupported = ref (false )
16091616 if schemaTagFlag -> Flag .unsafeHas (TagFlag .union -> Flag .with (TagFlag .unknown )) {
16101617 ()
1618+ } else if ! (inputTagFlag -> Flag .unsafeHas (TagFlag .unknown )) && schema .name === Some (jsonName ) {
1619+ if (
1620+ inputTagFlag -> Flag .unsafeHas (
1621+ TagFlag .string -> Flag .with (TagFlag .number )-> Flag .with (TagFlag .boolean ),
1622+ )
1623+ ) {
1624+ ()
1625+ } else if inputTagFlag -> Flag .unsafeHas (TagFlag .bigint ) {
1626+ input := b -> inputToString (input .contents )
1627+ } else {
1628+ isUnsupported := true
1629+ }
16111630 } else if isSchemaLiteral {
16121631 if isFromLiteral {
16131632 if input .contents .const !== schema .const {
@@ -1666,34 +1685,82 @@ let rec parse = (prevB: b, ~schema, ~input as inputArg: val, ~path) => {
16661685 inline : ` "${const}"` ,
16671686 }
16681687 } else {
1669- unsupportedTransform (~ from = input . contents -> Obj . magic , ~ target = schema )
1688+ isUnsupported := true
16701689 }
16711690 } else if inputTagFlag -> Flag .unsafeHas (TagFlag .unknown ) {
1672- if b .global .flag -> Flag .unsafeHas (Flag .typeValidation ) {
1673- b .filterCode = prevB -> B .typeFilterCode (~schema , ~input = input .contents , ~path )
1674- }
1675- // FIXME: Make it simpler
1676- let refined = b -> B .makeRefinedOf (~input = input .contents , ~schema )
1677- input .contents .tag = refined .tag
1678- input .contents .inline = refined .inline
1679- input .contents .var = refined .var
1680- input .contents .additionalItems = refined .additionalItems
1681- input .contents .properties = refined .properties
1682- if refined -> Obj .magic -> isLiteral {
1683- input .contents .const = refined .const
1691+ switch schema .ref {
1692+ | Some (ref ) =>
1693+ let defs = b .global .defs -> X .Option .getUnsafe
1694+ // Ignore #/$defs/
1695+ let identifier = ref -> Js .String2 .sliceToEnd (~from = 8 )
1696+ let def = defs -> Js .Dict .unsafeGet (identifier )
1697+ let flag = if schema .noValidation -> X .Option .getUnsafe {
1698+ b .global .flag -> Flag .without (Flag .typeValidation )
1699+ } else {
1700+ b .global .flag
1701+ }
1702+ let recOperation = switch def -> Obj .magic -> X .Dict .unsafeGetOptionByInt (flag ) {
1703+ | Some (fn ) =>
1704+ // A hacky way to prevent infinite recursion
1705+ if fn === %raw (` 0 ` ) {
1706+ b -> B .embed (def ) ++ ` [${flag-> X.Int.unsafeToString}]`
1707+ } else {
1708+ b -> B .embed (fn )
1709+ }
1710+ | None => {
1711+ def
1712+ -> Obj .magic
1713+ -> X .Dict .setByInt (flag , 0 )
1714+ let fn = internalCompile (~schema = def , ~flag , ~defs = b .global .defs )
1715+ def
1716+ -> Obj .magic
1717+ -> X .Dict .setByInt (flag , fn )
1718+ b -> B .embed (fn )
1719+ }
1720+ }
1721+ input :=
1722+ b -> B .withPathPrepend (~input = input .contents , ~path , (_ , ~input , ~path as _ ) => {
1723+ let output = B .Val .map (recOperation , input )
1724+ if def .isAsync === None {
1725+ let defsMut = defs -> X .Dict .copy
1726+ defsMut -> Js .Dict .set (identifier , unknown )
1727+ let _ = def -> isAsyncInternal (~defs = Some (defsMut ))
1728+ }
1729+ if def .isAsync -> X .Option .getUnsafe {
1730+ output .flag = output .flag -> Flag .with (ValFlag .async )
1731+ }
1732+ output
1733+ })
1734+ // Force rec function execution
1735+ // for the case when the value is not used
1736+ let _ = input .contents .var (b )
1737+ | None => {
1738+ if b .global .flag -> Flag .unsafeHas (Flag .typeValidation ) {
1739+ b .filterCode = prevB -> B .typeFilterCode (~schema , ~input = input .contents , ~path )
1740+ }
1741+ // FIXME: Make it simpler
1742+ let refined = b -> B .makeRefinedOf (~input = input .contents , ~schema )
1743+ input .contents .tag = refined .tag
1744+ input .contents .inline = refined .inline
1745+ input .contents .var = refined .var
1746+ input .contents .additionalItems = refined .additionalItems
1747+ input .contents .properties = refined .properties
1748+ if refined -> Obj .magic -> isLiteral {
1749+ input .contents .const = refined .const
1750+ }
1751+ }
16841752 }
16851753 } else if (
16861754 schemaTagFlag -> Flag .unsafeHas (TagFlag .string ) &&
16871755 inputTagFlag -> Flag .unsafeHas (
16881756 TagFlag .boolean -> Flag .with (TagFlag .number -> Flag .with (TagFlag .bigint )),
16891757 )
16901758 ) {
1691- input := b -> B . val ( ` ""+${ input.contents.inline}` , ~ schema )
1759+ input := b -> inputToString ( input .contents )
16921760 } else if ! isSameTag {
16931761 if inputTagFlag -> Flag .unsafeHas (TagFlag .string ) {
16941762 let inputVar = input .contents .var (b )
1695- switch schema {
1696- | {tag : Boolean } =>
1763+ if schemaTagFlag -> Flag .unsafeHas (TagFlag .boolean ) {
16971764 let output = b -> B .allocateVal (~schema ) // FIXME: schema should be only simple bool
16981765 b .code =
16991766 b .code ++
@@ -1703,13 +1770,12 @@ let rec parse = (prevB: b, ~schema, ~input as inputArg: val, ~path) => {
17031770 ~target= schema,
17041771 )};`
17051772 input := output
1706-
1707- | {tag : Number , ?format } =>
1773+ } else if schemaTagFlag -> Flag .unsafeHas (TagFlag .number ) {
17081774 let output = b -> B .val (` +${inputVar}` , ~schema ) // FIXME: schema
17091775 let outputVar = output .var (b )
17101776 b .code =
17111777 b .code ++
1712- switch format {
1778+ switch schema . format {
17131779 | None => ` Number.isNaN(${outputVar})`
17141780 | Some (_ ) =>
17151781 ` (${b
@@ -1718,8 +1784,7 @@ let rec parse = (prevB: b, ~schema, ~input as inputArg: val, ~path) => {
17181784 } ++
17191785 ` &&${b-> failTransform(~inputVar, ~path, ~target= schema)};`
17201786 input := output
1721-
1722- | {tag : BigInt } =>
1787+ } else if schemaTagFlag -> Flag .unsafeHas (TagFlag .bigint ) {
17231788 let output = b -> B .allocateVal (~schema ) // FIXME:
17241789 b .code =
17251790 b .code ++
@@ -1729,60 +1794,16 @@ let rec parse = (prevB: b, ~schema, ~input as inputArg: val, ~path) => {
17291794 ~target= schema,
17301795 )}}`
17311796 input := output
1732- | _ => unsupportedTransform (~from = input .contents -> Obj .magic , ~target = schema )
1797+ } else {
1798+ isUnsupported := true
17331799 }
17341800 } else {
1735- unsupportedTransform (~ from = input . contents -> Obj . magic , ~ target = schema )
1801+ isUnsupported := true
17361802 }
17371803 }
17381804
1739- switch schema .ref {
1740- | Some (ref ) =>
1741- let defs = b .global .defs -> X .Option .getUnsafe
1742- // Ignore #/$defs/
1743- let identifier = ref -> Js .String2 .sliceToEnd (~from = 8 )
1744- let def = defs -> Js .Dict .unsafeGet (identifier )
1745- let flag = if schema .noValidation -> X .Option .getUnsafe {
1746- b .global .flag -> Flag .without (Flag .typeValidation )
1747- } else {
1748- b .global .flag
1749- }
1750- let recOperation = switch def -> Obj .magic -> X .Dict .unsafeGetOptionByInt (flag ) {
1751- | Some (fn ) =>
1752- // A hacky way to prevent infinite recursion
1753- if fn === %raw (` 0 ` ) {
1754- b -> B .embed (def ) ++ ` [${flag-> X.Int.unsafeToString}]`
1755- } else {
1756- b -> B .embed (fn )
1757- }
1758- | None => {
1759- def
1760- -> Obj .magic
1761- -> X .Dict .setByInt (flag , 0 )
1762- let fn = internalCompile (~schema = def , ~flag , ~defs = b .global .defs )
1763- def
1764- -> Obj .magic
1765- -> X .Dict .setByInt (flag , fn )
1766- b -> B .embed (fn )
1767- }
1768- }
1769- input :=
1770- b -> B .withPathPrepend (~input = input .contents , ~path , (_ , ~input , ~path as _ ) => {
1771- let output = B .Val .map (recOperation , input )
1772- if def .isAsync === None {
1773- let defsMut = defs -> X .Dict .copy
1774- defsMut -> Js .Dict .set (identifier , unknown )
1775- let _ = def -> isAsyncInternal (~defs = Some (defsMut ))
1776- }
1777- if def .isAsync -> X .Option .getUnsafe {
1778- output .flag = output .flag -> Flag .with (ValFlag .async )
1779- }
1780- output
1781- })
1782- // Force rec function execution
1783- // for the case when the value is not used
1784- let _ = input .contents .var (b )
1785- | None => ()
1805+ if isUnsupported .contents {
1806+ unsupportedTransform (~from = input .contents -> Obj .magic , ~target = schema )
17861807 }
17871808
17881809 switch schema .refiner {
@@ -3327,7 +3348,6 @@ module String = {
33273348 let datetimeRe = %re (` /^\d {4}-\d {2}-\d {2}T\d {2}:\d {2}:\d {2}(\.\d +)?Z$/` )
33283349}
33293350
3330- let jsonName = ` JSON`
33313351let json = {
33323352 let jsonRef = base (Ref )
33333353 jsonRef .ref = Some (` ${defsPath}${jsonName}` )
@@ -3380,8 +3400,6 @@ module JsonString = {
33803400 message = > OperationFailed(message),
33813401 "t.message" ,
33823402 )}}`
3383-
3384- // b->B.typeValidation(~schema=item, ~input=jsonVal, ~path)
33853403 jsonVal
33863404 }),
33873405 )
0 commit comments