diff --git a/packages/reflex-base/src/reflex_base/.templates/web/utils/state.js b/packages/reflex-base/src/reflex_base/.templates/web/utils/state.js index fd2b5e5741b..d931a19299d 100644 --- a/packages/reflex-base/src/reflex_base/.templates/web/utils/state.js +++ b/packages/reflex-base/src/reflex_base/.templates/web/utils/state.js @@ -1,6 +1,5 @@ // State management for Reflex web apps. import io from "socket.io-client"; -import JSON5 from "json5"; import env from "$/env.json"; import reflexEnvironment from "$/reflex.json"; import Cookies from "universal-cookie"; @@ -436,6 +435,25 @@ const resolveSocket = (socket) => { return socket?.current ?? socket; }; +// Python's json.dumps emits bare Infinity/-Infinity/NaN tokens (invalid JSON). +// Rewrite them outside string literals so JSON.parse accepts the payload. +// 1e999 / -1e999 overflow to ±Infinity; NaN has no JSON literal, so it is +// swapped for a sentinel string and revived back to NaN after parsing. +// The alternation matches whole string literals first (passed through unchanged), +// guaranteeing bare-token matches only land in numeric positions. +const NAN_SENTINEL = "__reflex_nan__"; +const NON_FINITE_FLOAT_RE = /"(?:[^"\\]|\\.)*"|-?\bInfinity\b|\bNaN\b/g; +const NON_FINITE_REPLACEMENTS = { + Infinity: "1e999", + "-Infinity": "-1e999", + NaN: `"${NAN_SENTINEL}"`, +}; +const rewriteBareNonFiniteFloats = (str) => + str.replace(NON_FINITE_FLOAT_RE, (match) => + match[0] === '"' ? match : NON_FINITE_REPLACEMENTS[match], + ); +const reviveNonFiniteFloats = (_k, v) => (v === NAN_SENTINEL ? NaN : v); + /** * Queue events to be processed and trigger processing of queue. * @param events Array of events to queue. @@ -541,9 +559,16 @@ export const connect = async ( socket.current.io.encoder.replacer = (k, v) => (v === undefined ? null : v); socket.current.io.decoder.tryParse = (str) => { try { - return JSON5.parse(str); + return JSON.parse(str); } catch (e) { - return false; + try { + return JSON.parse( + rewriteBareNonFiniteFloats(str), + reviveNonFiniteFloats, + ); + } catch (e2) { + return false; + } } }; // Set up a reconnect helper function diff --git a/packages/reflex-base/src/reflex_base/constants/installer.py b/packages/reflex-base/src/reflex_base/constants/installer.py index 1578ace7f2c..d4891d8ae2d 100644 --- a/packages/reflex-base/src/reflex_base/constants/installer.py +++ b/packages/reflex-base/src/reflex_base/constants/installer.py @@ -122,7 +122,6 @@ def DEPENDENCIES(cls) -> dict[str, str]: A dictionary of dependencies with their versions. """ return { - "json5": "2.2.3", "react-router": cls._react_router_version, "react-router-dom": cls._react_router_version, "@react-router/node": cls._react_router_version,