fix: isolate dynamic JavaScript execution environments

Merged
SO
2d ago
+220-78

All Submissions:

  • Have you followed the guidelines stated in the CONTRIBUTING.md file?
  • Have you checked to ensure there aren't any other open Pull Requests for the desired change?

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality not to work as expected)
  • This change requires a documentation update

New Feature Submission:

  • Does your submission pass the tests?
  • Have you linted your code locally before submission?

Changes To Core Features:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your core changes, as applicable?
  • Have you successfully run tests with your changes locally?

closes #7860

Server-provided JavaScript (rx.call_script code, rx.call_function functions and their result callbacks) no longer runs through a direct eval in utils/state.js. A direct eval stops the minifier from mangling the chunk that holds it; with frontend_lazy_bundled_libraries on, this shrinks the shared chunk by about 88 KB (11 KB gzipped).

  • One runScript helper compiles a Function-constructor evaluator on first use, so a CSP without unsafe-eval still loads apps that never send scripts. Its body passes the code to eval, which sees only the Function's parameters and the globals, and runs it as a strict script, so statement lists keep their completion value.
  • Scripts see every export of utils/state.js (ReflexEvent, refs, queueEvents, pyMod, ...), the late-bound addEvents, the socket, navigate and params of the event, the session token, and the globals. Names the module does not export (its imports, such as eventLoop) are no longer in scope.
  • evalReactComponent uses a native import() of the data URI instead of eval("import(...)").
  • Tests: packages/reflex-frontend/tests/run_script.test.js pins completion values, strict mode, scope, late-bound addEvents across event-loop remounts, and lazy compilation. test_state_js_template.py checks that every runScript call site declares the addEvents alias first.