|
1 | 1 | // State management for Reflex web apps. |
2 | 2 | import io from "socket.io-client"; |
3 | | -import JSON5 from "json5"; |
4 | 3 | import env from "$/env.json"; |
5 | 4 | import reflexEnvironment from "$/reflex.json"; |
6 | 5 | import Cookies from "universal-cookie"; |
@@ -436,6 +435,25 @@ const resolveSocket = (socket) => { |
436 | 435 | return socket?.current ?? socket; |
437 | 436 | }; |
438 | 437 |
|
| 438 | +// Python's json.dumps emits bare Infinity/-Infinity/NaN tokens (invalid JSON). |
| 439 | +// Rewrite them outside string literals so JSON.parse accepts the payload. |
| 440 | +// 1e999 / -1e999 overflow to ±Infinity; NaN has no JSON literal, so it is |
| 441 | +// swapped for a sentinel string and revived back to NaN after parsing. |
| 442 | +// The alternation matches whole string literals first (passed through unchanged), |
| 443 | +// guaranteeing bare-token matches only land in numeric positions. |
| 444 | +const NAN_SENTINEL = "__reflex_nan__"; |
| 445 | +const NON_FINITE_FLOAT_RE = /"(?:[^"\\]|\\.)*"|-?\bInfinity\b|\bNaN\b/g; |
| 446 | +const NON_FINITE_REPLACEMENTS = { |
| 447 | + Infinity: "1e999", |
| 448 | + "-Infinity": "-1e999", |
| 449 | + NaN: `"${NAN_SENTINEL}"`, |
| 450 | +}; |
| 451 | +const rewriteBareNonFiniteFloats = (str) => |
| 452 | + str.replace(NON_FINITE_FLOAT_RE, (match) => |
| 453 | + match[0] === '"' ? match : NON_FINITE_REPLACEMENTS[match], |
| 454 | + ); |
| 455 | +const reviveNonFiniteFloats = (_k, v) => (v === NAN_SENTINEL ? NaN : v); |
| 456 | + |
439 | 457 | /** |
440 | 458 | * Queue events to be processed and trigger processing of queue. |
441 | 459 | * @param events Array of events to queue. |
@@ -541,9 +559,16 @@ export const connect = async ( |
541 | 559 | socket.current.io.encoder.replacer = (k, v) => (v === undefined ? null : v); |
542 | 560 | socket.current.io.decoder.tryParse = (str) => { |
543 | 561 | try { |
544 | | - return JSON5.parse(str); |
| 562 | + return JSON.parse(str); |
545 | 563 | } catch (e) { |
546 | | - return false; |
| 564 | + try { |
| 565 | + return JSON.parse( |
| 566 | + rewriteBareNonFiniteFloats(str), |
| 567 | + reviveNonFiniteFloats, |
| 568 | + ); |
| 569 | + } catch (e2) { |
| 570 | + return false; |
| 571 | + } |
547 | 572 | } |
548 | 573 | }; |
549 | 574 | // Set up a reconnect helper function |
|
0 commit comments